summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'gnu')
-rw-r--r--gnu/COPYING339
-rw-r--r--gnu/COPYING.LIB481
-rw-r--r--gnu/Makefile6
-rw-r--r--gnu/include/values.h177
-rw-r--r--gnu/lib/Makefile25
-rw-r--r--gnu/lib/csu/Makefile68
-rw-r--r--gnu/lib/libdialog/CHANGES9
-rw-r--r--gnu/lib/libdialog/COPYING339
-rw-r--r--gnu/lib/libdialog/Makefile49
-rw-r--r--gnu/lib/libdialog/README8
-rw-r--r--gnu/lib/libdialog/TESTS/Makefile19
-rw-r--r--gnu/lib/libdialog/TESTS/check1.c82
-rw-r--r--gnu/lib/libdialog/TESTS/check2.c104
-rw-r--r--gnu/lib/libdialog/TESTS/check3.c91
-rw-r--r--gnu/lib/libdialog/TESTS/dselect.c40
-rw-r--r--gnu/lib/libdialog/TESTS/fselect.c43
-rw-r--r--gnu/lib/libdialog/TESTS/ftree1.c44
-rw-r--r--gnu/lib/libdialog/TESTS/ftree1.test73
-rw-r--r--gnu/lib/libdialog/TESTS/ftree2.c46
-rw-r--r--gnu/lib/libdialog/TESTS/ftree2.test73
-rw-r--r--gnu/lib/libdialog/TESTS/gauge.c40
-rw-r--r--gnu/lib/libdialog/TESTS/input1.c44
-rw-r--r--gnu/lib/libdialog/TESTS/input2.c46
-rw-r--r--gnu/lib/libdialog/TESTS/menu1.c95
-rw-r--r--gnu/lib/libdialog/TESTS/menu2.c95
-rw-r--r--gnu/lib/libdialog/TESTS/menu3.c106
-rw-r--r--gnu/lib/libdialog/TESTS/msg.c41
-rw-r--r--gnu/lib/libdialog/TESTS/prgbox.c40
-rw-r--r--gnu/lib/libdialog/TESTS/radio1.c70
-rw-r--r--gnu/lib/libdialog/TESTS/radio2.c88
-rw-r--r--gnu/lib/libdialog/TESTS/radio3.c97
-rw-r--r--gnu/lib/libdialog/TESTS/text.c40
-rw-r--r--gnu/lib/libdialog/TESTS/tree.c110
-rw-r--r--gnu/lib/libdialog/TESTS/yesno.c44
-rw-r--r--gnu/lib/libdialog/TODO36
-rw-r--r--gnu/lib/libdialog/checklist.c636
-rw-r--r--gnu/lib/libdialog/colors.h219
-rw-r--r--gnu/lib/libdialog/dialog.3777
-rw-r--r--gnu/lib/libdialog/dialog.h211
-rw-r--r--gnu/lib/libdialog/dialog.priv.h183
-rw-r--r--gnu/lib/libdialog/dir.c549
-rw-r--r--gnu/lib/libdialog/dir.h38
-rw-r--r--gnu/lib/libdialog/fselect.c402
-rw-r--r--gnu/lib/libdialog/gauge.c78
-rw-r--r--gnu/lib/libdialog/help.c194
-rw-r--r--gnu/lib/libdialog/inputbox.c190
-rw-r--r--gnu/lib/libdialog/kernel.c527
-rw-r--r--gnu/lib/libdialog/lineedit.c213
-rw-r--r--gnu/lib/libdialog/menubox.c467
-rw-r--r--gnu/lib/libdialog/msgbox.c348
-rw-r--r--gnu/lib/libdialog/notify.c55
-rw-r--r--gnu/lib/libdialog/prgbox.c152
-rw-r--r--gnu/lib/libdialog/radiolist.c630
-rw-r--r--gnu/lib/libdialog/raw_popen.c161
-rw-r--r--gnu/lib/libdialog/rc.c375
-rw-r--r--gnu/lib/libdialog/rc.h222
-rw-r--r--gnu/lib/libdialog/textbox.c701
-rw-r--r--gnu/lib/libdialog/tree.c1135
-rw-r--r--gnu/lib/libdialog/ui_objects.c829
-rw-r--r--gnu/lib/libdialog/ui_objects.h114
-rw-r--r--gnu/lib/libdialog/yesno.c171
-rw-r--r--gnu/lib/libg2c/MAIN.c4
-rw-r--r--gnu/lib/libg2c/Makefile122
-rw-r--r--gnu/lib/libg2c/config.h107
-rw-r--r--gnu/lib/libg2c/g2c.h236
-rw-r--r--gnu/lib/libgcc/Makefile241
-rw-r--r--gnu/lib/libgcc_r/Makefile7
-rw-r--r--gnu/lib/libiberty/Makefile22
-rw-r--r--gnu/lib/libiberty/config.h255
-rw-r--r--gnu/lib/libobjc/Makefile39
-rw-r--r--gnu/lib/libreadline/Makefile5
-rw-r--r--gnu/lib/libreadline/Makefile.inc13
-rw-r--r--gnu/lib/libreadline/config.h150
-rw-r--r--gnu/lib/libreadline/history/Makefile15
-rw-r--r--gnu/lib/libreadline/history/doc/Makefile14
-rw-r--r--gnu/lib/libreadline/readline/Makefile26
-rw-r--r--gnu/lib/libreadline/readline/doc/Makefile20
-rw-r--r--gnu/lib/libregex/AUTHORS10
-rw-r--r--gnu/lib/libregex/COPYING339
-rw-r--r--gnu/lib/libregex/ChangeLog3030
-rw-r--r--gnu/lib/libregex/INSTALL117
-rw-r--r--gnu/lib/libregex/Makefile16
-rw-r--r--gnu/lib/libregex/Makefile.gnu99
-rw-r--r--gnu/lib/libregex/Makefile.in98
-rw-r--r--gnu/lib/libregex/NEWS62
-rw-r--r--gnu/lib/libregex/README60
-rw-r--r--gnu/lib/libregex/VERSION3
-rw-r--r--gnu/lib/libregex/config.status59
-rw-r--r--gnu/lib/libregex/configure462
-rw-r--r--gnu/lib/libregex/configure.in23
-rw-r--r--gnu/lib/libregex/doc/Makefile14
-rw-r--r--gnu/lib/libregex/doc/include.awk19
-rw-r--r--gnu/lib/libregex/doc/xregex.texi3021
-rw-r--r--gnu/lib/libregex/regex.c5101
-rw-r--r--gnu/lib/libregex/regex.h517
-rw-r--r--gnu/lib/libregex/test/ChangeLog77
-rw-r--r--gnu/lib/libregex/test/Makefile171
-rw-r--r--gnu/lib/libregex/test/Makefile.in170
-rw-r--r--gnu/lib/libregex/test/alloca.c194
-rw-r--r--gnu/lib/libregex/test/bsd-interf.c38
-rw-r--r--gnu/lib/libregex/test/debugmalloc.c273
-rw-r--r--gnu/lib/libregex/test/emacsmalloc.c844
-rw-r--r--gnu/lib/libregex/test/fileregex.c77
-rw-r--r--gnu/lib/libregex/test/g++malloc.c1288
-rw-r--r--gnu/lib/libregex/test/getpagesize.h25
-rw-r--r--gnu/lib/libregex/test/iregex.c164
-rw-r--r--gnu/lib/libregex/test/main.c49
-rw-r--r--gnu/lib/libregex/test/malloc-test.c47
-rw-r--r--gnu/lib/libregex/test/other.c503
-rw-r--r--gnu/lib/libregex/test/printchar.c14
-rw-r--r--gnu/lib/libregex/test/psx-basic.c253
-rw-r--r--gnu/lib/libregex/test/psx-extend.c1244
-rw-r--r--gnu/lib/libregex/test/psx-generic.c336
-rw-r--r--gnu/lib/libregex/test/psx-group.c440
-rw-r--r--gnu/lib/libregex/test/psx-interf.c624
-rw-r--r--gnu/lib/libregex/test/psx-interv.c140
-rw-r--r--gnu/lib/libregex/test/regexcpp.sed8
-rw-r--r--gnu/lib/libregex/test/syntax.skel74
-rw-r--r--gnu/lib/libregex/test/test.c782
-rw-r--r--gnu/lib/libregex/test/test.h141
-rw-r--r--gnu/lib/libregex/test/tregress.c464
-rw-r--r--gnu/lib/libregex/test/upcase.c39
-rw-r--r--gnu/lib/libregex/test/xmalloc.c21
-rw-r--r--gnu/lib/libstdc++/Makefile178
-rw-r--r--gnu/lib/libstdc++/c++config.h1154
-rw-r--r--gnu/lib/libstdc++/config.h1076
-rw-r--r--gnu/lib/libstdc++/doc/Makefile13
-rw-r--r--gnu/lib/libsupc++/Makefile27
-rw-r--r--gnu/usr.bin/Makefile16
-rw-r--r--gnu/usr.bin/Makefile.inc3
-rw-r--r--gnu/usr.bin/as/CONTRIBUTORS11
-rw-r--r--gnu/usr.bin/as/COPYING339
-rw-r--r--gnu/usr.bin/as/ChangeLog429
-rw-r--r--gnu/usr.bin/as/Makefile69
-rw-r--r--gnu/usr.bin/as/Makefile.in411
-rw-r--r--gnu/usr.bin/as/NOTES16
-rw-r--r--gnu/usr.bin/as/NOTES.config52
-rw-r--r--gnu/usr.bin/as/README212
-rw-r--r--gnu/usr.bin/as/README-vms248
-rw-r--r--gnu/usr.bin/as/README.coff79
-rw-r--r--gnu/usr.bin/as/README.pic25
-rw-r--r--gnu/usr.bin/as/README.rich144
-rw-r--r--gnu/usr.bin/as/VERSION1
-rw-r--r--gnu/usr.bin/as/app.c746
-rw-r--r--gnu/usr.bin/as/as.1283
-rw-r--r--gnu/usr.bin/as/as.1aout283
-rw-r--r--gnu/usr.bin/as/as.c428
-rw-r--r--gnu/usr.bin/as/as.h426
-rw-r--r--gnu/usr.bin/as/atof-generic.c526
-rw-r--r--gnu/usr.bin/as/bignum-copy.c76
-rw-r--r--gnu/usr.bin/as/bignum.h64
-rw-r--r--gnu/usr.bin/as/bit_fix.h54
-rw-r--r--gnu/usr.bin/as/cond.c219
-rw-r--r--gnu/usr.bin/as/config-gas.com76
-rw-r--r--gnu/usr.bin/as/config/Makefile.hp3007
-rw-r--r--gnu/usr.bin/as/config/Makefile.i3865
-rw-r--r--gnu/usr.bin/as/config/Makefile.pc5327
-rw-r--r--gnu/usr.bin/as/config/Makefile.sparc5
-rw-r--r--gnu/usr.bin/as/config/Makefile.vax4
-rw-r--r--gnu/usr.bin/as/config/aout.h440
-rw-r--r--gnu/usr.bin/as/config/atof-ieee.c525
-rw-r--r--gnu/usr.bin/as/config/atof-ns32k.c437
-rw-r--r--gnu/usr.bin/as/config/atof-tahoe.c428
-rw-r--r--gnu/usr.bin/as/config/atof-vax.c497
-rw-r--r--gnu/usr.bin/as/config/coff.h783
-rw-r--r--gnu/usr.bin/as/config/cplus-dem.c927
-rw-r--r--gnu/usr.bin/as/config/ho-ansi.h29
-rw-r--r--gnu/usr.bin/as/config/ho-decstation.h29
-rw-r--r--gnu/usr.bin/as/config/ho-generic.h30
-rw-r--r--gnu/usr.bin/as/config/ho-hpux.h34
-rw-r--r--gnu/usr.bin/as/config/ho-i386.h30
-rw-r--r--gnu/usr.bin/as/config/ho-i386aix.h24
-rw-r--r--gnu/usr.bin/as/config/ho-rs6000.h22
-rw-r--r--gnu/usr.bin/as/config/ho-sun3.h3
-rw-r--r--gnu/usr.bin/as/config/ho-sun386.h5
-rw-r--r--gnu/usr.bin/as/config/ho-sun4.h3
-rw-r--r--gnu/usr.bin/as/config/ho-sunos.h81
-rw-r--r--gnu/usr.bin/as/config/ho-sysv.h27
-rw-r--r--gnu/usr.bin/as/config/ho-vax.h27
-rw-r--r--gnu/usr.bin/as/config/ho-vms.h30
-rw-r--r--gnu/usr.bin/as/config/mh-i3861
-rw-r--r--gnu/usr.bin/as/config/mh-i386aix5
-rw-r--r--gnu/usr.bin/as/config/mh-i386v41
-rw-r--r--gnu/usr.bin/as/config/mt-ebmon29k6
-rw-r--r--gnu/usr.bin/as/config/mt-h83005
-rw-r--r--gnu/usr.bin/as/config/mt-h8300hds4
-rw-r--r--gnu/usr.bin/as/config/mt-i386aix3
-rw-r--r--gnu/usr.bin/as/config/mt-mips1
-rw-r--r--gnu/usr.bin/as/config/mt-rs60001
-rw-r--r--gnu/usr.bin/as/config/obj-aout.c670
-rw-r--r--gnu/usr.bin/as/config/obj-aout.h305
-rw-r--r--gnu/usr.bin/as/config/obj-bfd-sunos.c71
-rw-r--r--gnu/usr.bin/as/config/obj-bfd-sunos.h69
-rw-r--r--gnu/usr.bin/as/config/obj-bout.c476
-rw-r--r--gnu/usr.bin/as/config/obj-bout.h313
-rw-r--r--gnu/usr.bin/as/config/obj-coff.c1978
-rw-r--r--gnu/usr.bin/as/config/obj-coff.h598
-rw-r--r--gnu/usr.bin/as/config/obj-coffbfd.c2182
-rw-r--r--gnu/usr.bin/as/config/obj-coffbfd.h516
-rw-r--r--gnu/usr.bin/as/config/obj-generic.c41
-rw-r--r--gnu/usr.bin/as/config/obj-generic.h78
-rw-r--r--gnu/usr.bin/as/config/obj-ieee.c539
-rw-r--r--gnu/usr.bin/as/config/obj-ieee.h46
-rw-r--r--gnu/usr.bin/as/config/obj-vms.c5484
-rw-r--r--gnu/usr.bin/as/config/obj-vms.h474
-rw-r--r--gnu/usr.bin/as/config/tc-a29k.c1113
-rw-r--r--gnu/usr.bin/as/config/tc-a29k.h40
-rw-r--r--gnu/usr.bin/as/config/tc-generic.c0
-rw-r--r--gnu/usr.bin/as/config/tc-generic.h37
-rw-r--r--gnu/usr.bin/as/config/tc-h8300.c1295
-rw-r--r--gnu/usr.bin/as/config/tc-h8300.h38
-rw-r--r--gnu/usr.bin/as/config/tc-i386.c2345
-rw-r--r--gnu/usr.bin/as/config/tc-i386.h251
-rw-r--r--gnu/usr.bin/as/config/tc-i860.c1295
-rw-r--r--gnu/usr.bin/as/config/tc-i860.h24
-rw-r--r--gnu/usr.bin/as/config/tc-i960.c2759
-rw-r--r--gnu/usr.bin/as/config/tc-i960.h281
-rw-r--r--gnu/usr.bin/as/config/tc-m68851.h304
-rw-r--r--gnu/usr.bin/as/config/tc-m68k.c4088
-rw-r--r--gnu/usr.bin/as/config/tc-m68k.h62
-rw-r--r--gnu/usr.bin/as/config/tc-m68kmote.h64
-rw-r--r--gnu/usr.bin/as/config/tc-m88k.c1435
-rw-r--r--gnu/usr.bin/as/config/tc-m88k.h35
-rw-r--r--gnu/usr.bin/as/config/tc-mips.c0
-rw-r--r--gnu/usr.bin/as/config/tc-mips.h0
-rw-r--r--gnu/usr.bin/as/config/tc-ns32k.c2015
-rw-r--r--gnu/usr.bin/as/config/tc-ns32k.h66
-rw-r--r--gnu/usr.bin/as/config/tc-rs6000.c0
-rw-r--r--gnu/usr.bin/as/config/tc-rs6000.h0
-rw-r--r--gnu/usr.bin/as/config/tc-sparc.c1803
-rw-r--r--gnu/usr.bin/as/config/tc-sparc.h52
-rw-r--r--gnu/usr.bin/as/config/tc-tahoe.c1924
-rw-r--r--gnu/usr.bin/as/config/tc-tahoe.h36
-rw-r--r--gnu/usr.bin/as/config/tc-vax.c3073
-rw-r--r--gnu/usr.bin/as/config/tc-vax.h26
-rw-r--r--gnu/usr.bin/as/config/te-dpx2.h8
-rw-r--r--gnu/usr.bin/as/config/te-generic.h25
-rw-r--r--gnu/usr.bin/as/config/te-hpux.h99
-rw-r--r--gnu/usr.bin/as/config/te-i386aix.h19
-rw-r--r--gnu/usr.bin/as/config/te-ic960.h46
-rw-r--r--gnu/usr.bin/as/config/te-sco386.h7
-rw-r--r--gnu/usr.bin/as/config/te-sequent.h32
-rw-r--r--gnu/usr.bin/as/config/te-sun3.h49
-rw-r--r--gnu/usr.bin/as/config/te-sysv32.h4
-rw-r--r--gnu/usr.bin/as/config/vax-inst.h77
-rw-r--r--gnu/usr.bin/as/configdos.bat14
-rwxr-xr-xgnu/usr.bin/as/configure.in204
-rw-r--r--gnu/usr.bin/as/debug.c104
-rw-r--r--gnu/usr.bin/as/expr.c1000
-rw-r--r--gnu/usr.bin/as/expr.h85
-rw-r--r--gnu/usr.bin/as/flo-const.c161
-rw-r--r--gnu/usr.bin/as/flo-copy.c70
-rw-r--r--gnu/usr.bin/as/flonum-mult.c203
-rw-r--r--gnu/usr.bin/as/flonum.h125
-rw-r--r--gnu/usr.bin/as/frags.c296
-rw-r--r--gnu/usr.bin/as/frags.h89
-rw-r--r--gnu/usr.bin/as/gas-format.el79
-rw-r--r--gnu/usr.bin/as/hash.c992
-rw-r--r--gnu/usr.bin/as/hash.h65
-rw-r--r--gnu/usr.bin/as/hex-value.c61
-rw-r--r--gnu/usr.bin/as/input-file.c327
-rw-r--r--gnu/usr.bin/as/input-file.h88
-rw-r--r--gnu/usr.bin/as/input-scrub.c420
-rw-r--r--gnu/usr.bin/as/link.cmd10
-rw-r--r--gnu/usr.bin/as/listing.c1079
-rw-r--r--gnu/usr.bin/as/listing.h115
-rw-r--r--gnu/usr.bin/as/make-gas.com86
-rw-r--r--gnu/usr.bin/as/makefile.dos593
-rw-r--r--gnu/usr.bin/as/messages.c595
-rw-r--r--gnu/usr.bin/as/obj.h77
-rw-r--r--gnu/usr.bin/as/obstack.c374
-rw-r--r--gnu/usr.bin/as/obstack.h448
-rw-r--r--gnu/usr.bin/as/opcode/ChangeLog56
-rw-r--r--gnu/usr.bin/as/opcode/a29k.h327
-rw-r--r--gnu/usr.bin/as/opcode/h8300.h266
-rw-r--r--gnu/usr.bin/as/opcode/i386.h883
-rw-r--r--gnu/usr.bin/as/opcode/i860.h495
-rw-r--r--gnu/usr.bin/as/opcode/i960.h434
-rw-r--r--gnu/usr.bin/as/opcode/m68k.h1998
-rw-r--r--gnu/usr.bin/as/opcode/m88k.h282
-rw-r--r--gnu/usr.bin/as/opcode/mips.h363
-rw-r--r--gnu/usr.bin/as/opcode/np1.h422
-rw-r--r--gnu/usr.bin/as/opcode/ns32k.h491
-rw-r--r--gnu/usr.bin/as/opcode/pn.h282
-rw-r--r--gnu/usr.bin/as/opcode/pyr.h287
-rw-r--r--gnu/usr.bin/as/opcode/sparc.h885
-rw-r--r--gnu/usr.bin/as/opcode/tahoe.h247
-rw-r--r--gnu/usr.bin/as/opcode/vax.h382
-rw-r--r--gnu/usr.bin/as/output-file.c122
-rw-r--r--gnu/usr.bin/as/output-file.h40
-rw-r--r--gnu/usr.bin/as/read.c2412
-rw-r--r--gnu/usr.bin/as/read.h160
-rw-r--r--gnu/usr.bin/as/struc-symbol.h134
-rw-r--r--gnu/usr.bin/as/subsegs.c313
-rw-r--r--gnu/usr.bin/as/subsegs.h93
-rw-r--r--gnu/usr.bin/as/symbols.c654
-rw-r--r--gnu/usr.bin/as/symbols.h82
-rw-r--r--gnu/usr.bin/as/tc.h112
-rwxr-xr-xgnu/usr.bin/as/testscripts/doboth20
-rwxr-xr-xgnu/usr.bin/as/testscripts/doobjcmp89
-rwxr-xr-xgnu/usr.bin/as/testscripts/dostriptest15
-rwxr-xr-xgnu/usr.bin/as/testscripts/dotest44
-rwxr-xr-xgnu/usr.bin/as/testscripts/dounsortreloc9
-rwxr-xr-xgnu/usr.bin/as/testscripts/dounsortsymbols9
-rw-r--r--gnu/usr.bin/as/version.c30
-rw-r--r--gnu/usr.bin/as/write.c1224
-rw-r--r--gnu/usr.bin/as/write.h120
-rw-r--r--gnu/usr.bin/as/xmalloc.c75
-rw-r--r--gnu/usr.bin/as/xrealloc.c74
-rw-r--r--gnu/usr.bin/bc/Makefile17
-rw-r--r--gnu/usr.bin/bc/config.h84
-rw-r--r--gnu/usr.bin/binutils/Makefile18
-rw-r--r--gnu/usr.bin/binutils/Makefile.inc6
-rw-r--r--gnu/usr.bin/binutils/Makefile.inc049
-rw-r--r--gnu/usr.bin/binutils/addr2line/Makefile17
-rw-r--r--gnu/usr.bin/binutils/ar/Makefile18
-rw-r--r--gnu/usr.bin/binutils/as/Makefile34
-rw-r--r--gnu/usr.bin/binutils/as/Makefile.inc4
-rw-r--r--gnu/usr.bin/binutils/as/Makefile.inc042
-rw-r--r--gnu/usr.bin/binutils/as/alpha-freebsd/Makefile11
-rw-r--r--gnu/usr.bin/binutils/as/alpha-freebsd/config.h279
-rw-r--r--gnu/usr.bin/binutils/as/alpha-freebsd/targ-cpu.h1
-rw-r--r--gnu/usr.bin/binutils/as/i386-freebsd/Makefile11
-rw-r--r--gnu/usr.bin/binutils/as/i386-freebsd/config.h279
-rw-r--r--gnu/usr.bin/binutils/as/i386-freebsd/targ-cpu.h1
-rw-r--r--gnu/usr.bin/binutils/as/ia64-freebsd/Makefile11
-rw-r--r--gnu/usr.bin/binutils/as/ia64-freebsd/config.h279
-rw-r--r--gnu/usr.bin/binutils/as/ia64-freebsd/targ-cpu.h3
-rw-r--r--gnu/usr.bin/binutils/as/obj-format.h3
-rw-r--r--gnu/usr.bin/binutils/as/powerpc-freebsd/Makefile15
-rw-r--r--gnu/usr.bin/binutils/as/powerpc-freebsd/config.h279
-rw-r--r--gnu/usr.bin/binutils/as/powerpc-freebsd/itbl-cpu.h6
-rw-r--r--gnu/usr.bin/binutils/as/powerpc-freebsd/targ-cpu.h3
-rw-r--r--gnu/usr.bin/binutils/as/sparc64-freebsd/Makefile14
-rw-r--r--gnu/usr.bin/binutils/as/sparc64-freebsd/config.h279
-rw-r--r--gnu/usr.bin/binutils/as/sparc64-freebsd/targ-cpu.h3
-rw-r--r--gnu/usr.bin/binutils/as/targ-env.h3
-rw-r--r--gnu/usr.bin/binutils/as/x86-64-freebsd/Makefile8
-rw-r--r--gnu/usr.bin/binutils/as/x86-64-freebsd/config.h282
-rw-r--r--gnu/usr.bin/binutils/as/x86-64-freebsd/itbl-cpu.h3
-rw-r--r--gnu/usr.bin/binutils/as/x86-64-freebsd/targ-cpu.h3
-rw-r--r--gnu/usr.bin/binutils/doc/Makefile47
-rw-r--r--gnu/usr.bin/binutils/doc/asconfig.texi70
-rw-r--r--gnu/usr.bin/binutils/doc/inc-hist.diff31
-rw-r--r--gnu/usr.bin/binutils/gasp/Makefile16
-rw-r--r--gnu/usr.bin/binutils/gasp/gasp.1115
-rw-r--r--gnu/usr.bin/binutils/gdb/Makefile112
-rw-r--r--gnu/usr.bin/binutils/gdb/Makefile.alpha16
-rw-r--r--gnu/usr.bin/binutils/gdb/Makefile.i38610
-rw-r--r--gnu/usr.bin/binutils/gdb/alpha/freebsd-nat-stubs.c55
-rw-r--r--gnu/usr.bin/binutils/gdb/alpha/freebsd-nat.c174
-rw-r--r--gnu/usr.bin/binutils/gdb/alpha/kvm-fbsd.c451
-rw-r--r--gnu/usr.bin/binutils/gdb/alpha/nm.h97
-rw-r--r--gnu/usr.bin/binutils/gdb/alpha/tm.h48
-rw-r--r--gnu/usr.bin/binutils/gdb/alpha/version.c4
-rw-r--r--gnu/usr.bin/binutils/gdb/alpha/xm.h30
-rw-r--r--gnu/usr.bin/binutils/gdb/config.h330
-rw-r--r--gnu/usr.bin/binutils/gdb/freebsd-uthread.c1102
-rw-r--r--gnu/usr.bin/binutils/gdb/gdb.1385
-rw-r--r--gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c710
-rw-r--r--gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c1045
-rw-r--r--gnu/usr.bin/binutils/gdb/i386/nm.h168
-rw-r--r--gnu/usr.bin/binutils/gdb/i386/tm.h70
-rw-r--r--gnu/usr.bin/binutils/gdb/i386/version.c4
-rw-r--r--gnu/usr.bin/binutils/gdb/i386/xm.h23
-rw-r--r--gnu/usr.bin/binutils/gdb/kvm-fbsd.c1045
-rw-r--r--gnu/usr.bin/binutils/gdb5/Makefile115
-rw-r--r--gnu/usr.bin/binutils/gdb5/Makefile.alpha8
-rw-r--r--gnu/usr.bin/binutils/gdb5/Makefile.i3867
-rw-r--r--gnu/usr.bin/binutils/gdb5/Makefile.ia648
-rw-r--r--gnu/usr.bin/binutils/gdb5/alpha/freebsd-nat.c175
-rw-r--r--gnu/usr.bin/binutils/gdb5/alpha/kvm-fbsd.c438
-rw-r--r--gnu/usr.bin/binutils/gdb5/alpha/nm.h96
-rw-r--r--gnu/usr.bin/binutils/gdb5/alpha/tm.h45
-rw-r--r--gnu/usr.bin/binutils/gdb5/alpha/version.c5
-rw-r--r--gnu/usr.bin/binutils/gdb5/alpha/xm.h32
-rw-r--r--gnu/usr.bin/binutils/gdb5/config.h328
-rw-r--r--gnu/usr.bin/binutils/gdb5/freebsd-uthread.c1139
-rw-r--r--gnu/usr.bin/binutils/gdb5/i386/freebsd-nat.c672
-rw-r--r--gnu/usr.bin/binutils/gdb5/i386/kvm-fbsd.c995
-rw-r--r--gnu/usr.bin/binutils/gdb5/i386/nm.h169
-rw-r--r--gnu/usr.bin/binutils/gdb5/i386/tm.h66
-rw-r--r--gnu/usr.bin/binutils/gdb5/i386/version.c5
-rw-r--r--gnu/usr.bin/binutils/gdb5/i386/xm.h25
-rw-r--r--gnu/usr.bin/binutils/gdbreplay/Makefile23
-rw-r--r--gnu/usr.bin/binutils/gdbreplay5/Makefile23
-rw-r--r--gnu/usr.bin/binutils/gdbserver/Makefile24
-rw-r--r--gnu/usr.bin/binutils/gdbserver/low-fbsd.c341
-rw-r--r--gnu/usr.bin/binutils/gdbserver5/Makefile24
-rw-r--r--gnu/usr.bin/binutils/gdbserver5/low-fbsd.c341
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile58
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.alpha31
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.i38642
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.ia6425
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.m68k52
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.powerpc29
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.sparc6437
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.x86-6420
-rw-r--r--gnu/usr.bin/binutils/ld/config.h174
-rwxr-xr-xgnu/usr.bin/binutils/ld/genscripts.sh162
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile64
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile.alpha14
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile.i38619
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile.ia6439
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile.powerpc26
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile.sparc6427
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile.x86-6415
-rw-r--r--gnu/usr.bin/binutils/libbfd/alpha/bfd.h3921
-rw-r--r--gnu/usr.bin/binutils/libbfd/config.h.fbsd267
-rw-r--r--gnu/usr.bin/binutils/libbfd/i386/bfd.h3921
-rw-r--r--gnu/usr.bin/binutils/libbfd/ia64/bfd.h3823
-rw-r--r--gnu/usr.bin/binutils/libbfd/powerpc/bfd.h3918
-rw-r--r--gnu/usr.bin/binutils/libbfd/sparc64/bfd.h3918
-rw-r--r--gnu/usr.bin/binutils/libbfd/x86-64/bfd.h3918
-rw-r--r--gnu/usr.bin/binutils/libbinutils/Makefile18
-rw-r--r--gnu/usr.bin/binutils/libbinutils/config.h207
-rw-r--r--gnu/usr.bin/binutils/libiberty/Makefile20
-rw-r--r--gnu/usr.bin/binutils/libiberty/config.h257
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile21
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.alpha4
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.amd644
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.i3864
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.ia644
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.m68k6
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.powerpc4
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.sparc6
-rw-r--r--gnu/usr.bin/binutils/libopcodes/Makefile.sparc644
-rw-r--r--gnu/usr.bin/binutils/libopcodes/config.h135
-rw-r--r--gnu/usr.bin/binutils/nm/Makefile17
-rw-r--r--gnu/usr.bin/binutils/objcopy/Makefile17
-rw-r--r--gnu/usr.bin/binutils/objdump/Makefile19
-rw-r--r--gnu/usr.bin/binutils/ranlib/Makefile18
-rw-r--r--gnu/usr.bin/binutils/readelf/Makefile20
-rw-r--r--gnu/usr.bin/binutils/size/Makefile17
-rw-r--r--gnu/usr.bin/binutils/strings/Makefile17
-rw-r--r--gnu/usr.bin/binutils/strip/Makefile32
-rwxr-xr-xgnu/usr.bin/binutils/update.sh47
-rw-r--r--gnu/usr.bin/cc/Makefile31
-rw-r--r--gnu/usr.bin/cc/Makefile.fe5
-rw-r--r--gnu/usr.bin/cc/Makefile.inc49
-rw-r--r--gnu/usr.bin/cc/Makefile.tgt18
-rw-r--r--gnu/usr.bin/cc/c++/Makefile20
-rw-r--r--gnu/usr.bin/cc/c++filt/Makefile24
-rw-r--r--gnu/usr.bin/cc/cc/Makefile22
-rw-r--r--gnu/usr.bin/cc/cc1/Makefile34
-rw-r--r--gnu/usr.bin/cc/cc1obj/Makefile36
-rw-r--r--gnu/usr.bin/cc/cc1plus/Makefile37
-rw-r--r--gnu/usr.bin/cc/cc_drv/Makefile20
-rw-r--r--gnu/usr.bin/cc/cc_int/Makefile85
-rw-r--r--gnu/usr.bin/cc/cc_tools/Makefile240
-rw-r--r--gnu/usr.bin/cc/cc_tools/auto-host.h596
-rw-r--r--gnu/usr.bin/cc/cc_tools/freebsd-native.h72
-rw-r--r--gnu/usr.bin/cc/cccp/Makefile36
-rw-r--r--gnu/usr.bin/cc/collect2/Makefile14
-rw-r--r--gnu/usr.bin/cc/cpp/Makefile22
-rw-r--r--gnu/usr.bin/cc/cpp0/Makefile36
-rw-r--r--gnu/usr.bin/cc/doc/Makefile32
-rw-r--r--gnu/usr.bin/cc/f77/Makefile23
-rw-r--r--gnu/usr.bin/cc/f771/Makefile46
-rw-r--r--gnu/usr.bin/cc/f77doc/Makefile14
-rw-r--r--gnu/usr.bin/cc/gcov/Makefile14
-rw-r--r--gnu/usr.bin/cc/include/Makefile15
-rw-r--r--gnu/usr.bin/cc/protoize/Makefile21
-rw-r--r--gnu/usr.bin/cc/tradcpp0/Makefile23
-rw-r--r--gnu/usr.bin/cpio/Makefile23
-rw-r--r--gnu/usr.bin/cpio/doc/Makefile15
-rw-r--r--gnu/usr.bin/cvs/Makefile7
-rw-r--r--gnu/usr.bin/cvs/Makefile.inc25
-rw-r--r--gnu/usr.bin/cvs/contrib/Makefile33
-rw-r--r--gnu/usr.bin/cvs/contrib/easy-import.pl403
-rw-r--r--gnu/usr.bin/cvs/cvs/Makefile72
-rw-r--r--gnu/usr.bin/cvs/cvs/options.h201
-rw-r--r--gnu/usr.bin/cvs/cvs/prepend_args.c86
-rw-r--r--gnu/usr.bin/cvs/cvs/prepend_args.h26
-rw-r--r--gnu/usr.bin/cvs/cvsbug/Makefile24
-rw-r--r--gnu/usr.bin/cvs/doc/Makefile25
-rw-r--r--gnu/usr.bin/cvs/lib/Makefile23
-rw-r--r--gnu/usr.bin/cvs/lib/config.h335
-rw-r--r--gnu/usr.bin/cvs/lib/config.h.proto335
-rw-r--r--gnu/usr.bin/cvs/libdiff/Makefile17
-rw-r--r--gnu/usr.bin/dc/Makefile15
-rw-r--r--gnu/usr.bin/dc/doc/Makefile11
-rw-r--r--gnu/usr.bin/dialog/COPYING339
-rw-r--r--gnu/usr.bin/dialog/Makefile13
-rw-r--r--gnu/usr.bin/dialog/README161
-rw-r--r--gnu/usr.bin/dialog/README.lib3
-rw-r--r--gnu/usr.bin/dialog/TESTS/Makefile8
-rw-r--r--gnu/usr.bin/dialog/TESTS/README15
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/checklist33
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/ftreebox27
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/infobox15
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/inputbox28
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/menubox35
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/msgbox14
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/prgbox12
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/radiolist33
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/textbox42
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/treebox25
-rwxr-xr-xgnu/usr.bin/dialog/TESTS/yesno23
-rw-r--r--gnu/usr.bin/dialog/dialog.1313
-rw-r--r--gnu/usr.bin/dialog/dialog.c426
-rw-r--r--gnu/usr.bin/diff/Makefile21
-rw-r--r--gnu/usr.bin/diff/diff.1496
-rw-r--r--gnu/usr.bin/diff/doc/Makefile9
-rw-r--r--gnu/usr.bin/diff3/Makefile15
-rw-r--r--gnu/usr.bin/diff3/diff3.1210
-rw-r--r--gnu/usr.bin/gdb/doc/inc-hist.diff31
-rw-r--r--gnu/usr.bin/gperf/Makefile17
-rw-r--r--gnu/usr.bin/gperf/config.h21
-rw-r--r--gnu/usr.bin/gperf/doc/Makefile9
-rw-r--r--gnu/usr.bin/grep/AUTHORS41
-rw-r--r--gnu/usr.bin/grep/COPYING340
-rw-r--r--gnu/usr.bin/grep/ChangeLog1426
-rw-r--r--gnu/usr.bin/grep/Makefile51
-rw-r--r--gnu/usr.bin/grep/NEWS163
-rw-r--r--gnu/usr.bin/grep/README26
-rw-r--r--gnu/usr.bin/grep/THANKS49
-rw-r--r--gnu/usr.bin/grep/config.h209
-rw-r--r--gnu/usr.bin/grep/config.hin207
-rw-r--r--gnu/usr.bin/grep/dfa.c2586
-rw-r--r--gnu/usr.bin/grep/dfa.h374
-rw-r--r--gnu/usr.bin/grep/doc/Makefile6
-rw-r--r--gnu/usr.bin/grep/doc/grep.texi985
-rw-r--r--gnu/usr.bin/grep/doc/version.texi3
-rw-r--r--gnu/usr.bin/grep/getopt.c1049
-rw-r--r--gnu/usr.bin/grep/getopt.h169
-rw-r--r--gnu/usr.bin/grep/getopt1.c188
-rw-r--r--gnu/usr.bin/grep/getpagesize.h35
-rw-r--r--gnu/usr.bin/grep/grep.1625
-rw-r--r--gnu/usr.bin/grep/grep.c1501
-rw-r--r--gnu/usr.bin/grep/grep.h48
-rw-r--r--gnu/usr.bin/grep/kwset.c775
-rw-r--r--gnu/usr.bin/grep/kwset.h59
-rw-r--r--gnu/usr.bin/grep/obstack.c598
-rw-r--r--gnu/usr.bin/grep/obstack.h593
-rw-r--r--gnu/usr.bin/grep/savedir.c137
-rw-r--r--gnu/usr.bin/grep/savedir.h15
-rw-r--r--gnu/usr.bin/grep/search.c427
-rw-r--r--gnu/usr.bin/grep/stpcpy.c50
-rw-r--r--gnu/usr.bin/grep/system.h207
-rw-r--r--gnu/usr.bin/grep/tests/bre.awk26
-rwxr-xr-xgnu/usr.bin/grep/tests/bre.sh13
-rw-r--r--gnu/usr.bin/grep/tests/bre.tests62
-rwxr-xr-xgnu/usr.bin/grep/tests/empty.sh30
-rw-r--r--gnu/usr.bin/grep/tests/ere.awk31
-rwxr-xr-xgnu/usr.bin/grep/tests/ere.sh13
-rw-r--r--gnu/usr.bin/grep/tests/ere.tests215
-rw-r--r--gnu/usr.bin/grep/tests/khadafy.lines32
-rw-r--r--gnu/usr.bin/grep/tests/khadafy.regexp1
-rwxr-xr-xgnu/usr.bin/grep/tests/khadafy.sh20
-rwxr-xr-xgnu/usr.bin/grep/tests/options.sh36
-rw-r--r--gnu/usr.bin/grep/tests/spencer1.awk14
-rwxr-xr-xgnu/usr.bin/grep/tests/spencer1.sh13
-rw-r--r--gnu/usr.bin/grep/tests/spencer1.tests122
-rwxr-xr-xgnu/usr.bin/grep/tests/status.sh38
-rwxr-xr-xgnu/usr.bin/grep/tests/warning.sh19
-rw-r--r--gnu/usr.bin/groff/Makefile5
-rw-r--r--gnu/usr.bin/groff/Makefile.inc165
-rw-r--r--gnu/usr.bin/groff/contrib/Makefile5
-rw-r--r--gnu/usr.bin/groff/contrib/Makefile.inc6
-rw-r--r--gnu/usr.bin/groff/contrib/mm/Makefile30
-rw-r--r--gnu/usr.bin/groff/doc/Makefile6
-rw-r--r--gnu/usr.bin/groff/font/Makefile7
-rw-r--r--gnu/usr.bin/groff/font/Makefile.dev11
-rw-r--r--gnu/usr.bin/groff/font/Makefile.inc6
-rw-r--r--gnu/usr.bin/groff/font/Makefile.tty30
-rw-r--r--gnu/usr.bin/groff/font/devX100-12/Makefile7
-rw-r--r--gnu/usr.bin/groff/font/devX100/Makefile7
-rw-r--r--gnu/usr.bin/groff/font/devX75-12/Makefile7
-rw-r--r--gnu/usr.bin/groff/font/devX75/Makefile7
-rw-r--r--gnu/usr.bin/groff/font/devascii/Makefile6
-rw-r--r--gnu/usr.bin/groff/font/devcp1047/Makefile6
-rw-r--r--gnu/usr.bin/groff/font/devdvi/Makefile16
-rw-r--r--gnu/usr.bin/groff/font/devhtml/Makefile7
-rw-r--r--gnu/usr.bin/groff/font/devkoi8-r/DESC.proto8
-rw-r--r--gnu/usr.bin/groff/font/devkoi8-r/Makefile6
-rw-r--r--gnu/usr.bin/groff/font/devkoi8-r/R.proto314
-rw-r--r--gnu/usr.bin/groff/font/devlatin1/Makefile6
-rw-r--r--gnu/usr.bin/groff/font/devlbp/Makefile18
-rw-r--r--gnu/usr.bin/groff/font/devlj4/Makefile25
-rw-r--r--gnu/usr.bin/groff/font/devps/Makefile35
-rw-r--r--gnu/usr.bin/groff/font/devutf8/Makefile6
-rw-r--r--gnu/usr.bin/groff/man/Makefile7
-rw-r--r--gnu/usr.bin/groff/src/Makefile5
-rw-r--r--gnu/usr.bin/groff/src/devices/Makefile5
-rw-r--r--gnu/usr.bin/groff/src/devices/Makefile.inc6
-rw-r--r--gnu/usr.bin/groff/src/devices/grodvi/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/devices/grohtml/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/devices/grolbp/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/devices/grolj4/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/devices/grops/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/devices/grotty/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/include/defs.h12
-rw-r--r--gnu/usr.bin/groff/src/libs/Makefile5
-rw-r--r--gnu/usr.bin/groff/src/libs/Makefile.inc6
-rw-r--r--gnu/usr.bin/groff/src/libs/libbib/Makefile7
-rw-r--r--gnu/usr.bin/groff/src/libs/libdriver/Makefile7
-rw-r--r--gnu/usr.bin/groff/src/libs/libgroff/Makefile21
-rw-r--r--gnu/usr.bin/groff/src/preproc/Makefile8
-rw-r--r--gnu/usr.bin/groff/src/preproc/Makefile.inc6
-rw-r--r--gnu/usr.bin/groff/src/preproc/eqn/Makefile16
-rw-r--r--gnu/usr.bin/groff/src/preproc/grn/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/preproc/html/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/preproc/pic/Makefile13
-rw-r--r--gnu/usr.bin/groff/src/preproc/refer/Makefile10
-rw-r--r--gnu/usr.bin/groff/src/preproc/soelim/Makefile8
-rw-r--r--gnu/usr.bin/groff/src/preproc/tbl/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/roff/Makefile5
-rw-r--r--gnu/usr.bin/groff/src/roff/Makefile.inc6
-rw-r--r--gnu/usr.bin/groff/src/roff/groff/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/roff/grog/Makefile7
-rw-r--r--gnu/usr.bin/groff/src/roff/nroff/Makefile7
-rw-r--r--gnu/usr.bin/groff/src/roff/psroff/Makefile6
-rw-r--r--gnu/usr.bin/groff/src/roff/psroff/psroff.146
-rw-r--r--gnu/usr.bin/groff/src/roff/psroff/psroff.sh5
-rw-r--r--gnu/usr.bin/groff/src/roff/troff/Makefile19
-rw-r--r--gnu/usr.bin/groff/src/utils/Makefile5
-rw-r--r--gnu/usr.bin/groff/src/utils/Makefile.inc6
-rw-r--r--gnu/usr.bin/groff/src/utils/addftinfo/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/utils/afmtodit/Makefile7
-rw-r--r--gnu/usr.bin/groff/src/utils/hpftodit/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/utils/indxbib/Makefile13
-rw-r--r--gnu/usr.bin/groff/src/utils/lkbib/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/utils/lookbib/Makefile9
-rw-r--r--gnu/usr.bin/groff/src/utils/pfbtops/Makefile8
-rw-r--r--gnu/usr.bin/groff/src/utils/tfmtodit/Makefile9
-rw-r--r--gnu/usr.bin/groff/tmac/Makefile75
-rw-r--r--gnu/usr.bin/groff/tmac/hyphen.us-ru4833
-rw-r--r--gnu/usr.bin/groff/tmac/koi8-r126
-rw-r--r--gnu/usr.bin/groff/tmac/mdoc.local65
-rw-r--r--gnu/usr.bin/groff/tmac/ru.KOI8-R126
-rw-r--r--gnu/usr.bin/gzip/COPYING339
-rw-r--r--gnu/usr.bin/gzip/ChangeLog587
-rw-r--r--gnu/usr.bin/gzip/Makefile39
-rw-r--r--gnu/usr.bin/gzip/NEWS221
-rw-r--r--gnu/usr.bin/gzip/README144
-rw-r--r--gnu/usr.bin/gzip/THANKS276
-rw-r--r--gnu/usr.bin/gzip/TODO58
-rw-r--r--gnu/usr.bin/gzip/algorithm.doc164
-rw-r--r--gnu/usr.bin/gzip/bits.c205
-rw-r--r--gnu/usr.bin/gzip/crypt.c6
-rw-r--r--gnu/usr.bin/gzip/crypt.h12
-rw-r--r--gnu/usr.bin/gzip/deflate.c763
-rw-r--r--gnu/usr.bin/gzip/getopt.c755
-rw-r--r--gnu/usr.bin/gzip/getopt.h127
-rw-r--r--gnu/usr.bin/gzip/gzexe158
-rw-r--r--gnu/usr.bin/gzip/gzexe.143
-rw-r--r--gnu/usr.bin/gzip/gzip.1479
-rw-r--r--gnu/usr.bin/gzip/gzip.c1755
-rw-r--r--gnu/usr.bin/gzip/gzip.h315
-rw-r--r--gnu/usr.bin/gzip/inflate.c956
-rw-r--r--gnu/usr.bin/gzip/lzw.c26
-rw-r--r--gnu/usr.bin/gzip/lzw.h42
-rw-r--r--gnu/usr.bin/gzip/match.S379
-rw-r--r--gnu/usr.bin/gzip/revision.h16
-rw-r--r--gnu/usr.bin/gzip/tailor.h328
-rw-r--r--gnu/usr.bin/gzip/trees.c1075
-rw-r--r--gnu/usr.bin/gzip/unlzh.c401
-rw-r--r--gnu/usr.bin/gzip/unlzw.c377
-rw-r--r--gnu/usr.bin/gzip/unpack.c239
-rw-r--r--gnu/usr.bin/gzip/unzip.c199
-rw-r--r--gnu/usr.bin/gzip/util.c456
-rw-r--r--gnu/usr.bin/gzip/zdiff71
-rw-r--r--gnu/usr.bin/gzip/zdiff.144
-rw-r--r--gnu/usr.bin/gzip/zforce38
-rw-r--r--gnu/usr.bin/gzip/zforce.118
-rw-r--r--gnu/usr.bin/gzip/zgrep72
-rw-r--r--gnu/usr.bin/gzip/zgrep.144
-rw-r--r--gnu/usr.bin/gzip/zgrep.getopt94
-rw-r--r--gnu/usr.bin/gzip/zgrep.libz18
-rw-r--r--gnu/usr.bin/gzip/zip.c117
-rw-r--r--gnu/usr.bin/gzip/zmore52
-rw-r--r--gnu/usr.bin/gzip/zmore.1147
-rw-r--r--gnu/usr.bin/gzip/znew150
-rw-r--r--gnu/usr.bin/gzip/znew.139
-rw-r--r--gnu/usr.bin/ld/Makefile17
-rw-r--r--gnu/usr.bin/ld/PORTING194
-rw-r--r--gnu/usr.bin/ld/cplus-dem.c3003
-rw-r--r--gnu/usr.bin/ld/demangle.h110
-rw-r--r--gnu/usr.bin/ld/ld.1295
-rw-r--r--gnu/usr.bin/ld/ld.1aout295
-rw-r--r--gnu/usr.bin/ld/ld.c3825
-rw-r--r--gnu/usr.bin/ld/ld.h387
-rw-r--r--gnu/usr.bin/ld/lib.c876
-rw-r--r--gnu/usr.bin/ld/rrs.c1272
-rw-r--r--gnu/usr.bin/ld/sparc/md-static-funcs.c37
-rw-r--r--gnu/usr.bin/ld/sparc/md.c351
-rw-r--r--gnu/usr.bin/ld/sparc/md.h302
-rw-r--r--gnu/usr.bin/ld/sparc/mdprologue.S101
-rw-r--r--gnu/usr.bin/ld/symbol.c194
-rw-r--r--gnu/usr.bin/ld/symseg.h359
-rw-r--r--gnu/usr.bin/ld/warnings.c810
-rw-r--r--gnu/usr.bin/ld/xbits.c168
-rw-r--r--gnu/usr.bin/man/COPYING339
-rw-r--r--gnu/usr.bin/man/Makefile12
-rw-r--r--gnu/usr.bin/man/Makefile.inc36
-rw-r--r--gnu/usr.bin/man/README134
-rw-r--r--gnu/usr.bin/man/TODO123
-rw-r--r--gnu/usr.bin/man/apropos/Makefile22
-rw-r--r--gnu/usr.bin/man/apropos/apropos.man47
-rw-r--r--gnu/usr.bin/man/apropos/apropos.sh111
-rw-r--r--gnu/usr.bin/man/catman/Makefile8
-rw-r--r--gnu/usr.bin/man/catman/catman.1132
-rw-r--r--gnu/usr.bin/man/catman/catman.perl439
-rw-r--r--gnu/usr.bin/man/lib/Makefile27
-rw-r--r--gnu/usr.bin/man/lib/config.h_dist210
-rw-r--r--gnu/usr.bin/man/lib/gripes.c180
-rw-r--r--gnu/usr.bin/man/lib/gripes.h30
-rw-r--r--gnu/usr.bin/man/lib/util.c160
-rw-r--r--gnu/usr.bin/man/makewhatis/Makefile12
-rw-r--r--gnu/usr.bin/man/makewhatis/makewhatis.1148
-rw-r--r--gnu/usr.bin/man/makewhatis/makewhatis.local.880
-rw-r--r--gnu/usr.bin/man/makewhatis/makewhatis.local.sh58
-rw-r--r--gnu/usr.bin/man/makewhatis/makewhatis.perl574
-rw-r--r--gnu/usr.bin/man/man/Makefile33
-rw-r--r--gnu/usr.bin/man/man/glob.c712
-rw-r--r--gnu/usr.bin/man/man/man.c1708
-rw-r--r--gnu/usr.bin/man/man/man.man251
-rw-r--r--gnu/usr.bin/man/man/ndir.h51
-rw-r--r--gnu/usr.bin/man/man/version.h17
-rw-r--r--gnu/usr.bin/man/manpath/Makefile17
-rw-r--r--gnu/usr.bin/man/manpath/manpath.c599
-rw-r--r--gnu/usr.bin/man/manpath/manpath.config29
-rw-r--r--gnu/usr.bin/man/manpath/manpath.h32
-rw-r--r--gnu/usr.bin/man/manpath/manpath.man97
-rw-r--r--gnu/usr.bin/patch/EXTERN.h21
-rw-r--r--gnu/usr.bin/patch/INTERN.h19
-rw-r--r--gnu/usr.bin/patch/Makefile8
-rw-r--r--gnu/usr.bin/patch/backupfile.c390
-rw-r--r--gnu/usr.bin/patch/backupfile.h44
-rw-r--r--gnu/usr.bin/patch/common.h190
-rw-r--r--gnu/usr.bin/patch/config.h81
-rw-r--r--gnu/usr.bin/patch/getopt.c724
-rw-r--r--gnu/usr.bin/patch/getopt.h133
-rw-r--r--gnu/usr.bin/patch/getopt1.c176
-rw-r--r--gnu/usr.bin/patch/inp.c397
-rw-r--r--gnu/usr.bin/patch/inp.h18
-rw-r--r--gnu/usr.bin/patch/patch.1594
-rw-r--r--gnu/usr.bin/patch/patch.c965
-rw-r--r--gnu/usr.bin/patch/patchlevel.h1
-rw-r--r--gnu/usr.bin/patch/pch.c1404
-rw-r--r--gnu/usr.bin/patch/pch.h36
-rw-r--r--gnu/usr.bin/patch/util.c458
-rw-r--r--gnu/usr.bin/patch/util.h88
-rw-r--r--gnu/usr.bin/patch/version.c25
-rw-r--r--gnu/usr.bin/patch/version.h9
-rw-r--r--gnu/usr.bin/rcs/CREDITS24
-rw-r--r--gnu/usr.bin/rcs/Makefile3
-rw-r--r--gnu/usr.bin/rcs/Makefile.inc7
-rw-r--r--gnu/usr.bin/rcs/NEWS548
-rw-r--r--gnu/usr.bin/rcs/REFS90
-rw-r--r--gnu/usr.bin/rcs/ci/Makefile8
-rw-r--r--gnu/usr.bin/rcs/ci/ci.1898
-rw-r--r--gnu/usr.bin/rcs/ci/ci.c1318
-rw-r--r--gnu/usr.bin/rcs/co/Makefile8
-rw-r--r--gnu/usr.bin/rcs/co/co.1736
-rw-r--r--gnu/usr.bin/rcs/co/co.c826
-rw-r--r--gnu/usr.bin/rcs/doc/rcs.ms1518
-rw-r--r--gnu/usr.bin/rcs/doc/rcs_func.ms95
-rw-r--r--gnu/usr.bin/rcs/ident/Makefile8
-rw-r--r--gnu/usr.bin/rcs/ident/ident.1182
-rw-r--r--gnu/usr.bin/rcs/ident/ident.c270
-rw-r--r--gnu/usr.bin/rcs/lib/Makefile14
-rw-r--r--gnu/usr.bin/rcs/lib/conf.h400
-rw-r--r--gnu/usr.bin/rcs/lib/maketime.c344
-rw-r--r--gnu/usr.bin/rcs/lib/maketime.h39
-rw-r--r--gnu/usr.bin/rcs/lib/merger.c148
-rw-r--r--gnu/usr.bin/rcs/lib/partime.c701
-rw-r--r--gnu/usr.bin/rcs/lib/partime.h71
-rw-r--r--gnu/usr.bin/rcs/lib/rcsbase.h762
-rw-r--r--gnu/usr.bin/rcs/lib/rcsedit.c1958
-rw-r--r--gnu/usr.bin/rcs/lib/rcsfcmp.c354
-rw-r--r--gnu/usr.bin/rcs/lib/rcsfnms.c1132
-rw-r--r--gnu/usr.bin/rcs/lib/rcsgen.c681
-rw-r--r--gnu/usr.bin/rcs/lib/rcskeep.c452
-rw-r--r--gnu/usr.bin/rcs/lib/rcskeys.c186
-rw-r--r--gnu/usr.bin/rcs/lib/rcslex.c1568
-rw-r--r--gnu/usr.bin/rcs/lib/rcsmap.c69
-rw-r--r--gnu/usr.bin/rcs/lib/rcsrev.c911
-rw-r--r--gnu/usr.bin/rcs/lib/rcssyn.c681
-rw-r--r--gnu/usr.bin/rcs/lib/rcstime.c191
-rw-r--r--gnu/usr.bin/rcs/lib/rcsutil.c1398
-rw-r--r--gnu/usr.bin/rcs/lib/version.c2
-rw-r--r--gnu/usr.bin/rcs/merge/Makefile8
-rw-r--r--gnu/usr.bin/rcs/merge/merge.1137
-rw-r--r--gnu/usr.bin/rcs/merge/merge.c113
-rw-r--r--gnu/usr.bin/rcs/rcs/Makefile10
-rw-r--r--gnu/usr.bin/rcs/rcs/rcs.1454
-rw-r--r--gnu/usr.bin/rcs/rcs/rcs.c1629
-rw-r--r--gnu/usr.bin/rcs/rcs/rcsfile.5425
-rw-r--r--gnu/usr.bin/rcs/rcs/rcsintro.1302
-rw-r--r--gnu/usr.bin/rcs/rcsclean/Makefile8
-rw-r--r--gnu/usr.bin/rcs/rcsclean/rcsclean.1203
-rw-r--r--gnu/usr.bin/rcs/rcsclean/rcsclean.c333
-rw-r--r--gnu/usr.bin/rcs/rcsdiff/Makefile8
-rw-r--r--gnu/usr.bin/rcs/rcsdiff/rcsdiff.1158
-rw-r--r--gnu/usr.bin/rcs/rcsdiff/rcsdiff.c480
-rw-r--r--gnu/usr.bin/rcs/rcsfreeze/Makefile10
-rw-r--r--gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.168
-rw-r--r--gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh99
-rw-r--r--gnu/usr.bin/rcs/rcsmerge/Makefile8
-rw-r--r--gnu/usr.bin/rcs/rcsmerge/rcsmerge.1189
-rw-r--r--gnu/usr.bin/rcs/rcsmerge/rcsmerge.c286
-rwxr-xr-xgnu/usr.bin/rcs/rcstest454
-rw-r--r--gnu/usr.bin/rcs/rlog/Makefile8
-rw-r--r--gnu/usr.bin/rcs/rlog/rlog.1318
-rw-r--r--gnu/usr.bin/rcs/rlog/rlog.c1290
-rw-r--r--gnu/usr.bin/sdiff/Makefile16
-rw-r--r--gnu/usr.bin/sdiff/sdiff.1198
-rw-r--r--gnu/usr.bin/send-pr/COPYING339
-rw-r--r--gnu/usr.bin/send-pr/Makefile35
-rw-r--r--gnu/usr.bin/send-pr/README43
-rw-r--r--gnu/usr.bin/send-pr/categories16
-rw-r--r--gnu/usr.bin/send-pr/doc/Makefile4
-rw-r--r--gnu/usr.bin/send-pr/doc/categ.texi125
-rw-r--r--gnu/usr.bin/send-pr/doc/fields.texi522
-rw-r--r--gnu/usr.bin/send-pr/doc/s-usage.texi570
-rw-r--r--gnu/usr.bin/send-pr/doc/send-pr.texi658
-rw-r--r--gnu/usr.bin/send-pr/doc/states.texi58
-rw-r--r--gnu/usr.bin/send-pr/doc/version.texi3
-rwxr-xr-xgnu/usr.bin/send-pr/install-sid.sh82
-rw-r--r--gnu/usr.bin/send-pr/send-pr-el.in813
-rw-r--r--gnu/usr.bin/send-pr/send-pr.1313
-rw-r--r--gnu/usr.bin/send-pr/send-pr.sh571
-rw-r--r--gnu/usr.bin/sort/Makefile30
-rw-r--r--gnu/usr.bin/sort/config.h1316
-rw-r--r--gnu/usr.bin/sort/libintl.h6
-rw-r--r--gnu/usr.bin/sort/unlocked-io.h2
-rw-r--r--gnu/usr.bin/tar/Makefile23
-rw-r--r--gnu/usr.bin/tar/config.h582
-rw-r--r--gnu/usr.bin/tar/doc/Makefile6
-rw-r--r--gnu/usr.bin/tar/localedir.h1
-rw-r--r--gnu/usr.bin/tar/tar.1573
-rw-r--r--gnu/usr.bin/texinfo/Makefile7
-rw-r--r--gnu/usr.bin/texinfo/Makefile.inc14
-rw-r--r--gnu/usr.bin/texinfo/doc/Makefile11
-rw-r--r--gnu/usr.bin/texinfo/info/Makefile18
-rw-r--r--gnu/usr.bin/texinfo/infokey/Makefile12
-rw-r--r--gnu/usr.bin/texinfo/install-info/Makefile10
-rw-r--r--gnu/usr.bin/texinfo/libtxi/Makefile10
-rw-r--r--gnu/usr.bin/texinfo/makeinfo/Makefile13
-rw-r--r--gnu/usr.bin/texinfo/texindex/Makefile10
842 files changed, 241698 insertions, 0 deletions
diff --git a/gnu/COPYING b/gnu/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/gnu/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/COPYING.LIB b/gnu/COPYING.LIB
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/gnu/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/gnu/Makefile b/gnu/Makefile
new file mode 100644
index 0000000..6656adf
--- /dev/null
+++ b/gnu/Makefile
@@ -0,0 +1,6 @@
+# @(#)Makefile 5.33.1.1 (Berkeley) 5/6/91
+# $FreeBSD$
+
+SUBDIR= lib usr.bin
+
+.include <bsd.subdir.mk>
diff --git a/gnu/include/values.h b/gnu/include/values.h
new file mode 100644
index 0000000..9ba3e23
--- /dev/null
+++ b/gnu/include/values.h
@@ -0,0 +1,177 @@
+#if __GNUC__
+#warning "this file includes <values.h> which is obsoleted, use <limits.h> or <float.h> instead"
+#endif
+
+/*
+Copyright (C) 1988 Free Software Foundation
+ written by Doug Lea (dl@rocky.oswego.edu)
+
+This file is part of the GNU C++ Library. This library is free
+software; you can redistribute it and/or modify it under the terms of
+the GNU Library General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version. This library is distributed in the hope
+that it will be useful, but WITHOUT ANY WARRANTY; without even the
+implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU Library General Public License for more details.
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#ifndef _VALUES_H_
+#define _VALUES_H_
+
+#define BITSPERBYTE 8
+#define BITS(type) (BITSPERBYTE * (int)sizeof(type))
+
+#define CHARBITS BITS(char)
+#define SHORTBITS BITS(short)
+#define INTBITS BITS(int)
+#define LONGBITS BITS(long)
+#define PTRBITS BITS(char*)
+#define DOUBLEBITS BITS(double)
+#define FLOATBITS BITS(float)
+
+#define MINSHORT ((short)(1 << (SHORTBITS - 1)))
+#define MININT (1 << (INTBITS - 1))
+#define MINLONG (1L << (LONGBITS - 1))
+
+#define MAXSHORT ((short)~MINSHORT)
+#define MAXINT (~MININT)
+#define MAXLONG (~MINLONG)
+
+#define HIBITS MINSHORT
+#define HIBITL MINLONG
+
+#if defined(sun) || defined(hp300) || defined(hpux) || defined(masscomp) || defined(sgi)
+#ifdef masscomp
+#define MAXDOUBLE \
+({ \
+ double maxdouble_val; \
+ \
+ __asm ("fmove%.d #0x7fefffffffffffff,%0" /* Max double */ \
+ : "=f" (maxdouble_val) \
+ : /* no inputs */); \
+ maxdouble_val; \
+})
+#define MAXFLOAT ((float) 3.40e+38)
+#else
+#define MAXDOUBLE 1.79769313486231470e+308
+#define MAXFLOAT ((float)3.40282346638528860e+38)
+#endif
+#define MINDOUBLE 4.94065645841246544e-324
+#define MINFLOAT ((float)1.40129846432481707e-45)
+#define _IEEE 1
+#define _DEXPLEN 11
+#define _FEXPLEN 8
+#define _HIDDENBIT 1
+#define DMINEXP (-(DMAXEXP + DSIGNIF - _HIDDENBIT - 3))
+#define FMINEXP (-(FMAXEXP + FSIGNIF - _HIDDENBIT - 3))
+#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
+
+#elif defined(sony)
+#define MAXDOUBLE 1.79769313486231470e+308
+#define MAXFLOAT ((float)3.40282346638528860e+38)
+#define MINDOUBLE 2.2250738585072010e-308
+#define MINFLOAT ((float)1.17549435e-38)
+#define _IEEE 1
+#define _DEXPLEN 11
+#define _FEXPLEN 8
+#define _HIDDENBIT 1
+#define DMINEXP (-(DMAXEXP + DSIGNIF - _HIDDENBIT - 3))
+#define FMINEXP (-(FMAXEXP + FSIGNIF - _HIDDENBIT - 3))
+#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
+
+#elif defined(sequent)
+extern double _maxdouble, _mindouble;
+extern float _maxfloat, _minfloat;
+#define MAXDOUBLE _maxdouble
+#define MAXFLOAT _maxfloat
+#define MINDOUBLE _mindouble
+#define MINFLOAT _minfloat
+#define _IEEE 1
+#define _DEXPLEN 11
+#define _FEXPLEN 8
+#define _HIDDENBIT 1
+#define DMINEXP (-(DMAXEXP - 3))
+#define FMINEXP (-(FMAXEXP - 3))
+#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
+
+#elif defined(i386)
+#define MAXDOUBLE 1.79769313486231570e+308
+#define MAXFLOAT ((float)3.40282346638528860e+38)
+#define MINDOUBLE 2.22507385850720140e-308
+#define MINFLOAT ((float)1.17549435082228750e-38)
+#define _IEEE 0
+#define _DEXPLEN 11
+#define _FEXPLEN 8
+#define _HIDDENBIT 1
+#define DMINEXP (-DMAXEXP)
+#define FMINEXP (-FMAXEXP)
+#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
+
+/* from Andrew Klossner <andrew%frip.wv.tek.com@relay.cs.net> */
+#elif defined(m88k)
+ /* These are "good" guesses ...
+ I'll figure out the true mins and maxes later, at the time I find
+ out the mins and maxes that the compiler can tokenize. */
+#define MAXDOUBLE 1.79769313486231e+308
+#define MAXFLOAT ((float)3.40282346638528e+38)
+#define MINDOUBLE 2.22507385850720e-308
+#define MINFLOAT ((float)1.17549435082228e-38)
+#define _IEEE 1
+#define _DEXPLEN 11
+#define _FEXPLEN 8
+#define _HIDDENBIT 1
+#define DMINEXP (1-DMAXEXP)
+#define FMINEXP (1-FMAXEXP)
+#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
+
+#elif defined(convex)
+#define MAXDOUBLE 8.9884656743115785e+306
+#define MAXFLOAT ((float) 1.70141173e+38)
+#define MINDOUBLE 5.5626846462680035e-308
+#define MINFLOAT ((float) 2.93873588e-39)
+#define _IEEE 0
+#define _DEXPLEN 11
+#define _FEXPLEN 8
+#define _HIDDENBIT 1
+#define DMINEXP (-DMAXEXP)
+#define FMINEXP (-FMAXEXP)
+#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
+
+/* #elif defined(vax) */
+/* use vax versions by default -- they seem to be the most conservative */
+#else
+
+#define MAXDOUBLE 1.701411834604692293e+38
+#define MINDOUBLE (2.938735877055718770e-39)
+
+#define MAXFLOAT 1.7014117331926443e+38
+#define MINFLOAT 2.9387358770557188e-39
+
+#define _IEEE 0
+#define _DEXPLEN 8
+#define _FEXPLEN 8
+#define _HIDDENBIT 1
+#define DMINEXP (-DMAXEXP)
+#define FMINEXP (-FMAXEXP)
+#define DMAXEXP ((1 << _DEXPLEN - 1) - 1 + _IEEE)
+#define FMAXEXP ((1 << _FEXPLEN - 1) - 1 + _IEEE)
+#endif
+
+#define DSIGNIF (DOUBLEBITS - _DEXPLEN + _HIDDENBIT - 1)
+#define FSIGNIF (FLOATBITS - _FEXPLEN + _HIDDENBIT - 1)
+#define DMAXPOWTWO ((double)(1L << LONGBITS -2)*(1L << DSIGNIF - LONGBITS +1))
+#define FMAXPOWTWO ((float)(1L << FSIGNIF - 1))
+
+#endif /* !_VALUES_H_ */
+
diff --git a/gnu/lib/Makefile b/gnu/lib/Makefile
new file mode 100644
index 0000000..9c07c7c
--- /dev/null
+++ b/gnu/lib/Makefile
@@ -0,0 +1,25 @@
+# $FreeBSD$
+
+SUBDIR= csu libgcc libdialog libregex libreadline
+
+.if ${OBJFORMAT} == aout
+.if !defined(NOLIBC_R)
+SUBDIR+= libgcc_r
+.endif
+.endif
+
+# libsupc++ uses libstdc++ headers, although 'make includes' should
+# have taken care of that already.
+.if !defined(NO_CXX)
+SUBDIR+= libstdc++ libsupc++
+.endif
+
+.if !defined(NO_OBJC)
+SUBDIR+= libobjc
+.endif
+
+.if !defined(NO_FORTRAN)
+SUBDIR+= libg2c
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/gnu/lib/csu/Makefile b/gnu/lib/csu/Makefile
new file mode 100644
index 0000000..b65c195
--- /dev/null
+++ b/gnu/lib/csu/Makefile
@@ -0,0 +1,68 @@
+# $FreeBSD$
+
+GCCDIR= ${.CURDIR}/../../../contrib/gcc
+CCDIR= ${.CURDIR}/../../usr.bin/cc
+.include "${CCDIR}/Makefile.tgt"
+
+.PATH: ${GCCDIR}/config/${GCC_CPU} ${GCCDIR}
+
+SRCS= crtstuff.c tconfig.h
+OBJS= crtbegin.o crtend.o
+SOBJS= crtbegin.So crtend.So
+CFLAGS+= -DIN_GCC -DHAVE_LD_EH_FRAME_HDR
+CFLAGS+= -finhibit-size-directive -fno-inline-functions \
+ -fno-exceptions -fno-omit-frame-pointer
+CFLAGS+= -I${GCCDIR}/config -I${GCCDIR} -I. \
+ -I${CCDIR}/cc_tools
+CRTS_CFLAGS= -DCRTSTUFFS_O -DSHARED ${PICFLAG}
+MKDEPCMD= CC="${CC}" MKDEP_CPP_OPTS="-M -DCRT_BEGIN" mkdep
+
+.if ${TARGET_ARCH} == "ia64"
+BEGINSRC= crtbegin.asm
+ENDSRC= crtend.asm
+CFLAGS+= -x assembler-with-cpp # Ugly hack
+.undef SRCS # hack for 'make depend'
+.endif
+.if ${TARGET_ARCH} == "powerpc"
+TGTOBJS= crtsavres.o
+SRCS+= crtsavres.asm
+.endif
+.if ${TARGET_ARCH} == "alpha" || ${TARGET_ARCH} == "sparc64"
+TGTOBJS= crtfastmath.o
+SRCS+= crtfastmath.c
+.endif
+BEGINSRC?= crtstuff.c
+ENDSRC?= crtstuff.c
+
+all: ${OBJS} ${SOBJS} ${TGTOBJS}
+${OBJS} ${SOBJS}: tconfig.h
+
+CLEANFILES= ${OBJS} ${SOBJS} ${TGTOBJS}
+
+crtbegin.o: ${BEGINSRC}
+ ${CC} ${CFLAGS} -g0 -DCRT_BEGIN \
+ -c -o ${.TARGET} ${.ALLSRC:N*.h}
+
+crtbegin.So: ${BEGINSRC}
+ ${CC} ${CFLAGS} -g0 -DCRT_BEGIN ${CRTS_CFLAGS} \
+ -c -o ${.TARGET} ${.ALLSRC:N*.h}
+
+crtend.o: ${ENDSRC}
+ ${CC} ${CFLAGS} -g0 -DCRT_END \
+ -c -o ${.TARGET} ${.ALLSRC:N*.h}
+
+crtend.So: ${ENDSRC}
+ ${CC} ${CFLAGS} -g0 -DCRT_END ${CRTS_CFLAGS} \
+ -c -o ${.TARGET} ${.ALLSRC:N*.h}
+
+CLEANFILES+= tconfig.h
+tconfig.h: ${CCDIR}/cc_tools/Makefile
+ ${MAKE} -f ${.ALLSRC} MFILE=${.ALLSRC} GCCDIR=${GCCDIR} ${.TARGET}
+
+realinstall:
+.for file in ${OBJS} ${SOBJS} ${TGTOBJS}
+ ${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
+ ${file} ${DESTDIR}${LIBDIR}/${file:S/.So$/S.o/}
+.endfor
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libdialog/CHANGES b/gnu/lib/libdialog/CHANGES
new file mode 100644
index 0000000..1467a0e
--- /dev/null
+++ b/gnu/lib/libdialog/CHANGES
@@ -0,0 +1,9 @@
+- Added two variables to call to dialog_menu() to save the position
+ in the menu when choosing a menu-option.
+
+- Added dialog_fselect(), implements a fileselector dialog
+- Added ui-interface objects: Stringobject, Listobject and Buttonobject.
+ The fileselector dialog was built using these objects.
+- changed dialog_menu to use PGUP and PGDN
+- Added dialog_mesgbox, which display text given in a char buffer.
+-
diff --git a/gnu/lib/libdialog/COPYING b/gnu/lib/libdialog/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/gnu/lib/libdialog/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/lib/libdialog/Makefile b/gnu/lib/libdialog/Makefile
new file mode 100644
index 0000000..40d98b4
--- /dev/null
+++ b/gnu/lib/libdialog/Makefile
@@ -0,0 +1,49 @@
+# Makefile for libdialog
+# $FreeBSD$
+
+LIB= dialog
+INCS= dialog.h
+MAN= dialog.3
+
+SHLIB_MAJOR= 4
+SHLIB_MINOR= 0
+SRCS= kernel.c rc.c checklist.c inputbox.c menubox.c msgbox.c \
+ lineedit.c radiolist.c textbox.c yesno.c prgbox.c raw_popen.c \
+ fselect.c ui_objects.c dir.c notify.c help.c gauge.c tree.c
+
+EXAMPLES= Makefile check1.c check2.c check3.c dselect.c fselect.c \
+ ftree1.c ftree1.test ftree2.c ftree2.test gauge.c input1.c \
+ input2.c menu1.c menu2.c menu3.c msg.c prgbox.c radio1.c \
+ radio2.c radio3.c text.c tree.c yesno.c
+
+CFLAGS+= -I${.CURDIR} -Wall -Wstrict-prototypes -DLOCALE
+
+LDADD+= -lncurses
+DPADD+= ${LIBNCURSES}
+
+.if !defined(NOHTML)
+afterinstall:
+.for file in ${EXAMPLES}
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \
+ ${.CURDIR}/TESTS/${file} ${DESTDIR}/usr/share/examples/libdialog
+.endfor
+.endif
+
+MLINKS+=dialog.3 draw_shadow.3 dialog.3 draw_box.3 \
+ dialog.3 line_edit.3 dialog.3 strheight.3 \
+ dialog.3 strwidth.3 dialog.3 dialog_create_rc.3 \
+ dialog.3 dialog_yesno.3 dialog.3 dialog_noyes.3 \
+ dialog.3 dialog_prgbox.3 \
+ dialog.3 dialog_textbox.3 dialog.3 dialog_menu.3 \
+ dialog.3 dialog_checklist.3 dialog.3 dialog_radiolist.3 \
+ dialog.3 dialog_inputbox.3 dialog.3 dialog_clear_norefresh.3 \
+ dialog.3 dialog_clear.3 dialog.3 dialog_update.3 \
+ dialog.3 dialog_fselect.3 dialog.3 dialog_notify.3 \
+ dialog.3 dialog_mesgbox.3 dialog.3 dialog_gauge.3 \
+ dialog.3 init_dialog.3 dialog.3 end_dialog.3 \
+ dialog.3 use_helpfile.3 dialog.3 use_helpline.3 \
+ dialog.3 get_helpline.3 dialog.3 restore_helpline.3 \
+ dialog.3 dialog_msgbox.3 dialog.3 dialog_ftree.3 \
+ dialog.3 dialog_tree.3
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libdialog/README b/gnu/lib/libdialog/README
new file mode 100644
index 0000000..e5e6d56
--- /dev/null
+++ b/gnu/lib/libdialog/README
@@ -0,0 +1,8 @@
+This library was split out from the `dialog' program for use
+in C programs. For a list of interface functions, see dialog.h.
+For usage examples, see the `dialog' program sources in
+/usr/src/gnu/usr.bin/dialog.
+
+You can additionally use any ncurses functions after init_dialog().
+
+ Ache.
diff --git a/gnu/lib/libdialog/TESTS/Makefile b/gnu/lib/libdialog/TESTS/Makefile
new file mode 100644
index 0000000..ddfd122
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/Makefile
@@ -0,0 +1,19 @@
+# Really quick and evil Makefile for building all the tests. I wish that
+# bmake was friendlier to the concept of multiple progs/libs in the same
+# directory.
+#
+# $FreeBSD$
+
+PROGS= msg yesno prgbox gauge dselect fselect text menu1 menu2 menu3 \
+ input1 input2 check1 check2 check3 radio1 radio2 radio3 \
+ ftree1 ftree2 tree
+
+CFLAGS+= -Wall -Wstrict-prototypes
+LDFLAGS+= -ldialog
+
+all: ${PROGS}
+
+clean:
+ rm -f ${PROGS}
+
+.include <bsd.prog.mk>
diff --git a/gnu/lib/libdialog/TESTS/check1.c b/gnu/lib/libdialog/TESTS/check1.c
new file mode 100644
index 0000000..b3cf6f5
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/check1.c
@@ -0,0 +1,82 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Hook functions */
+
+static int
+getBool(dialogMenuItem *self)
+{
+ if (self->data && *((int *)self->data))
+ return TRUE;
+ return FALSE;
+}
+
+static int
+setBool(dialogMenuItem *self)
+{
+ if (self->data) {
+ *((int *)self->data) = !*((int *)self->data);
+ return DITEM_SUCCESS;
+ }
+ return DITEM_FAILURE;
+}
+
+static int german_book, italian_book, slang_book;
+
+static int
+clearBooks(dialogMenuItem *self)
+{
+ german_book = italian_book = slang_book = FALSE;
+ return DITEM_SUCCESS | DITEM_REDRAW;
+}
+
+/* menu2 - A more advanced way of using checked and fire hooks to manipulate the backing-variables directly */
+/* prompt title checked fire sel data */
+static dialogMenuItem menu2[] = {
+ { "German", "Buy book on learning German", getBool, setBool, NULL, &german_book},
+ { "Italian", "Buy book on learning Italian", getBool, setBool, NULL, &italian_book },
+ { "Slang", "Buy book on commonly used insults", getBool, setBool, NULL, &slang_book },
+ { "Clear", "Clear book list", NULL, clearBooks, NULL, NULL, ' ', ' ', ' ' },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_checklist("this is a dialog_checklist() in action, test #1",
+ "this checklist menu shows off some of the straight-forward features\n"
+ "of the new menu system's check & fire dispatch hooks", -1, -1, 4, -4, menu2, NULL);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_checklist was %d (%d %d %d)\n", retval, german_book, italian_book, slang_book);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/check2.c b/gnu/lib/libdialog/TESTS/check2.c
new file mode 100644
index 0000000..d5ad569
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/check2.c
@@ -0,0 +1,104 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Hook functions */
+
+static int
+getBool(dialogMenuItem *self)
+{
+ if (self->data && *((int *)self->data))
+ return TRUE;
+ return FALSE;
+}
+
+static int
+setBool(dialogMenuItem *self)
+{
+ if (self->data) {
+ *((int *)self->data) = !*((int *)self->data);
+ return DITEM_SUCCESS;
+ }
+ return DITEM_FAILURE;
+}
+
+static int german_book, italian_book, slang_book;
+
+static int
+clearBooks(dialogMenuItem *self)
+{
+ german_book = italian_book = slang_book = FALSE;
+ return DITEM_SUCCESS | DITEM_REDRAW;
+}
+
+static int
+buyBooks(dialogMenuItem *self)
+{
+ char foo[256];
+
+ if (german_book || italian_book || slang_book) {
+ strcpy(foo, "Ok, you're buying books on");
+ if (german_book)
+ strcat(foo, " german");
+ if (italian_book)
+ strcat(foo, " italian");
+ if (slang_book)
+ strcat(foo, " slang");
+ }
+ else
+ strcpy(foo, "You're not buying any books?");
+ dialog_mesgbox("This is a direct callback for the `Buy' button", foo, -1, -1);
+ return DITEM_SUCCESS;
+}
+
+/* menu3 - Look mom! We can finally use our own OK and Cancel buttons! */
+/* prompt title checked fire sel data */
+static dialogMenuItem menu3[] = {
+ { "Buy!", NULL, NULL, buyBooks }, /* New "OK" button */
+ { "No Way!", NULL, NULL, NULL }, /* New "Cancel" button */
+ { "German", "Buy books on learning German", getBool, setBool, NULL, &german_book },
+ { "Italian", "Buy books on learning Italian", getBool, setBool, NULL, &italian_book },
+ { "Slang", "Buy books on commonly used insults", getBool, setBool, NULL, &slang_book },
+ { "Clear", "Clear book list", NULL, clearBooks, NULL, NULL, ' ', ' ', ' ' },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_checklist("this is dialog_checklist() in action, test #2",
+ "Same as before, but now we relabel the buttons and override the OK action.",
+ -1, -1, 4, -4, menu3 + 2, (char *)TRUE);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_checklist was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/check3.c b/gnu/lib/libdialog/TESTS/check3.c
new file mode 100644
index 0000000..8b4c0e5
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/check3.c
@@ -0,0 +1,91 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Hook functions */
+
+static int
+getBool(dialogMenuItem *self)
+{
+ if (self->data && *((int *)self->data))
+ return TRUE;
+ return FALSE;
+}
+
+static int
+setBool(dialogMenuItem *self)
+{
+ if (self->data) {
+ *((int *)self->data) = !*((int *)self->data);
+ return DITEM_SUCCESS;
+ }
+ return DITEM_FAILURE;
+}
+
+static int german_book, italian_book, slang_book;
+static int spending;
+
+static int
+check(dialogMenuItem *self)
+{
+ return ((int)self->data == spending);
+}
+
+static int
+spend(dialogMenuItem *self)
+{
+ spending = (int)self->data;
+ return DITEM_SUCCESS | DITEM_REDRAW;
+}
+
+/* menu4 - Show off a simulated compound menu (group at top is checklist, group at bottom radio) */
+/* prompt title checked fire sel, data lbra mark rbra */
+static dialogMenuItem menu4[] = {
+ { "German", "Buy books on learning German", getBool, setBool, NULL, &german_book },
+ { "Italian","Buy books on learning Italian", getBool, setBool, NULL, &italian_book },
+ { "Slang", "Buy books on commonly used insults", getBool, setBool, NULL, &slang_book },
+ { "-----", "----------------------------------", NULL, NULL, NULL, NULL, ' ', ' ', ' ' },
+ { "1000", "Spend $1,000", check, spend, NULL, (void *)1000, '(', '*', ')' },
+ { "500", "Spend $500", check, spend, NULL, (void *)500, '(', '*', ')' },
+ { "100", "Spend $100", check, spend, NULL, (void *)100, '(', '*', ')' },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+
+ retval = dialog_checklist("this is dialog_checklist() in action, test #3",
+ "Now we show off some of the button 'styles' one can create.",
+ -1, -1, 7, -7, menu4, NULL);
+ dialog_clear();
+ fprintf(stderr, "spent $%d on %s%s%s books\n", spending, german_book ? " german" : "",
+ italian_book ? " italian" : "", slang_book ? " slang" : "");
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/dselect.c b/gnu/lib/libdialog/TESTS/dselect.c
new file mode 100644
index 0000000..2547af9
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/dselect.c
@@ -0,0 +1,40 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_dselect(".", "*");
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_dselect was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/fselect.c b/gnu/lib/libdialog/TESTS/fselect.c
new file mode 100644
index 0000000..184faac
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/fselect.c
@@ -0,0 +1,43 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ char *retval;
+
+ init_dialog();
+
+ retval = dialog_fselect(".", "*.[ch]");
+ dialog_clear();
+ if (retval)
+ fprintf(stderr, "returned value for dialog_fselect was %s\n", retval);
+ else
+ fprintf(stderr, "returned value for dialog_fselect was NULL\n");
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/ftree1.c b/gnu/lib/libdialog/TESTS/ftree1.c
new file mode 100644
index 0000000..836ae0c
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/ftree1.c
@@ -0,0 +1,44 @@
+/*
+ * ftree1.c
+ *
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1998, Anatoly A. Orehovsky
+ *
+ * file ./ftree1.test with xterm widget tree from
+ * direct editres(1) dump needed !!!
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dialog.h>
+
+int
+main(int argc, char **argv)
+{
+ int retval;
+ unsigned char *tresult;
+
+ init_dialog();
+ retval = dialog_ftree("ftree1.test", '\t',
+ "ftree dialog box example",
+ "xterm widget tree from direct editres(1) dump",
+ -1, -1, 15,
+ &tresult);
+
+ dialog_update();
+
+ dialog_clear();
+
+ end_dialog();
+
+ if (!retval)
+ {
+ puts(tresult);
+ free(tresult);
+ }
+
+ exit(retval);
+}
diff --git a/gnu/lib/libdialog/TESTS/ftree1.test b/gnu/lib/libdialog/TESTS/ftree1.test
new file mode 100644
index 0000000..4a8f0fa
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/ftree1.test
@@ -0,0 +1,73 @@
+XTerm login
+ VendorShellExt shellext
+ VT100 vt100
+ SimpleMenu fontMenu
+ SmeBSB menuLabel
+ SmeBSB fontdefault
+ SmeBSB font1
+ SmeBSB font2
+ SmeBSB font3
+ SmeBSB font4
+ SmeBSB font5
+ SmeBSB font6
+ SmeBSB fontescape
+ SmeBSB fontsel
+ SimpleMenu mainMenu
+ SmeBSB menuLabel
+ SmeBSB securekbd
+ SmeBSB allowsends
+ SmeBSB redraw
+ SmeLine line1
+ SmeBSB 8-bit control
+ SmeBSB sun function-keys
+ SmeLine line2
+ SmeBSB suspend
+ SmeBSB continue
+ SmeBSB interrupt
+ SmeBSB hangup
+ SmeBSB terminate
+ SmeBSB kill
+ SmeLine line3
+ SmeBSB quit
+ SimpleMenu vtMenu
+ SmeBSB menuLabel
+ SmeBSB scrollbar
+ SmeBSB jumpscroll
+ SmeBSB reversevideo
+ SmeBSB autowrap
+ SmeBSB reversewrap
+ SmeBSB autolinefeed
+ SmeBSB appcursor
+ SmeBSB appkeypad
+ SmeBSB scrollkey
+ SmeBSB scrollttyoutput
+ SmeBSB allow132
+ SmeBSB cursesemul
+ SmeBSB visualbell
+ SmeBSB marginbell
+ SmeBSB altscreen
+ SmeLine line1
+ SmeBSB softreset
+ SmeBSB hardreset
+ SmeBSB clearsavedlines
+ SmeLine line2
+ SmeBSB tekshow
+ SmeBSB tekmode
+ SmeBSB vthide
+ TopLevelShell tektronix
+ VendorShellExt shellext
+ Tek4014 tek4014
+ SimpleMenu tekMenu
+ SmeBSB menuLabel
+ SmeBSB tektextlarge
+ SmeBSB tektext2
+ SmeBSB tektext3
+ SmeBSB tektextsmall
+ SmeLine line1
+ SmeBSB tekpage
+ SmeBSB tekreset
+ SmeBSB tekcopy
+ SmeLine line2
+ SmeBSB vtshow
+ SmeBSB vtmode
+ SmeBSB tekhide
diff --git a/gnu/lib/libdialog/TESTS/ftree2.c b/gnu/lib/libdialog/TESTS/ftree2.c
new file mode 100644
index 0000000..11a1b7b
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/ftree2.c
@@ -0,0 +1,46 @@
+/*
+ * ftree2.c
+ *
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1998, Anatoly A. Orehovsky
+ *
+ * file ./ftree2.test with xterm widget tree from
+ * preprocess editres(1) dump needed !!!
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dialog.h>
+
+int
+main(int argc, char **argv)
+{
+ int retval;
+ unsigned char *tresult;
+
+ init_dialog();
+ use_helpfile("ftree2.test");
+ use_helpline("Press Arrows, Tab, Enter or F1");
+ retval = dialog_ftree("ftree2.test", '\t',
+ "ftree dialog box example",
+ "xterm widget tree from preprocess editres(1) dump",
+ -1, -1, 15,
+ &tresult);
+
+ dialog_update();
+
+ dialog_clear();
+
+ end_dialog();
+
+ if (!retval)
+ {
+ puts(tresult);
+ free(tresult);
+ }
+
+ exit(retval);
+}
diff --git a/gnu/lib/libdialog/TESTS/ftree2.test b/gnu/lib/libdialog/TESTS/ftree2.test
new file mode 100644
index 0000000..0850862
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/ftree2.test
@@ -0,0 +1,73 @@
+XTerm login
+XTerm login VendorShellExt shellext
+XTerm login VT100 vt100
+XTerm login SimpleMenu fontMenu
+XTerm login SimpleMenu fontMenu SmeBSB menuLabel
+XTerm login SimpleMenu fontMenu SmeBSB fontdefault
+XTerm login SimpleMenu fontMenu SmeBSB font1
+XTerm login SimpleMenu fontMenu SmeBSB font2
+XTerm login SimpleMenu fontMenu SmeBSB font3
+XTerm login SimpleMenu fontMenu SmeBSB font4
+XTerm login SimpleMenu fontMenu SmeBSB font5
+XTerm login SimpleMenu fontMenu SmeBSB font6
+XTerm login SimpleMenu fontMenu SmeBSB fontescape
+XTerm login SimpleMenu fontMenu SmeBSB fontsel
+XTerm login SimpleMenu mainMenu
+XTerm login SimpleMenu mainMenu SmeBSB menuLabel
+XTerm login SimpleMenu mainMenu SmeBSB securekbd
+XTerm login SimpleMenu mainMenu SmeBSB allowsends
+XTerm login SimpleMenu mainMenu SmeBSB redraw
+XTerm login SimpleMenu mainMenu SmeLine line1
+XTerm login SimpleMenu mainMenu SmeBSB 8-bit control
+XTerm login SimpleMenu mainMenu SmeBSB sun function-keys
+XTerm login SimpleMenu mainMenu SmeLine line2
+XTerm login SimpleMenu mainMenu SmeBSB suspend
+XTerm login SimpleMenu mainMenu SmeBSB continue
+XTerm login SimpleMenu mainMenu SmeBSB interrupt
+XTerm login SimpleMenu mainMenu SmeBSB hangup
+XTerm login SimpleMenu mainMenu SmeBSB terminate
+XTerm login SimpleMenu mainMenu SmeBSB kill
+XTerm login SimpleMenu mainMenu SmeLine line3
+XTerm login SimpleMenu mainMenu SmeBSB quit
+XTerm login SimpleMenu vtMenu
+XTerm login SimpleMenu vtMenu SmeBSB menuLabel
+XTerm login SimpleMenu vtMenu SmeBSB scrollbar
+XTerm login SimpleMenu vtMenu SmeBSB jumpscroll
+XTerm login SimpleMenu vtMenu SmeBSB reversevideo
+XTerm login SimpleMenu vtMenu SmeBSB autowrap
+XTerm login SimpleMenu vtMenu SmeBSB reversewrap
+XTerm login SimpleMenu vtMenu SmeBSB autolinefeed
+XTerm login SimpleMenu vtMenu SmeBSB appcursor
+XTerm login SimpleMenu vtMenu SmeBSB appkeypad
+XTerm login SimpleMenu vtMenu SmeBSB scrollkey
+XTerm login SimpleMenu vtMenu SmeBSB scrollttyoutput
+XTerm login SimpleMenu vtMenu SmeBSB allow132
+XTerm login SimpleMenu vtMenu SmeBSB cursesemul
+XTerm login SimpleMenu vtMenu SmeBSB visualbell
+XTerm login SimpleMenu vtMenu SmeBSB marginbell
+XTerm login SimpleMenu vtMenu SmeBSB altscreen
+XTerm login SimpleMenu vtMenu SmeLine line1
+XTerm login SimpleMenu vtMenu SmeBSB softreset
+XTerm login SimpleMenu vtMenu SmeBSB hardreset
+XTerm login SimpleMenu vtMenu SmeBSB clearsavedlines
+XTerm login SimpleMenu vtMenu SmeLine line2
+XTerm login SimpleMenu vtMenu SmeBSB tekshow
+XTerm login SimpleMenu vtMenu SmeBSB tekmode
+XTerm login SimpleMenu vtMenu SmeBSB vthide
+XTerm login TopLevelShell tektronix
+XTerm login TopLevelShell tektronix VendorShellExt shellext
+XTerm login TopLevelShell tektronix Tek4014 tek4014
+XTerm login SimpleMenu tekMenu
+XTerm login SimpleMenu tekMenu SmeBSB menuLabel
+XTerm login SimpleMenu tekMenu SmeBSB tektextlarge
+XTerm login SimpleMenu tekMenu SmeBSB tektext2
+XTerm login SimpleMenu tekMenu SmeBSB tektext3
+XTerm login SimpleMenu tekMenu SmeBSB tektextsmall
+XTerm login SimpleMenu tekMenu SmeLine line1
+XTerm login SimpleMenu tekMenu SmeBSB tekpage
+XTerm login SimpleMenu tekMenu SmeBSB tekreset
+XTerm login SimpleMenu tekMenu SmeBSB tekcopy
+XTerm login SimpleMenu tekMenu SmeLine line2
+XTerm login SimpleMenu tekMenu SmeBSB vtshow
+XTerm login SimpleMenu tekMenu SmeBSB vtmode
+XTerm login SimpleMenu tekMenu SmeBSB tekhide
diff --git a/gnu/lib/libdialog/TESTS/gauge.c b/gnu/lib/libdialog/TESTS/gauge.c
new file mode 100644
index 0000000..1e16c59
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/gauge.c
@@ -0,0 +1,40 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int i;
+
+ init_dialog();
+
+ for (i = 0; i <= 100; i++) {
+ dialog_gauge("Gas tank", "When this gets 100% full, you'd better yank out the nozzle!", 10, 1, 7, 70, i);
+ usleep(30000);
+ }
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/input1.c b/gnu/lib/libdialog/TESTS/input1.c
new file mode 100644
index 0000000..5f46483
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/input1.c
@@ -0,0 +1,44 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+ unsigned char result[128];
+
+ init_dialog();
+
+ strcpy(result, "not this!");
+ retval = dialog_inputbox("this is dialog_inputbox() in action, test #1",
+ "Enter something really profound below, please.",
+ -1, -1, result);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_inputbox was %d (%s)\n", retval, result);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/input2.c b/gnu/lib/libdialog/TESTS/input2.c
new file mode 100644
index 0000000..0f5b82a
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/input2.c
@@ -0,0 +1,46 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+ unsigned char result[128];
+
+ init_dialog();
+
+ result[0]='\0';
+ DialogInputAttrs |= DITEM_NO_ECHO;
+ retval = dialog_inputbox("this is dialog_inputbox() in action, test #2 (no echo)",
+ "Enter something really secret below, please.",
+ -1, -1, result);
+ DialogInputAttrs &= DITEM_NO_ECHO;
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_inputbox was %d (%s)\n", retval, result);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/menu1.c b/gnu/lib/libdialog/TESTS/menu1.c
new file mode 100644
index 0000000..977ffd4
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/menu1.c
@@ -0,0 +1,95 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Start of hook functions */
+static enum { nowhere, berlin, rome, ny } where;
+
+static int
+_menu1_berlin_action(dialogMenuItem *self)
+{
+ if (where == berlin) {
+ dialog_mesgbox("excuse me?", "But you're already *in* Berlin!", -1, -1);
+ }
+ else {
+ where = berlin;
+ dialog_mesgbox("whoosh!", "Welcome to Berlin! Have a beer!", -1, -1);
+ }
+ return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE;
+}
+
+static int
+_menu1_rome_action(dialogMenuItem *self)
+{
+ if (where == rome) {
+ dialog_mesgbox("The wine must be getting to you..", "You're already in Rome!", -1, -1);
+ }
+ else {
+ where = rome;
+ dialog_mesgbox("whoosh!", "Welcome to Rome! Have a coffee!", -1, -1);
+ }
+ return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE;
+}
+
+static int
+_menu1_ny_action(dialogMenuItem *self)
+{
+ if (where == ny) {
+ dialog_mesgbox("Say what?", "You're already there!", -1, -1);
+ }
+ else {
+ where = ny;
+ dialog_mesgbox("whoosh!", "Welcome to New York! Now go someplace else!", -1, -1);
+ }
+ return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE;
+}
+
+/* menu1 - show off the "fire" action hook */
+/* prompt title checked fire */
+static dialogMenuItem menu1[] = {
+ { "Berlin", "Go visit Germany's new capitol", NULL, _menu1_berlin_action },
+ { "Rome", "Go visit the Roman ruins", NULL, _menu1_rome_action },
+ { "New York", "Go visit the streets of New York", NULL, _menu1_ny_action },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_menu("this is dialog_menu() in action, test #1",
+ "this simple menu shows off some of the straight-forward features\n"
+ "of the new menu system's action dispatch hooks. Select Cancel to leave",
+ -1, -1, 3, -3, menu1, NULL, NULL, NULL);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_menu was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/menu2.c b/gnu/lib/libdialog/TESTS/menu2.c
new file mode 100644
index 0000000..2c8b8b8
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/menu2.c
@@ -0,0 +1,95 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Start of hook functions */
+static enum { nowhere, berlin, rome, ny } where;
+
+static int
+_menu1_berlin_action(dialogMenuItem *self)
+{
+ if (where == berlin)
+ dialog_mesgbox("excuse me?", "But you're already *in* Berlin!", -1, -1);
+ else {
+ where = berlin;
+ dialog_mesgbox("whoosh!", "Welcome to Berlin! Have a beer!", -1, -1);
+ }
+ return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE;
+}
+
+static int
+_menu1_rome_action(dialogMenuItem *self)
+{
+ if (where == rome)
+ dialog_mesgbox("The wine must be getting to you..", "You're already in Rome!", -1, -1);
+ else {
+ where = rome;
+ dialog_mesgbox("whoosh!", "Welcome to Rome! Have a coffee!", -1, -1);
+ }
+ return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE;
+}
+
+static int
+_menu1_ny_action(dialogMenuItem *self)
+{
+ if (where == ny)
+ dialog_mesgbox("Say what?", "You're already there!", -1, -1);
+ else {
+ where = ny;
+ dialog_mesgbox("whoosh!", "Welcome to New York! Now go someplace else!", -1, -1);
+ }
+ return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE;
+}
+
+/* menu1 - show off the "fire" action hook */
+/* prompt title checked fire */
+static dialogMenuItem menu1[] = {
+ { "Berlin", "Go visit Germany's new capitol", NULL, _menu1_berlin_action },
+ { "Rome", "Go visit the Roman ruins", NULL, _menu1_rome_action },
+ { "New York", "Go visit the streets of New York", NULL, _menu1_ny_action },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ use_helpfile("menu2.c");
+ use_helpline("Type F1 to view the source for this demo");
+ retval = dialog_menu("this is dialog_menu() in action, test #2",
+ "this simple menu shows off some of the straight-forward features\n"
+ "of the new menu system's action dispatch hooks as well as a helpline\n"
+ "and a helpfile. Select Cancel to leave",
+ -1, -1, 3, -3, menu1, NULL, NULL, NULL);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_menu was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/menu3.c b/gnu/lib/libdialog/TESTS/menu3.c
new file mode 100644
index 0000000..becbf54
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/menu3.c
@@ -0,0 +1,106 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Hook functions */
+
+static int
+stop(dialogMenuItem *self)
+{
+ dialog_mesgbox("!", "I'm no idiot!", -1, -1);
+ return DITEM_SUCCESS;
+}
+
+static int
+maybe(dialogMenuItem *self)
+{
+ dialog_mesgbox("!", "I said don't rush me! I'm THINKING!", -1, -1);
+ return DITEM_SUCCESS | DITEM_RESTORE | DITEM_CONTINUE;
+}
+
+/* Dummy menu just to show of the ability */
+static char *insurance[] = {
+ "1,000,000", "Mondo insurance policy", "Off",
+ "5,000,000", "Mega insurance policy", "Off",
+ "10,000,000", "Friend! Most Favored customer!"
+};
+
+static void
+preinsure(dialogMenuItem *self, int is_selected)
+{
+ if (is_selected) {
+ static WINDOW *w;
+
+ /* This has to be here first if you want to see selection traverse properly in the invoking menu */
+ refresh();
+
+ w = dupwin(newscr);
+ DialogX = 1;
+ DialogY = 13;
+ dialog_radiolist("How much insurance would you like to take out?",
+ "If you're really going to do this, we recommend some insurance\n"
+ "first! What kind of life insurance policy would you like?",
+ -1, -1, 3, 3, insurance, NULL);
+ touchwin(w);
+ wrefresh(w);
+ delwin(w);
+ }
+}
+
+/*
+ * Show a simple menu that puts up a sub menu when a certain item is traversed to
+ */
+
+/* prompt title checked fire sel */
+static dialogMenuItem doit[] = {
+ { "Rah!" },
+ { "No way!" },
+ { "Stop", "No, I'm not going to do that!", NULL, stop, NULL },
+ { "Maybe", "I'm still thinking about it, don't rush me!", NULL, maybe, NULL, },
+ { "Go", "Yes! Yes! I want to do it!", NULL, NULL, preinsure },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+
+ DialogX = 5;
+ DialogY = 1;
+ retval = dialog_menu("Do you have the GUTS?",
+ "C'mon, macho man! Do you have what it takes to do something REALLY\n"
+ "dangerous and stupid? WHAT ARE YOU WAITING FOR?!",
+ -1, -1, 3, -3, doit + 2, (char *)TRUE, NULL, NULL);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_menu was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/msg.c b/gnu/lib/libdialog/TESTS/msg.c
new file mode 100644
index 0000000..cd1abe0
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/msg.c
@@ -0,0 +1,41 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_msgbox("This is dialog_msgbox() in action with pause on", "Hi there. Please press return now.",
+ -1, -1, 1);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_msgbox was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/prgbox.c b/gnu/lib/libdialog/TESTS/prgbox.c
new file mode 100644
index 0000000..47e3552
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/prgbox.c
@@ -0,0 +1,40 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_prgbox("This is dialog_prgbox() in action with cal(1)", "cal", 14, 50, TRUE, TRUE);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_prgbox was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/radio1.c b/gnu/lib/libdialog/TESTS/radio1.c
new file mode 100644
index 0000000..2d1f582
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/radio1.c
@@ -0,0 +1,70 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Hook functions */
+
+static int spending;
+
+static int
+check(dialogMenuItem *self)
+{
+ return ((int)self->data == spending);
+}
+
+static int
+spend(dialogMenuItem *self)
+{
+ spending = (int)self->data;
+ return DITEM_SUCCESS | DITEM_REDRAW;
+}
+
+/* menu5 - Show a simple radiolist menu that inherits the radio appearance by default */
+/* prompt title checked fire sel data */
+static dialogMenuItem menu5[] = {
+ { "1000", "Spend $1,000", check, spend, NULL, (void *)1000 },
+ { "500", "Spend $500", check, spend, NULL, (void *)500 },
+ { "100", "Spend $100", check, spend, NULL, (void *)100 },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+
+ retval = dialog_radiolist("this is dialog_radiolist() in action, test #1",
+ "this radio menu shows off some of the straight-forward features\n"
+ "of the new menu system's check & fire dispatch hooks", -1, -1, 3, -3, menu5, NULL);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_radiolist was %d (money set to %d)\n", retval, spending);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/radio2.c b/gnu/lib/libdialog/TESTS/radio2.c
new file mode 100644
index 0000000..eee1421
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/radio2.c
@@ -0,0 +1,88 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Hook functions */
+
+static char bachelor[10], bachelette[10];
+
+static int
+getBachelor(dialogMenuItem *self)
+{
+ return !strcmp(bachelor, self->prompt);
+}
+
+static int
+setBachelor(dialogMenuItem *self)
+{
+ strcpy(bachelor, self->prompt);
+ return DITEM_SUCCESS | DITEM_REDRAW;
+}
+
+static int
+getBachelette(dialogMenuItem *self)
+{
+ return !strcmp(bachelette, self->prompt);
+}
+
+static int
+setBachelette(dialogMenuItem *self)
+{
+ strcpy(bachelette, self->prompt);
+ return DITEM_SUCCESS | DITEM_REDRAW;
+}
+
+/* menu6- More complex radiolist menu that creates two groups in a single menu */
+/* prompt title checked fire */
+static dialogMenuItem menu6[] = {
+ { "Tom", "Tom's a dynamic shoe salesman from Tulsa, OK!", getBachelor, setBachelor },
+ { "Dick", "Dick's a retired engine inspector from McDonnell-Douglas!", getBachelor, setBachelor },
+ { "Harry", "Harry's a professional female impersonator from Las Vegas!", getBachelor, setBachelor },
+ { "-----", "----------------------------------", NULL, NULL, NULL, NULL, ' ', ' ', ' ' },
+ { "Jane", "Jane's a twice-divorced housewife from Moose, Oregon!", getBachelette, setBachelette },
+ { "Sally", "Sally's a shy Human Resources Manager for IBM!", getBachelette, setBachelette },
+ { "Mary", "Mary's an energetic serial killer on the lam!", getBachelette, setBachelette },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_radiolist("this is dialog_radiolist() in action, test #2",
+ "Welcome to \"The Love Blender!\" - America's favorite game show\n"
+ "where YOU, the contestant, get to choose which of these two\n"
+ "fine specimens of humanity will go home together, whether they\n"
+ "like it or not!", -1, -1, 7, -7, menu6, NULL);
+ dialog_clear();
+ fprintf(stderr, "I'm sure that %s and %s will be very happy together!\n", bachelor, bachelette);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/radio3.c b/gnu/lib/libdialog/TESTS/radio3.c
new file mode 100644
index 0000000..2844326
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/radio3.c
@@ -0,0 +1,97 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Hook functions */
+
+static int spending;
+
+static int
+check(dialogMenuItem *self)
+{
+ return ((int)self->data == spending);
+}
+
+static int
+spend(dialogMenuItem *self)
+{
+ spending = (int)self->data;
+ return DITEM_SUCCESS | DITEM_REDRAW;
+}
+
+static void
+ask(dialogMenuItem *self, int is_selected)
+{
+ if (is_selected) {
+ char *str;
+
+ if (!strcmp(self->prompt, "1000"))
+ str = "You'd better ask both your parents first! ";
+ else if (!strcmp(self->prompt, "500"))
+ str = "You'd better at least ask your Dad! ";
+ else
+ str = "Yes, being frugal is probably a good idea!";
+ DialogX = 15;
+ DialogY = 17;
+ dialog_msgbox("Free Advice", str, -1, -1, 0);
+ }
+}
+
+/*
+ * menu5 - Show a simple radiolist menu that inherits the radio appearance by default and appears at
+ * a different location, leaving room for a msg box below it. This shows off the DialogX/DialogY extensions.
+ */
+
+/* prompt title checked fire sel data */
+static dialogMenuItem menu5[] = {
+ { "1000", "Spend $1,000", check, spend, ask, (void *)1000 },
+ { "500", "Spend $500", check, spend, ask, (void *)500 },
+ { "100", "Spend $100", check, spend, ask, (void *)100 },
+};
+
+/* End of hook functions */
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+
+ DialogX = 5;
+ DialogY = 1;
+ retval = dialog_radiolist("this is dialog_radiolist() in action, test #3",
+ "This radio menu shows off the ability to put dialog menus and other\n"
+ "controls at different locations, as well as the `selected' hook which\n"
+ "lets you follow the traversal of the selection bar as well as what's\n"
+ "selected.",
+ -1, -1, 3, -3, menu5, NULL);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_radiolist was %d (money set to %d)\n", retval, spending);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/text.c b/gnu/lib/libdialog/TESTS/text.c
new file mode 100644
index 0000000..98ca815
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/text.c
@@ -0,0 +1,40 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int retval;
+
+ init_dialog();
+
+ retval = dialog_textbox("This is dialog_textbox() in action with /etc/passwd", "/etc/passwd", 10, 60);
+ dialog_clear();
+ fprintf(stderr, "returned value for dialog_textbox was %d\n", retval);
+
+ end_dialog();
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TESTS/tree.c b/gnu/lib/libdialog/TESTS/tree.c
new file mode 100644
index 0000000..b56a4df
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/tree.c
@@ -0,0 +1,110 @@
+/*
+ * tree.c
+ *
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1998, Anatoly A. Orehovsky
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dialog.h>
+
+unsigned char *names[] = {
+ "/",
+ "/dev",
+ "/dev/fd",
+ "/tmp",
+ "/usr",
+ "/var",
+ "/home",
+ "/stand",
+ "/stand/etc",
+ "/stand/en_US.ISO8859-1",
+ "/stand/info",
+ "/stand/info/bin",
+ "/stand/info/des",
+ "/stand/info/games",
+ "/stand/info/manpages",
+ "/stand/info/proflibs",
+ "/stand/info/dict",
+ "/stand/info/info",
+ "/stand/info/src",
+ "/etc",
+ "/etc/gnats",
+ "/etc/kerberosIV",
+ "/etc/mtree",
+ "/etc/namedb",
+ "/etc/ppp",
+ "/etc/uucp",
+ "/etc/sliphome",
+ "/proc",
+ "/lkm",
+ "/mnt",
+ "/root",
+ "/sbin",
+ "/bin",
+ 0
+};
+
+unsigned char *names1[] = {
+ "a",
+ "a:b",
+ "a:b:c",
+ "a:d"
+};
+
+int
+main(int argc, char **argv)
+{
+ int retval;
+ unsigned char *tresult;
+ char comstr[BUFSIZ];
+
+ init_dialog();
+ do {
+ use_helpline("Press OK for listing directory");
+ retval = dialog_tree(names,
+ sizeof(names)/sizeof(unsigned char *) - 1,
+ '/',
+ "tree dialog box example",
+ "Typical find -x / -type d output",
+ -1, -1, 15,
+ &tresult);
+
+ if (retval)
+ break;
+
+ use_helpline(NULL);
+ (void)snprintf(comstr, sizeof(comstr),
+ "ls -CF %s", tresult);
+
+ retval = dialog_prgbox(
+ comstr,
+ comstr, 20, 60, TRUE, TRUE);
+
+ dialog_clear();
+
+ retval = dialog_tree(names1,
+ sizeof(names1)/sizeof(unsigned char *),
+ ':',
+ "tree dialog box example",
+ "Other tree",
+ -1, -1, 5,
+ &tresult);
+ if (!retval)
+ {
+ dialog_clear();
+ }
+ } while (!retval);
+
+ dialog_update();
+
+ dialog_clear();
+
+ end_dialog();
+
+ exit(retval);
+}
diff --git a/gnu/lib/libdialog/TESTS/yesno.c b/gnu/lib/libdialog/TESTS/yesno.c
new file mode 100644
index 0000000..50b4dbe
--- /dev/null
+++ b/gnu/lib/libdialog/TESTS/yesno.c
@@ -0,0 +1,44 @@
+/*
+ * small test-driver for new dialog functionality
+ *
+ * Copyright (c) 1995, Jordan Hubbard
+ *
+ * All rights reserved.
+ *
+ * This source code may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of the software nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+/* Kick it off, James! */
+int
+main(int argc, char **argv)
+{
+ int rval1, rval2;
+
+ init_dialog();
+
+ rval1 = dialog_yesno("This is dialog_yesno() in action",
+ "Have you stopped deliberately putting bugs into your code?", -1, -1);
+ dialog_clear();
+ rval2 = dialog_noyes("This is dialog_noyes() in action",
+ "Have you stopped beating your wife?", -1, -1);
+ dialog_clear();
+ end_dialog();
+ fprintf(stderr, "returned value for dialog_yesno was %d\n", rval1);
+ fprintf(stderr, "returned value for dialog_noyes was %d\n", rval2);
+ return 0;
+}
diff --git a/gnu/lib/libdialog/TODO b/gnu/lib/libdialog/TODO
new file mode 100644
index 0000000..132a4a4
--- /dev/null
+++ b/gnu/lib/libdialog/TODO
@@ -0,0 +1,36 @@
+- cut off names in the listbox that are to long
+done 27Jan95
+ The current behaviour may not be desirable. When browsing through
+ long names these, when highlighted, will be shown with the first
+ characters cut off, when not highlighted the last characters will
+ be cut off.
+
+- look at behaviour of TAB key when browsing through directories.
+done 28Jan95
+
+- make sure the full name of the directory is written to the
+ "Directory:"-box
+done 28Jan95
+
+- mark current selections in listbox when initializing the listobject
+Idontknow
+- test and use Notify() when checking for error conditions
+ok
+- test overall
+- adapt color of buttons when changing focus to the button.
+done 28Jan95
+- add shade to dialog_fselect()-window
+done 29Jan95
+- add (nn%) indication to lists.
+done 30Jan95
+- add use_helpfile()
+done 13Feb95
+- add use_helpline()
+
+NOTE: apparently there is a bug (or a strange interaction between pkg_manage
+and dialog_textbox) in dialog_textbox. When I use this routine to display
+the helpfile in display_helpfile() the program gets mysterious segmentation
+faults and bus errors.
+I now use dialog_mesgbox, after I have read the file into a buffer.
+
+
diff --git a/gnu/lib/libdialog/checklist.c b/gnu/lib/libdialog/checklist.c
new file mode 100644
index 0000000..c696d47
--- /dev/null
+++ b/gnu/lib/libdialog/checklist.c
@@ -0,0 +1,636 @@
+/*
+ * checklist.c -- implements the checklist box
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * Substantial rennovation: 12/18/95, Jordan K. Hubbard
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <dialog.h>
+#include "dialog.priv.h"
+
+
+static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, dialogMenuItem *me, int list_width, int item_x, int check_x);
+
+#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL)
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ */
+int
+dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width,
+ int list_height, int cnt, void *it, unsigned char *result)
+{
+ int i, j, x, y, cur_x, cur_y, old_x, old_y, box_x, box_y, key = 0, button,
+ choice, l, k, scroll, max_choice, item_no = 0, *status;
+ int redraw_menu = FALSE, cursor_reset = FALSE;
+ int rval = 0, onlist = 1, ok_space, cancel_space;
+ char okButton, cancelButton;
+ WINDOW *dialog, *list;
+ unsigned char **items = NULL;
+ dialogMenuItem *ditems;
+ int list_width, check_x, item_x;
+
+ /* Allocate space for storing item on/off status */
+ if ((status = alloca(sizeof(int) * abs(cnt))) == NULL) {
+ endwin();
+ fprintf(stderr, "\nCan't allocate memory in dialog_checklist().\n");
+ exit(-1);
+ }
+
+draw:
+ choice = scroll = button = 0;
+ /* Previous calling syntax, e.g. just a list of strings? */
+ if (cnt >= 0) {
+ items = it;
+ ditems = NULL;
+ item_no = cnt;
+ /* Initializes status */
+ for (i = 0; i < item_no; i++)
+ status[i] = !strcasecmp(items[i*3 + 2], "on");
+ }
+ /* It's the new specification format - fake the rest of the code out */
+ else {
+ item_no = abs(cnt);
+ ditems = it;
+ if (!items)
+ items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *));
+
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
+ items[i*3] = ditems[i].prompt;
+ items[i*3 + 1] = ditems[i].title;
+ items[i*3 + 2] = status[i] ? "on" : "off";
+ }
+ }
+ max_choice = MIN(list_height, item_no);
+
+ check_x = 0;
+ item_x = 0;
+ /* Find length of longest item in order to center checklist */
+ for (i = 0; i < item_no; i++) {
+ l = strlen(items[i*3]);
+ for (j = 0; j < item_no; j++) {
+ k = strlen(items[j*3 + 1]);
+ check_x = MAX(check_x, l + k + 6);
+ }
+ item_x = MAX(item_x, l);
+ }
+ if (height < 0)
+ height = strheight(prompt)+list_height+4+2;
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i,j);
+ width = MAX(width,check_x+4)+4;
+ }
+ width = MAX(width,24);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = (COLS - width)/2;
+ y = (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width, y, x);
+ return -1;
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+ print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE);
+
+ list_width = width - 6;
+ getyx(dialog, cur_y, cur_x);
+ box_y = cur_y + 1;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1);
+ if (list == NULL) {
+ delwin(dialog);
+ endwin();
+ fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width,
+ y + box_y + 1, x + box_x + 1);
+ return -1;
+ }
+ keypad(list, TRUE);
+
+ /* draw a box around the list items */
+ draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + item_x + 6;
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++)
+ print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i), list_width, item_x, check_x);
+ wnoutrefresh(list);
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+
+ display_helpline(dialog, height - 1, width);
+
+ x = width / 2 - 11;
+ y = height - 2;
+ /* Is this a fancy new style argument string where we get to override
+ * the buttons, or an old style one where they're fixed?
+ */
+ if (ditems && result) {
+ cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]);
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE);
+ okButton = toupper(ditems[OK_BUTTON].prompt[0]);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE);
+ }
+ else {
+ cancelButton = 'C';
+ print_button(dialog, "Cancel", y, x + 14, FALSE);
+ okButton = 'O';
+ print_button(dialog, " OK ", y, x, TRUE);
+ }
+ wnoutrefresh(dialog);
+ wmove(list, choice, check_x+1);
+ wrefresh(list);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ /* Shortcut to OK? */
+ if (toupper(key) == okButton) {
+ if (ditems) {
+ if (result && ditems[OK_BUTTON].fire) {
+ int st;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ st = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]);
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ }
+ }
+ else if (result) {
+ *result = '\0';
+ for (i = 0; i < item_no; i++) {
+ if (status[i]) {
+ strcat(result, items[i*3]);
+ strcat(result, "\n");
+ }
+ }
+ }
+ rval = 0;
+ key = ESC; /* Lemme out! */
+ break;
+ }
+
+ /* Shortcut to cancel? */
+ if (toupper(key) == cancelButton) {
+ if (ditems && result && ditems[CANCEL_BUTTON].fire) {
+ int st;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ st = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]);
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ wmove(dialog, cur_y, cur_x);
+ }
+ delwin(save);
+ }
+ rval = 1;
+ key = ESC; /* I gotta go! */
+ break;
+ }
+
+ /* Check if key pressed matches first character of any item tag in list */
+ for (i = 0; i < max_choice; i++)
+ if (key != ' ' && key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0]))
+ break;
+
+ if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) ||
+ KEY_IS_UP(key) || KEY_IS_DOWN(key) || ((key == ' ' || key == '\n' ||
+ key == '\r') && onlist)) {
+
+ /* if moving from buttons to the list, reset and redraw buttons */
+ if (!onlist) {
+ onlist = 1;
+ button = 0;
+
+ if (ditems && result) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ }
+ wmove(list, choice, check_x+1);
+ wnoutrefresh(dialog);
+ wrefresh(list);
+ }
+
+ if (key >= '1' && key <= MIN('9', '0'+max_choice))
+ i = key - '1';
+
+ else if (KEY_IS_UP(key)) {
+ if (!choice) {
+ if (scroll) {
+ /* Scroll list down */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (list_height > 1) {
+ /* De-highlight current first item before scrolling down */
+ print_item(list, items[scroll * 3], items[scroll * 3 + 1], status[scroll], 0,
+ FALSE, DREF(ditems, scroll), list_width, item_x, check_x);
+ scrollok(list, TRUE);
+ wscrl(list, -1);
+ scrollok(list, FALSE);
+ }
+ scroll--;
+ print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
+ TRUE, DREF(ditems, scroll), list_width, item_x, check_x);
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+ wmove(list, choice, check_x+1);
+ wnoutrefresh(dialog);
+ wrefresh(list);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice - 1;
+ }
+ else if (KEY_IS_DOWN(key)) {
+ if (choice == max_choice - 1) {
+ if (scroll + choice < item_no - 1) {
+ /* Scroll list up */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (list_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item(list, items[(scroll + max_choice - 1) * 3],
+ items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1], max_choice - 1,
+ FALSE, DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
+ scrollok(list, TRUE);
+ scroll(list);
+ scrollok(list, FALSE);
+ }
+ scroll++;
+ print_item(list, items[(scroll + max_choice - 1) * 3],
+ items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1], max_choice - 1, TRUE,
+ DREF(ditems, scroll + max_choice - 1), list_width, item_x, check_x);
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+ wmove(list, choice, check_x+1);
+ wnoutrefresh(dialog);
+ wrefresh(list);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice + 1;
+ }
+ else if ((key == ' ' || key == '\n' || key == '\r') && onlist) { /* Toggle item status */
+ char lbra = 0, rbra = 0, mark = 0;
+
+ getyx(list, old_y, old_x); /* Save cursor position */
+
+ if (ditems) {
+ if (ditems[scroll + choice].fire) {
+ int st;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ st = ditems[scroll + choice].fire(&ditems[scroll + choice]); /* Call "fire" action */
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ if (st & DITEM_REDRAW) {
+ wclear(list);
+ for (i = 0; i < item_no; i++)
+ status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
+ for (i = 0; i < max_choice; i++) {
+ print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1],
+ status[scroll + i], i, i == choice, DREF(ditems, scroll + i), list_width, item_x, check_x);
+ }
+ wnoutrefresh(list);
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4,
+ cur_x, cur_y);
+ wrefresh(dialog);
+ }
+ if (st & DITEM_LEAVE_MENU) {
+ /* Allow a fire action to take us out of the menu */
+ key = ESC;
+ rval = 0;
+ break;
+ }
+ else if (st & DITEM_RECREATE) {
+ delwin(list);
+ delwin(dialog);
+ dialog_clear();
+ goto draw;
+ }
+ }
+ status[scroll + choice] = ditems[scroll + choice].checked ?
+ ditems[scroll + choice].checked(&ditems[scroll + choice]) : FALSE;
+ lbra = ditems[scroll + choice].lbra;
+ rbra = ditems[scroll + choice].rbra;
+ mark = ditems[scroll + choice].mark;
+ }
+ else
+ status[scroll + choice] = !status[scroll + choice];
+ wmove(list, choice, check_x);
+ wattrset(list, check_selected_attr);
+ if (!lbra)
+ lbra = '[';
+ if (!rbra)
+ rbra = ']';
+ if (!mark)
+ mark = 'X';
+ wprintw(list, "%c%c%c", lbra, status[scroll + choice] ? mark : ' ', rbra);
+ wmove(list, old_y, old_x); /* Restore cursor to previous position */
+ wrefresh(list);
+ continue; /* wait for another key press */
+ }
+
+ if (i != choice) {
+ /* De-highlight current item */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, FALSE, DREF(ditems, scroll + choice), list_width, item_x, check_x);
+
+ /* Highlight new item */
+ choice = i;
+ print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1], status[scroll + choice], choice, TRUE, DREF(ditems, scroll + choice), list_width, item_x, check_x);
+ wmove(list, choice, check_x+1); /* Restore cursor to previous position */
+ wrefresh(list);
+ }
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_PPAGE: /* can we go up? */
+ if (scroll > height - 4)
+ scroll -= (height-4);
+ else
+ scroll = 0;
+ redraw_menu = TRUE;
+ if (!onlist) {
+ onlist = 1;
+ button = 0;
+ }
+ break;
+
+ case KEY_NPAGE: /* can we go down a full page? */
+ if (scroll + list_height >= item_no-1 - list_height) {
+ scroll = item_no - list_height;
+ if (scroll < 0)
+ scroll = 0;
+ }
+ else
+ scroll += list_height;
+ redraw_menu = TRUE;
+ if (!onlist) {
+ onlist = 1;
+ button = 0;
+ }
+ break;
+
+ case KEY_HOME: /* go to the top */
+ scroll = 0;
+ choice = 0;
+ redraw_menu = TRUE;
+ cursor_reset = TRUE;
+ onlist = 1;
+ break;
+
+ case KEY_END: /* Go to the bottom */
+ scroll = item_no - list_height;
+ if (scroll < 0)
+ scroll = 0;
+ choice = max_choice - 1;
+ redraw_menu = TRUE;
+ cursor_reset = TRUE;
+ onlist = 1;
+ break;
+
+ case TAB:
+ case KEY_BTAB:
+ /* move to next component */
+ if (onlist) { /* on list, next is ok button */
+ onlist = 0;
+ if (ditems && result) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ ok_space = 1;
+ cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ ok_space = 3;
+ cancel_space = 15;
+ }
+ if (button)
+ wmove(dialog, y, x + cancel_space);
+ else
+ wmove(dialog, y, x + ok_space);
+ wrefresh(dialog);
+ break;
+ }
+ else if (button) { /* on cancel button, next is list */
+ button = 0;
+ onlist = 1;
+ redraw_menu = TRUE;
+ break;
+ }
+ /* on ok button, next is cancel button, same as left/right case */
+
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ onlist = 0;
+ button = !button;
+ if (ditems && result) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ ok_space = 1;
+ cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ ok_space = 3;
+ cancel_space = 15;
+ }
+ if (button)
+ wmove(dialog, y, x + cancel_space);
+ else
+ wmove(dialog, y, x + ok_space);
+ wrefresh(dialog);
+ break;
+
+ case ' ':
+ case '\n':
+ case '\r':
+ if (!onlist) {
+ if (ditems) {
+ if (result && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) {
+ int st;
+ WINDOW *save = dupwin(newscr);
+
+ st = ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]);
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ if (st == DITEM_FAILURE)
+ continue;
+ }
+ }
+ else if (result) {
+ *result = '\0';
+ for (i = 0; i < item_no; i++) {
+ if (status[i]) {
+ strcat(result, items[i*3]);
+ strcat(result, "\n");
+ }
+ }
+ }
+ rval = button;
+ key = ESC; /* Bail out! */
+ break;
+ }
+
+ /* Let me outta here! */
+ case ESC:
+ rval = -1;
+ break;
+
+ /* Help! */
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+
+ if (redraw_menu) {
+ getyx(list, old_y, old_x);
+ wclear(list);
+ for (i = 0; i < max_choice; i++)
+ print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i], i, i == choice, DREF(ditems, scroll + i), list_width, item_x, check_x);
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+
+ /* redraw buttons to fix highlighting */
+ if (ditems && result) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ }
+ wnoutrefresh(dialog);
+ if (cursor_reset) {
+ wmove(list, choice, check_x+1);
+ cursor_reset = FALSE;
+ }
+ else {
+ wmove(list, old_y, old_x);
+ }
+ wrefresh(list);
+ redraw_menu = FALSE;
+ }
+ }
+ delwin(list);
+ delwin(dialog);
+ return rval;
+}
+
+
+/*
+ * Print list item
+ */
+static void
+print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, dialogMenuItem *me, int list_width, int item_x, int check_x)
+{
+ int i;
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+ for (i = 0; i < list_width; i++)
+ waddch(win, ' ');
+ wmove(win, choice, check_x);
+ wattrset(win, selected ? check_selected_attr : check_attr);
+ wprintw(win, "%c%c%c", me && me->lbra ? me->lbra : '[',
+ status ? me && me->mark ? me->mark : 'X' : ' ',
+ me && me->rbra ? me->rbra : ']');
+ wattrset(win, menubox_attr);
+ waddch(win, ' ');
+ wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
+ waddch(win, tag[0]);
+ wattrset(win, selected ? tag_selected_attr : tag_attr);
+ waddstr(win, tag + 1);
+ wmove(win, choice, item_x);
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ waddstr(win, item);
+ /* If have a selection handler for this, call it */
+ if (me && me->selected) {
+ wrefresh(win);
+ me->selected(me, selected);
+ }
+}
+/* End of print_item() */
diff --git a/gnu/lib/libdialog/colors.h b/gnu/lib/libdialog/colors.h
new file mode 100644
index 0000000..7cea0a0
--- /dev/null
+++ b/gnu/lib/libdialog/colors.h
@@ -0,0 +1,219 @@
+/*
+ * colors.h -- color attribute definitions
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ */
+
+
+/*
+ * Default color definitions
+ *
+ * *_FG = foreground
+ * *_BG = background
+ * *_HL = highlight?
+ */
+#define SCREEN_FG COLOR_CYAN
+#define SCREEN_BG COLOR_BLUE
+#define SCREEN_HL TRUE
+
+#define SHADOW_FG COLOR_BLACK
+#define SHADOW_BG COLOR_BLACK
+#define SHADOW_HL TRUE
+
+#define DIALOG_FG COLOR_BLACK
+#define DIALOG_BG COLOR_WHITE
+#define DIALOG_HL FALSE
+
+#define TITLE_FG COLOR_YELLOW
+#define TITLE_BG COLOR_WHITE
+#define TITLE_HL TRUE
+
+#define BORDER_FG COLOR_WHITE
+#define BORDER_BG COLOR_WHITE
+#define BORDER_HL TRUE
+
+#define BUTTON_ACTIVE_FG COLOR_WHITE
+#define BUTTON_ACTIVE_BG COLOR_BLUE
+#define BUTTON_ACTIVE_HL TRUE
+
+#define BUTTON_INACTIVE_FG COLOR_BLACK
+#define BUTTON_INACTIVE_BG COLOR_WHITE
+#define BUTTON_INACTIVE_HL FALSE
+
+#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE
+#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE
+#define BUTTON_KEY_ACTIVE_HL TRUE
+
+#define BUTTON_KEY_INACTIVE_FG COLOR_RED
+#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE
+#define BUTTON_KEY_INACTIVE_HL FALSE
+
+#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW
+#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE
+#define BUTTON_LABEL_ACTIVE_HL TRUE
+
+#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK
+#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE
+#define BUTTON_LABEL_INACTIVE_HL TRUE
+
+#define INPUTBOX_FG COLOR_BLACK
+#define INPUTBOX_BG COLOR_WHITE
+#define INPUTBOX_HL FALSE
+
+#define INPUTBOX_BORDER_FG COLOR_BLACK
+#define INPUTBOX_BORDER_BG COLOR_WHITE
+#define INPUTBOX_BORDER_HL FALSE
+
+#define SEARCHBOX_FG COLOR_BLACK
+#define SEARCHBOX_BG COLOR_WHITE
+#define SEARCHBOX_HL FALSE
+
+#define SEARCHBOX_TITLE_FG COLOR_YELLOW
+#define SEARCHBOX_TITLE_BG COLOR_WHITE
+#define SEARCHBOX_TITLE_HL TRUE
+
+#define SEARCHBOX_BORDER_FG COLOR_WHITE
+#define SEARCHBOX_BORDER_BG COLOR_WHITE
+#define SEARCHBOX_BORDER_HL TRUE
+
+#define POSITION_INDICATOR_FG COLOR_YELLOW
+#define POSITION_INDICATOR_BG COLOR_WHITE
+#define POSITION_INDICATOR_HL TRUE
+
+#define MENUBOX_FG COLOR_BLACK
+#define MENUBOX_BG COLOR_WHITE
+#define MENUBOX_HL FALSE
+
+#define MENUBOX_BORDER_FG COLOR_WHITE
+#define MENUBOX_BORDER_BG COLOR_WHITE
+#define MENUBOX_BORDER_HL TRUE
+
+#define ITEM_FG COLOR_BLACK
+#define ITEM_BG COLOR_WHITE
+#define ITEM_HL FALSE
+
+#define ITEM_SELECTED_FG COLOR_WHITE
+#define ITEM_SELECTED_BG COLOR_BLUE
+#define ITEM_SELECTED_HL TRUE
+
+#define TAG_FG COLOR_YELLOW
+#define TAG_BG COLOR_WHITE
+#define TAG_HL TRUE
+
+#define TAG_SELECTED_FG COLOR_YELLOW
+#define TAG_SELECTED_BG COLOR_BLUE
+#define TAG_SELECTED_HL TRUE
+
+#define TAG_KEY_FG COLOR_RED
+#define TAG_KEY_BG COLOR_WHITE
+#define TAG_KEY_HL TRUE
+
+#define TAG_KEY_SELECTED_FG COLOR_RED
+#define TAG_KEY_SELECTED_BG COLOR_BLUE
+#define TAG_KEY_SELECTED_HL TRUE
+
+#define CHECK_FG COLOR_BLACK
+#define CHECK_BG COLOR_WHITE
+#define CHECK_HL FALSE
+
+#define CHECK_SELECTED_FG COLOR_WHITE
+#define CHECK_SELECTED_BG COLOR_BLUE
+#define CHECK_SELECTED_HL TRUE
+
+#define UARROW_FG COLOR_GREEN
+#define UARROW_BG COLOR_WHITE
+#define UARROW_HL TRUE
+
+#define DARROW_FG COLOR_GREEN
+#define DARROW_BG COLOR_WHITE
+#define DARROW_HL TRUE
+
+/* End of default color definitions */
+
+#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y)))
+#define COLOR_NAME_LEN 10
+#define COLOR_COUNT 8
+
+
+/*
+ * Global variables
+ */
+
+typedef struct {
+ unsigned char name[COLOR_NAME_LEN];
+ int value;
+} color_names_st;
+
+
+#ifdef __DIALOG_MAIN__
+
+/*
+ * For matching color names with color values
+ */
+color_names_st color_names[] = {
+ {"BLACK", COLOR_BLACK},
+ {"RED", COLOR_RED},
+ {"GREEN", COLOR_GREEN},
+ {"YELLOW", COLOR_YELLOW},
+ {"BLUE", COLOR_BLUE},
+ {"MAGENTA", COLOR_MAGENTA},
+ {"CYAN", COLOR_CYAN},
+ {"WHITE", COLOR_WHITE},
+}; /* color names */
+
+
+/*
+ * Table of color values
+ */
+int color_table[][3] = {
+ {SCREEN_FG, SCREEN_BG, SCREEN_HL },
+ {SHADOW_FG, SHADOW_BG, SHADOW_HL },
+ {DIALOG_FG, DIALOG_BG, DIALOG_HL },
+ {TITLE_FG, TITLE_BG, TITLE_HL },
+ {BORDER_FG, BORDER_BG, BORDER_HL },
+ {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL },
+ {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL },
+ {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL },
+ {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL },
+ {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL },
+ {BUTTON_LABEL_INACTIVE_FG,BUTTON_LABEL_INACTIVE_BG,BUTTON_LABEL_INACTIVE_HL},
+ {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL },
+ {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL },
+ {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL },
+ {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL },
+ {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL },
+ {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL },
+ {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL },
+ {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL },
+ {ITEM_FG, ITEM_BG, ITEM_HL },
+ {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL },
+ {TAG_FG, TAG_BG, TAG_HL },
+ {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL },
+ {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL },
+ {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL },
+ {CHECK_FG, CHECK_BG, CHECK_HL },
+ {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL },
+ {UARROW_FG, UARROW_BG, UARROW_HL },
+ {DARROW_FG, DARROW_BG, DARROW_HL },
+}; /* color_table */
+
+#else
+
+extern color_names_st color_names[];
+extern int color_table[][3];
+
+#endif /* __DIALOG_MAIN__ */
diff --git a/gnu/lib/libdialog/dialog.3 b/gnu/lib/libdialog/dialog.3
new file mode 100644
index 0000000..fee9232
--- /dev/null
+++ b/gnu/lib/libdialog/dialog.3
@@ -0,0 +1,777 @@
+.\"
+.\" Copyright (c) 1995, Jordan Hubbard
+.\"
+.\" All rights reserved.
+.\"
+.\" This manual page may be used, modified, copied, distributed, and
+.\" sold, in both source and binary form provided that the above
+.\" copyright and these terms are retained, verbatim, as the first
+.\" lines of this file. Under no circumstances is the author
+.\" responsible for the proper functioning of the software described herein
+.\" nor does the author assume any responsibility for damages incurred with
+.\" its use.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 1, 2000
+.Dt DIALOG 3
+.Os
+.Sh NAME
+.Nm draw_shadow ,
+.Nm draw_box ,
+.Nm line_edit ,
+.Nm strheight ,
+.Nm strwidth ,
+.Nm dialog_create_rc ,
+.Nm dialog_yesno ,
+.Nm dialog_noyes ,
+.Nm dialog_prgbox ,
+.Nm dialog_msgbox ,
+.Nm dialog_textbox ,
+.Nm dialog_menu ,
+.Nm dialog_checklist ,
+.Nm dialog_radiolist ,
+.Nm dialog_inputbox ,
+.Nm dialog_clear_norefresh ,
+.Nm dialog_clear ,
+.Nm dialog_update ,
+.Nm dialog_fselect ,
+.Nm dialog_notify ,
+.Nm dialog_mesgbox ,
+.Nm dialog_gauge ,
+.Nm init_dialog ,
+.Nm end_dialog ,
+.Nm use_helpfile ,
+.Nm use_helpline ,
+.Nm get_helpline ,
+.Nm restore_helpline ,
+.Nm dialog_ftree ,
+.Nm dialog_tree
+.Nd provide a simple ncurses-based GUI interface
+.Sh SYNOPSIS
+.In dialog.h
+.Ft "void"
+.Fn draw_shadow "WINDOW *win" "int y" "int x" "int height" "int width"
+.Ft "void"
+.Fn draw_box "WINDOW *win" "int y" "int x" "int height" "int width" "chtype box" "chtype border"
+.Ft "int"
+.Fo line_edit
+.Fa "WINDOW *dialog"
+.Fa "int box_y"
+.Fa "int box_x"
+.Fa "int flen"
+.Fa "int box_width"
+.Fa "chtype attr"
+.Fa "int first"
+.Fa "unsigned char *result"
+.Fa "int attr_mask"
+.Fc
+.Ft "int"
+.Fn strheight "const char *p"
+.Ft "int"
+.Fn strwidth "const char *p"
+.Ft "void"
+.Fn dialog_create_rc "unsigned char *filename"
+.Ft "int"
+.Fn dialog_yesno "unsigned char *title" "unsigned char *prompt" "int height" "int width"
+.Ft "int"
+.Fn dialog_noyes "unsigned char *title" "unsigned char *prompt" "int height" "int width"
+.Ft "int"
+.Fn dialog_prgbox "unsigned char *title" "const unsigned char *line" "int height" "int width" "int pause" "int use_shell"
+.Ft "int"
+.Fn dialog_textbox "unsigned char *title" "unsigned char *file" "int height" "int width"
+.Ft "int"
+.Fo dialog_menu
+.Fa "unsigned char *title"
+.Fa "unsigned char *prompt"
+.Fa "int height"
+.Fa "int width"
+.Fa "int menu_height"
+.Fa "int cnt"
+.Fa "void *it"
+.Fa "unsigned char *result"
+.Fa "int *ch"
+.Fa "int *sc"
+.Fc
+.Ft "int"
+.Fn dialog_checklist "unsigned char *title" "unsigned char *prompt" "int height" "int width" "int list_height" "int cnt" "void *it" "unsigned char *result"
+.Ft "int"
+.Fn dialog_radiolist "unsigned char *title" "unsigned char *prompt" "int height" "int width" "int list_height" "int cnt" "void *it" "unsigned char *result"
+.Ft "int"
+.Fn dialog_inputbox "unsigned char *title" "unsigned char *prompt" "int height" "int width" "unsigned char *result"
+.Ft "char *"
+.Fn dialog_fselect "char *dir" "char *fmask"
+.Ft "int"
+.Fn dialog_dselect "char *dir" "char *fmask"
+.Ft "void"
+.Fn dialog_notify "char *msg"
+.Ft "int"
+.Fn dialog_mesgbox "unsigned char *title" "unsigned char *prompt" "int height" "int width"
+.Ft "void"
+.Fn dialog_gauge "char *title" "char *prompt" "int y" "int x" "int height" "int width" "int perc"
+.Ft "void"
+.Fn use_helpfile "char *hfile"
+.Ft "void"
+.Fn use_helpline "char *hline"
+.Ft "char *"
+.Fn get_helpline "void"
+.Ft "void"
+.Fn dialog_clear_norefresh "void"
+.Ft "void"
+.Fn dialog_clear "void"
+.Ft "void"
+.Fn dialog_update "void"
+.Ft "void"
+.Fn init_dialog "void"
+.Ft "void"
+.Fn end_dialog "void"
+.Ft "int"
+.Fn dialog_ftree "unsigned char *filename" "unsigned char FS" "unsigned char *title" "unsigned char *prompt" "int height" "int width" "int menu_height" "unsigned char **result"
+.Ft "int"
+.Fo dialog_tree
+.Fa "unsigned char **names"
+.Fa "int size"
+.Fa "unsigned char FS"
+.Fa "unsigned char *title"
+.Fa "unsigned char *prompt"
+.Fa "int height"
+.Fa "int width"
+.Fa "int menu_height"
+.Fa "unsigned char **result"
+.Fc
+.Sh DESCRIPTION
+The dialog library attempts to provide a fairly simplistic set of
+fixed-presentation menus, input boxes, gauges, file requestors and
+other general purpose GUI (a bit of a stretch, since it uses
+ncurses) objects. Since the library also had its roots in a
+shell-script writer's utility (see the
+.Xr dialog 1
+command), the
+early API was somewhat primitively based on strings being passed in or
+out and parsed. This API was later extended to take either the
+original arguments or arrays of
+.Va dialogMenuItem
+structures,
+giving the user much more control over the internal behavior of each
+control. The
+.Va dialogMenuItem
+structure internals are public:
+.Bd -literal -offset indent
+typedef struct _dmenu_item {
+ char *prompt;
+ char *title;
+ int (*checked)(struct _dmenu_item *self);
+ int (*fire)(struct _dmenu_item *self);
+ int (*selected)(struct _dmenu_item *self, int is_selected);
+ void *data;
+ char lbra, mark, rbra;
+ long aux;
+} dialogMenuItem;
+.Ed
+.Pp
+The
+.Dv prompt
+and
+.Dv title
+strings are pretty much self-explanatory,
+and the
+.Va checked
+and
+.Va fire
+function pointers provide optional
+display and action hooks (the
+.Dv data
+variable being available for
+the convenience of those hooks) when more tightly coupled feedback between
+a menu object and user code is required. The
+.Va selected
+hook also
+allows you to verify whether or not a given item is selected (the cursor is
+over it) for implementing pretty much any possible context-sensitive
+behavior. A number of clever tricks for simulating various kinds of item
+types can also be done by adjusting the values of
+.Va lbra
+(default: '['),
+.Va mark
+(default: '*' for radio menus, 'X' for check menus)
+and
+.Va rbra
+(default: ']') and declaring a reasonable
+.Va checked
+hook,
+which should return TRUE for the
+.Dq marked
+state and FALSE for
+.Dq unmarked .
+The
+.Va aux
+field is not used internally, and is available for miscellaneous usage.
+If an item has a
+.Va fire
+hook associated with it, it will also be called
+whenever the item is "toggled" in some way and should return one of the
+following codes:
+.Bd -literal -offset 4n
+#define DITEM_SUCCESS 0 /* Successful completion */
+#define DITEM_FAILURE 1 /* Failed to "fire" */
+.Ed
+.Pp
+The following flags are in the upper 16 bits of return status:
+.Bd -literal -offset 4n
+#define DITEM_LEAVE_MENU (1 << 16)
+#define DITEM_REDRAW (1 << 17)
+#define DITEM_RECREATE (1 << 18)
+#define DITEM_RESTORE (1 << 19)
+#define DITEM_CONTINUE (1 << 20)
+.Ed
+.Pp
+Two special globals also exist for putting a dialog at any arbitrary
+X,Y location (the early designers rather short-sightedly made no provisions
+for this). If set to zero, the default centering behavior will be in
+effect.
+.Pp
+Below is a short description of the various functions:
+.Pp
+.Fn draw_shadow
+draws a shadow in curses window
+.Va win
+using the dimensions of
+.Va x , y , width
+and
+.Va height .
+.Pp
+.Fn draw_box
+draws a bordered box using the dimensions of
+.Va x , y , width
+and
+.Va height .
+The attributes from
+.Va box
+and
+.Va border
+are used, if specified, while painting the box and border regions of the
+object.
+.Pp
+.Fn line_edit
+invoke a simple line editor with an edit box of dimensions
+.Va box_x , box_y
+and
+.Va box_width .
+The field length is constrained by
+.Va flen ,
+starting at the
+.Va first
+character specified and
+optionally displayed with character attributes
+.Va attr .
+The string being edited is stored in
+.Va result .
+Returns 0 on success, 1 on Cancel, and -1 on failure or ESC.
+.Pp
+.Fn strheight
+returns the height of string in
+.Va p ,
+counting newlines.
+.Pp
+.Fn strwidth
+returns the width of string in
+.Va p ,
+counting newlines.
+.Pp
+.Fn dialog_create_rc
+dump dialog library settings into
+.Pa filename
+for later retrieval as defaults. Returns 0 on success, -1 on failure.
+.Pp
+.Fn dialog_yesno
+display a text box using
+.Va title
+and
+.Va prompt
+strings of dimensions
+.Va height
+and
+.Va width .
+Also paint a pair of
+.Em Yes
+and
+.Em \&No
+buttons at the bottom.
+The default selection is
+.Em Yes .
+If the
+.Em Yes
+button is chosen, return FALSE. If
+.Em \&No ,
+return TRUE.
+.Pp
+.Fn dialog_noyes
+is the same as
+.Fn dialog_yesno ,
+except the default selection is
+.Em \&No .
+.Pp
+.Fn dialog_prgbox
+display a text box of dimensions
+.Va height
+and
+.Va width
+containing the output of command
+.Va line .
+If
+.Va use_shell
+is TRUE,
+.Va line
+is passed as an argument to
+.Xr sh 1 ,
+otherwise it is simply passed to
+.Xr exec 3 .
+If
+.Va pause
+is TRUE, a final confirmation requestor will be put up when execution
+terminates. Returns 0 on success, -1 on failure.
+.Pp
+.Fn dialog_textbox
+display a text box containing the contents of
+.Va file
+with dimensions of
+.Va height
+and
+.Va width .
+.Pp
+.Fn dialog_menu
+display a menu of dimensions
+.Va height
+and
+.Va width
+with an optional internal menu height of
+.Va menu_height .
+The
+.Va cnt
+and
+.Va it
+arguments are of particular importance since they,
+together, determine which of the 2 available APIs to use. To use the
+older and traditional interface,
+.Va cnt
+should be a positive
+integer representing the number of string pointer pairs to find in
+.Va it
+(which should be of type
+.Ft char "**" ) ,
+the strings are
+expected to be in prompt and title order for each item and the
+.Va result
+parameter is expected to point to an array where the
+prompt string of the item selected will be copied. To use the newer
+interface,
+.Va cnt
+should be a
+.Va negative
+integer representing the number of
+.Va dialogMenuItem
+structures pointed to by
+.Va it
+(which should be of type
+.Vt dialogMenuItem "*" ) ,
+one structure per item. In the new interface, the
+.Va result
+variable is used as a simple boolean (not a pointer) and should be NULL if
+.Va it
+only points to menu items and the default OK and Cancel buttons are desired. If
+.Va result
+is non-NULL, then
+.Va it
+is actually expected to point 2 locations
+.Va past
+the start of the menu item list.
+.Va it
+is then expected to
+point to an item representing the Cancel button, from which the
+.Va prompt
+and
+.Va fire
+actions are used to override the default behavior, and
+.Va it
+to the same for the OK button.
+.Pp
+Using either API behavior, the
+.Va ch
+and
+.Va sc
+values may be passed in to preserve current
+item selection and scroll position values across calls.
+.Pp
+.Fn dialog_checklist
+display a menu of dimensions
+.Va height
+and
+.Va width
+with an
+optional internal menu height of
+.Va list_height .
+The
+.Va cnt
+and
+.Va it
+arguments are of particular importance since they,
+together, determine which of the 2 available APIs to use. To use the
+older and traditional interface,
+.Va cnt
+should be a positive
+integer representing the number of string pointer tuples to find in
+.Va it
+(which should be of type
+.Ft "char **" ) ,
+the strings are
+expected to be in prompt, title and state ("on" or "off") order for
+each item and the
+.Va result
+parameter is expected to point to an
+array where the prompt string of the item(s) selected will be
+copied. To use the newer interface,
+.Va cnt
+should be a
+.Em negative
+integer representing the number of
+.Ft dialogMenuItem
+structures pointed to by
+.Va it
+(which should be of type
+.Ft "dialogMenuItem *" ) ,
+one structure per item. In the new interface,
+the
+.Va result
+variable is used as a simple boolean (not a pointer)
+and should be NULL if
+.Va it
+only points to menu items and the default OK and Cancel
+buttons are desired. If
+.Va result
+is non-NULL, then
+.Va it
+is actually expected to
+point 2 locations
+.Va past
+the start of the menu item list.
+.Va it
+is then expected to point to an item representing the Cancel
+button, from which the
+.Va prompt
+and
+.Va fire
+actions are used to override the default behavior, and
+.Va it
+to the same for the OK button.
+.Pp
+In the standard API model, the menu supports the selection of multiple items,
+each of which is marked with an `X' character to denote selection. When
+the OK button is selected, the prompt values for all items selected are
+concatenated into the
+.Va result
+string.
+.Pp
+In the new API model, it is not actually necessary to preserve
+"checklist" semantics at all since practically everything about how
+each item is displayed or marked as "selected" is fully configurable.
+You could have a single checklist menu that actually contained a group
+of items with "radio" behavior, "checklist" behavior and standard menu
+item behavior. The only reason to call
+.Fn dialog_checklist
+over
+.Fn dialog_radiolist
+in the new API model is to inherit the base
+behavior, you're no longer constrained by it.
+.Pp
+Returns 0 on success, 1 on Cancel, and -1 on failure or ESC.
+.Pp
+.Fn dialog_radiolist
+display a menu of dimensions
+.Va height
+and
+.Va width
+with an
+optional internal menu height of
+.Va list_height .
+The
+.Va cnt
+and
+.Va it
+arguments are of particular importance since they,
+together, determine which of the 2 available APIs to use. To use the
+older and traditional interface,
+.Va cnt
+should be a positive
+integer representing the number of string pointer tuples to find in
+.Va it
+(which should be of type
+.Ft "char **" ) ,
+the strings are
+expected to be in prompt, title and state ("on" or "off") order for
+each item and the
+.Va result
+parameter is expected to point to an
+array where the prompt string of the item(s) selected will be
+copied. To use the newer interface,
+.Va cnt
+should be a
+.Dv negative
+integer representing the number of
+.Ft dialogMenuItem
+structures pointed to by
+.Va it
+(which should be of type
+.Ft "dialogMenuItem *" ,
+one structure per item. In the new interface,
+the
+.Va result
+variable is used as a simple boolean (not a pointer)
+and should be NULL if
+.Va it
+only points to menu items and the default OK and Cancel
+buttons are desired. If
+.Va result
+is non-NULL, then
+.Va it
+is actually expected to point 2 locations
+.Va past
+the start of the menu item list.
+.Va it
+is then expected to point to an item representing the Cancel
+button, from which the
+.Va prompt
+and
+.Va fire
+actions are used to override the default behavior, and
+.Va it
+does the same for the traditional OK button.
+.Pp
+In the standard API model, the menu supports the selection of only one
+of multiple items, the currently active item marked with an `*'
+character to denote selection. When the OK button is selected, the
+prompt value for this item is copied into the
+.Va result
+string.
+.Pp
+In the new API model, it is not actually necessary to preserve
+"radio button" semantics at all since practically everything about how
+each item is displayed or marked as "selected" is fully configurable.
+You could have a single radio menu that actually contained a group
+of items with "checklist" behavior, "radio" behavior and standard menu
+item behavior. The only reason to call
+.Fn dialog_radiolist
+over
+.Fn dialog_checklistlist
+in the new API model is to inherit the base
+behavior.
+.Pp
+Returns 0 on success, 1 on Cancel and -1 on failure or ESC.
+.Pp
+.Fn dialog_inputbox
+displays a single-line text input field in a box displaying
+.Va title
+and
+.Va prompt
+of dimensions
+.Va height
+and
+.Va width .
+The field entered is stored in
+.Va result .
+.Pp
+Returns 0 on success, -1 on failure or ESC.
+.Pp
+.Fn dialog_fselect
+brings up a file selector dialog starting at
+.Va dir
+and showing only those file names
+matching
+.Va fmask .
+.Pp
+Returns filename selected or NULL.
+.Pp
+.Fn dialog_dselect
+brings up a directory selector dialog starting at
+.Va dir
+and showing only those directory names
+matching
+.Va fmask .
+.Pp
+Returns directory name selected or NULL.
+.Pp
+.Fn dialog_notify
+brings up a generic "hey, you!" notifier dialog containing
+.Va msg .
+.Pp
+.Fn dialog_mesgbox
+like a notifier dialog, but with more control over
+.Va title ,
+.Va prompt ,
+.Va width
+and
+.Va height .
+This object will also wait for user confirmation, unlike
+.Fn dialog_notify .
+.Pp
+Returns 0 on success, -1 on failure.
+.Pp
+.Fn dialog_gauge
+displays a horizontal bar-graph style gauge. A value of
+.Em 100
+for
+.Em perc
+constitutes a full gauge, a value of
+.Em 0
+an empty one.
+.Pp
+.Fn use_helpfile
+for any menu supporting context sensitive help, invoke the text box
+object on this file whenever the
+.Em F1
+key is pressed.
+.Pp
+.Fn use_helpline
+displays this line of helpful text below any menu being displayed.
+.Pp
+.Fn get_helpline
+get the current value of the helpful text line.
+.Pp
+.Fn dialog_clear_norefresh
+clear the screen back to the dialog background color, but don't refresh the
+contents just yet.
+.Pp
+.Fn dialog_clear
+clear the screen back to the dialog background color immediately.
+.Pp
+.Fn dialog_update
+do any pending screen refreshes now.
+.Pp
+.Fn init_dialog
+initialize the dialog library (call this routine before any other dialog
+API calls).
+.Pp
+.Fn end_dialog
+shut down the dialog library (call this if you need to get back to sanity).
+.Pp
+.Fn dialog_ftree
+shows a tree described by the data from the file
+.Pa filename .
+The data in the file should look like
+.Xr find 1
+output.
+For the
+.Xr find 1
+output, the field separator
+.Va FS
+will be
+.Dq \&/ .
+If
+.Va height
+and
+.Va width
+are positive numbers, they set the absolute
+size of the whole
+.Fn dialog_ftree
+box. If
+.Va height
+and
+.Va width
+are negative numbers, the size of the
+.Fn dialog_ftree
+box will be calculated automatically.
+.Va menu_height
+sets the height of the tree subwindow inside the
+.Fn dialog_ftree
+box and must be set.
+.Va title
+is shown centered on the upper border of the
+.Fn dialog_ftree
+box.
+.Va prompt
+is shown inside the
+.Fn dialog_ftree
+box above the tree subwindow and can contain
+.Ql \e\&n
+to split lines. One can navigate in
+the tree by pressing UP/DOWN or
+.Sm off
+.So \&+ Sc \&/ So \&- Sc ,
+.Sm on
+PG_UP/PG_DOWN or
+.Sm off
+.So b Sc \&/SPACE
+.Sm on
+and
+HOME/END or
+.Sm off
+.So g Sc \&/ So G Sc .
+.Sm on
+A leaf of the
+tree is selected by pressing TAB or LEFT/RIGHT the OK
+button and pressing ENTER. filename may contain data like
+.Xr find 1
+output, as well as like the output of
+.Xr find 1
+with
+.Fl d
+option. Some of the transient paths to the leaves of the tree may
+be absent. Such data is corrected when fed from filename.
+.Pp
+The function returns 0 and a pointer to the selected leaf (to the path to
+the leaf from the root of the tree) into result, if the OK button was
+selected. The memory allocated for the building of the tree is freed on
+exiting
+.Fn dialog_ftree .
+The memory for the result line should be freed
+later manually, if necessary. If the Cancel button was selected, the
+function returns 1. In case of exiting
+.Fn dialog_ftree
+on ESC, the function returns -1.
+.Pp
+.Fn dialog_tree
+function returns the same results as
+.Fn dialog_ftree .
+If 0 is returned, result will contain a pointer from the array
+.Va names .
+.\" \fBdialog_tree\fR displays the tree very much like \fBdialog_ftree\fR does,
+.\" with some exceptions. The source data for the building of the tree is an
+.\" array \fBnames\fR of paths to the leaves (should be similar to \fBfind(1)\fR
+.\" output) of the size \fBsize\fR. However, there is no correction of data like
+.\" in \fBdialog_ftree\fR. Thus, to display a correct tree, the array must
+.\" already contain correct data. Besides, in each session every unique use of
+.\" \fBdialog_tree\fR is kept in memory, and later, when calling
+.\" \fBdialog_tree\fR with the same \fBnames\fR, \fBsize\fR, \fBFS\fR,
+.\" \fBheight\fR, \fBwidth\fR and \fBmenu_height\fR the position of the cursor
+.\" in the tree subwindow is restored.
+.Sh SEE ALSO
+.Xr dialog 1 ,
+.Xr ncurses 3
+.Sh AUTHORS
+The primary author would appear to be
+.An Savio Lam Aq lam836@cs.cuhk.hk
+with contributions over the years by
+.An Stuart Herbert Aq S.Herbert@sheffield.ac.uk ,
+.An Marc van Kempen Aq wmbfmk@urc.tue.nl ,
+.An Andrey Chernov Aq ache@FreeBSD.org ,
+.An Jordan Hubbard Aq jkh@FreeBSD.org
+and
+.An Anatoly A. Orehovsky Aq tolik@mpeks.tomsk.su .
+.Sh HISTORY
+These functions appeared in
+.Fx 2.0
+as the
+.Xr dialog 1
+command and were soon split into a separate library
+and command by
+.An Andrey Chernov .
+.An Marc van Kempen implemented most of the
+extra controls and objects,
+.An Jordan Hubbard
+added the dialogMenuItem renovations and this man page and
+.An Anatoly A. Orehovsky
+implemented
+.Fn dialog_ftree
+and
+.Fn dialog_tree .
+.Sh BUGS
+Sure!
diff --git a/gnu/lib/libdialog/dialog.h b/gnu/lib/libdialog/dialog.h
new file mode 100644
index 0000000..94675a4
--- /dev/null
+++ b/gnu/lib/libdialog/dialog.h
@@ -0,0 +1,211 @@
+#ifndef _DIALOG_H_INCLUDE
+#define _DIALOG_H_INCLUDE
+
+/*
+ * dialog.h -- common declarations for all dialog modules
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * Substantial rennovation: 12/18/95, Jordan K. Hubbard
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#define HAVE_NCURSES
+
+#ifdef HAVE_NCURSES
+#include <ncurses.h>
+
+#else
+
+#ifdef ultrix
+#include <cursesX.h>
+#else
+#include <curses.h>
+#endif
+
+#endif
+
+/* special return codes for `fire' actions */
+#define DITEM_STATUS(flag) ((flag) & 0x0000FFFF)
+#define DITEM_SUCCESS 0
+#define DITEM_FAILURE 1
+
+/* Flags - returned in upper 16 bits of return status */
+#define DITEM_LEAVE_MENU (1 << 16)
+#define DITEM_REDRAW (1 << 17)
+#define DITEM_RECREATE (1 << 18)
+#define DITEM_RESTORE (1 << 19)
+#define DITEM_CONTINUE (1 << 20)
+
+/* Attributes as used by entry fields right now */
+#define DITEM_NO_ECHO 0x0001
+
+
+/* negative offsets for buttons in item lists, if specified */
+#define OK_BUTTON -2
+#define CANCEL_BUTTON -1
+
+/* for use in describing more exotic behaviors */
+typedef struct _dmenu_item {
+ char *prompt;
+ char *title;
+ int (*checked)(struct _dmenu_item *self);
+ int (*fire)(struct _dmenu_item *self);
+ void (*selected)(struct _dmenu_item *self, int is_selected);
+ void *data;
+ char lbra, mark, rbra;
+ long aux;
+} dialogMenuItem;
+
+#define VERSION "0.4"
+#define MAX_LEN 2048
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+extern int DialogX, DialogY, DialogInputAttrs;
+
+/*
+ * Attribute names
+ */
+#define screen_attr attributes[0]
+#define shadow_attr attributes[1]
+#define dialog_attr attributes[2]
+#define title_attr attributes[3]
+#define border_attr attributes[4]
+#define button_active_attr attributes[5]
+#define button_inactive_attr attributes[6]
+#define button_key_active_attr attributes[7]
+#define button_key_inactive_attr attributes[8]
+#define button_label_active_attr attributes[9]
+#define button_label_inactive_attr attributes[10]
+#define inputbox_attr attributes[11]
+#define inputbox_border_attr attributes[12]
+#define searchbox_attr attributes[13]
+#define searchbox_title_attr attributes[14]
+#define searchbox_border_attr attributes[15]
+#define position_indicator_attr attributes[16]
+#define menubox_attr attributes[17]
+#define menubox_border_attr attributes[18]
+#define item_attr attributes[19]
+#define item_selected_attr attributes[20]
+#define tag_attr attributes[21]
+#define tag_selected_attr attributes[22]
+#define tag_key_attr attributes[23]
+#define tag_key_selected_attr attributes[24]
+#define check_attr attributes[25]
+#define check_selected_attr attributes[26]
+#define uarrow_attr attributes[27]
+#define darrow_attr attributes[28]
+
+/* number of attributes */
+#define ATTRIBUTE_COUNT 29
+
+extern chtype attributes[];
+
+#ifdef HAVE_NCURSES
+extern bool use_shadow;
+void draw_shadow(WINDOW *win, int y, int x, int height, int width);
+#endif
+void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border);
+int line_edit(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, chtype attrs, int first, unsigned char *result, int attr_mask);
+int strheight(const char *p);
+int strwidth(const char *p);
+
+void dialog_create_rc(unsigned char *filename);
+int dialog_yesno(unsigned char *title, unsigned char *prompt, int height, int width);
+int dialog_noyes(unsigned char *title, unsigned char *prompt, int height, int width);
+int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, int width, int pause, int use_shell);
+int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int width, int pause);
+int dialog_textbox(unsigned char *title, unsigned char *file, int height, int width);
+int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height,
+ int item_no, void *itptr, unsigned char *result, int *ch, int *sc);
+int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height,
+ int item_no, void *itptr, unsigned char *result);
+int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height,
+ int item_no, void *itptr, unsigned char *result);
+int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int width, unsigned char *result);
+void dialog_clear_norefresh(void);
+void dialog_clear(void);
+void dialog_update(void);
+void init_dialog(void);
+void end_dialog(void);
+
+/* Additions to libdialog */
+char *dialog_fselect(char *dir, char *fmask);
+int dialog_dselect(char *dir, char *fmask);
+void dialog_notify(char *msg);
+int dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int width);
+void use_helpfile(char *helpfile);
+void use_helpline(char *helpline);
+char *get_helpline(void);
+void restore_helpline(char *helpline);
+void dialog_gauge(char *title, char *prompt, int y, int x, int height, int width, int perc);
+
+/*
+ * Display a tree menu from file
+ *
+ * filename - file with like find(1) output
+ * FS - fields separator
+ * title - title of dialog box
+ * prompt - prompt text into dialog box
+ * height - height of dialog box
+ * width - width of dialog box
+ * menu_height - height of menu box
+ * result - pointer to char array
+ *
+ * return values:
+ * -1 - ESC pressed
+ * 0 - Ok, result set (must be freed later)
+ * 1 - Cancel
+ */
+int dialog_ftree(unsigned char *filename, unsigned char FS,
+ unsigned char *title, unsigned char *prompt,
+ int height, int width, int menu_height,
+ unsigned char **result);
+
+/*
+ * Display a tree menu from array
+ *
+ * names - array with like find(1) output
+ * size - size of array
+ * FS - fields separator
+ * title - title of dialog box
+ * prompt - prompt text into dialog box
+ * height - height of dialog box
+ * width - width of dialog box
+ * menu_height - height of menu box
+ * result - pointer to char array
+ *
+ * return values:
+ * -1 - ESC pressed
+ * 0 - Ok, result set
+ * 1 - Cancel
+ */
+
+int dialog_tree(unsigned char **names, int size, unsigned char FS,
+ unsigned char *title, unsigned char *prompt,
+ int height, int width, int menu_height,
+ unsigned char **result);
+
+#endif /* _DIALOG_H_INCLUDE */
diff --git a/gnu/lib/libdialog/dialog.priv.h b/gnu/lib/libdialog/dialog.priv.h
new file mode 100644
index 0000000..06c01a5
--- /dev/null
+++ b/gnu/lib/libdialog/dialog.priv.h
@@ -0,0 +1,183 @@
+/*
+ * dialog.h -- common declarations for all dialog modules
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+
+#if defined(LOCALE)
+#include <locale.h>
+#endif
+
+
+/*
+ * Change these if you want
+ */
+#define USE_SHADOW TRUE
+#define USE_COLORS TRUE
+
+#define ESC 27
+#define TAB 9
+#define BUF_SIZE (10*1024)
+
+#ifndef MIN
+#define MIN(x,y) (x < y ? x : y)
+#endif
+#ifndef MAX
+#define MAX(x,y) (x > y ? x : y)
+#endif
+
+#ifndef ctrl
+#define ctrl(a) ((a) - 'a' + 1)
+#endif
+
+#ifndef HAVE_NCURSES
+#ifndef ACS_ULCORNER
+#define ACS_ULCORNER '+'
+#endif
+#ifndef ACS_LLCORNER
+#define ACS_LLCORNER '+'
+#endif
+#ifndef ACS_URCORNER
+#define ACS_URCORNER '+'
+#endif
+#ifndef ACS_LRCORNER
+#define ACS_LRCORNER '+'
+#endif
+#ifndef ACS_HLINE
+#define ACS_HLINE '-'
+#endif
+#ifndef ACS_VLINE
+#define ACS_VLINE '|'
+#endif
+#ifndef ACS_LTEE
+#define ACS_LTEE '+'
+#endif
+#ifndef ACS_RTEE
+#define ACS_RTEE '+'
+#endif
+#ifndef ACS_UARROW
+#define ACS_UARROW '^'
+#endif
+#ifndef ACS_DARROW
+#define ACS_DARROW 'v'
+#endif
+#endif /* HAVE_NCURSES */
+
+/* Travel key conventions */
+#define KEY_IS_UP(key) ((key) == KEY_UP || (key) == '-' || key == '\020' /* ^P */)
+#define KEY_IS_DOWN(key) ((key) == KEY_DOWN || (key) == '+' || key == '\016' /* ^N */)
+
+/*
+ * Global variables
+ */
+#ifdef __DIALOG_MAIN__
+
+#ifdef HAVE_NCURSES
+
+/* use colors by default? */
+bool use_colors = USE_COLORS;
+
+/* shadow dialog boxes by default?
+ Note that 'use_shadow' implies 'use_colors' */
+bool use_shadow = USE_SHADOW;
+
+#endif
+
+
+/*
+ * Attribute values, default is for mono display
+ */
+chtype attributes[] = {
+ A_NORMAL, /* screen_attr */
+ A_NORMAL, /* shadow_attr */
+ A_REVERSE, /* dialog_attr */
+ A_REVERSE, /* title_attr */
+ A_REVERSE, /* border_attr */
+ A_BOLD, /* button_active_attr */
+ A_DIM, /* button_inactive_attr */
+ A_UNDERLINE, /* button_key_active_attr */
+ A_UNDERLINE, /* button_key_inactive_attr */
+ A_NORMAL, /* button_label_active_attr */
+ A_NORMAL, /* button_label_inactive_attr */
+ A_REVERSE, /* inputbox_attr */
+ A_REVERSE, /* inputbox_border_attr */
+ A_REVERSE, /* searchbox_attr */
+ A_REVERSE, /* searchbox_title_attr */
+ A_REVERSE, /* searchbox_border_attr */
+ A_REVERSE, /* position_indicator_attr */
+ A_REVERSE, /* menubox_attr */
+ A_REVERSE, /* menubox_border_attr */
+ A_REVERSE, /* item_attr */
+ A_NORMAL, /* item_selected_attr */
+ A_REVERSE, /* tag_attr */
+ A_REVERSE, /* tag_selected_attr */
+ A_NORMAL, /* tag_key_attr */
+ A_BOLD, /* tag_key_selected_attr */
+ A_REVERSE, /* check_attr */
+ A_REVERSE, /* check_selected_attr */
+ A_REVERSE, /* uarrow_attr */
+ A_REVERSE /* darrow_attr */
+};
+
+#else
+
+#ifdef HAVE_NCURSES
+extern bool use_colors;
+#endif
+
+#endif /* __DIALOG_MAIN__ */
+
+
+
+#ifdef HAVE_NCURSES
+
+/*
+ * Function prototypes
+ */
+#ifdef __DIALOG_MAIN__
+
+extern int parse_rc(void);
+
+#endif /* __DIALOG_MAIN__ */
+
+#endif
+
+
+#ifdef HAVE_NCURSES
+void color_setup(void);
+#endif
+
+void attr_clear(WINDOW *win, int height, int width, chtype attr);
+void print_autowrap(WINDOW *win, unsigned char *prompt, int height, int width, int maxwidth,
+ int y, int x, int center, int rawmode);
+void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected);
+FILE *raw_popen(const char *program, char * const *argv, const char *type);
+int raw_pclose(FILE *iop);
+void display_helpfile(void);
+void display_helpline(WINDOW *w, int y, int width);
+void print_arrows(WINDOW *dialog, int scroll, int menu_height, int item_no, int box_x,
+ int box_y, int tag_x, int cur_x, int cur_y);
+
diff --git a/gnu/lib/libdialog/dir.c b/gnu/lib/libdialog/dir.c
new file mode 100644
index 0000000..5348c2f
--- /dev/null
+++ b/gnu/lib/libdialog/dir.c
@@ -0,0 +1,549 @@
+/****************************************************************************
+ *
+ * Program: dir.c
+ * Author: Marc van Kempen
+ * desc: Directory routines, sorting and reading
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h> /* XXX for _POSIX_VERSION ifdefs */
+
+#if !defined sgi && !defined _POSIX_VERSION
+#include <sys/dir.h>
+#endif
+#if defined __sun__
+#include <sys/dirent.h>
+#endif
+#if defined sgi || defined _POSIX_VERSION
+#include <dirent.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fnmatch.h>
+#include <sys/param.h>
+#include "dir.h"
+
+/****************************************************************************
+ *
+ * local prototypes
+ *
+ ****************************************************************************/
+
+void toggle_dotfiles(void);
+int show_dotfiles(void);
+int dir_alphasort(const void *d1, const void *d2);
+int dir_sizesort(const void *d1, const void *d2);
+int dir_datesort(const void *d1, const void *d2);
+int dir_extsort(const void *d1, const void *d2);
+
+/****************************************************************************
+ *
+ * global variables
+ *
+ ****************************************************************************/
+
+
+/* This is user-selectable, I've set them fixed for now however */
+
+void *_sort_func = dir_alphasort;
+static int _showdotfiles = TRUE;
+
+/****************************************************************************
+ *
+ * Functions
+ *
+ ****************************************************************************/
+
+int
+dir_select_nd(
+#if defined __linux__
+ const struct dirent *d
+#else
+ struct dirent *d
+#endif
+)
+/*
+ * desc: allways include a directory entry <d>, except
+ * for the current directory and other dot-files
+ * keep '..' however.
+ * pre: <d> points to a dirent
+ * post: returns TRUE if d->d_name != "." else FALSE
+ */
+{
+ if (strcmp(d->d_name, ".")==0 ||
+ (d->d_name[0] == '.' && strlen(d->d_name) > 1 && d->d_name[1] != '.')) {
+ return(FALSE);
+ } else {
+ return(TRUE);
+ }
+}/* dir_select_nd() */
+
+
+int
+dir_select(
+#ifdef __linux__
+ const struct dirent *d
+#else
+ struct dirent *d
+#endif
+)
+/*
+ * desc: allways include a directory entry <d>, except
+ * for the current directory
+ * pre: <d> points to a dirent
+ * post: returns TRUE if d->d_name != "." else FALSE
+ */
+{
+ if (strcmp(d->d_name, ".")==0) { /* don't include the current directory */
+ return(FALSE);
+ } else {
+ return(TRUE);
+ }
+} /* dir_select() */
+
+int
+dir_select_root_nd(
+#ifdef __linux__
+ const struct dirent *d
+#else
+ struct dirent *d
+#endif
+)
+/*
+ * desc: allways include a directory entry <d>, except
+ * for the current directory and the parent directory.
+ * Also skip any other dot-files.
+ * pre: <d> points to a dirent
+ * post: returns TRUE if d->d_name[0] != "." else FALSE
+ */
+{
+ if (d->d_name[0] == '.') { /* don't include the current directory */
+ return(FALSE); /* nor the parent directory */
+ } else {
+ return(TRUE);
+ }
+} /* dir_select_root_nd() */
+
+
+int
+dir_select_root(
+#ifdef __linux__
+ const struct dirent *d
+#else
+ struct dirent *d
+#endif
+)
+/*
+ * desc: allways include a directory entry <d>, except
+ * for the current directory and the parent directory
+ * pre: <d> points to a dirent
+ * post: returns TRUE if d->d_name[0] != "." else FALSE
+ */
+{
+ if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) {
+ return(FALSE);
+ } else {
+ return(TRUE);
+ }
+}/* dir_select_root() */
+
+
+#ifdef NO_ALPHA_SORT
+int
+alphasort(const void *d1, const void *d2)
+/*
+ * desc: a replacement for what should be in the library
+ */
+{
+ return(strcmp(((struct dirent *) d1)->d_name,
+ ((struct dirent *) d2)->d_name));
+} /* alphasort() */
+#endif
+
+int
+dir_alphasort(const void *d1, const void *d2)
+/*
+ * desc: compare d1 and d2, but put directories always first
+ * put '..' always on top
+ *
+ */
+{
+ DirList *f1 = ((DirList *) d1),
+ *f2 = ((DirList *) d2);
+ struct stat *s1 = &(f1->filestatus);
+ struct stat *s2 = &(f2->filestatus);
+
+ /* check for '..' */
+ if (strcmp(((DirList *) d1)->filename, "..") == 0) {
+ return(-1);
+ }
+ if (strcmp(((DirList *) d2)->filename, "..") == 0) {
+ return(1);
+ }
+
+ /* put directories first */
+ if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
+ return(strcmp(f1->filename, f2->filename));
+ };
+ if (s1->st_mode & S_IFDIR) {
+ return(-1);
+ }
+ if (s2->st_mode & S_IFDIR) {
+ return(1);
+ }
+ return(strcmp(f1->filename, f2->filename));
+
+} /* dir_alphasort() */
+
+
+int
+dir_sizesort(const void *d1, const void *d2)
+/*
+ * desc: compare d1 and d2, but put directories always first
+ *
+ */
+{
+ DirList *f1 = ((DirList *) d1),
+ *f2 = ((DirList *) d2);
+ struct stat *s1 = &(f1->filestatus);
+ struct stat *s2 = &(f2->filestatus);
+
+ /* check for '..' */
+ if (strcmp(((DirList *) d1)->filename, "..") == 0) {
+ return(-1);
+ }
+ if (strcmp(((DirList *) d2)->filename, "..") == 0) {
+ return(1);
+ }
+
+ /* put directories first */
+ if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
+ return(s1->st_size < s2->st_size ?
+ -1
+ :
+ s1->st_size >= s2->st_size);
+ };
+ if (s1->st_mode & S_IFDIR) {
+ return(-1);
+ }
+ if (s2->st_mode & S_IFDIR) {
+ return(1);
+ }
+ return(s1->st_size < s2->st_size ?
+ -1
+ :
+ s1->st_size >= s2->st_size);
+
+} /* dir_sizesort() */
+
+int
+dir_datesort(const void *d1, const void *d2)
+/*
+ * desc: compare d1 and d2 on date, but put directories always first
+ */
+{
+ DirList *f1 = ((DirList *) d1),
+ *f2 = ((DirList *) d2);
+ struct stat *s1 = &(f1->filestatus);
+ struct stat *s2 = &(f2->filestatus);
+
+
+ /* check for '..' */
+ if (strcmp(((DirList *) d1)->filename, "..") == 0) {
+ return(-1);
+ }
+ if (strcmp(((DirList *) d2)->filename, "..") == 0) {
+ return(1);
+ }
+
+ /* put directories first */
+ if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
+ return(s1->st_mtime < s2->st_mtime ?
+ -1
+ :
+ s1->st_mtime >= s2->st_mtime);
+ };
+ if (s1->st_mode & S_IFDIR) {
+ return(-1);
+ }
+ if (s2->st_mode & S_IFDIR) {
+ return(1);
+ }
+ return(s1->st_mtime < s2->st_mtime ?
+ -1
+ :
+ s1->st_mtime >= s2->st_mtime);
+
+} /* dir_datesort() */
+
+
+int
+null_strcmp(char *s1, char *s2)
+/*
+ * desc: compare strings allowing NULL pointers
+ */
+{
+ if ((s1 == NULL) && (s2 == NULL)) {
+ return(0);
+ }
+ if (s1 == NULL) {
+ return(-1);
+ }
+ if (s2 == NULL) {
+ return(1);
+ }
+ return(strcmp(s1, s2));
+} /* null_strcmp() */
+
+
+int
+dir_extsort(const void *d1, const void *d2)
+/*
+ * desc: compare d1 and d2 on extension, but put directories always first
+ * extension = "the characters after the last dot in the filename"
+ * pre: d1 and d2 are pointers to DirList type records
+ * post: see code
+ */
+{
+ DirList *f1 = ((DirList *) d1),
+ *f2 = ((DirList *) d2);
+ struct stat *s1 = &(f1->filestatus);
+ struct stat *s2 = &(f2->filestatus);
+ char *ext1, *ext2;
+ int extf, ret;
+
+
+ /* check for '..' */
+ if (strcmp(((DirList *) d1)->filename, "..") == 0) {
+ return(-1);
+ }
+ if (strcmp(((DirList *) d2)->filename, "..") == 0) {
+ return(1);
+ }
+
+
+ /* find the first extension */
+
+ ext1 = f1->filename + strlen(f1->filename);
+ extf = FALSE;
+ while (!extf && (ext1 > f1->filename)) {
+ extf = (*--ext1 == '.');
+ }
+ if (!extf) {
+ ext1 = NULL;
+ } else {
+ ext1++;
+ }
+ /* ext1 == NULL if there's no "extension" else ext1 points */
+ /* to the first character of the extension string */
+
+ /* find the second extension */
+
+ ext2 = f2->filename + strlen(f2->filename);
+ extf = FALSE;
+ while (!extf && (ext2 > f2->filename)) {
+ extf = (*--ext2 == '.');
+ }
+ if (!extf) {
+ ext2 = NULL;
+ } else {
+ ext2++;
+ }
+ /* idem as for ext1 */
+
+ if ((s1->st_mode & S_IFDIR) && (s2->st_mode & S_IFDIR)) {
+ ret = null_strcmp(ext1, ext2);
+ if (ret == 0) {
+ return(strcmp(f1->filename, f2->filename));
+ } else {
+ return(ret);
+ }
+ };
+ if (s1->st_mode & S_IFDIR) {
+ return(-1);
+ }
+ if (s2->st_mode & S_IFDIR) {
+ return(1);
+ }
+ ret = null_strcmp(ext1, ext2);
+ if (ret == 0) {
+ return(strcmp(f1->filename, f2->filename));
+ } else {
+ return(ret);
+ }
+
+} /* dir_extsort() */
+
+
+void
+get_dir(char *dirname, char *fmask, DirList **dir, int *n)
+/*
+ * desc: get the files in the current directory
+ * pre: <dir> == NULL
+ * post: <dir> contains <n> dir-entries
+ */
+{
+ char cwd[MAXPATHLEN];
+ char buf[256];
+ struct dirent **dire;
+ struct stat status;
+ int i, j, nb;
+ long d;
+
+
+ getcwd(cwd, MAXPATHLEN);
+ if (strcmp(cwd, "/") == 0) { /* we are in the root directory */
+ if (show_dotfiles()) {
+ *n = scandir(dirname, &dire, dir_select_root, alphasort);
+ } else {
+ *n = scandir(dirname, &dire, dir_select_root_nd, alphasort);
+ }
+ } else {
+ if (show_dotfiles()) {
+ *n = scandir(dirname, &dire, dir_select, alphasort);
+ } else {
+ *n = scandir(dirname, &dire, dir_select_nd, alphasort);
+ }
+ }
+
+ /* There is the possibility that we have entered a directory */
+ /* which we are not allowed to read, scandir thus returning */
+ /* -1 for *n. */
+ /* Actually I should also check for lack of memory, but I'll */
+ /* let my application happily crash if this is the case */
+ /* Solution: */
+ /* manually insert the parent directory as the only */
+ /* directory entry, and return. */
+
+ if (*n == -1) {
+ *n = 1;
+ *dir = (DirList *) malloc(sizeof(DirList));
+ strcpy((*dir)[0].filename, "..");
+ lstat("..", &status);
+ (*dir)[0].filestatus = status;
+ (*dir)[0].link = FALSE;
+ return;
+ }
+
+ *dir = (DirList *) malloc( *n * sizeof(DirList) );
+ d = 0;
+ i = 0;
+ j = 0;
+ while (j<*n) {
+ lstat(dire[j]->d_name, &status);
+ /* check if this file is to be included */
+ /* always include directories, the rest is subject to fmask */
+ if (S_ISDIR(status.st_mode)
+ || fnmatch(fmask, dire[j]->d_name, FNM_NOESCAPE) != FNM_NOMATCH) {
+ strcpy((*dir)[i].filename, dire[j]->d_name);
+ (*dir)[i].filestatus = status;
+ if ((S_IFMT & status.st_mode) == S_IFLNK) { /* handle links */
+ (*dir)[i].link = TRUE;
+ stat(dire[j]->d_name, &status);
+ nb = readlink(dire[j]->d_name, buf, sizeof(buf) - 1);
+ if (nb == -1) {
+ printf("get_dir(): Error reading link: %s\n", dire[j]->d_name);
+ exit(-1);
+ } else {
+ (*dir)[i].linkname = malloc(sizeof(char) * nb + 1);
+ strncpy((*dir)[i].linkname, buf, nb);
+ (*dir)[i].linkname[nb] = 0;
+ }
+ (*dir)[i].filestatus = status;
+ } else {
+ (*dir)[i].link = FALSE;
+ (*dir)[i].linkname = NULL;
+ }
+ i++;
+ } else {
+ /* skip this entry */
+ }
+ j++;
+ }
+ *n = i;
+
+ /* sort the directory with the directory names on top */
+ qsort((*dir), *n, sizeof(DirList), _sort_func);
+
+ /* Free the allocated memory */
+ for (i=0; i<*n; i++) {
+ free(dire[i]);
+ }
+ free(dire);
+
+ return;
+}/* get_dir() */
+
+
+void
+FreeDir(DirList *d, int n)
+/*
+ * desc: free the dirlist d
+ * pre: d != NULL
+ * post: memory allocated to d has been released
+ */
+{
+ int i;
+
+ if (d) {
+ for (i=0; i<n; i++) {
+ if (d[i].linkname) {
+ free(d[i].linkname);
+ }
+ }
+ free(d);
+ } else {
+ printf("dir.c:FreeDir(): d == NULL\n");
+ exit(-1);
+ }
+
+ return;
+} /* FreeDir() */
+
+void
+toggle_dotfiles(void)
+/*
+ * desc: toggle visibility of dot-files
+ */
+{
+ _showdotfiles = !_showdotfiles;
+
+ return;
+} /* toggle_dotfiles() */
+
+int
+show_dotfiles(void)
+/*
+ * desc: return the value of _showdotfiles
+ */
+{
+ return(_showdotfiles);
+} /* show_dotfiles() */
+
+void
+set_dotfiles(int b)
+/*
+ * desc: set the value of _showdotfiles
+ */
+{
+ _showdotfiles = b;
+
+ return;
+} /* set_dotfiles() */
diff --git a/gnu/lib/libdialog/dir.h b/gnu/lib/libdialog/dir.h
new file mode 100644
index 0000000..eadc0c5
--- /dev/null
+++ b/gnu/lib/libdialog/dir.h
@@ -0,0 +1,38 @@
+/*
+ * include file for dir.c
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dirent.h>
+
+typedef struct DirList { /* structure to hold the directory entries */
+ char filename[MAXNAMLEN]; /* together with the stat-info per file */
+ struct stat filestatus; /* filename, or the name to which it points */
+ int link; /* is it a link ? */
+ char *linkname; /* the name of the file the link points to */
+} DirList;
+
+#ifndef TRUE
+#define TRUE (1)
+#endif
+#ifndef FALSE
+#define FALSE (0)
+#endif
+
+void get_dir(char *dirname, char *fmask, DirList **dir, int *n);
+void get_filenames(DirList *d, int n, char ***names, int *nf);
+void FreeDir(DirList *d, int n);
diff --git a/gnu/lib/libdialog/fselect.c b/gnu/lib/libdialog/fselect.c
new file mode 100644
index 0000000..6669edc
--- /dev/null
+++ b/gnu/lib/libdialog/fselect.c
@@ -0,0 +1,402 @@
+/*
+ * program: fselect.c
+ * author: Marc van Kempen (wmbfmk@urc.tue.nl)
+ * Desc: File selection routine
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <dialog.h>
+#include "ui_objects.h"
+#include "dir.h"
+#include "dialog.priv.h"
+
+/*
+ * Local prototypes
+ */
+
+char *dialog_dfselect(char *dir, char *fmask, int is_fselect);
+
+/*
+ * Functions
+ */
+
+void
+get_directories(DirList *d, int n, char ***names, int *nd)
+/*
+ * Desc: return the directorienames in <dir> as an array in
+ * <names>, the # of entries in <nd>, memory allocated
+ * to *names should be freed when done with it.
+ */
+{
+ int i;
+
+ /* count the directories, which are in front */
+ *nd = 0;
+ while ((*nd < n) && (S_ISDIR(d[*nd].filestatus.st_mode))) (*nd)++;
+ *names = (char **) malloc( *nd * sizeof(char *) );
+ for (i=0; i<*nd; i++) {
+ (*names)[i] = (char *) malloc( strlen(d[i].filename) + 1);
+ strcpy((*names)[i], d[i].filename);
+ }
+
+ return;
+} /* get_directories() */
+
+void
+get_filenames(DirList *d, int n, char ***names, int *nf)
+/*
+ * Desc: return the filenames in <dir> as an arry in
+ * <names>, the # of entries in <nf>, memory allocated
+ * to *names should be freed when done.
+ */
+{
+ int nd, i;
+
+ /* the # of regular files is the total # of files - # of directories */
+ /* count the # of directories */
+ nd = 0;
+ while ((nd < n) && (S_ISDIR(d[nd].filestatus.st_mode))) nd++;
+
+ *names = (char **) malloc( (n-nd) * sizeof(char *) );
+ *nf = n - nd;
+ for (i=0; i<*nf; i++) {
+ (*names)[i] = (char *) malloc( strlen(d[i+nd].filename) + 1);
+ strcpy((*names)[i], d[i+nd].filename);
+ }
+
+ return;
+} /* get_filenames() */
+
+void
+FreeNames(char **names, int n)
+/*
+ * Desc: free the space occupied by names
+ */
+{
+ int i;
+
+ /* free the space occupied by names */
+ for (i=0; i<n; i++) {
+ free(names[i]);
+ }
+ free(names);
+
+ return;
+} /* FreeNames() */
+
+int
+dialog_dselect_old(void)
+/*
+ * Desc: starting from the current directory,
+ * choose a new current directory
+ */
+{
+ DirList *d = NULL;
+ char **names, old_dir[MAXPATHLEN];
+ WINDOW *ds_win;
+ ButtonObj *okbut, *cancelbut;
+ ListObj *dirs_obj;
+ StringObj *dir_obj;
+ char o_dir[MAXPATHLEN];
+ struct ComposeObj *obj = NULL;
+ int n, nd, okbutton, cancelbutton,
+ quit, cancel, ret;
+
+ ds_win = newwin(LINES-8, COLS-30, 4, 15);
+ if (ds_win == NULL) {
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n",
+ LINES-8, COLS-30, 4, 15);
+ exit(1);
+ }
+ draw_box(ds_win, 0, 0, LINES-8, COLS-30, dialog_attr, border_attr);
+ wattrset(ds_win, dialog_attr);
+ mvwaddstr(ds_win, 0, (COLS-30)/2 - 9, " Directory Select ");
+ draw_shadow(stdscr, 4, 15, LINES-8, COLS-30);
+ display_helpline(ds_win, LINES-9, COLS-30);
+
+ /* the Directory string input field */
+ getcwd(o_dir, MAXPATHLEN);
+ dir_obj = NewStringObj(ds_win, "Directory:", o_dir, 1, 2, COLS-34, MAXPATHLEN-1);
+ AddObj(&obj, STRINGOBJ, (void *) dir_obj);
+
+ /* the list of directories */
+ get_dir(".", "*", &d, &n);
+ get_directories(d, n, &names, &nd);
+ dirs_obj = NewListObj(ds_win, "Directories:", names, o_dir, 5, 2,
+ LINES-15, COLS-48, nd);
+ AddObj(&obj, LISTOBJ, (void *) dirs_obj);
+
+ /* the Ok-button */
+ okbutton = FALSE;
+ okbut = NewButtonObj(ds_win, "Continue", &okbutton, 7, COLS-45);
+ AddObj(&obj, BUTTONOBJ, (void *) okbut);
+
+ /* the Cancel-button */
+ cancelbutton = FALSE;
+ cancelbut = NewButtonObj(ds_win, "Return", &cancelbutton, 11, COLS-44);
+ AddObj(&obj, BUTTONOBJ, (void *) cancelbut);
+
+ quit = FALSE;
+ cancel = FALSE;
+ strcpy(old_dir, o_dir);
+ while (!quit) {
+ ret = PollObj(&obj);
+ switch(ret) {
+ case SEL_BUTTON:
+ if (okbutton) {
+ quit = TRUE;
+ }
+ if (cancelbutton) {
+ quit = TRUE;
+ cancel = TRUE;
+ }
+ break;
+ case SEL_CR:
+ if (strcmp(old_dir, o_dir)) {
+ /* the directory was changed, cd into it */
+ if (chdir(o_dir)) {
+ dialog_notify("Could not change into directory");
+ strcpy(o_dir, old_dir);
+ } else {
+ getcwd(o_dir, MAXPATHLEN);
+ strcpy(old_dir, o_dir);
+ }
+ RefreshStringObj(dir_obj);
+ }
+ get_dir(".", "*", &d, &n);
+ FreeNames(names, nd);
+ get_directories(d, n, &names, &nd);
+ UpdateListObj(dirs_obj, names, nd);
+ if (((obj->prev)->obj == (void *) dirs_obj)) {
+ obj=obj->prev;
+ }
+ break;
+ case SEL_ESC:
+ quit = TRUE;
+ cancel = TRUE;
+ break;
+ case KEY_F(1):
+ display_helpfile();
+ break;
+ }
+ }
+
+ FreeNames(names, nd);
+ DelObj(obj);
+ delwin(ds_win);
+
+ return(cancel);
+
+} /* dialog_dselect() */
+
+int
+dialog_dselect(char *dir, char *fmask)
+/*
+ * Desc: Choose a directory
+ */
+{
+ if (dialog_dfselect(dir, fmask, FALSE)) {
+ return(FALSE); /* esc or cancel was pressed */
+ } else {
+ return(TRUE); /* directory was selected */
+ }
+} /* dialog_dselect() */
+
+char *
+dialog_fselect(char *dir, char *fmask)
+/*
+ * Desc: Choose a file from a directory
+ */
+{
+ return(dialog_dfselect(dir, fmask, TRUE));
+} /* dialog_fselect() */
+
+char *
+dialog_dfselect(char *dir, char *fmask, int is_fselect)
+/*
+ * Desc: choose a file from the directory <dir>, which
+ * initially display files with the mask <filemask>
+ * pre: <dir> is the initial directory
+ * only files corresponding to the mask <fmask> are displayed
+ * post: returns NULL if no file was selected
+ * else returns pointer to filename, space is allocated, should
+ * be freed after use.
+ */
+{
+ DirList *d = NULL;
+ char msg[512];
+ char **fnames, **dnames, *ret_name;
+ WINDOW *fs_win;
+ int n, nd, nf, ret;
+ StringObj *fm_obj, *dir_obj, *sel_obj;
+ char o_fm[255], o_dir[MAXPATHLEN], o_sel[MAXPATHLEN];
+ char old_fmask[255], old_dir[MAXPATHLEN];
+ ListObj *dirs_obj, *files_obj;
+ struct ComposeObj *obj = NULL, *o;
+ int quit, cancel;
+ ButtonObj *okbut_obj, *canbut_obj;
+ int ok_button, cancel_button;
+
+ if (chdir(dir)) {
+ sprintf(msg, "Could not move into specified directory: %s", dir);
+ dialog_notify(msg);
+ return(NULL);
+ }
+ getcwd(o_dir, MAXPATHLEN);
+
+ /* setup the fileselect-window and initialize its components */
+ fs_win = newwin(LINES-2, COLS-20, 1, 10);
+ if (fs_win == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n",
+ LINES-2, COLS-20, 2, 10);
+ exit(1);
+ }
+ draw_box(fs_win, 0, 0, LINES-2, COLS-20, dialog_attr, border_attr);
+ wattrset(fs_win, dialog_attr);
+ if (is_fselect) {
+ mvwaddstr(fs_win, 0, (COLS-20)/2 - 7, " File Select ");
+ } else {
+ mvwaddstr(fs_win, 0, (COLS-20)/2 - 9, " Directory Select ");
+ }
+ draw_shadow(stdscr, 1, 10, LINES-2, COLS-20);
+ display_helpline(fs_win, LINES-3, COLS-20);
+
+ /* Filemask entry */
+ strcpy(o_fm, fmask);
+ fm_obj = NewStringObj(fs_win, "Filemask:", o_fm, 1, 2, 19, 255);
+ AddObj(&obj, STRINGOBJ, (void *) fm_obj);
+
+ /* Directory entry */
+ dir_obj = NewStringObj(fs_win, "Directory:", o_dir, 1, 22, COLS-44, 255);
+ AddObj(&obj, STRINGOBJ, (void *) dir_obj);
+
+ /* Directory list */
+ get_dir(".", fmask, &d, &n); /* read the entire directory */
+ get_directories(d, n, &dnames, &nd); /* extract the dir-entries */
+ if (is_fselect) {
+ dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2,
+ LINES-16, (COLS-20)/2-2, nd);
+ } else {
+ dirs_obj = NewListObj(fs_win, "Directories:", dnames, o_dir, 5, 2,
+ LINES-12, (COLS-20)/2-2, nd);
+ }
+ AddObj(&obj, LISTOBJ, (void *) dirs_obj);
+
+ /* Filenames list */
+ get_filenames(d, n, &fnames, &nf); /* extract the filenames */
+ if (is_fselect) {
+ files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1,
+ LINES-16, (COLS-20)/2-3, nf);
+ } else {
+ files_obj = NewListObj(fs_win, "Files:", fnames, o_sel, 5, (COLS-20)/2+1,
+ LINES-12, (COLS-20)/2-3, nf);
+ }
+ AddObj(&obj, LISTOBJ, (void *) files_obj);
+
+ if (is_fselect) {
+ /* Selection entry */
+ o_sel[0] = '\0';
+ sel_obj = NewStringObj(fs_win, "Selection:", o_sel, LINES-10, 2, COLS-24, 255);
+ AddObj(&obj, STRINGOBJ, (void *) sel_obj);
+ }
+
+ /* Ok button */
+ ok_button = FALSE;
+ okbut_obj = NewButtonObj(fs_win, "Ok", &ok_button, LINES-6, 20);
+ AddObj(&obj, BUTTONOBJ, (void *) okbut_obj);
+
+ /* Cancel button */
+ cancel_button = FALSE;
+ canbut_obj = NewButtonObj(fs_win, "Cancel", &cancel_button, LINES-6, 30);
+ AddObj(&obj, BUTTONOBJ, (void *) canbut_obj);
+
+ /* Make sure all objects on the window are drawn */
+ wrefresh(fs_win);
+ keypad(fs_win, TRUE);
+
+ /* Start the reading */
+ o = obj;
+ strcpy(old_fmask, o_fm);
+ strcpy(old_dir, o_dir);
+ quit = FALSE;
+ cancel = FALSE;
+ while (!quit) {
+ ret = PollObj(&o);
+ switch(ret) {
+ case SEL_CR:
+ if (strcmp(old_fmask, o_fm) || strcmp(old_dir, o_dir)) {
+ /* reread directory and update the listobjects */
+ if (strcmp(old_dir, o_dir)) { /* dir entry was changed */
+ if (chdir(o_dir)) {
+ dialog_notify("Could not change into directory");
+ strcpy(o_dir, old_dir);
+ } else {
+ getcwd(o_dir, MAXPATHLEN);
+ strcpy(old_dir, o_dir);
+ }
+ RefreshStringObj(dir_obj);
+ } else { /* fmask entry was changed */
+ strcpy(old_fmask, o_fm);
+ }
+ get_dir(".", o_fm, &d, &n);
+ FreeNames(dnames, nd);
+ get_directories(d, n, &dnames, &nd);
+ UpdateListObj(dirs_obj, dnames, nd);
+ FreeNames(fnames, nf);
+ get_filenames(d, n, &fnames, &nf);
+ UpdateListObj(files_obj, fnames, nf);
+ if (((o->prev)->obj == (void *) dirs_obj)) {
+ o=o->prev;
+ }
+ }
+ break;
+ case SEL_BUTTON:
+ /* check which button was pressed */
+ if (ok_button) {
+ quit = TRUE;
+ }
+ if (cancel_button) {
+ quit = TRUE;
+ cancel = TRUE;
+ }
+ break;
+ case SEL_ESC:
+ quit = TRUE;
+ cancel = TRUE;
+ break;
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+ }
+ DelObj(obj);
+ FreeNames(dnames, nd);
+ FreeNames(fnames, nf);
+ delwin(fs_win);
+
+ if (cancel || (strlen(o_sel) == 0)) {
+ return(NULL);
+ } else {
+ ret_name = (char *) malloc( strlen(o_sel) + 1 );
+ strcpy(ret_name, o_sel);
+ return(ret_name);
+ }
+} /* dialog_fselect() */
+
diff --git a/gnu/lib/libdialog/gauge.c b/gnu/lib/libdialog/gauge.c
new file mode 100644
index 0000000..2fffcd3
--- /dev/null
+++ b/gnu/lib/libdialog/gauge.c
@@ -0,0 +1,78 @@
+/*
+ * gauge.c
+ *
+ * progress indicator for libdialog
+ *
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+#include "dialog.h"
+
+void
+dialog_gauge(char *title, char *prompt, int y, int x,
+ int height, int width, int perc)
+/*
+ * Desc: display a progress bar, progress indicated by <perc>
+ */
+{
+ WINDOW *gw;
+ int glen, i;
+ char percs[5];
+
+ gw = newwin(height, width, y, x);
+ if (!gw) {
+ fprintf(stderr, "dialog_gauge: Error creating window (%d, %d, %d, %d)",
+ height, width, y, x);
+ exit(-1);
+ }
+
+ draw_box(gw, 0, 0, height, width, dialog_attr, border_attr);
+ draw_shadow(stdscr, y, x, height, width);
+
+ wattrset(gw, title_attr);
+ if (title) {
+ wmove(gw, 0, (width - strlen(title))/2 - 1);
+ waddstr(gw, "[ ");
+ waddstr(gw, title);
+ waddstr(gw, " ]");
+ }
+ wattrset(gw, dialog_attr);
+ if (prompt) {
+ wmove(gw, 1, (width - strlen(prompt))/2 - 1);
+ waddstr(gw, prompt);
+ }
+
+ draw_box(gw, 2, 2, 3, width-4, dialog_attr, border_attr);
+ glen = (int) ((float) perc/100 * (width-6));
+
+ wattrset(gw, dialog_attr);
+ sprintf(percs, "%3d%%", perc);
+ wmove(gw, 5, width/2 - 2);
+ waddstr(gw, percs);
+
+ wattrset(gw, A_BOLD);
+ wmove(gw, 3, 3);
+ for (i=0; i<glen; i++) waddch(gw, ' ');
+
+ wrefresh(gw);
+ delwin(gw);
+
+ return;
+} /* dialog_gauge() */
+
diff --git a/gnu/lib/libdialog/help.c b/gnu/lib/libdialog/help.c
new file mode 100644
index 0000000..de49c6a
--- /dev/null
+++ b/gnu/lib/libdialog/help.c
@@ -0,0 +1,194 @@
+/***************************************************************
+ *
+ * Program: help.c
+ * Author: Marc van Kempen
+ * Desc: get help
+ *
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ ***************************************************************/
+
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <dialog.h>
+
+static char _helpfilebuf[MAXPATHLEN];
+static char _helplinebuf[77]; /* limit the helpline to 76 characters */
+static char *_helpfile = NULL;
+static char *_helpline = NULL;
+
+/******************************************************************
+ *
+ * helpfile routines
+ *
+ ******************************************************************/
+
+void
+use_helpfile(char *hfile)
+/*
+ * desc: set the helpfile to be opened on pressing F1 to <helpfile>
+ */
+{
+ if (hfile != NULL) {
+ _helpfile = _helpfilebuf;
+ strcpy(_helpfile, hfile);
+ } else {
+ _helpfile = NULL;
+ }
+
+ return;
+} /* use_helpfile() */
+
+void
+display_helpfile(void)
+/*
+ * desc: display the current helpfile in a window
+ */
+{
+ WINDOW *w;
+ FILE *f;
+ struct stat sb;
+ char msg[80], *buf;
+ static int in_help = FALSE;
+ char *savehline = NULL;
+
+ if (in_help) return; /* dont call help when you're in help */
+
+ if (_helpfile != NULL) {
+ if ((w = dupwin(newscr)) == NULL) {
+ dialog_notify("No memory to dup previous screen\n");
+ return;
+ }
+ if ((f = fopen(_helpfile, "r")) == NULL) {
+ sprintf(msg, "Can't open helpfile : %s\n", _helpfile);
+ dialog_notify(msg);
+ return;
+ }
+ if (fstat(fileno(f), &sb)) {
+ sprintf(msg, "Can't stat helpfile : %s\n", _helpfile);
+ dialog_notify(msg);
+ return;
+ }
+ if ((buf = (char *) malloc( sb.st_size )) == NULL) {
+ sprintf(msg, "Could not malloc space for helpfile : %s\n", _helpfile);
+ dialog_notify(msg);
+ return;
+ }
+ if (fread(buf, 1, sb.st_size, f) != sb.st_size) {
+ sprintf(msg, "Could not read entire help file : %s", _helpfile);
+ dialog_notify(msg);
+ free(buf);
+ return;
+ }
+ buf[sb.st_size] = 0;
+ in_help = TRUE;
+ savehline = get_helpline();
+ use_helpline("Use arrowkeys, PgUp, PgDn, Home and End to move through text");
+ dialog_mesgbox("Online help", buf, LINES-4, COLS-4);
+ restore_helpline(savehline);
+ in_help = FALSE;
+ touchwin(w);
+ wrefresh(w);
+ delwin(w);
+ free(buf);
+ } else {
+ /* do nothing */
+ }
+
+ return;
+} /* display_helpfile() */
+
+
+/******************************************************************
+ *
+ * helpline routines
+ *
+ ******************************************************************/
+
+void
+use_helpline(char *hline)
+/*
+ * desc: set the helpline to printed in dialogs
+ */
+{
+ if (hline) {
+ _helpline = _helplinebuf;
+ if (strlen(hline) > 76) {
+ /* only display the first 76 characters in the helpline */
+ strncpy(_helpline, hline, 76);
+ _helpline[76] = 0;
+ } else {
+ strcpy(_helpline, hline);
+ }
+ } else {
+ _helpline = NULL;
+ }
+
+ return;
+} /* use_helpline() */
+
+void
+display_helpline(WINDOW *w, int y, int width)
+/*
+ * desc: display the helpline at the given coordinates <y, x> in the window <w>
+ */
+{
+ if (_helpline != NULL) {
+ if (strlen(_helpline) > width - 6) {
+ _helpline[width - 6] = 0;
+ }
+ wmove(w, y, (int) (width - strlen(_helpline)- 4) / 2);
+ wattrset(w, title_attr);
+ waddstr(w, "[ ");
+ waddstr(w, _helpline);
+ waddstr(w, " ]");
+ } else {
+ /* do nothing */
+ }
+
+ return;
+}
+
+char *
+get_helpline(void)
+/*
+ * desc: allocate new space, copy the helpline to it and return a pointer to it
+ */
+{
+ char *hlp;
+
+ if (_helpline) {
+ hlp = (char *) malloc( strlen(_helpline) + 1 );
+ strcpy(hlp, _helpline);
+ } else {
+ hlp = NULL;
+ }
+
+ return(hlp);
+} /* get_helpline() */
+
+void
+restore_helpline(char *helpline)
+/*
+ * Desc: set the helpline to <helpline> and free the space allocated to it
+ */
+{
+ use_helpline(helpline);
+ free(helpline);
+
+ return;
+} /* restore_helpline() */
diff --git a/gnu/lib/libdialog/inputbox.c b/gnu/lib/libdialog/inputbox.c
new file mode 100644
index 0000000..1f61ed5
--- /dev/null
+++ b/gnu/lib/libdialog/inputbox.c
@@ -0,0 +1,190 @@
+/*
+ * inputbox.c -- implements the input box
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 <dialog.h>
+#include "dialog.priv.h"
+
+
+/*
+ * Display a dialog box for inputing a string
+ */
+int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int width, unsigned char *result)
+{
+ int i, j, x, y, box_y, box_x, box_width, first,
+ key = 0, button = -1;
+ unsigned char instr[MAX_LEN+1];
+ WINDOW *dialog;
+
+ if (height < 0)
+ height = strheight(prompt)+2+4;
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i,j) + 4;
+ }
+ width = MAX(width,24);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = DialogX ? DialogX : (COLS - width)/2;
+ y = DialogY ? DialogY : (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
+ exit(1);
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+ print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE);
+
+ /* Draw the input field box */
+ box_width = width-6;
+ getyx(dialog, y, x);
+ box_y = y + 2;
+ box_x = (width - box_width)/2;
+ draw_box(dialog, y+1, box_x-1, 3, box_width+2, border_attr, dialog_attr);
+
+ display_helpline(dialog, height-1, width);
+
+ x = width/2-11;
+ y = height-2;
+ print_button(dialog, "Cancel", y, x+14, FALSE);
+ print_button(dialog, " OK ", y, x, TRUE);
+
+ first = 1;
+ strcpy(instr, result);
+ wattrset(dialog, dialog_attr);
+
+ while (key != ESC) {
+
+ if (button == -1) { /* Input box selected */
+ key = line_edit(dialog, box_y, box_x, -1, box_width, inputbox_attr, first, instr, DialogInputAttrs);
+ first = 0;
+ }
+ else
+ key = wgetch(dialog);
+
+ switch (key) {
+ case 'O':
+ case 'o':
+ delwin(dialog);
+ strcpy(result, instr);
+ return 0;
+ case 'C':
+ case 'c':
+ delwin(dialog);
+ return 1;
+ case KEY_UP:
+ case KEY_LEFT:
+ case KEY_BTAB:
+ switch (button) {
+ case -1:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_button(dialog, " OK ", y, x, FALSE);
+ print_button(dialog, "Cancel", y, x+14, TRUE);
+ wrefresh(dialog);
+ break;
+ case 0:
+ button = -1; /* Indicates input box is selected */
+ print_button(dialog, "Cancel", y, x+14, FALSE);
+ print_button(dialog, " OK ", y, x, TRUE);
+ break;
+ case 1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_button(dialog, "Cancel", y, x+14, FALSE);
+ print_button(dialog, " OK ", y, x, TRUE);
+ wrefresh(dialog);
+ break;
+ }
+ break;
+ case TAB:
+ case KEY_DOWN:
+ case KEY_RIGHT:
+ switch (button) {
+ case -1:
+ button = 0; /* Indicates "OK" button is selected */
+ print_button(dialog, "Cancel", y, x+14, FALSE);
+ print_button(dialog, " OK ", y, x, TRUE);
+ wrefresh(dialog);
+ break;
+ case 0:
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_button(dialog, " OK ", y, x, FALSE);
+ print_button(dialog, "Cancel", y, x+14, TRUE);
+ wrefresh(dialog);
+ break;
+ case 1:
+ button = -1; /* Indicates input box is selected */
+ print_button(dialog, "Cancel", y, x+14, FALSE);
+ print_button(dialog, " OK ", y, x, TRUE);
+ break;
+ }
+ break;
+ case ' ':
+ case '\n':
+ case '\r':
+ delwin(dialog);
+ if (button < 1)
+ strcpy(result, instr);
+ return (button == -1 ? 0 : button);
+ case ESC:
+ break;
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+ }
+
+ delwin(dialog);
+ return -1; /* ESC pressed */
+}
+/* End of dialog_inputbox() */
diff --git a/gnu/lib/libdialog/kernel.c b/gnu/lib/libdialog/kernel.c
new file mode 100644
index 0000000..c30e478
--- /dev/null
+++ b/gnu/lib/libdialog/kernel.c
@@ -0,0 +1,527 @@
+/*
+ * dialog - Display simple dialog boxes from shell scripts
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ *
+ * HISTORY:
+ *
+ * 17/12/93 - Version 0.1 released.
+ *
+ * 19/12/93 - menu will now scroll if there are more items than can fit
+ * on the screen.
+ * - added 'checklist', a dialog box with a list of options that
+ * can be turned on or off. A list of options that are on is
+ * returned on exit.
+ *
+ * 20/12/93 - Version 0.15 released.
+ *
+ * 29/12/93 - Incorporated patch from Patrick J. Volkerding
+ * (volkerdi@mhd1.moorhead.msus.edu) that made these changes:
+ * - increased MAX_LEN to 2048
+ * - added 'infobox', equivalent to a message box without pausing
+ * - added option '--clear' that will clear the screen
+ * - Explicit line breaking when printing prompt text can be
+ * invoked by real newline '\n' besides the string "\n"
+ * - an optional parameter '--title <string>' can be used to
+ * specify a title string for the dialog box
+ *
+ * 03/01/94 - added 'textbox', a dialog box for displaying text from a file.
+ * - Version 0.2 released.
+ *
+ * 04/01/94 - some fixes and improvements for 'textbox':
+ * - fixed a bug that will cause a segmentation violation when a
+ * line is longer than MAX_LEN characters. Lines will now be
+ * truncated if they are longer than MAX_LEN characters.
+ * - removed wrefresh() from print_line(). This will increase
+ * efficiency of print_page() which calls print_line().
+ * - display current position in the form of percentage into file.
+ * - Version 0.21 released.
+ *
+ * 05/01/94 - some changes for faster screen update.
+ *
+ * 07/01/94 - much more flexible color settings. Can use all 16 colors
+ * (8 normal, 8 highlight) of the Linux console.
+ *
+ * 08/01/94 - added run-time configuration using configuration file.
+ *
+ * 09/01/94 - some minor bug fixes and cleanups for menubox, checklist and
+ * textbox.
+ *
+ * 11/01/94 - added a man page.
+ *
+ * 13/01/94 - some changes for easier porting to other Unix systems (tested
+ * on Ultrix, SunOS and HPUX)
+ * - Version 0.3 released.
+ *
+ * 08/06/94 - Patches by Stuart Herbert - S.Herbert@shef.ac.uk
+ * Fixed attr_clear and the textbox stuff to work with ncurses 1.8.5
+ * Fixed the wordwrap routine - it'll actually wrap properly now
+ * Added a more 3D look to everything - having your own rc file could
+ * prove 'interesting' to say the least :-)
+ * Added radiolist option
+ * - Version 0.4 released.
+ */
+
+#define __DIALOG_MAIN__
+
+#include <dialog.h>
+#include "dialog.priv.h"
+#ifdef HAVE_NCURSES
+#include "colors.h"
+#endif
+
+/* These are two "secret" globals that can be fiddled to make a dialog
+ * come up someplace other than a "centered" calculation for X,Y
+ */
+int DialogX, DialogY;
+
+/* This "secret" global allows you to change the behavior of an input field */
+int DialogInputAttrs;
+
+/*
+ * Do some initialization for dialog
+ */
+void init_dialog(void)
+{
+#if defined(LOCALE)
+ (void) setlocale(LC_ALL, "");
+#endif
+
+#ifdef HAVE_NCURSES
+ if (parse_rc() == -1) /* Read the configuration file */
+ exit(-1);
+#endif
+
+ if (initscr() == NULL) { /* Init curses */
+ fprintf(stderr, "\nCurses initialization error.\n");
+ exit(-1);
+ }
+ keypad(stdscr, TRUE);
+ cbreak();
+ noecho();
+
+#ifdef HAVE_NCURSES
+ if (use_colors || use_shadow) /* Set up colors */
+ color_setup();
+#endif
+
+ /* Set screen to screen attribute */
+ dialog_clear_norefresh();
+ DialogX = DialogY = 0;
+}
+/* End of init_dialog() */
+
+
+#ifdef HAVE_NCURSES
+/*
+ * Setup for color display
+ */
+void color_setup(void)
+{
+ int i;
+
+ if (has_colors()) { /* Terminal supports color? */
+ start_color();
+
+ /* Initialize color pairs */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ init_pair(i+1, color_table[i][0], color_table[i][1]);
+
+ /* Setup color attributes */
+ for (i = 0; i < ATTRIBUTE_COUNT; i++)
+ attributes[i] = C_ATTR(color_table[i][2], i+1);
+ }
+}
+/* End of color_setup() */
+#endif
+
+
+/*
+ * Set window to attribute 'attr'
+ */
+void attr_clear(WINDOW *win, int height, int width, chtype attr)
+{
+ int i, j;
+
+ wattrset(win, attr); /* Set window to attribute 'attr' */
+ for (i = 0; i < height; i++) {
+ wmove(win, i, 0);
+ for (j = 0; j < width; j++)
+ waddch(win, ' ');
+ }
+}
+/* End of attr_clear() */
+
+
+/*
+ * Print a string of text in a window, automatically wrap around to the
+ * next line if the string is too long to fit on one line. Note that the
+ * string may contain "\n" to represent a newline character or the real
+ * newline '\n', but in that case, auto wrap around will be disabled.
+ */
+void print_autowrap(WINDOW *win, unsigned char *prompt, int height, int width, int maxwidth, int y, int x, int center, int rawmode)
+{
+ int cur_x, cur_y, i;
+ unsigned char tempstr[MAX_LEN+1], *word, *tempptr, *tempptr1;
+ chtype ostuff[132], attrs = 0, init_bottom = 0;
+
+ wsetscrreg(win, y, height);
+ getyx(win, cur_y, cur_x);
+
+ strncpy(tempstr, prompt, MAX_LEN);
+ tempstr[MAX_LEN] = '\0';
+ if ((!rawmode && strstr(tempstr, "\\n") != NULL) ||
+ (strchr(tempstr, '\n') != NULL)) { /* Prompt contains "\n" or '\n' */
+ word = tempstr;
+ while (1) {
+ tempptr = rawmode ? NULL : strstr(word, "\\n");
+ tempptr1 = strchr(word, '\n');
+ if (tempptr == NULL && tempptr1 == NULL)
+ break;
+ else if (tempptr == NULL) { /* No more "\n" */
+ tempptr = tempptr1;
+ tempptr[0] = '\0';
+ }
+ else if (tempptr1 == NULL) { /* No more '\n' */
+ tempptr[0] = '\0';
+ tempptr++;
+ }
+ else { /* Prompt contains both "\n" and '\n' */
+ if (strlen(tempptr)-2 < strlen(tempptr1)-1) {
+ tempptr = tempptr1;
+ tempptr[0] = '\0';
+ }
+ else {
+ tempptr[0] = '\0';
+ tempptr++;
+ }
+ }
+
+ waddstr(win, word);
+ word = tempptr + 1;
+ if (++cur_y > height) {
+ cur_y--;
+ if (!init_bottom) {
+ for (i = 0; i < x; i++)
+ ostuff[i] = mvwinch(win, cur_y, i);
+ for (i = width; i < maxwidth; i++)
+ ostuff[i] = mvwinch(win, cur_y, i);
+ attrs = getattrs(win);
+ init_bottom = 1;
+ }
+ scrollok(win, TRUE);
+ scroll(win);
+ scrollok(win, FALSE);
+ wmove(win, cur_y, 0);
+ for (i = 0; i < x; i++) {
+ wattrset(win, ostuff[i]&A_ATTRIBUTES);
+ waddch(win, ostuff[i]);
+ }
+ wattrset(win, attrs);
+ for ( ; i < width; i++)
+ waddch(win, ' ');
+ for ( ; i < maxwidth; i++) {
+ wattrset(win, ostuff[i]&A_ATTRIBUTES);
+ waddch(win, ostuff[i]);
+ }
+ wattrset(win, attrs);
+ wrefresh(win);
+ }
+ wmove(win, cur_y, cur_x = x);
+ }
+ waddstr(win, word);
+ }
+ else if (center && strlen(tempstr) <= width-x*2) { /* If prompt is short */
+ wmove(win, cur_y, (width - strlen(tempstr)) / 2);
+ waddstr(win, tempstr);
+ }
+ else if (!center && strlen(tempstr) <= width-cur_x) { /* If prompt is short */
+ waddstr(win, tempstr);
+ }
+ else {
+ char *p = tempstr;
+
+ /* Print prompt word by word, wrap around if necessary */
+ while ((word = strsep(&p, "\t\n ")) != NULL) {
+ int loop;
+ unsigned char sc;
+
+ if (*word == '\0')
+ continue;
+ do {
+ loop = 0;
+ if (cur_x+strlen(word) >= width+1) { /* wrap around to next line */
+ if (x+strlen(word) >= width+1) {
+ sc = word[width-cur_x-1];
+ word[width-cur_x-1] = '\0';
+ wmove(win, cur_y, cur_x);
+ waddstr(win, word);
+ word[width-cur_x-1] = sc;
+ word += width-cur_x-1;
+ getyx(win, cur_y, cur_x);
+ loop = 1;
+ }
+ cur_y++;
+ cur_x = x;
+ if (cur_y > height) {
+ cur_y--;
+ if (!init_bottom) {
+ for (i = 0; i < x; i++)
+ ostuff[i] = mvwinch(win, cur_y, i);
+ for (i = width; i < maxwidth; i++)
+ ostuff[i] = mvwinch(win, cur_y, i);
+ attrs = getattrs(win);
+ init_bottom = 1;
+ }
+ scrollok(win, TRUE);
+ scroll(win);
+ scrollok(win, FALSE);
+ wmove(win, cur_y, 0);
+ for (i = 0; i < x; i++) {
+ wattrset(win, ostuff[i]&A_ATTRIBUTES);
+ waddch(win, ostuff[i]);
+ }
+ wattrset(win, attrs);
+ for ( ; i < width; i++)
+ waddch(win, ' ');
+ for ( ; i < maxwidth; i++) {
+ wattrset(win, ostuff[i]&A_ATTRIBUTES);
+ waddch(win, ostuff[i]);
+ }
+ wattrset(win, attrs);
+ wrefresh(win);
+ }
+ }
+ }
+ while(loop);
+ wmove(win, cur_y, cur_x);
+ waddstr(win, word);
+ getyx(win, cur_y, cur_x);
+ cur_x++;
+ }
+ }
+}
+/* End of print_autowrap() */
+
+
+/*
+ * Print a button
+ */
+void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected)
+{
+ int i, temp;
+
+ wmove(win, y, x);
+ wattrset(win, selected ? button_active_attr : button_inactive_attr);
+ waddstr(win, selected ? "[" : " ");
+ temp = strspn(label, " ");
+ label += temp;
+ for (i = 0; i < temp; i++)
+ waddch(win, ' ');
+ wattrset(win, selected ? button_key_active_attr : button_key_inactive_attr);
+ waddch(win, label[0]);
+ wattrset(win, selected ? button_active_attr : button_inactive_attr);
+ waddstr(win, label+1);
+ waddstr(win, selected ? "]" : " ");
+ wmove(win, y, x+temp+1);
+}
+/* End of print_button() */
+
+
+/*
+ * Draw a rectangular box with line drawing characters
+ */
+void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border)
+{
+ int i, j;
+
+ wattrset(win, 0);
+ for (i = 0; i < height; i++) {
+ wmove(win, y + i, x);
+ for (j = 0; j < width; j++)
+ if (!i && !j)
+ waddch(win, border | ACS_ULCORNER);
+ else if (i == height-1 && !j)
+ waddch(win, border | ACS_LLCORNER);
+ else if (!i && j == width-1)
+ waddch(win, box | ACS_URCORNER);
+ else if (i == height-1 && j == width-1)
+ waddch(win, box | ACS_LRCORNER);
+ else if (!i)
+ waddch(win, border | ACS_HLINE);
+ else if (i == height-1)
+ waddch(win, box | ACS_HLINE);
+ else if (!j)
+ waddch(win, border | ACS_VLINE);
+ else if (j == width-1)
+ waddch(win, box | ACS_VLINE);
+ else
+ waddch(win, box | ' ');
+ }
+}
+/* End of draw_box() */
+
+
+#ifdef HAVE_NCURSES
+/*
+ * Draw shadows along the right and bottom edge to give a more 3D look
+ * to the boxes
+ */
+void draw_shadow(WINDOW *win, int y, int x, int height, int width)
+{
+ int i,sx,sy;
+ chtype attrs;
+
+ if (has_colors()) { /* Whether terminal supports color? */
+ getbegyx(win,sy,sx);
+ attrs = getattrs(win);
+ if (y+height < getmaxy(win)) {
+ /* small touch */
+ wattrset(win, A_INVIS);
+ wmove(win, y + height, x + 2);
+ for (i = 0; i < width; i++)
+ if (i+x+2 < getmaxx(win))
+ waddch(win, ' ');
+ /* end touch */
+ wattrset(win, shadow_attr);
+ wmove(win, y + height, x + 2);
+ for (i = 0; i < width; i++)
+ if (i+x+2 < getmaxx(win))
+ waddch(win, mvwinch(newscr, sy+y+height, sx+x+2+i) & A_CHARTEXT);
+ }
+ if (x+width < getmaxx(win)) {
+ for (i = y + 1; i < y + height + 1; i++) {
+ if (i < getmaxy(win)) {
+ /* small touch */
+ wattrset(win, A_INVIS);
+ wmove(win, i, x + width);
+ waddch(win, ' ');
+ if (x+width+1 < getmaxx(win))
+ waddch(win, ' ');
+ /* end touch */
+ wattrset(win, shadow_attr);
+ wmove(win, i, x + width);
+ waddch(win, mvwinch(newscr, sy+i, sx+x+width) & A_CHARTEXT);
+ if (x+width+1 < getmaxx(win))
+ waddch(win, mvwinch(newscr, sy+i, sx+x+width+1) & A_CHARTEXT);
+ }
+ }
+ }
+ wattrset(win, attrs);
+ wnoutrefresh(win);
+ }
+}
+/* End of draw_shadow() */
+#endif
+
+void dialog_clear_norefresh(void)
+{
+ attr_clear(stdscr, LINES, COLS, screen_attr);
+ touchwin(stdscr);
+ wnoutrefresh(stdscr);
+}
+
+void dialog_clear(void)
+{
+ dialog_clear_norefresh();
+ doupdate();
+}
+
+void dialog_update(void)
+{
+ refresh();
+}
+
+void end_dialog(void)
+{
+ endwin();
+}
+
+int strwidth(const char *p)
+{
+ int i = 0, len, incr;
+ const char *start, *s, *s1, *s2;
+
+ for (start = s = p; ; start = (s += incr)) {
+ s1 = strchr(s, '\n');
+ s2 = strstr(s, "\\n");
+ if (s2 == NULL)
+ s = s1;
+ else if (s1 == NULL)
+ s = s2;
+ else
+ s = MIN(s1, s2);
+ if (s == NULL)
+ break;
+ incr = 1 + (s == s2);
+ len = s - start;
+ if (len > i)
+ i = len;
+ }
+ len = strlen(start);
+ if (len > i)
+ i = len;
+ return i;
+}
+
+int strheight(const char *p)
+{
+ int i = 1, incr;
+ const char *s, *s1, *s2;
+
+ for (s = p; ; s += incr) {
+ s1 = strchr(s, '\n');
+ s2 = strstr(s, "\\n");
+ if (s2 == NULL)
+ s = s1;
+ else if (s1 == NULL)
+ s = s2;
+ else
+ s = MIN(s1, s2);
+ if (s == NULL)
+ break;
+ incr = 1 + (s == s2);
+ i++;
+ }
+ return i;
+}
+
+void print_arrows(WINDOW *dialog, int scroll, int menu_height, int item_no,
+ int box_x, int box_y, int tag_x, int cur_x, int cur_y)
+{
+ wmove(dialog, box_y, box_x + tag_x + 1);
+ wattrset(dialog, scroll ? uarrow_attr : menubox_attr);
+ waddch(dialog, scroll ? ACS_UARROW : ACS_HLINE);
+ wmove(dialog, box_y, box_x + tag_x + 2);
+ waddch(dialog, scroll ? '(' : ACS_HLINE);
+ wmove(dialog, box_y, box_x + tag_x + 3);
+ waddch(dialog, scroll ? '-' : ACS_HLINE);
+ wmove(dialog, box_y, box_x + tag_x + 4);
+ waddch(dialog, scroll ? ')' : ACS_HLINE);
+ wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 1);
+ wattrset(dialog, scroll+menu_height < item_no ? darrow_attr : menubox_border_attr);
+ waddch(dialog, scroll+menu_height < item_no ? ACS_DARROW : ACS_HLINE);
+ wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 2);
+ waddch(dialog, scroll+menu_height < item_no ? '(' : ACS_HLINE);
+ wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 3);
+ waddch(dialog, scroll+menu_height < item_no ? '+' : ACS_HLINE);
+ wmove(dialog, box_y + menu_height + 1, box_x + tag_x + 4);
+ waddch(dialog, scroll+menu_height < item_no ? ')' : ACS_HLINE);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+}
+
diff --git a/gnu/lib/libdialog/lineedit.c b/gnu/lib/libdialog/lineedit.c
new file mode 100644
index 0000000..7bfe0e0
--- /dev/null
+++ b/gnu/lib/libdialog/lineedit.c
@@ -0,0 +1,213 @@
+/*
+ * Changes Copyright (C) 1995 by Andrey A. Chernov, Moscow
+ *
+ * Original Copyright:
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 <dialog.h>
+#include "dialog.priv.h"
+
+static void redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit, int attr_mask);
+
+/*
+ * Line editor
+ */
+int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, chtype attr, int first, unsigned char *result, int attr_mask)
+{
+ int i, key;
+ chtype old_attr;
+ static int input_x, scroll;
+ static unsigned char instr[MAX_LEN+1];
+ unsigned char erase_char = erasechar();
+ unsigned char kill_char = killchar();
+#ifdef notyet
+ unsignec char werase_char = cur_term->Ottyb.c_cc[VWERASE];
+#endif
+
+ old_attr = getattrs(dialog);
+ keypad(dialog, TRUE);
+
+ if (first) {
+ memset(instr, 0, sizeof(instr));
+ strcpy(instr, result);
+ i = strlen(instr);
+/* input_x = i % box_width;*/
+ input_x = (i > box_width) ? box_width - 1 : i;
+/* scroll = i - input_x;*/
+ scroll = (i > box_width) ? i - box_width + 1: 0;
+ }
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+
+ for (;;) {
+ wattrset(dialog, attr);
+ wrefresh(dialog);
+ key = wgetch(dialog);
+ switch (key) {
+ case ctrl('q'):
+ goto ret;
+ break;
+ case KEY_F(1):
+ display_helpfile();
+ break;
+ case TAB:
+ case KEY_BTAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ case ESC:
+ case '\r':
+ case '\n':
+ for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--)
+ instr[i] = '\0';
+ if (key == '\r')
+ key = '\n';
+ goto ret;
+ case '\025':
+ case '\030':
+ kill_it:
+ input_x = scroll = 0;
+ /* fall through */
+ case '\013':
+ case KEY_EOL:
+ memset(instr + scroll + input_x, '\0', sizeof(instr) - scroll - input_x);
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ continue;
+ case '\001':
+ case KEY_HOME:
+ input_x = scroll = 0;
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ continue;
+ case '\005':
+ case KEY_END:
+ for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--)
+ instr[i] = '\0';
+ i++;
+ input_x = i % box_width;
+ scroll = i - input_x;
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ continue;
+ case '\002':
+ case KEY_LEFT:
+ if (input_x || scroll) {
+ if (!input_x) {
+ int oldscroll = scroll;
+ scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1);
+ input_x = oldscroll - 1 - scroll;
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ } else {
+ input_x--;
+ wmove(dialog, box_y, input_x + box_x);
+ }
+ } else
+ beep();
+ continue;
+ case '\006':
+ case KEY_RIGHT:
+ if ( scroll+input_x < MAX_LEN
+ && (flen < 0 || scroll+input_x < flen)
+ ) {
+ if (!instr[scroll+input_x])
+ instr[scroll+input_x] = ' ';
+ if (input_x == box_width-1) {
+ scroll++;
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ }
+ else {
+ wmove(dialog, box_y, input_x + box_x);
+ waddch(dialog, instr[scroll+input_x]);
+ input_x++;
+ }
+ } else
+ beep(); /* Alarm user about overflow */
+ continue;
+ case '\b':
+ case '\177':
+ case KEY_BACKSPACE:
+ erase_it:
+ if (input_x || scroll) {
+ i = strlen(instr);
+ memmove(instr+scroll+input_x-1, instr+scroll+input_x, i-(scroll+input_x)+1);
+ if (!input_x) {
+ int oldscroll = scroll;
+ scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1);
+ input_x = oldscroll - 1 - scroll;
+ } else
+ input_x--;
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ } else
+ beep();
+ continue;
+ case '\004':
+ case KEY_DC:
+ for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--)
+ instr[i] = '\0';
+ i++;
+ if (i == 0) {
+ beep();
+ continue;
+ }
+ memmove(instr+scroll+input_x, instr+scroll+input_x+1, i-(scroll+input_x));
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ continue;
+ default:
+ if (CCEQ(key, erase_char))
+ goto erase_it;
+ if (CCEQ(key, kill_char))
+ goto kill_it;
+ if (key < 0x100 && isprint(key)) {
+ for (i = strlen(instr) - 1; i >= scroll + input_x && instr[i] == ' '; i--)
+ instr[i] = '\0';
+ i++;
+ if (i < MAX_LEN && (flen < 0 || scroll+input_x < flen)) {
+ if (flen < 0 || i < flen)
+ memmove(instr+scroll+input_x+1, instr+scroll+input_x, i-(scroll+input_x));
+ instr[scroll+input_x] = key;
+ if (input_x == box_width-1 && (flen < 0 || i < flen))
+ scroll++;
+ else
+ input_x++;
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
+ } else
+ beep(); /* Alarm user about overflow */
+ continue;
+ }
+ }
+ }
+ret:
+ redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, TRUE, attr_mask);
+ wrefresh(dialog);
+ strcpy(result, instr);
+ return key;
+}
+
+static void
+redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit, int attr_mask)
+{
+ int i, fix_len;
+
+ wattrset(dialog, fexit ? old_attr : attr);
+ wmove(dialog, box_y, box_x);
+ fix_len = flen >= 0 ? MIN(flen-scroll,box_width) : box_width;
+ for (i = 0; i < fix_len; i++)
+ waddch(dialog, instr[scroll+i] ? ((attr_mask & DITEM_NO_ECHO) ? '*' : instr[scroll+i]) : ' ');
+ wattrset(dialog, old_attr);
+ for ( ; i < box_width; i++)
+ waddch(dialog, instr[scroll+i] ? ((attr_mask & DITEM_NO_ECHO) ? '*' : instr[scroll+i]) : ' ');
+ wmove(dialog, box_y, input_x + box_x);
+}
diff --git a/gnu/lib/libdialog/menubox.c b/gnu/lib/libdialog/menubox.c
new file mode 100644
index 0000000..0f4cd00
--- /dev/null
+++ b/gnu/lib/libdialog/menubox.c
@@ -0,0 +1,467 @@
+/*
+ * menubox.c -- implements the menu box
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * Substantial rennovation: 12/18/95, Jordan K. Hubbard
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <dialog.h>
+#include "dialog.priv.h"
+#include <ncurses.h>
+
+static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected, dialogMenuItem *me, int menu_width, int tag_x, int item_x);
+
+#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL)
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+int
+dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int cnt, void *it, unsigned char *result, int *ch, int *sc)
+{
+ int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button, choice,
+ l, k, scroll, max_choice, item_no, redraw_menu = FALSE;
+ char okButton, cancelButton;
+ int rval = 0, ok_space, cancel_space;
+ WINDOW *dialog, *menu;
+ unsigned char **items = NULL;
+ dialogMenuItem *ditems;
+ int menu_width, tag_x, item_x;
+
+draw:
+ choice = ch ? *ch : 0;
+ scroll = sc ? *sc : 0;
+ button = 0;
+
+ /* If item_no is a positive integer, use old item specification format */
+ if (cnt >= 0) {
+ items = it;
+ ditems = NULL;
+ item_no = cnt;
+ }
+ /* It's the new specification format - fake the rest of the code out */
+ else {
+ item_no = abs(cnt);
+ ditems = it;
+ if (!items)
+ items = (unsigned char **)alloca((item_no * 2) * sizeof(unsigned char *));
+
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ items[i*2] = ditems[i].prompt;
+ items[i*2 + 1] = ditems[i].title;
+ }
+ }
+ max_choice = MIN(menu_height, item_no);
+
+ tag_x = 0;
+ item_x = 0;
+ /* Find length of longest item in order to center menu */
+ for (i = 0; i < item_no; i++) {
+ l = strlen(items[i * 2]);
+ for (j = 0; j < item_no; j++) {
+ k = strlen(items[j * 2 + 1]);
+ tag_x = MAX(tag_x, l + k + 2);
+ }
+ item_x = MAX(item_x, l);
+ }
+ if (height < 0)
+ height = strheight(prompt) + menu_height + 4 + 2;
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i, j);
+ width = MAX(width, tag_x + 4) + 4;
+ }
+ width = MAX(width, 24);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = DialogX ? DialogX : (COLS - width) / 2;
+ y = DialogY ? DialogY : (LINES - height) / 2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height, width, y, x);
+ return -1;
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ wmove(dialog, height - 3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height - 2, 1);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ' ');
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title)) / 2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+ print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE);
+
+ menu_width = width - 6;
+ getyx(dialog, cur_y, cur_x);
+ box_y = cur_y + 1;
+ box_x = (width - menu_width) / 2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1);
+ if (menu == NULL) {
+ delwin(dialog);
+ endwin();
+ fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height, menu_width,
+ y + box_y + 1, x + box_x + 1);
+ return -1;
+ }
+ keypad(menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box(dialog, box_y, box_x, menu_height+2, menu_width+2, menubox_border_attr, menubox_attr);
+
+ tag_x = menu_width > tag_x + 1 ? (menu_width - tag_x) / 2 : 1;
+ item_x = menu_width > item_x + 4 ? tag_x + item_x + 2 : menu_width - 3;
+
+ /* Print the menu */
+ for (i = 0; i < max_choice; i++)
+ print_item(menu, items[(scroll + i) * 2], items[(scroll + i) * 2 + 1], i, i == choice, DREF(ditems, scroll + i), menu_width, tag_x, item_x);
+ wnoutrefresh(menu);
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y);
+
+ display_helpline(dialog, height - 1, width);
+
+ x = width / 2 - 11;
+ y = height - 2;
+
+ if (ditems && result) {
+ cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]);
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE);
+ okButton = toupper(ditems[OK_BUTTON].prompt[0]);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE);
+ }
+ else {
+ cancelButton = 'C';
+ print_button(dialog, "Cancel", y, x + 14, FALSE);
+ okButton = 'O';
+ print_button(dialog, " OK ", y, x, TRUE);
+ }
+
+ wrefresh(dialog);
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ /* Shortcut to OK? */
+ if (toupper(key) == okButton) {
+ if (ditems) {
+ if (result && ditems[OK_BUTTON].fire) {
+ int status;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ status = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]);
+ if (status & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ }
+ }
+ else if (result)
+ strcpy(result, items[(scroll + choice) * 2]);
+ rval = 0;
+ key = ESC; /* Punt! */
+ break;
+ }
+
+ /* Shortcut to cancel? */
+ if (toupper(key) == cancelButton) {
+ if (ditems && result && ditems[CANCEL_BUTTON].fire) {
+ int status;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ status = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]);
+ if (status & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ }
+ rval = 1;
+ key = ESC; /* Run away! */
+ break;
+ }
+
+ /* Check if key pressed matches first character of any item tag in menu */
+ for (i = 0; i < max_choice; i++)
+ if (key < 0x100 && key != ' ' && toupper(key) == toupper(items[(scroll + i) * 2][0]))
+ break;
+
+ if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || KEY_IS_UP(key) || KEY_IS_DOWN(key)) {
+ if (key >= '1' && key <= MIN('9', '0'+max_choice))
+ i = key - '1';
+ else if (KEY_IS_UP(key)) {
+ if (!choice) {
+ if (scroll) {
+ /* Scroll menu down */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (menu_height > 1) {
+ /* De-highlight current first item before scrolling down */
+ print_item(menu, items[scroll * 2], items[scroll * 2 + 1], 0, FALSE, DREF(ditems, scroll), menu_width, tag_x, item_x);
+ scrollok(menu, TRUE);
+ wscrl(menu, -1);
+ scrollok(menu, FALSE);
+ }
+ scroll--;
+ print_item(menu, items[scroll * 2], items[scroll * 2 + 1], 0, TRUE, DREF(ditems, scroll), menu_width, tag_x, item_x);
+ wnoutrefresh(menu);
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y);
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice - 1;
+ }
+ else if (KEY_IS_DOWN(key)) {
+ if (choice == max_choice - 1) {
+ if (scroll + choice < item_no - 1) {
+ /* Scroll menu up */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (menu_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item(menu, items[(scroll + max_choice - 1) * 2],
+ items[(scroll + max_choice - 1) * 2 + 1],
+ max_choice-1, FALSE, DREF(ditems, scroll + max_choice - 1), menu_width, tag_x, item_x);
+ scrollok(menu, TRUE);
+ scroll(menu);
+ scrollok(menu, FALSE);
+ }
+ scroll++;
+ print_item(menu, items[(scroll + max_choice - 1) * 2],
+ items[(scroll + max_choice - 1) * 2 + 1],
+ max_choice - 1, TRUE, DREF(ditems, scroll + max_choice - 1), menu_width, tag_x, item_x);
+ wnoutrefresh(menu);
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y);
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice + 1;
+ }
+
+ if (i != choice) {
+ /* De-highlight current item */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ print_item(menu, items[(scroll + choice) * 2], items[(scroll + choice) * 2 + 1], choice, FALSE, DREF(ditems, scroll + choice), menu_width, tag_x, item_x);
+
+ /* Highlight new item */
+ choice = i;
+ print_item(menu, items[(scroll + choice) * 2], items[(scroll + choice) * 2 + 1], choice, TRUE, DREF(ditems, scroll + choice), menu_width, tag_x, item_x);
+ wnoutrefresh(menu);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_PPAGE:
+ if (scroll > height - 4) { /* can we go up? */
+ scroll -= (height - 4);
+ } else {
+ scroll = 0;
+ }
+ redraw_menu = TRUE;
+ break;
+
+ case KEY_NPAGE:
+ if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */
+ scroll = item_no - menu_height;
+ if (scroll < 0)
+ scroll = 0;
+ } else {
+ scroll += menu_height;
+ }
+ redraw_menu = TRUE;
+ break;
+
+ case KEY_HOME:
+ scroll = 0;
+ choice = 0;
+ redraw_menu = TRUE;
+ break;
+
+ case KEY_END:
+ scroll = item_no - menu_height;
+ if (scroll < 0)
+ scroll = 0;
+ choice = max_choice - 1;
+ redraw_menu = TRUE;
+ break;
+
+ case KEY_BTAB:
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = !button;
+ if (ditems && result) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x, ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ ok_space = 1;
+ cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ ok_space = 3;
+ cancel_space = 15;
+ }
+ if (button)
+ wmove(dialog, y, x+cancel_space);
+ else
+ wmove(dialog, y, x+ok_space);
+ wrefresh(dialog);
+ break;
+
+ case ' ':
+ case '\r':
+ case '\n':
+ if (!button) {
+ /* A fire routine can do just about anything to the screen, so be prepared
+ to accept some hints as to what to do in the aftermath. */
+ if (ditems) {
+ if (ditems[scroll + choice].fire) {
+ int status;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ status = ditems[scroll + choice].fire(&ditems[scroll + choice]);
+ if (status & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ if (status & DITEM_CONTINUE)
+ continue;
+ else if (status & DITEM_LEAVE_MENU) {
+ /* Allow a fire action to take us out of the menu */
+ key = ESC;
+ break;
+ }
+ else if (status & DITEM_RECREATE) {
+ delwin(menu);
+ delwin(dialog);
+ dialog_clear();
+ goto draw;
+ }
+ }
+ }
+ else if (result)
+ strcpy(result, items[(scroll+choice)*2]);
+ }
+ rval = button;
+ key = ESC;
+ break;
+
+ case ESC:
+ rval = -1;
+ break;
+
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+
+ /* save info about menu item position */
+ if (ch)
+ *ch = choice;
+ if (sc)
+ *sc = scroll;
+
+ if (redraw_menu) {
+ for (i = 0; i < max_choice; i++) {
+ print_item(menu, items[(scroll + i) * 2], items[(scroll + i) * 2 + 1], i, i == choice, DREF(ditems, scroll + i), menu_width, tag_x, item_x);
+ }
+ wnoutrefresh(menu);
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
+ wrefresh(dialog);
+ redraw_menu = FALSE;
+ }
+ }
+ delwin(menu);
+ delwin(dialog);
+ return rval;
+}
+
+
+/*
+ * Print menu item
+ */
+static void
+print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int choice, int selected, dialogMenuItem *me, int menu_width, int tag_x, int item_x)
+{
+ int i;
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+ for (i = 0; i < menu_width; i++)
+ waddch(win, ' ');
+ wmove(win, choice, tag_x);
+ wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
+ waddch(win, tag[0]);
+ wattrset(win, selected ? tag_selected_attr : tag_attr);
+ waddnstr(win, tag + 1, item_x - tag_x - 3);
+ wmove(win, choice, item_x);
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ waddnstr(win, item, menu_width - item_x - 1);
+ /* If have a selection handler for this, call it */
+ if (me && me->selected) {
+ wrefresh(win);
+ me->selected(me, selected);
+ }
+}
+/* End of print_item() */
diff --git a/gnu/lib/libdialog/msgbox.c b/gnu/lib/libdialog/msgbox.c
new file mode 100644
index 0000000..ac0e7e6
--- /dev/null
+++ b/gnu/lib/libdialog/msgbox.c
@@ -0,0 +1,348 @@
+/*
+ * msgbox.c -- implements the message box and info box
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <dialog.h>
+#include "dialog.priv.h"
+
+
+/* local prototypes */
+static int getnlines(unsigned char *buf);
+static void print_page(WINDOW *win, int height, int width, unsigned char *buf, int startline, int hscroll);
+static void print_perc(WINDOW *win, int y, int x, float p);
+
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int width, int pause)
+{
+ int i, j, x, y, key = 0;
+ WINDOW *dialog;
+
+ if (height < 0)
+ height = strheight(prompt)+2+2*(!!pause);
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i,j)+4;
+ }
+ if (pause)
+ width = MAX(width,10);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = DialogX ? DialogX : (COLS - width)/2;
+ y = DialogY ? DialogY : (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
+ exit(1);
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+ print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE);
+
+ if (pause) {
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+ display_helpline(dialog, height-1, width);
+ print_button(dialog, " OK ", height-2, width/2-6, TRUE);
+ wrefresh(dialog);
+ while (key != ESC && key != '\n' && key != ' ' && key != '\r')
+ key = wgetch(dialog);
+ if (key == '\r')
+ key = '\n';
+ }
+ else {
+ key = '\n';
+ wrefresh(dialog);
+ }
+
+ delwin(dialog);
+ return (key == ESC ? -1 : 0);
+}
+/* End of dialog_msgbox() */
+
+int
+dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int width)
+/*
+ * Desc: basically the same as dialog_msgbox, but ... can use PGUP, PGDN and
+ * arrowkeys to move around the text and pause is always enabled
+ */
+{
+ int i, j, x, y, key=0;
+ int theight, startline, hscroll, max_lines;
+ WINDOW *dialog;
+
+ if (height < 0)
+ height = strheight(prompt)+2+2;
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i,j)+4;
+ }
+ width = MAX(width,10);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = (COLS - width)/2;
+ y = (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
+ exit(1);
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+ display_helpline(dialog, height-1, width);
+ print_button(dialog, " OK ", height-2, width/2-6, TRUE);
+ wattrset(dialog, dialog_attr);
+
+ theight = height - 4;
+ startline = 0;
+ hscroll = 0;
+ max_lines = getnlines(prompt);
+ print_page(dialog, theight, width, prompt, startline, hscroll);
+ print_perc(dialog, height-3, width-9, (float) (startline+theight)/max_lines);
+ wmove(dialog, height-2, width/2-3);
+ wrefresh(dialog);
+ while ((key != ESC) && (key != '\n') && (key != '\r') && (key != ' ')) {
+ key = wgetch(dialog);
+ switch(key) {
+ case KEY_HOME:
+ startline=0;
+ hscroll=0;
+ break;
+ case KEY_END:
+ startline = max_lines - theight;
+ if (startline < 0) startline = 0;
+ break;
+ case '\020': /* ^P */
+ case KEY_UP:
+ if (startline > 0) startline--;
+ break;
+ case '\016': /* ^N */
+ case KEY_DOWN:
+ if (startline < max_lines - theight) startline++;
+ break;
+ case KEY_RIGHT:
+ hscroll+=5;
+ break;
+ case KEY_LEFT:
+ if (hscroll > 0) hscroll-=5;
+ if (hscroll < 0) hscroll =0;
+ break;
+ case KEY_PPAGE:
+ if (startline - height > 0) {
+ startline -= theight;
+ } else {
+ startline = 0;
+ }
+ break;
+ case KEY_NPAGE:
+ if (startline + theight < max_lines - theight) {
+ startline += theight;
+ } else {
+ startline = max_lines - theight;
+ if (startline < 0) startline = 0;
+ }
+ break;
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+ print_page(dialog, theight, width, prompt, startline, hscroll);
+ print_perc(dialog, height-3, width-9, (float) (startline+theight)/max_lines);
+ wmove(dialog, height-2, width/2-3);
+ wrefresh(dialog);
+ }
+
+ delwin(dialog);
+ return (key == ESC ? -1 : 0);
+
+} /* dialog_mesgbox() */
+
+static void
+print_perc(WINDOW *win, int y, int x, float p)
+/*
+ * Desc: print p as a percentage at the coordinates (y,x)
+ */
+{
+ char ps[10];
+
+ if (p>1.0) p=1.0;
+ sprintf(ps, "(%3d%%)", (int) (p*100));
+ wmove(win, y, x);
+ waddstr(win, ps);
+
+ return;
+} /* print_perc() */
+
+static int
+getnlines(unsigned char *buf)
+/*
+ * Desc: count the # of lines in <buf>
+ */
+{
+ int i = 0;
+
+ if (*buf)
+ i++;
+ while (*buf) {
+ if (*buf == '\n' || *buf == '\r')
+ i++;
+ buf++;
+ }
+ return(i);
+} /* getlines() */
+
+
+unsigned char *
+getline(unsigned char *buf, int n)
+/*
+ * Desc: return a pointer to the n'th line in <buf> or NULL if its
+ * not there
+ */
+{
+ int i;
+
+ if (n<0) {
+ return(NULL);
+ }
+
+ i=0;
+ while (*buf && i<n) {
+ if (*buf == '\n' || *buf == '\r') {
+ i++;
+ }
+ buf++;
+ }
+ if (i<n) {
+ return(NULL);
+ } else {
+ return(buf);
+ }
+} /* getline() */
+
+static void
+print_page(WINDOW *win, int height, int width, unsigned char *buf, int startline, int hscroll)
+/*
+ * Desc: Print a page of text in the current window, starting at line <startline>
+ * with a <horizontal> scroll of hscroll from buffer <buf>
+ */
+{
+ int i, j;
+ unsigned char *b;
+
+ b = getline(buf, startline);
+ for (i=0; i<height; i++) {
+ /* clear line */
+ wmove(win, 1+i, 1);
+ for (j=0; j<width-2; j++) waddnstr(win, " ", 1);
+ wmove(win, 1+i, 1);
+ j = 0;
+ /* scroll to the right */
+ while (*b && (*b != '\n') && (*b != '\r') && (j<hscroll)) {
+ b++;
+ j++;
+ }
+ /* print new line */
+ j = 0;
+ while (*b && (*b != '\n') && (*b != '\r') && (j<width-2)) {
+ waddnstr(win, b, 1);
+ if (*b != '\t') { /* check for tabs */
+ j++;
+ } else {
+ j = ((int) (j+1)/8 + 1) * 8 - 1;
+ }
+ b++;
+ }
+ while (*b && (*b != '\n') && (*b != '\r')) b++;
+ if (*b) b++; /* skip over '\n', if it exists */
+ }
+} /* print_page() */
+
+
+
+
diff --git a/gnu/lib/libdialog/notify.c b/gnu/lib/libdialog/notify.c
new file mode 100644
index 0000000..4f09aa9
--- /dev/null
+++ b/gnu/lib/libdialog/notify.c
@@ -0,0 +1,55 @@
+/*
+ * File: notify.c
+ * Author: Marc van Kempen
+ * Desc: display a notify box with a message
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <dialog.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+dialog_notify(char *msg)
+/*
+ * Desc: display an error message
+ */
+{
+ char *tmphlp;
+ WINDOW *w;
+
+ w = dupwin(newscr);
+ if (w == NULL) {
+ endwin();
+ fprintf(stderr, "\ndupwin(newscr) failed, malloc memory corrupted\n");
+ exit(1);
+ }
+ tmphlp = get_helpline();
+ use_helpline("Press enter or space");
+ dialog_mesgbox("Message", msg, -1, -1);
+ restore_helpline(tmphlp);
+ touchwin(w);
+ wrefresh(w);
+ delwin(w);
+
+ return;
+
+} /* dialog_notify() */
+
diff --git a/gnu/lib/libdialog/prgbox.c b/gnu/lib/libdialog/prgbox.c
new file mode 100644
index 0000000..10d39e4
--- /dev/null
+++ b/gnu/lib/libdialog/prgbox.c
@@ -0,0 +1,152 @@
+/*
+ * prgbox.c -- implements the message box and info box
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * $FreeBSD$
+ */
+
+
+#include <sys/types.h>
+
+#include <dialog.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include "dialog.priv.h"
+
+/*
+ * Display a message box. Program will pause and display an "OK" button
+ * if the parameter 'pause' is non-zero.
+ */
+int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, int width, int pause, int use_shell)
+{
+ int i, x, y, key = 0;
+ WINDOW *dialog;
+ FILE *f;
+ const unsigned char *name;
+ unsigned char *s, buf[MAX_LEN];
+ int status;
+
+ if (height < 0 || width < 0) {
+ endwin();
+ fprintf(stderr, "\nAutosizing is impossible in dialog_prgbox().\n");
+ exit(-1);
+ }
+ width = MAX(width,10);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = DialogX ? DialogX : (COLS - width)/2;
+ y = DialogY ? DialogY : (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
+ exit(1);
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+
+ if (!use_shell) {
+ char cmdline[MAX_LEN];
+ char *av[51], **ap = av, *val, *p;
+
+ strcpy(cmdline, line);
+ p = cmdline;
+ while ((val = strsep(&p," \t")) != NULL) {
+ if (*val != '\0')
+ *ap++ = val;
+ }
+ *ap = NULL;
+ f = raw_popen(name = av[0], av, "r");
+ } else
+ f = raw_popen(name = line, NULL, "r");
+
+ status = -1;
+ if (f == NULL) {
+ err:
+ sprintf(buf, "%s: %s\n", name, strerror(errno));
+ prr:
+ print_autowrap(dialog, buf, height-(pause?3:1), width-2, width, 1, 2, FALSE, TRUE);
+ wrefresh(dialog);
+ } else {
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ i = strlen(buf);
+ if (buf[i-1] == '\n')
+ buf[i-1] = '\0';
+ s = buf;
+ while ((s = strchr(s, '\t')) != NULL)
+ *s++ = ' ';
+ print_autowrap(dialog, buf, height-(pause?3:1), width-2, width, 1, 2, FALSE, TRUE);
+ print_autowrap(dialog, "\n", height-(pause?3:1), width-2, width, 1, 2, FALSE, FALSE);
+ wrefresh(dialog);
+ }
+ if ((status = raw_pclose(f)) == -1)
+ goto err;
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 127) {
+ sprintf(buf, "%s: program not found\n", name);
+ goto prr;
+ }
+ }
+
+ if (pause) {
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+ display_helpline(dialog, height-1, width);
+ print_button(dialog, " OK ", height-2, width/2-6, TRUE);
+ wrefresh(dialog);
+ while (key != ESC && key != '\n' && key != ' ' && key != '\r')
+ key = wgetch(dialog);
+ if (key == '\r')
+ key = '\n';
+ }
+ else {
+ key = '\n';
+ wrefresh(dialog);
+ }
+
+ delwin(dialog);
+ return (status);
+}
+/* End of dialog_msgbox() */
diff --git a/gnu/lib/libdialog/radiolist.c b/gnu/lib/libdialog/radiolist.c
new file mode 100644
index 0000000..39b362b
--- /dev/null
+++ b/gnu/lib/libdialog/radiolist.c
@@ -0,0 +1,630 @@
+/*
+ * radiolist.c -- implements the radiolist box
+ *
+ * AUTHOR: Stuart Herbert - S.Herbert@sheffield.ac.uk
+ * (from checklist.c by Savio Lam (lam836@cs.cuhk.hk))
+ *
+ * Substantial rennovation: 12/18/95, Jordan K. Hubbard
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <dialog.h>
+#include "dialog.priv.h"
+
+
+static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected, dialogMenuItem *me);
+
+#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL)
+
+static int list_width, check_x, item_x;
+
+
+/*
+ * Display a dialog box with a list of options that can be turned on or off
+ */
+int
+dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height,
+ int cnt, void *it, unsigned char *result)
+{
+ int i, j, x, y, cur_x, cur_y, old_x, old_y, box_x, box_y, key = 0, button,
+ choice, l, k, scroll, max_choice, *status, item_no = 0, was_on = 0;
+ int redraw_menu = FALSE, cursor_reset = FALSE;
+ int rval = 0, onlist = 1, ok_space, cancel_space;
+ char okButton, cancelButton;
+ WINDOW *dialog, *list;
+ unsigned char **items = NULL;
+ dialogMenuItem *ditems;
+
+ /* Allocate space for storing item on/off status */
+ if ((status = alloca(sizeof(int) * abs(cnt))) == NULL) {
+ endwin();
+ fprintf(stderr, "\nCan't allocate memory in dialog_radiolist().\n");
+ exit(-1);
+ }
+
+draw:
+ button = choice = scroll = 0;
+ /* Previous calling syntax, e.g. just a list of strings? */
+ if (cnt >= 0) {
+ items = it;
+ ditems = NULL;
+ item_no = cnt;
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ status[i] = !strcasecmp(items[i*3 + 2], "on");
+ if (status[i]) {
+ if (was_on)
+ status[i] = FALSE;
+ else
+ was_on = 1;
+ }
+ }
+ }
+ /* It's the new specification format - fake the rest of the code out */
+ else {
+ item_no = abs(cnt);
+ ditems = it;
+ if (!items)
+ items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *));
+ /* Initializes status */
+ for (i = 0; i < item_no; i++) {
+ status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
+ if (status[i]) {
+ if (was_on)
+ status[i] = FALSE;
+ else
+ was_on = 1;
+ }
+ items[i*3] = ditems[i].prompt;
+ items[i*3 + 1] = ditems[i].title;
+ items[i*3 + 2] = status[i] ? "on" : "off";
+ }
+ }
+ max_choice = MIN(list_height, item_no);
+
+ check_x = 0;
+ item_x = 0;
+ /* Find length of longest item in order to center radiolist */
+ for (i = 0; i < item_no; i++) {
+ l = strlen(items[i * 3]);
+ for (j = 0; j < item_no; j++) {
+ k = strlen(items[j * 3 + 1]);
+ check_x = MAX(check_x, l + k + 6);
+ }
+ item_x = MAX(item_x, l);
+ }
+ if (height < 0)
+ height = strheight(prompt) + list_height + 4 + 2;
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i, j);
+ width = MAX(width, check_x + 4) + 4;
+ }
+ width = MAX(width, 24);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = DialogX ? DialogX : (COLS - width) / 2;
+ y = DialogY ? DialogY : (LINES - height) / 2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height, width, y, x);
+ return -1;
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ wmove(dialog, height - 3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height - 2, 1);
+ for (i = 0; i < width - 2; i++)
+ waddch(dialog, ' ');
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title)) / 2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+ print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE);
+
+ list_width = width - 6;
+ getyx(dialog, cur_y, cur_x);
+ box_y = cur_y + 1;
+ box_x = (width - list_width) / 2 - 1;
+
+ /* create new window for the list */
+ list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1);
+ if (list == NULL) {
+ delwin(dialog);
+ endwin();
+ fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width,
+ y + box_y + 1,x + box_x + 1);
+ return -1;
+ }
+ keypad(list, TRUE);
+
+ /* draw a box around the list items */
+ draw_box(dialog, box_y, box_x, list_height+2, list_width+2, menubox_border_attr, menubox_attr);
+
+ check_x = (list_width - check_x) / 2;
+ item_x = check_x + item_x + 6;
+
+ /* Print the list */
+ for (i = 0; i < max_choice; i++)
+ print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i));
+ wnoutrefresh(list);
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+
+ display_helpline(dialog, height-1, width);
+
+ x = width/ 2 - 11;
+ y = height - 2;
+ if (ditems && result) {
+ cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]);
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5,
+ ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : FALSE);
+ okButton = toupper(ditems[OK_BUTTON].prompt[0]);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x,
+ ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : TRUE);
+ }
+ else {
+ cancelButton = 'C';
+ print_button(dialog, "Cancel", y, x + 14, FALSE);
+ okButton = 'O';
+ print_button(dialog, " OK ", y, x, TRUE);
+ }
+ wnoutrefresh(dialog);
+ wmove(list, choice, check_x+1);
+ wrefresh(list);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+
+ /* See if its the short-cut to "OK" */
+ if (toupper(key) == okButton) {
+ if (ditems) {
+ if (result && ditems[OK_BUTTON].fire) {
+ int st;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ st = ditems[OK_BUTTON].fire(&ditems[OK_BUTTON]);
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ }
+ }
+ else if (result) {
+ *result = '\0';
+ for (i = 0; i < item_no; i++) {
+ if (status[i]) {
+ strcat(result, items[i*3]);
+ break;
+ }
+ }
+ }
+ rval = 0;
+ key = ESC;
+ break;
+ }
+
+ /* Shortcut to cancel */
+ if (toupper(key) == cancelButton) {
+ if (ditems && result && ditems[CANCEL_BUTTON].fire) {
+ int st;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ st = ditems[CANCEL_BUTTON].fire(&ditems[CANCEL_BUTTON]);
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ }
+ rval = 1;
+ key = ESC;
+ break;
+ }
+
+ /* Check if key pressed matches first character of any item tag in list */
+ for (i = 0; i < max_choice; i++)
+ if (key != ' ' && toupper(key) == toupper(items[(scroll + i) * 3][0]))
+ break;
+
+ if (i < max_choice || (key >= '1' && key <= MIN('9', '0' + max_choice)) ||
+ KEY_IS_UP(key) || KEY_IS_DOWN(key) || ((key == ' ' || key == '\r' || key == '\n') && onlist == 1)) {
+
+ /* if moving from buttons to the list, reset and redraw buttons */
+ if (!onlist) {
+ onlist = 1;
+ button = 0;
+
+ if (ditems && result ) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5,
+ ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x,
+ ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ }
+ }
+ wmove(list, choice, check_x+1);
+ wnoutrefresh(dialog);
+ wrefresh(list);
+
+ if (key >= '1' && key <= MIN('9', '0' + max_choice))
+ i = key - '1';
+ else if (KEY_IS_UP(key)) {
+ if (!choice) {
+ if (scroll) {
+ /* Scroll list down */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (list_height > 1) {
+ /* De-highlight current first item before scrolling down */
+ print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
+ FALSE, DREF(ditems, scroll));
+ scrollok(list, TRUE);
+ wscrl(list, -1);
+ scrollok(list, FALSE);
+ }
+ scroll--;
+ print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
+ TRUE, DREF(ditems, scroll));
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+ wmove(list, choice, check_x+1);
+ wnoutrefresh(dialog);
+ wrefresh(list);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice - 1;
+ }
+ else if (KEY_IS_DOWN(key)) {
+ if (choice == max_choice - 1) {
+ if (scroll + choice < item_no - 1) {
+ /* Scroll list up */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (list_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item(list, items[(scroll + max_choice - 1) * 3],
+ items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1], max_choice - 1,
+ FALSE, DREF(ditems, scroll + max_choice - 1));
+ scrollok(list, TRUE);
+ scroll(list);
+ scrollok(list, FALSE);
+ }
+ scroll++;
+ print_item(list, items[(scroll + max_choice - 1) * 3],
+ items[(scroll + max_choice - 1) * 3 + 1],
+ status[scroll + max_choice - 1], max_choice - 1,
+ TRUE, DREF(ditems, scroll + max_choice - 1));
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+ wmove(list, choice, check_x+1);
+ wnoutrefresh(dialog);
+ wrefresh(list);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice + 1;
+ }
+ else if ((key == ' ' || key == '\r' || key == '\n') && onlist) { /* Toggle item status */
+ getyx(list, old_y, old_x); /* Save cursor position */
+ if (status[scroll + choice])
+ continue;
+ else if (ditems) {
+ if (ditems[scroll + choice].fire) {
+ int st;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ st = ditems[scroll + choice].fire(&ditems[scroll + choice]);
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ if (st & DITEM_REDRAW) {
+ wclear(list);
+ for (i = 0; i < item_no; i++)
+ status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
+
+ for (i = 0; i < max_choice; i++) {
+ print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1],
+ status[scroll + i], i, i == choice,
+ DREF(ditems, scroll + i));
+ }
+/* wmove(list, old_y, old_x);*/ /* Restore cursor to previous position */
+/* wrefresh(list); */
+ }
+ if (st & DITEM_LEAVE_MENU) {
+ /* Allow a fire action to take us out of the menu */
+ key = ESC;
+ break;
+ }
+ else if (st & DITEM_RECREATE) {
+ delwin(list);
+ delwin(dialog);
+ dialog_clear();
+ goto draw;
+ }
+ }
+ for (i = 0; i < item_no; i++)
+ status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
+ }
+ else {
+ for (i = 0; i < item_no; i++)
+ status[i] = 0;
+ status[scroll + choice] = TRUE;
+ }
+ for (i = 0; i < max_choice; i++)
+ print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1],
+ status[scroll + i], i, i == choice, DREF(ditems, scroll + i));
+ wmove(list, choice, check_x+1); /* Restore cursor position */
+ wrefresh(list);
+ continue; /* wait for another key press */
+ }
+
+ if (i != choice) {
+ /* De-highlight current item */
+ print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 +1],
+ status[scroll + choice], choice, FALSE, DREF(ditems, scroll + choice));
+ /* Highlight new item */
+ choice = i;
+ print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1],
+ status[scroll + choice], choice, TRUE, DREF(ditems, scroll + choice));
+ wmove(list, choice, check_x+1); /* Restore cursor position */
+ wrefresh(list);
+ }
+ continue; /* wait for another key press */
+ }
+
+ switch (key) {
+ case KEY_PPAGE:
+ if (scroll > height-4) /* can we go up? */
+ scroll -= (height-4);
+ else
+ scroll = 0;
+ redraw_menu = TRUE;
+ if (!onlist) {
+ onlist = 1;
+ button = 0;
+ }
+ break;
+
+ case KEY_NPAGE:
+ if (scroll + list_height >= item_no-1 - list_height) { /* can we go down a full page? */
+ scroll = item_no - list_height;
+ if (scroll < 0)
+ scroll = 0;
+ }
+ else
+ scroll += list_height;
+ redraw_menu = TRUE;
+ if (!onlist) {
+ onlist = 1;
+ button = 0;
+ }
+ break;
+
+ case KEY_HOME:
+ scroll = 0;
+ choice = 0;
+ redraw_menu = TRUE;
+ cursor_reset = TRUE;
+ onlist = 1;
+ break;
+
+ case KEY_END:
+ scroll = item_no - list_height;
+ if (scroll < 0)
+ scroll = 0;
+ choice = max_choice - 1;
+ redraw_menu = TRUE;
+ cursor_reset = TRUE;
+ onlist = 1;
+ break;
+
+ case TAB:
+ case KEY_BTAB:
+ /* move to next component */
+ if (onlist) { /* on list, next is ok button */
+ onlist = 0;
+ if (ditems && result)
+ ok_space = 1;
+ else
+ ok_space = 3;
+ wmove(dialog, y, x + ok_space);
+ wrefresh(dialog);
+ break;
+ }
+ else if (button) { /* on cancel button, next is list */
+ button = 0;
+ onlist = 1;
+ redraw_menu = TRUE;
+ break;
+ }
+ /* on ok button, next is cancel button, same as left/right case */
+
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ onlist = 0;
+ button = !button;
+ if (ditems && result) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5,
+ ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x,
+ ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ ok_space = 1;
+ cancel_space = strlen(ditems[OK_BUTTON].prompt) + 6;
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ ok_space = 3;
+ cancel_space = 15;
+ }
+ if (button)
+ wmove(dialog, y, x + cancel_space);
+ else
+ wmove(dialog, y, x + ok_space);
+ wrefresh(dialog);
+ break;
+
+ case ' ':
+ case '\r':
+ case '\n':
+ if (!onlist) {
+ if (ditems) {
+ if (result && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) {
+ int st;
+ WINDOW *save;
+
+ save = dupwin(newscr);
+ st = ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]);
+ if (st & DITEM_RESTORE) {
+ touchwin(save);
+ wrefresh(save);
+ }
+ delwin(save);
+ }
+ }
+ else if (result) {
+ *result = '\0';
+ for (i = 0; i < item_no; i++) {
+ if (status[i]) {
+ strcpy(result, items[i*3]);
+ break;
+ }
+ }
+ }
+ rval = button;
+ key = ESC;
+ break;
+ }
+
+ case ESC:
+ rval = -1;
+ break;
+
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+
+ if (redraw_menu) {
+ getyx(list, old_y, old_x);
+ wclear(list);
+ for (i = 0; i < max_choice; i++)
+ print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i],
+ i, i == choice, DREF(ditems, scroll + i));
+ print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
+
+ /* redraw buttons to fix highlighting */
+ if (ditems && result) {
+ print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5,
+ ditems[CANCEL_BUTTON].checked ? ditems[CANCEL_BUTTON].checked(&ditems[CANCEL_BUTTON]) : button);
+ print_button(dialog, ditems[OK_BUTTON].prompt, y, x,
+ ditems[OK_BUTTON].checked ? ditems[OK_BUTTON].checked(&ditems[OK_BUTTON]) : !button);
+ }
+ else {
+ print_button(dialog, "Cancel", y, x + 14, button);
+ print_button(dialog, " OK ", y, x, !button);
+ }
+ wnoutrefresh(dialog);
+ if (cursor_reset) {
+ wmove(list, choice, check_x+1);
+ cursor_reset = FALSE;
+ }
+ else {
+ wmove(list, old_y, old_x);
+ }
+ wrefresh(list);
+ redraw_menu = FALSE;
+ }
+ }
+
+ delwin(list);
+ delwin(dialog);
+ return rval; /* ESC pressed */
+}
+
+/*
+ * Print list item
+ */
+static void
+print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected, dialogMenuItem *me)
+{
+ int i;
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+ for (i = 0; i < list_width; i++)
+ waddch(win, ' ');
+ wmove(win, choice, check_x);
+ wattrset(win, selected ? check_selected_attr : check_attr);
+ wprintw(win, "%c%c%c", me && me->lbra ? me->lbra : '(',
+ status ? me && me->mark ? me->mark : '*' : ' ',
+ me && me->rbra ? me->rbra : ')');
+ wattrset(win, menubox_attr);
+ waddch(win, ' ');
+ wattrset(win, selected ? tag_key_selected_attr : tag_key_attr);
+ waddch(win, tag[0]);
+ wattrset(win, selected ? tag_selected_attr : tag_attr);
+ waddstr(win, tag + 1);
+ wmove(win, choice, item_x);
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ waddstr(win, item);
+ /* If have a selection handler for this, call it */
+ if (me && me->selected) {
+ wrefresh(win);
+ me->selected(me, selected);
+ }
+}
+/* End of print_item() */
diff --git a/gnu/lib/libdialog/raw_popen.c b/gnu/lib/libdialog/raw_popen.c
new file mode 100644
index 0000000..d343abe
--- /dev/null
+++ b/gnu/lib/libdialog/raw_popen.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)popen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+
+static struct pid {
+ struct pid *next;
+ FILE *fp;
+ pid_t pid;
+} *pidlist;
+
+FILE *
+raw_popen(const char *program, char * const *argv, const char *type)
+{
+ struct pid *cur;
+ FILE *iop;
+ int pdes[2], pid;
+
+ if ((*type != 'r' && *type != 'w') || type[1])
+ return (NULL);
+
+ if ((cur = malloc(sizeof(struct pid))) == NULL)
+ return (NULL);
+
+ if (pipe(pdes) < 0) {
+ (void)free(cur);
+ return (NULL);
+ }
+
+ switch (pid = vfork()) {
+ case -1: /* Error. */
+ (void)close(pdes[0]);
+ (void)close(pdes[1]);
+ (void)free(cur);
+ return (NULL);
+ /* NOTREACHED */
+ case 0: /* Child. */
+ if (*type == 'r') {
+ if (pdes[1] != STDOUT_FILENO) {
+ (void)dup2(pdes[1], STDOUT_FILENO);
+ (void)close(pdes[1]);
+ }
+ (void) close(pdes[0]);
+ } else {
+ if (pdes[0] != STDIN_FILENO) {
+ (void)dup2(pdes[0], STDIN_FILENO);
+ (void)close(pdes[0]);
+ }
+ (void)close(pdes[1]);
+ }
+ if (argv == NULL)
+ execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL);
+ else
+ execvp(program, argv);
+ _exit(127);
+ /* NOTREACHED */
+ }
+
+ /* Parent; assume fdopen can't fail. */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ (void)close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ (void)close(pdes[0]);
+ }
+
+ /* Link into list of file descriptors. */
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+
+ return (iop);
+}
+
+/*
+ * pclose --
+ * Pclose returns -1 if stream is not associated with a `popened' command,
+ * if already `pclosed', or waitpid returns an error.
+ */
+int
+raw_pclose(FILE *iop)
+{
+ register struct pid *cur, *last;
+ int omask, pstat;
+ pid_t pid;
+
+ (void)fclose(iop);
+
+ /* Find the appropriate file pointer. */
+ for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ if (cur->fp == iop)
+ break;
+ if (cur == NULL)
+ return (-1);
+
+ /* Get the status of the process. */
+ omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
+ do {
+ pid = waitpid(cur->pid, (int *) &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+ (void)sigsetmask(omask);
+
+ /* Remove the entry from the linked list. */
+ if (last == NULL)
+ pidlist = cur->next;
+ else
+ last->next = cur->next;
+ free(cur);
+
+ return (pid == -1 ? -1 : pstat);
+}
diff --git a/gnu/lib/libdialog/rc.c b/gnu/lib/libdialog/rc.c
new file mode 100644
index 0000000..36631a6
--- /dev/null
+++ b/gnu/lib/libdialog/rc.c
@@ -0,0 +1,375 @@
+/*
+ * rc.c -- routines for processing the configuration file
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 <dialog.h>
+#include "dialog.priv.h"
+#include "colors.h"
+#include "rc.h"
+
+
+static unsigned char *attr_to_str(int fg, int bg, int hl);
+static int str_to_attr(unsigned char *str, int *fg, int *bg, int *hl);
+static int parse_line(unsigned char *line, unsigned char **var, unsigned char **value);
+
+
+/*
+ * Create the configuration file
+ */
+void dialog_create_rc(unsigned char *filename)
+{
+ int i;
+ FILE *rc_file;
+
+ if ((rc_file = fopen(filename, "wt")) == NULL) {
+ fprintf(stderr, "\nError opening file for writing in create_rc().\n");
+ exit(-1);
+ }
+
+ fprintf(rc_file, "#\
+\n# Run-time configuration file for dialog\
+\n#\
+\n# Automatically generated by \"dialog --create-rc <file>\"\
+\n#\
+\n#\
+\n# Types of values:\
+\n#\
+\n# Number - <number>\
+\n# String - \"string\"\
+\n# Boolean - <ON|OFF>\
+\n# Attribute - (foreground,background,highlight?)\
+\n#\n\n");
+
+ /* Print an entry for each configuration variable */
+ for (i = 0; i < VAR_COUNT; i++) {
+ fprintf(rc_file, "\n# %s\n", vars[i].comment); /* print comment */
+ switch (vars[i].type) {
+ case VAL_INT:
+ fprintf(rc_file, "%s = %d\n", vars[i].name, *((int *) vars[i].var));
+ break;
+ case VAL_STR:
+ fprintf(rc_file, "%s = \"%s\"\n", vars[i].name, (unsigned char *) vars[i].var);
+ break;
+ case VAL_BOOL:
+ fprintf(rc_file, "%s = %s\n", vars[i].name, *((bool *) vars[i].var) ? "ON" : "OFF");
+ break;
+ case VAL_ATTR:
+ fprintf(rc_file, "%s = %s\n", vars[i].name, attr_to_str(((int *) vars[i].var)[0], ((int *) vars[i].var)[1], ((int *) vars[i].var)[2]));
+ break;
+ }
+ }
+
+ fclose(rc_file);
+}
+/* End of create_rc() */
+
+
+/*
+ * Parse the configuration file and set up variables
+ */
+int parse_rc(void)
+{
+ int i, l = 1, parse, fg, bg, hl;
+ unsigned char str[MAX_LEN+1], *var, *value, *tempptr;
+ FILE *rc_file;
+
+ /*
+ *
+ * At start, 'dialog' determines the settings to use as follows:
+ *
+ * a) if environment variable DIALOGRC is set, it's value determines the
+ * name of the configuration file.
+ *
+ * b) if the file in (a) can't be found, use the file $HOME/.dialogrc
+ * as the configuration file.
+ *
+ * c) if the file in (b) can't be found, use compiled in defaults.
+ *
+ */
+
+ if ((tempptr = getenv("DIALOGRC")) != NULL)
+ rc_file = fopen(tempptr, "rt");
+
+ if (tempptr == NULL || rc_file == NULL) { /* step (a) failed? */
+ /* try step (b) */
+ if ((tempptr = getenv("HOME")) == NULL)
+ return 0; /* step (b) failed, use default values */
+
+ if (tempptr[0] == '\0' || lastch(tempptr) == '/')
+ sprintf(str, "%s%s", tempptr, DIALOGRC);
+ else
+ sprintf(str, "%s/%s", tempptr, DIALOGRC);
+
+ if ((rc_file = fopen(str, "rt")) == NULL)
+ return 0; /* step (b) failed, use default values */
+ }
+
+ /* Scan each line and set variables */
+ while (fgets(str, MAX_LEN, rc_file) != NULL) {
+ if (lastch(str) != '\n') { /* ignore rest of file if line too long */
+ fprintf(stderr, "\nParse error: line %d of configuration file too long.\n", l);
+ fclose(rc_file);
+ return -1; /* parse aborted */
+ }
+ else {
+ lastch(str) = '\0';
+ parse = parse_line(str, &var, &value); /* parse current line */
+
+ switch (parse) {
+ case LINE_BLANK: /* ignore blank lines and comments */
+ case LINE_COMMENT:
+ break;
+ case LINE_OK:
+ /* search table for matching config variable name */
+ for (i = 0; i < VAR_COUNT && strcmp(vars[i].name, var); i++);
+
+ if (i == VAR_COUNT) { /* no match */
+ fprintf(stderr, "\nParse error: unknown variable at line %d of configuration file.\n", l);
+ return -1; /* parse aborted */
+ }
+ else { /* variable found in table, set run time variables */
+ switch (vars[i].type) {
+ case VAL_INT:
+ *((int *) vars[i].var) = atoi(value);
+ break;
+ case VAL_STR:
+ if (!isquote(value[0]) || !isquote(lastch(value)) || strlen(value) < 2) {
+ fprintf(stderr, "\nParse error: string value expected at line %d of configuration file.\n", l);
+ return -1; /* parse aborted */
+ }
+ else {
+ /* remove the (") quotes */
+ value++;
+ lastch(value) = '\0';
+ strcpy((unsigned char *) vars[i].var, value);
+ }
+ break;
+ case VAL_BOOL:
+ if (!strcasecmp(value, "ON"))
+ *((bool *) vars[i].var) = TRUE;
+ else if (!strcasecmp(value, "OFF"))
+ *((bool *) vars[i].var) = FALSE;
+ else {
+ fprintf(stderr, "\nParse error: boolean value expected at line %d of configuration file.\n", l);
+ return -1; /* parse aborted */
+ }
+ break;
+ case VAL_ATTR:
+ if (str_to_attr(value, &fg, &bg, &hl) == -1) {
+ fprintf(stderr, "\nParse error: attribute value expected at line %d of configuration file.\n", l);
+ return -1; /* parse aborted */
+ }
+ ((int *) vars[i].var)[0] = fg;
+ ((int *) vars[i].var)[1] = bg;
+ ((int *) vars[i].var)[2] = hl;
+ break;
+ }
+ }
+ break;
+ case LINE_ERROR:
+ fprintf(stderr, "\nParse error: syntax error at line %d of configuration file.\n", l);
+ return -1; /* parse aborted */
+ }
+ }
+
+ l++; /* next line */
+ }
+
+ fclose(rc_file);
+ return 0; /* parse successful */
+}
+/* End of parse_rc() */
+
+
+/*
+ * Convert an attribute to a string representation like this:
+ *
+ * "(foreground,background,highlight)"
+ */
+static unsigned char *attr_to_str(int fg, int bg, int hl)
+{
+ int i;
+ static unsigned char str[MAX_LEN+1];
+
+ strcpy(str, "(");
+ /* foreground */
+ for (i = 0; fg != color_names[i].value; i++);
+ strcat(str, color_names[i].name);
+ strcat(str, ",");
+
+ /* background */
+ for (i = 0; bg != color_names[i].value; i++);
+ strcat(str, color_names[i].name);
+
+ /* highlight */
+ strcat(str, hl ? ",ON)" : ",OFF)");
+
+ return str;
+}
+/* End of attr_to_str() */
+
+
+/*
+ * Extract the foreground, background and highlight values from an attribute
+ * represented as a string in this form:
+ *
+ * "(foreground,background,highlight)"
+ */
+static int str_to_attr(unsigned char *str, int *fg, int *bg, int *hl)
+{
+ int i = 0, j, get_fg = 1;
+ unsigned char tempstr[MAX_LEN+1], *part;
+
+ if (str[0] != '(' || lastch(str) != ')')
+ return -1; /* invalid representation */
+
+ /* remove the parenthesis */
+ strcpy(tempstr, str + 1);
+ lastch(tempstr) = '\0';
+
+
+ /* get foreground and background */
+
+ while (1) {
+ /* skip white space before fg/bg string */
+ while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
+ if (tempstr[i] == '\0')
+ return -1; /* invalid representation */
+ part = tempstr + i; /* set 'part' to start of fg/bg string */
+
+ /* find end of fg/bg string */
+ while(!whitespace(tempstr[i]) && tempstr[i] != ',' && tempstr[i] != '\0') i++;
+
+ if (tempstr[i] == '\0')
+ return -1; /* invalid representation */
+ else if (whitespace(tempstr[i])) { /* not yet ',' */
+ tempstr[i++] = '\0';
+
+ /* skip white space before ',' */
+ while(whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
+
+ if (tempstr[i] != ',')
+ return -1; /* invalid representation */
+ }
+
+ tempstr[i++] = '\0'; /* skip the ',' */
+ for (j = 0; j < COLOR_COUNT && strcasecmp(part, color_names[j].name); j++);
+ if (j == COLOR_COUNT) /* invalid color name */
+ return -1;
+ if (get_fg) {
+ *fg = color_names[j].value;
+ get_fg = 0; /* next we have to get the background */
+ }
+ else {
+ *bg = color_names[j].value;
+ break;
+ }
+ } /* got foreground and background */
+
+
+ /* get highlight */
+
+ /* skip white space before highlight string */
+ while (whitespace(tempstr[i]) && tempstr[i] != '\0') i++;
+ if (tempstr[i] == '\0')
+ return -1; /* invalid representation */
+ part = tempstr + i; /* set 'part' to start of highlight string */
+
+ /* trim trailing white space from highlight string */
+ i = strlen(part) - 1;
+ while(whitespace(part[i])) i--;
+ part[i+1] = '\0';
+
+ if (!strcasecmp(part, "ON"))
+ *hl = TRUE;
+ else if (!strcasecmp(part, "OFF"))
+ *hl = FALSE;
+ else
+ return -1; /* invalid highlight value */
+
+ return 0;
+}
+/* End of str_to_attr() */
+
+
+/*
+ * Parse a line in the configuration file
+ *
+ * Each line is of the form: "variable = value". On exit, 'var' will contain
+ * the variable name, and 'value' will contain the value string.
+ *
+ * Return values:
+ *
+ * LINE_BLANK - line is blank
+ * LINE_COMMENT - line is comment
+ * LINE_OK - line is ok
+ * LINE_ERROR - syntax error in line
+ */
+static int parse_line(unsigned char *line, unsigned char **var, unsigned char **value)
+{
+ int i = 0;
+
+ /* ignore white space at beginning of line */
+ while(whitespace(line[i]) && line[i] != '\0') i++;
+
+ if (line[i] == '\0') /* line is blank */
+ return LINE_BLANK;
+ else if (line[i] == '#') /* line is comment */
+ return LINE_COMMENT;
+ else if (line[i] == '=') /* variables names can't strart with a '=' */
+ return LINE_ERROR;
+
+ /* set 'var' to variable name */
+ *var = line + i++; /* skip to next character */
+
+ /* find end of variable name */
+ while(!whitespace(line[i]) && line[i] != '=' && line[i] != '\0') i++;
+
+ if (line[i] == '\0') /* syntax error */
+ return LINE_ERROR;
+ else if (line[i] == '=')
+ line[i++] = '\0';
+ else {
+ line[i++] = '\0';
+
+ /* skip white space before '=' */
+ while(whitespace(line[i]) && line[i] != '\0') i++;
+
+ if (line[i] != '=') /* syntax error */
+ return LINE_ERROR;
+ else
+ i++; /* skip the '=' */
+ }
+
+ /* skip white space after '=' */
+ while(whitespace(line[i]) && line[i] != '\0') i++;
+
+ if (line[i] == '\0')
+ return LINE_ERROR;
+ else
+ *value = line + i; /* set 'value' to value string */
+
+ /* trim trailing white space from 'value' */
+ i = strlen(*value) - 1;
+ while(whitespace((*value)[i])) i--;
+ (*value)[i+1] = '\0';
+
+ return LINE_OK; /* no syntax error in line */
+}
+/* End of parse_line() */
diff --git a/gnu/lib/libdialog/rc.h b/gnu/lib/libdialog/rc.h
new file mode 100644
index 0000000..fc19d03
--- /dev/null
+++ b/gnu/lib/libdialog/rc.h
@@ -0,0 +1,222 @@
+/*
+ * rc.h -- declarations for configuration file processing
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#define DIALOGRC ".dialogrc"
+#define VAR_LEN 30
+#define COMMENT_LEN 70
+
+/* Types of values */
+#define VAL_INT 0
+#define VAL_STR 1
+#define VAL_BOOL 2
+#define VAL_ATTR 3
+
+/* Type of line in configuration file */
+#define LINE_BLANK 2
+#define LINE_COMMENT 1
+#define LINE_OK 0
+#define LINE_ERROR -1
+
+/* number of configuration variables */
+#define VAR_COUNT (sizeof(vars) / sizeof(vars_st))
+
+/* check if character is white space */
+#define whitespace(c) (c == ' ' || c == '\t')
+
+/* check if character is string quoting characters */
+#define isquote(c) (c == '"' || c == '\'')
+
+/* get last character of string */
+#define lastch(str) str[strlen(str)-1]
+
+/*
+ * Configuration variables
+ */
+typedef struct {
+ unsigned char name[VAR_LEN]; /* name of configuration variable as in DIALOGRC */
+ void *var; /* address of actually variable to change */
+ int type; /* type of value */
+ unsigned char comment[COMMENT_LEN]; /* comment to put in "rc" file */
+} vars_st;
+
+vars_st vars[] = {
+ { "use_shadow",
+ &use_shadow,
+ VAL_BOOL,
+ "Shadow dialog boxes? This also turns on color." },
+
+ { "use_colors",
+ &use_colors,
+ VAL_BOOL,
+ "Turn color support ON or OFF" },
+
+ { "screen_color",
+ color_table[0],
+ VAL_ATTR,
+ "Screen color" },
+
+ { "shadow_color",
+ color_table[1],
+ VAL_ATTR,
+ "Shadow color" },
+
+ { "dialog_color",
+ color_table[2],
+ VAL_ATTR,
+ "Dialog box color" },
+
+ { "title_color",
+ color_table[3],
+ VAL_ATTR,
+ "Dialog box title color" },
+
+ { "border_color",
+ color_table[4],
+ VAL_ATTR,
+ "Dialog box border color" },
+
+ { "button_active_color",
+ color_table[5],
+ VAL_ATTR,
+ "Active button color" },
+
+ { "button_inactive_color",
+ color_table[6],
+ VAL_ATTR,
+ "Inactive button color" },
+
+ { "button_key_active_color",
+ color_table[7],
+ VAL_ATTR,
+ "Active button key color" },
+
+ { "button_key_inactive_color",
+ color_table[8],
+ VAL_ATTR,
+ "Inactive button key color" },
+
+ { "button_label_active_color",
+ color_table[9],
+ VAL_ATTR,
+ "Active button label color" },
+
+ { "button_label_inactive_color",
+ color_table[10],
+ VAL_ATTR,
+ "Inactive button label color" },
+
+ { "inputbox_color",
+ color_table[11],
+ VAL_ATTR,
+ "Input box color" },
+
+ { "inputbox_border_color",
+ color_table[12],
+ VAL_ATTR,
+ "Input box border color" },
+
+ { "searchbox_color",
+ color_table[13],
+ VAL_ATTR,
+ "Search box color" },
+
+ { "searchbox_title_color",
+ color_table[14],
+ VAL_ATTR,
+ "Search box title color" },
+
+ { "searchbox_border_color",
+ color_table[15],
+ VAL_ATTR,
+ "Search box border color" },
+
+ { "position_indicator_color",
+ color_table[16],
+ VAL_ATTR,
+ "File position indicator color" },
+
+ { "menubox_color",
+ color_table[17],
+ VAL_ATTR,
+ "Menu box color" },
+
+ { "menubox_border_color",
+ color_table[18],
+ VAL_ATTR,
+ "Menu box border color" },
+
+ { "item_color",
+ color_table[19],
+ VAL_ATTR,
+ "Item color" },
+
+ { "item_selected_color",
+ color_table[20],
+ VAL_ATTR,
+ "Selected item color" },
+
+ { "tag_color",
+ color_table[21],
+ VAL_ATTR,
+ "Tag color" },
+
+ { "tag_selected_color",
+ color_table[22],
+ VAL_ATTR,
+ "Selected tag color" },
+
+ { "tag_key_color",
+ color_table[23],
+ VAL_ATTR,
+ "Tag key color" },
+
+ { "tag_key_selected_color",
+ color_table[24],
+ VAL_ATTR,
+ "Selected tag key color" },
+
+ { "check_color",
+ color_table[25],
+ VAL_ATTR,
+ "Check box color" },
+
+ { "check_selected_color",
+ color_table[26],
+ VAL_ATTR,
+ "Selected check box color" },
+
+ { "uarrow_color",
+ color_table[27],
+ VAL_ATTR,
+ "Up arrow color" },
+
+ { "darrow_color",
+ color_table[28],
+ VAL_ATTR,
+ "Down arrow color" }
+}; /* vars */
+
+
+
+/*
+ * Routines to process configuration file
+ */
+int parse_rc(void);
diff --git a/gnu/lib/libdialog/textbox.c b/gnu/lib/libdialog/textbox.c
new file mode 100644
index 0000000..8c6e1a1
--- /dev/null
+++ b/gnu/lib/libdialog/textbox.c
@@ -0,0 +1,701 @@
+/*
+ * textbox.c -- implements the text box
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <dialog.h>
+#include "dialog.priv.h"
+
+
+static void back_lines(int n);
+static void print_page(WINDOW *win, int height, int width);
+static void print_line(WINDOW *win, int row, int width);
+static unsigned char *get_line(void);
+static int get_search_term(WINDOW *win, unsigned char *search_term, int height, int width);
+static void print_position(WINDOW *win, int height, int width);
+
+
+static int hscroll = 0, fd, file_size, bytes_read, begin_reached = 1,
+ end_reached = 0, page_length;
+static unsigned char *buf, *page;
+
+
+/*
+ * Display text from a file in a dialog box.
+ */
+int dialog_textbox(unsigned char *title, unsigned char *file, int height, int width)
+{
+ int i, x, y, cur_x, cur_y, fpos, key = 0, dir, temp, temp1;
+#ifdef HAVE_NCURSES
+ int passed_end;
+#endif
+ unsigned char search_term[MAX_LEN+1], *tempptr, *found;
+ WINDOW *dialog, *text;
+
+ if (height < 0 || width < 0) {
+ fprintf(stderr, "\nAutosizing is impossible in dialog_textbox().\n");
+ return(-1);
+ }
+
+ search_term[0] = '\0'; /* no search term entered yet */
+
+ /* Open input file for reading */
+ if ((fd = open(file, O_RDONLY)) == -1) {
+ fprintf(stderr, "\nCan't open input file <%s>in dialog_textbox().\n", file);
+ return(-1);
+ }
+ /* Get file size. Actually, 'file_size' is the real file size - 1,
+ since it's only the last byte offset from the beginning */
+ if ((file_size = lseek(fd, 0, SEEK_END)) == -1) {
+ fprintf(stderr, "\nError getting file size in dialog_textbox().\n");
+ return(-1);
+ }
+ /* Restore file pointer to beginning of file after getting file size */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ return(-1);
+ }
+ /* Allocate space for read buffer */
+ if ((buf = malloc(BUF_SIZE+1)) == NULL) {
+ endwin();
+ fprintf(stderr, "\nCan't allocate memory in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ return(-1);
+ }
+ buf[bytes_read] = '\0'; /* mark end of valid data */
+ page = buf; /* page is pointer to start of page to be displayed */
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = DialogX ? DialogX : (COLS - width)/2;
+ y = DialogY ? DialogY : (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
+ exit(1);
+ }
+ keypad(dialog, TRUE);
+
+ /* Create window for text region, used for scrolling text */
+/* text = newwin(height-4, width-2, y+1, x+1); */
+ text = subwin(dialog, height-4, width-2, y+1, x+1);
+ if (text == NULL) {
+ endwin();
+ fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", height-4,width-2,y+1,x+1);
+ exit(1);
+ }
+ keypad(text, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ display_helpline(dialog, height-1, width);
+
+ print_button(dialog, " OK ", height-2, width/2-6, TRUE);
+ wnoutrefresh(dialog);
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+
+ /* Print first page of text */
+ attr_clear(text, height-4, width-2, dialog_attr);
+ print_page(text, height-4, width-2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+
+ while ((key != ESC) && (key != '\n') && (key != '\r') && (key != ' ')) {
+ key = wgetch(dialog);
+ switch (key) {
+ case 'E': /* Exit */
+ case 'e':
+ delwin(dialog);
+ free(buf);
+ close(fd);
+ return 0;
+ case 'g': /* First page */
+ case KEY_HOME:
+ if (!begin_reached) {
+ begin_reached = 1;
+ /* First page not in buffer? */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) { /* Yes, we have to read it in */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf;
+ print_page(text, height-4, width-2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'G': /* Last page */
+#ifdef HAVE_NCURSES
+ case KEY_END:
+#endif
+ end_reached = 1;
+ /* Last page not in buffer? */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if (fpos < file_size) { /* Yes, we have to read it in */
+ if (lseek(fd, -BUF_SIZE, SEEK_END) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ page = buf + bytes_read;
+ back_lines(height-4);
+ print_page(text, height-4, width-2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ break;
+ case 'K': /* Previous line */
+ case 'k':
+ case '\020': /* ^P */
+ case KEY_UP:
+ if (!begin_reached) {
+ back_lines(page_length+1);
+#ifdef HAVE_NCURSES
+ /* We don't call print_page() here but use scrolling to ensure
+ faster screen update. However, 'end_reached' and 'page_length'
+ should still be updated, and 'page' should point to start of
+ next page. This is done by calling get_line() in the following
+ 'for' loop. */
+ scrollok(text, TRUE);
+ wscrl(text, -1); /* Scroll text region down one line */
+ scrollok(text, FALSE);
+ page_length = 0;
+ passed_end = 0;
+ for (i = 0; i < height-4; i++) {
+ if (!i) {
+ print_line(text, 0, width-2); /* print first line of page */
+ wnoutrefresh(text);
+ }
+ else
+ get_line(); /* Called to update 'end_reached' and 'page' */
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+#else
+ print_page(text, height-4, width-2);
+#endif
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'B': /* Previous page */
+ case 'b':
+ case KEY_PPAGE:
+ if (!begin_reached) {
+ back_lines(page_length + height-4);
+ print_page(text, height-4, width-2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'J': /* Next line */
+ case 'j':
+ case '\016': /* ^N */
+ case KEY_DOWN:
+ if (!end_reached) {
+ begin_reached = 0;
+ scrollok(text, TRUE);
+ scroll(text); /* Scroll text region up one line */
+ scrollok(text, FALSE);
+ print_line(text, height-5, width-2);
+#ifndef HAVE_NCURSES
+ wmove(text, height-5, 0);
+ waddch(text, ' ');
+ wmove(text, height-5, width-3);
+ waddch(text, ' ');
+#endif
+ wnoutrefresh(text);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'F': /* Next page */
+ case 'f':
+ case KEY_NPAGE:
+ if (!end_reached) {
+ begin_reached = 0;
+ print_page(text, height-4, width-2);
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case '0': /* Beginning of line */
+ case 'H': /* Scroll left */
+ case 'h':
+ case KEY_LEFT:
+ if (hscroll > 0) {
+ if (key == '0')
+ hscroll = 0;
+ else
+ hscroll--;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ print_page(text, height-4, width-2);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case 'L': /* Scroll right */
+ case 'l':
+ case KEY_RIGHT:
+ if (hscroll < MAX_LEN) {
+ hscroll++;
+ /* Reprint current page to scroll horizontally */
+ back_lines(page_length);
+ print_page(text, height-4, width-2);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ break;
+ case '/': /* Forward search */
+ case 'n': /* Repeat forward search */
+ case '?': /* Backward search */
+ case 'N': /* Repeat backward search */
+ /* set search direction */
+ dir = (key == '/' || key == 'n') ? 1 : 0;
+ if (dir ? !end_reached : !begin_reached) {
+ if (key == 'n' || key == 'N') {
+ if (search_term[0] == '\0') { /* No search term yet */
+ fprintf(stderr, "\a"); /* beep */
+ break;
+ }
+ }
+ else /* Get search term from user */
+ if (get_search_term(text, search_term, height-4, width-2) == -1) {
+ /* ESC pressed in get_search_term(). Reprint page to clear box */
+ wattrset(text, dialog_attr);
+ back_lines(page_length);
+ print_page(text, height-4, width-2);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ break;
+ }
+ /* Save variables for restoring in case search term can't be found */
+ tempptr = page;
+ temp = begin_reached;
+ temp1 = end_reached;
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ fpos -= bytes_read;
+ /* update 'page' to point to next (previous) line before
+ forward (backward) searching */
+ back_lines(dir ? page_length-1 : page_length+1);
+ found = NULL;
+ if (dir) /* Forward search */
+ while((found = strstr(get_line(), search_term)) == NULL) {
+ if (end_reached)
+ break;
+ }
+ else /* Backward search */
+ while((found = strstr(get_line(), search_term)) == NULL) {
+ if (begin_reached)
+ break;
+ back_lines(2);
+ }
+ if (found == NULL) { /* not found */
+ fprintf(stderr, "\a"); /* beep */
+ /* Restore program state to that before searching */
+ if (lseek(fd, fpos, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in dialog_textbox().\n");
+ exit(-1);
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in dialog_textbox().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ page = tempptr;
+ begin_reached = temp;
+ end_reached = temp1;
+ /* move 'page' to point to start of current page in order to
+ re-print current page. Note that 'page' always points to
+ start of next page, so this is necessary */
+ back_lines(page_length);
+ }
+ else /* Search term found */
+ back_lines(1);
+ /* Reprint page */
+ wattrset(text, dialog_attr);
+ print_page(text, height-4, width-2);
+ if (found != NULL)
+ print_position(dialog, height, width);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
+ wrefresh(dialog);
+ }
+ else /* no need to find */
+ fprintf(stderr, "\a"); /* beep */
+ break;
+ case ESC:
+ break;
+ case KEY_F(1):
+ display_helpfile();
+ break;
+ }
+ }
+
+ delwin(dialog);
+ free(buf);
+ close(fd);
+ return (key == ESC ? -1 : 0);
+}
+/* End of dialog_textbox() */
+
+
+/*
+ * Go back 'n' lines in text file. Called by dialog_textbox().
+ * 'page' will be updated to point to the desired line in 'buf'.
+ */
+static void back_lines(int n)
+{
+ int i, fpos;
+
+ begin_reached = 0;
+ /* We have to distinguish between end_reached and !end_reached since at end
+ of file, the line is not ended by a '\n'. The code inside 'if' basically
+ does a '--page' to move one character backward so as to skip '\n' of the
+ previous line */
+ if (!end_reached) {
+ /* Either beginning of buffer or beginning of file reached? */
+ if (page == buf) {
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) { /* Not beginning of file yet */
+ /* We've reached beginning of buffer, but not beginning of file yet,
+ so read previous part of file into buffer. Note that we only
+ move backward for BUF_SIZE/2 bytes, but not BUF_SIZE bytes to
+ avoid re-reading again in print_page() later */
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE/2 + bytes_read) {
+ /* No, move less then */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + fpos - bytes_read;
+ }
+ else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek(fd, -(BUF_SIZE/2 + bytes_read), SEEK_CUR) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + BUF_SIZE/2;
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in back_lines().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ if (*(--page) != '\n') { /* '--page' here */
+ /* Something's wrong... */
+ endwin();
+ fprintf(stderr, "\nInternal error in back_lines().\n");
+ exit(-1);
+ }
+ }
+
+ /* Go back 'n' lines */
+ for (i = 0; i < n; i++)
+ do {
+ if (page == buf) {
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ if (fpos > bytes_read) {
+ /* Really possible to move backward BUF_SIZE/2 bytes? */
+ if (fpos < BUF_SIZE/2 + bytes_read) {
+ /* No, move less then */
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + fpos - bytes_read;
+ }
+ else { /* Move backward BUF_SIZE/2 bytes */
+ if (lseek(fd, -(BUF_SIZE/2 + bytes_read), SEEK_CUR) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in back_lines().\n");
+ exit(-1);
+ }
+ page = buf + BUF_SIZE/2;
+ }
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in back_lines().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ }
+ else { /* Beginning of file reached */
+ begin_reached = 1;
+ return;
+ }
+ }
+ } while (*(--page) != '\n');
+ page++;
+}
+/* End of back_lines() */
+
+
+/*
+ * Print a new page of text. Called by dialog_textbox().
+ */
+static void print_page(WINDOW *win, int height, int width)
+{
+ int i, passed_end = 0;
+
+ page_length = 0;
+ for (i = 0; i < height; i++) {
+ print_line(win, i, width);
+ if (!passed_end)
+ page_length++;
+ if (end_reached && !passed_end)
+ passed_end = 1;
+ }
+ wnoutrefresh(win);
+}
+/* End of print_page() */
+
+
+/*
+ * Print a new line of text. Called by dialog_textbox() and print_page().
+ */
+static void print_line(WINDOW *win, int row, int width)
+{
+ int i, y, x;
+ unsigned char *line;
+
+ line = get_line();
+ line += MIN(strlen(line),hscroll); /* Scroll horizontally */
+ wmove(win, row, 0); /* move cursor to correct line */
+ waddch(win,' ');
+#ifdef HAVE_NCURSES
+ waddnstr(win, line, MIN(strlen(line),width-2));
+#else
+ line[MIN(strlen(line),width-2)] = '\0';
+ waddstr(win, line);
+#endif
+
+ getyx(win, y, x);
+ /* Clear 'residue' of previous line */
+ for (i = 0; i < width-x; i++)
+ waddch(win, ' ');
+}
+/* End of print_line() */
+
+
+/*
+ * Return current line of text. Called by dialog_textbox() and print_line().
+ * 'page' should point to start of current line before calling, and will be
+ * updated to point to start of next line.
+ */
+static unsigned char *get_line(void)
+{
+ int i = 0, fpos;
+ static unsigned char line[MAX_LEN+1];
+
+ end_reached = 0;
+ while (*page != '\n') {
+ if (*page == '\0') { /* Either end of file or end of buffer reached */
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in get_line().\n");
+ exit(-1);
+ }
+ if (fpos < file_size) { /* Not end of file yet */
+ /* We've reached end of buffer, but not end of file yet, so read next
+ part of file into buffer */
+ if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError reading file in get_line().\n");
+ exit(-1);
+ }
+ buf[bytes_read] = '\0';
+ page = buf;
+ }
+ else {
+ if (!end_reached)
+ end_reached = 1;
+ break;
+ }
+ }
+ else
+ if (i < MAX_LEN)
+ line[i++] = *(page++);
+ else {
+ if (i == MAX_LEN) /* Truncate lines longer than MAX_LEN characters */
+ line[i++] = '\0';
+ page++;
+ }
+ }
+ if (i <= MAX_LEN)
+ line[i] = '\0';
+ if (!end_reached)
+ page++; /* move pass '\n' */
+
+ return line;
+}
+/* End of get_line() */
+
+
+/*
+ * Display a dialog box and get the search term from user
+ */
+static int get_search_term(WINDOW *win, unsigned char *search_term, int height, int width)
+{
+ int x, y, key = 0, first,
+ box_height = 3, box_width = 30;
+
+ x = (width - box_width)/2;
+ y = (height - box_height)/2;
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(win, y, x, box_height, box_width);
+#endif
+ draw_box(win, y, x, box_height, box_width, dialog_attr, searchbox_border_attr);
+ wattrset(win, searchbox_title_attr);
+ wmove(win, y, x+box_width/2-4);
+ waddstr(win, " Search ");
+ wattrset(win, dialog_attr);
+
+ search_term[0] = '\0';
+
+ first = 1;
+ while (key != ESC) {
+ key = line_edit(win, y+1, x+1, -1, box_width-2, searchbox_attr, first, search_term, 0);
+ first = 0;
+ switch (key) {
+ case '\n':
+ if (search_term[0] != '\0')
+ return 0;
+ break;
+ case ESC:
+ break;
+ }
+ }
+
+ return -1; /* ESC pressed */
+}
+/* End of get_search_term() */
+
+
+/*
+ * Print current position
+ */
+static void print_position(WINDOW *win, int height, int width)
+{
+ int fpos, percent;
+
+ if ((fpos = lseek(fd, 0, SEEK_CUR)) == -1) {
+ endwin();
+ fprintf(stderr, "\nError moving file pointer in print_position().\n");
+ exit(-1);
+ }
+ wattrset(win, position_indicator_attr);
+ percent = !file_size ? 100 : ((fpos-bytes_read+page-buf)*100)/file_size;
+ wmove(win, height-3, width-9);
+ wprintw(win, "(%3d%%)", percent);
+}
+/* End of print_position() */
diff --git a/gnu/lib/libdialog/tree.c b/gnu/lib/libdialog/tree.c
new file mode 100644
index 0000000..031c05b
--- /dev/null
+++ b/gnu/lib/libdialog/tree.c
@@ -0,0 +1,1135 @@
+/*
+ * tree.c -- implements the 'tree' interface element for libdialog
+ *
+ * Author: Anatoly A. Orehovsky (tolik@mpeks.tomsk.su)
+ *
+ * Copyright (c) 1997, Anatoly A. Orehovsky
+ * 09/28/98 - patched by Anatoly A. Orehovsky (smart_tree())
+ *
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <stdlib.h>
+#include <strings.h>
+#include <stdio.h>
+#include <dialog.h>
+#include "dialog.priv.h"
+#include <ncurses.h>
+
+/* static utils for make tree */
+struct leaf {
+ unsigned char *name; /* name of leaf */
+ unsigned char *branches; /* branches that going by leaf */
+ unsigned char slip; /* slip of leaf*/
+ int shift; /* shift relative root of tree */
+};
+
+static int mk_slip(struct leaf array[], int arr_size,
+ int number, int shift);
+
+/* make tree from file
+ *
+ * filename - name of file with like find(1) output
+ * p_names - pointer to array of strings
+ * p_size - pointer to size of array
+ * FS - fields separator
+ * p_array - pointer to array of leafs
+ *
+ * return values:
+ * 0 - ok and names by p_names, size by p_size, array by p_array set
+ * -1 - memory allocation error (errno set)
+ */
+
+static int mk_ftree(char *filename,
+ unsigned char ***p_names, int *p_size, unsigned char FS,
+ struct leaf **p_array);
+
+/* make tree from array
+ *
+ * names - array of strings
+ * size - size of array
+ * FS - fields separator
+ * p_array - pointer to array of leafs
+ *
+ * return values:
+ * 0 - ok and array by p_array set
+ * -1 - memory allocation error (errno set)
+ */
+
+static int mk_tree(unsigned char **names, int size, unsigned char FS,
+ struct leaf **p_array);
+
+/* free memory from tree (leafs)
+ *
+ * return values:
+ * nothing
+ */
+
+static void free_leafs(struct leaf *array, int size);
+
+/* free memory from source data for tree (names)
+ *
+ * return values:
+ * if 0 <= choice <= size - pointer to name from names,
+ * and memory for name not released (must be freed later)
+ * else - NULL (recomended choice -1 for it)
+ */
+
+static unsigned char *free_names(unsigned char **names,
+ int size, int choice);
+
+/* end of static utils for make tree */
+
+/* static utils for ftree */
+
+/* control struct for queue */
+struct queue {
+ int size; /* size of queue */
+ struct m_queue *first; /* begin of queue */
+ struct m_queue *last; /* end of queue */
+};
+
+/* queue member */
+struct m_queue {
+ void *pointer; /* queue member */
+ struct m_queue *next; /* next queue member */
+};
+
+/* init struct queue by zeros */
+static void init_queue(struct queue *queue);
+
+/* add pointer to queue */
+/* return - pointer or NULL if error */
+static void *p2_queue(struct queue *queue, void *pointer);
+
+/* get first from queue */
+/* return - pointer or NULL if queue is empty */
+static void *first_queue(struct queue *queue);
+
+/* make zero terminated array from queue */
+/* return - pointer to array or NULL if error */
+static void **q2arr(struct queue *queue, int depth);
+
+/* smart_tree (for like find(1) with -d flag output compliance) */
+/* return - not NULL or NULL if malloc error */
+static unsigned char *smart_tree(struct queue *queue, unsigned char FS,
+ unsigned char *current,
+ unsigned char *prev);
+
+/* end of static utils for ftree */
+
+/* static utils for saved_tree */
+
+/* saved values for unique tree */
+struct saved_tree {
+ unsigned char **names; /* names + */
+ int size; /* size + */
+ unsigned char FS; /* FS + */
+ int height; /* height + */
+ int width; /* width + */
+ int menu_height; /* menu_height - unique for treebox ? */
+ int ch; /* saved ch - choice */
+ int sc; /* saved sc - scroll */
+};
+
+/* search saved tree within queue */
+/* return - struct saved_tree * or NULL if not found */
+static struct saved_tree *search_saved_tree(struct queue *queue,
+ unsigned char **names,
+ int size,
+ unsigned char FS,
+ int height,
+ int width,
+ int menu_height);
+
+/* end of static utils for saved_tree */
+
+static void print_item(WINDOW *win, struct leaf item, int choice, int selected);
+
+static void print_position(WINDOW *win, int x, int y,
+ int cur_pos, int size);
+
+static int menu_width, item_x;
+
+static int dialog_treemenu(unsigned char *title, unsigned char *prompt,
+ int height, int width, int menu_height,
+ int item_no, struct leaf items[],
+ int *result,
+ int *ch, int *sc);
+
+/*
+ * Display a menu for choosing among a number of options
+ */
+static
+int dialog_treemenu(unsigned char *title, unsigned char *prompt,
+ int height, int width, int menu_height,
+ int item_no, struct leaf items[],
+ int *result,
+ int *ch, int *sc)
+{
+ int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0,
+ l, scroll = 0, max_choice, redraw_menu = FALSE;
+ WINDOW *dialog, *menu;
+
+ if (ch) /* restore menu item info */
+ choice = *ch;
+ if (sc)
+ scroll = *sc;
+
+ max_choice = MIN(menu_height, item_no);
+
+ item_x = 0;
+ /* Find length of longest item in order to center menu */
+ for (i = 0; i < item_no; i++) {
+ l = strlen(items[i].name) + strlen(items[i].branches) * 4 + 4;
+ item_x = MAX(item_x, l);
+ }
+
+ if (height < 0)
+ height = strheight(prompt)+menu_height+4+2;
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i,j);
+ width = MAX(width,item_x+4)+4;
+ }
+ width = MAX(width,24);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = (COLS - width)/2;
+ y = (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
+ exit(1);
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+ print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE);
+
+ menu_width = width-6;
+ getyx(dialog, cur_y, cur_x);
+ box_y = cur_y + 1;
+ box_x = (width - menu_width)/2 - 1;
+
+ /* create new window for the menu */
+ menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1);
+ if (menu == NULL) {
+ endwin();
+ fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height,menu_width,y+box_y+1,x+box_x+1);
+ exit(1);
+ }
+ keypad(menu, TRUE);
+
+ /* draw a box around the menu items */
+ draw_box(dialog, box_y, box_x, menu_height+2, menu_width+2, menubox_border_attr, menubox_attr);
+
+ item_x = 1;
+
+ /* Print the menu */
+ for (i = 0; i < max_choice; i++)
+ print_item(menu, items[(scroll+i)], i, i == choice);
+ wnoutrefresh(menu);
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y);
+ print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no);
+
+ display_helpline(dialog, height-1, width);
+
+ x = width/2-11;
+ y = height-2;
+ print_button(dialog, "Cancel", y, x+14, FALSE);
+ print_button(dialog, " OK ", y, x, TRUE);
+
+ wrefresh(dialog);
+
+ while (key != ESC) {
+ key = wgetch(dialog);
+ /* Check if key pressed matches first character of any item tag in menu */
+
+ if (key == KEY_UP || key == KEY_DOWN || key == '-' || key == '+') {
+ if (key == KEY_UP || key == '-') {
+ if (!choice) {
+ if (scroll) {
+#ifdef BROKEN_WSCRL
+ /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation
+ violation when scrolling windows of height = 4, so scrolling is not
+ used for now */
+ scroll--;
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ /* Reprint menu to scroll down */
+ for (i = 0; i < max_choice; i++)
+ print_item(menu, items[(scroll+i)], i, i == choice);
+
+#else
+
+ /* Scroll menu down */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (menu_height > 1) {
+ /* De-highlight current first item before scrolling down */
+ print_item(menu, items[scroll], 0, FALSE);
+ scrollok(menu, TRUE);
+ wscrl(menu, -1);
+ scrollok(menu, FALSE);
+ }
+ scroll--;
+ print_item(menu, items[scroll], 0, TRUE);
+#endif
+ wnoutrefresh(menu);
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y);
+ print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice - 1;
+ }
+ else if (key == KEY_DOWN || key == '+') {
+ if (choice == max_choice - 1) {
+ if (scroll+choice < item_no-1) {
+#ifdef BROKEN_WSCRL
+ /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation
+ violation when scrolling windows of height = 4, so scrolling is not
+ used for now */
+ scroll++;
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ /* Reprint menu to scroll up */
+ for (i = 0; i < max_choice; i++)
+ print_item(menu, items[(scroll+i)], i, i == choice);
+
+#else
+
+ /* Scroll menu up */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ if (menu_height > 1) {
+ /* De-highlight current last item before scrolling up */
+ print_item(menu, items[(scroll+max_choice-1)], max_choice-1, FALSE);
+ scrollok(menu, TRUE);
+ scroll(menu);
+ scrollok(menu, FALSE);
+ }
+ scroll++;
+ print_item(menu, items[(scroll+max_choice-1)], max_choice-1, TRUE);
+#endif
+ wnoutrefresh(menu);
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y);
+ print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+ else
+ i = choice + 1;
+ }
+
+ if (i != choice) {
+ /* De-highlight current item */
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ print_item(menu, items[(scroll+choice)], choice, FALSE);
+
+ /* Highlight new item */
+ choice = i;
+ print_item(menu, items[(scroll+choice)], choice, TRUE);
+ wnoutrefresh(menu);
+ print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
+ wrefresh(dialog);
+ }
+ continue; /* wait for another key press */
+ }
+
+ /* save info about menu item position */
+ if (ch)
+ *ch = choice;
+ if (sc)
+ *sc = scroll;
+
+ switch (key) {
+ case KEY_PPAGE:
+ case 'B' :
+ case 'b' :
+ if (scroll > menu_height) { /* can we go up? */
+ scroll -= (menu_height);
+ } else {
+ scroll = 0;
+ }
+ redraw_menu = TRUE;
+ break;
+ case KEY_NPAGE:
+ case 'F' :
+ case 'f' :
+ if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */
+ scroll = item_no - menu_height;
+ if (scroll < 0) scroll = 0;
+ } else {
+ scroll += menu_height;
+ }
+ redraw_menu = TRUE;
+ break;
+ case KEY_HOME:
+ case 'g' :
+ scroll = 0;
+ choice = 0;
+ redraw_menu = TRUE;
+ break;
+ case KEY_END:
+ case 'G' :
+ scroll = item_no - menu_height;
+ if (scroll < 0) scroll = 0;
+ choice = max_choice - 1;
+ redraw_menu = TRUE;
+ break;
+ case 'O':
+ case 'o':
+ delwin(dialog);
+ *result = scroll+choice;
+ return 0;
+ case 'C':
+ case 'c':
+ delwin(dialog);
+ return 1;
+ case KEY_BTAB:
+ case TAB:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ if (!button) {
+ button = 1; /* Indicates "Cancel" button is selected */
+ print_button(dialog, " OK ", y, x, FALSE);
+ print_button(dialog, "Cancel", y, x+14, TRUE);
+ }
+ else {
+ button = 0; /* Indicates "OK" button is selected */
+ print_button(dialog, "Cancel", y, x+14, FALSE);
+ print_button(dialog, " OK ", y, x, TRUE);
+ }
+ wrefresh(dialog);
+ break;
+ case ' ':
+ case '\r':
+ case '\n':
+ delwin(dialog);
+ if (!button)
+ *result = scroll+choice;
+ return button;
+ case ESC:
+ break;
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+ if (redraw_menu) {
+ for (i = 0; i < max_choice; i++) {
+ print_item(menu, items[(scroll+i)],
+ i, i == choice);
+ }
+ wnoutrefresh(menu);
+ getyx(dialog, cur_y, cur_x); /* Save cursor position */
+ print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y);
+ print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no);
+ wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
+ wrefresh(dialog);
+ redraw_menu = FALSE;
+ }
+ }
+
+ delwin(dialog);
+ return -1; /* ESC pressed */
+}
+/* End of dialog_treemenu() */
+
+
+/*
+ * Print menu item
+ */
+static void print_item(WINDOW *win, struct leaf item, int choice, int selected)
+{
+ int i, j = menu_width - 2;
+ char *branches = item.branches;
+
+ /* Clear 'residue' of last item */
+ wattrset(win, menubox_attr);
+ wmove(win, choice, 0);
+ for (i = 0; i < menu_width; i++)
+ waddch(win, ' ');
+ wmove(win, choice, item_x);
+
+ while(*branches && j)
+ {
+ switch (*branches++) {
+ case ' ' : waddch(win, ' ');
+ break;
+ case '|' : waddch(win, ACS_VLINE);
+ }
+
+ j--;
+ i = 3;
+ while(i-- && j)
+ {
+ waddch(win, ' ');
+ j--;
+ }
+ }
+
+ if (j)
+ {
+ switch (item.slip) {
+ case '+' : waddch(win, ACS_LTEE);
+ break;
+ case '`' : waddch(win, ACS_LLCORNER);
+ }
+ j--;
+ }
+
+ i = 3;
+ while(i-- && j)
+ {
+ waddch(win, ACS_HLINE);
+ j--;
+ }
+
+ wattrset(win, selected ? item_selected_attr : item_attr);
+ if (j)
+ waddnstr(win, item.name, j);
+}
+/* End of print_item() */
+
+/*
+ * Print current position
+ */
+static void print_position(WINDOW *win, int x, int y,
+ int cur_pos, int size)
+{
+ int percent;
+
+ wattrset(win, position_indicator_attr);
+ percent = cur_pos == size - 1 ? 100 : (cur_pos * 100)/(size - 1);
+ wmove(win, y + 1, x - 6);
+ wprintw(win, "(%3d%%)", percent);
+}
+/* End of print_position() */
+
+/*
+ * Display a tree menu from file
+ *
+ * filename - file with like find(1) output
+ * FS - fields separator
+ * title - title of dialog box
+ * prompt - prompt text into dialog box
+ * height - height of dialog box
+ * width - width of dialog box
+ * menu_height - height of menu box
+ * result - pointer to char array
+ *
+ * return values:
+ * -1 - ESC pressed
+ * 0 - Ok, result set (must be freed later)
+ * 1 - Cancel
+ */
+
+int dialog_ftree(unsigned char *filename, unsigned char FS,
+ unsigned char *title, unsigned char *prompt,
+ int height, int width, int menu_height,
+ unsigned char **result)
+{
+ int retcode, choice, size;
+ struct leaf *items;
+ unsigned char **names;
+
+ if (mk_ftree(filename, &names, &size, FS, &items))
+ {
+ perror("dialog_ftree");
+ end_dialog();
+ exit(-1);
+ }
+
+ if (!size)
+ {
+ fprintf(stderr, "\ndialog_ftree: file %s is empty\n", filename);
+ end_dialog();
+ exit(-1);
+ }
+
+ retcode = dialog_treemenu(title, prompt, height, width, menu_height,
+ size, items, &choice, NULL, NULL);
+
+ free_leafs(items, size);
+
+ if (!retcode)
+ *result = free_names(names, size, choice);
+ else
+ (void)free_names(names, size, -1);
+
+ return retcode;
+}
+/* End of dialog_ftree() */
+
+/*
+ * Display a tree menu from array
+ *
+ * names - array with like find(1) output
+ * size - size of array
+ * FS - fields separator
+ * title - title of dialog box
+ * prompt - prompt text into dialog box
+ * height - height of dialog box
+ * width - width of dialog box
+ * menu_height - height of menu box
+ * result - pointer to char array
+ *
+ * return values:
+ * -1 - ESC pressed
+ * 0 - Ok, result set
+ * 1 - Cancel
+ */
+
+int dialog_tree(unsigned char **names, int size, unsigned char FS,
+ unsigned char *title, unsigned char *prompt,
+ int height, int width, int menu_height,
+ unsigned char **result)
+{
+ int retcode, choice;
+ struct leaf *items;
+ struct saved_tree *st;
+ static struct queue *q_saved_tree = NULL;
+
+ if (!size)
+ {
+ fprintf(stderr, "\ndialog_tree: source array is empty\n");
+ end_dialog();
+ exit(-1);
+ }
+
+ if (mk_tree(names, size, FS, &items))
+ {
+ perror("dialog_tree");
+ end_dialog();
+ exit(-1);
+ }
+
+/* is tree saved ? */
+ if (!(st = search_saved_tree(q_saved_tree, names,
+ size, FS,
+ height, width, menu_height))) {
+ if (!q_saved_tree) {
+ if (!(q_saved_tree =
+ calloc(sizeof (struct queue), 1))) {
+ perror("dialog_tree");
+ end_dialog();
+ exit(-1);
+ }
+ }
+
+ if (!(st = calloc(sizeof (struct saved_tree), 1))) {
+ perror("dialog_tree");
+ end_dialog();
+ exit(-1);
+ }
+
+ st->names = names;
+ st->size = size;
+ st->FS = FS;
+ st->height = height;
+ st->width = width;
+ st->menu_height = menu_height;
+
+ if (!p2_queue(q_saved_tree, st)) {
+ perror("dialog_tree");
+ end_dialog();
+ exit(-1);
+ }
+ }
+
+ retcode = dialog_treemenu(title, prompt, height, width, menu_height,
+ size, items, &choice,
+ &(st->ch), &(st->sc));
+
+ free_leafs(items, size);
+
+ if (!retcode)
+ *result = names[choice];
+
+ return retcode;
+}
+/* End of dialog_tree() */
+
+/* utils for ftree */
+
+/* init struct queue by zeros */
+static void
+init_queue(struct queue *queue)
+{
+ bzero((void *)queue, sizeof(struct queue));
+}
+
+/* add pointer to queue */
+/* return - pointer or NULL if error */
+static void *
+p2_queue(struct queue *queue, void *pointer)
+{
+ if (!queue)
+ return NULL;
+
+ if (!queue->first)
+ {
+ if (!(queue->first = queue->last =
+ calloc(1, sizeof(struct m_queue))))
+ return NULL;
+
+ }
+ else
+ {
+ if (!(queue->last->next =
+ calloc(1, sizeof(struct m_queue))))
+ return NULL;
+
+ queue->last = queue->last->next;
+ }
+
+ queue->size++;
+ return queue->last->pointer = pointer;
+}
+
+/* get first from queue */
+/* return - pointer or NULL if queue is empty */
+static void *
+first_queue(struct queue *queue)
+{
+ void *retval;
+ struct m_queue *new_first;
+
+ if (!queue ||
+ !queue->first ||
+ !queue->size)
+ return NULL;
+
+ retval = queue->first->pointer;
+ new_first = queue->first->next;
+ free(queue->first);
+ queue->first = new_first;
+ queue->size--;
+
+ return retval;
+
+}
+
+/* make zero terminated array from queue */
+/* return - pointer to array or NULL if error */
+static void **
+q2arr(struct queue *queue, int depth)
+{
+ void **mono, **end;
+
+ if (!queue ||
+ !queue->first ||
+ !queue->size)
+ return NULL;
+
+ /* memory allocation for array */
+ if (!(mono = end = malloc(depth * sizeof(void *) + 1)))
+ return NULL;
+
+ while(depth--)
+ {
+ if (!(*end++ = first_queue(queue)))
+ break;
+ }
+
+ *end = NULL;
+
+ return mono;
+
+}
+
+/*
+ * smart_tree (for like find(1) with -d flag output compliance)
+ *
+ * return values:
+ * NULL - malloc error
+ * not NULL - ok
+ *
+ */
+static
+unsigned char *
+smart_tree(struct queue *queue,
+ unsigned char FS,
+ unsigned char *current,
+ unsigned char *prev) {
+ unsigned char *pcurrent = current, *pprev = prev, *toqueue;
+ register char break_flag = 0;
+
+ while(*pcurrent && *pprev) {
+ if (*pcurrent == *pprev) {
+ pcurrent++;
+ pprev++;
+ }
+ else {
+ break_flag = 1;
+ break;
+ }
+ }
+
+ if (!*pprev || break_flag) {
+ if (*pcurrent == FS) {
+ pcurrent++;
+
+ if ((!*prev) && (*pcurrent)) {
+ unsigned char tchar = *pcurrent;
+
+ *pcurrent = '\0';
+ if (!(toqueue = strdup(current))) {
+ *pcurrent = tchar;
+ return NULL;
+ }
+ if (!p2_queue(queue, toqueue)) {
+ *pcurrent = tchar;
+ return NULL;
+ }
+ *pcurrent = tchar;
+ }
+ }
+
+ while(*pcurrent) {
+ if (*pcurrent == FS) {
+ *pcurrent = '\0';
+ if (!(toqueue = strdup(current))) {
+ *pcurrent = FS;
+ return NULL;
+ }
+ if (!p2_queue(queue, toqueue)) {
+ *pcurrent = FS;
+ return NULL;
+ }
+ *pcurrent = FS;
+ }
+ pcurrent++;
+ }
+ if (!p2_queue(queue, current))
+ return NULL;
+ }
+ return current;
+}
+
+/* end of utils for ftree */
+
+/* utils for make tree */
+
+/* if error - return -1 */
+static
+int
+mk_slip(struct leaf array[], int arr_size, int number, int shift)
+{
+ int t_number;
+ int t_shift;
+
+ if (number > arr_size - 1)
+ return number - 1;
+
+ t_shift = shift;
+
+ if (!(array[number].branches = calloc(1, t_shift + 1)))
+ return -1;
+
+ (void)memset(array[number].branches, ' ', t_shift);
+
+ t_number = number;
+
+ while (array[number].shift < array[t_number + 1].shift)
+ {
+ t_number = mk_slip(array, arr_size, t_number + 1, t_shift + 1);
+ if (t_number < 0)
+ return -1;
+ if (t_number == arr_size - 1)
+ break;
+ }
+
+ if (array[number].shift == array[t_number + 1].shift)
+ array[number].slip = '+';
+
+ if ((array[number].shift > array[t_number + 1].shift) ||
+ t_number == arr_size - 1)
+ array[number].slip = '`';
+
+ return t_number;
+
+} /* mk_slip() */
+
+/* make tree from file
+ *
+ * filename - name of file with like find(1) output
+ * p_names - pointer to array of strings
+ * p_size - pointer to size of array
+ * FS - fields separator
+ * p_array - pointer to array of leafs
+ *
+ * return values:
+ * 0 - ok and names by p_names, size by p_size, array by p_array set
+ * -1 - memory allocation error (errno set)
+ */
+
+static
+int
+mk_ftree(char *filename,
+ unsigned char ***p_names, int *p_size, unsigned char FS,
+ struct leaf **p_array)
+{
+ int NR; /* number of input records */
+ struct queue queue;
+ unsigned char *string, *sstring = "";
+ unsigned char **names;
+
+ FILE *input_file;
+
+ if (!(input_file = fopen(filename, "r")))
+ return -1;
+
+ init_queue(&queue);
+
+ if (!(string = malloc(BUFSIZ)))
+ return -1;
+
+ /* read input file into queue */
+ while(fgets(string, BUFSIZ, input_file))
+ {
+ if (strchr(string, '\n'))
+ *strchr(string, '\n') = '\0';
+
+ if (!(string = realloc(string, strlen(string) + 1)))
+ return -1;
+
+ if (!smart_tree(&queue, FS, string, sstring))
+ return -1;
+ sstring = string;
+
+ if (!(string = malloc(BUFSIZ)))
+ return -1;
+ } /* read input file into queue */
+
+ if (fclose(input_file) == EOF)
+ return -1;
+
+ if (!(NR = queue.size))
+ {
+ *p_size = 0;
+ return 0;
+ }
+
+ /* make array from queue */
+ if (!(names = (unsigned char **)q2arr(&queue, NR)))
+ return -1;
+
+ *p_names = names;
+ *p_size = NR;
+
+ /* make tree from array */
+ return mk_tree(names, NR, FS, p_array);
+
+} /* mk_ftree */
+
+/* make tree from array
+ *
+ * names - array of strings
+ * size - size of array
+ * FS - fields separator
+ * p_array - pointer to array of leafs
+ *
+ * return values:
+ * 0 - ok and array by p_array set
+ * -1 - memory allocation error (errno set)
+ */
+
+static
+int
+mk_tree(unsigned char **names, int size, unsigned char FS,
+ struct leaf **p_array)
+{
+ int i;
+ struct leaf *array;
+
+ /* make array of leafs */
+ if (!(array = calloc(size, sizeof(struct leaf))))
+ return -1;
+
+ /* init leafs */
+ for (i = 0; i < size; i++)
+ {
+ unsigned char *in_string, *name;
+ int shift = 0;
+
+ in_string = name = names[i];
+ while(*in_string)
+ {
+ if (*in_string == FS) {
+ if (!i && !*(in_string + 1))
+ name = in_string;
+ else
+ {
+ shift++;
+ name = in_string + 1;
+ }
+ }
+ in_string++;
+ }
+ array[i].name = name;
+ array[i].shift = shift;
+ array[i].slip = '\0';
+ array[i].branches = NULL;
+ } /* init leafs */
+
+ /* make slips */
+ for (i = 0;i < size; i++)
+ {
+ i = mk_slip(array, size, i, 0);
+ if (i < 0)
+ return -1;
+ } /* make slips */
+
+ /* make branches */
+ for (i = 1;i < size; i++)
+ {
+ unsigned char *src = array[i - 1].branches;
+ unsigned char *dst = array[i].branches;
+
+ while(*src && *dst)
+ *dst++ = *src++;
+
+ if (*dst)
+ switch (array[i - 1].slip) {
+ case '+' : *dst = '|';
+ break;
+ case '`' : *dst = ' ';
+ }
+ } /* make branches */
+
+ *p_array = array;
+ return 0;
+
+} /* mk_tree() */
+
+/* free memory from tree (leafs)
+ *
+ * return values:
+ * nothing
+ */
+
+static
+void
+free_leafs(struct leaf *array, int size)
+{
+ struct leaf *p_array = array;
+
+ while (size--)
+ free(array++->branches);
+
+ free(p_array);
+} /* free_leafs() */
+
+/* free memory from source data for tree (names)
+ *
+ * return values:
+ * if 0 <= choice <= size - pointer to name from names,
+ * and memory for name not released (must be freed later)
+ * else - NULL (recomended choice -1 for it)
+ */
+
+static
+unsigned char *
+free_names(unsigned char **names, int size, int choice)
+{
+ unsigned char *retval = NULL;
+ unsigned char **p_names = names;
+
+ while (size--)
+ {
+ if (!choice--)
+ retval = *names++;
+ else
+ free(*names++);
+ }
+ free(p_names);
+ return retval;
+} /* free_names() */
+
+/* end of utils for make tree */
+
+/* static utils for saved_tree */
+
+/* search saved tree within queue */
+/* return - struct *saved_tree or NULL if not found */
+static
+struct saved_tree *
+search_saved_tree(struct queue *queue, unsigned char **names, int size,
+ unsigned char FS,
+ int height, int width,
+ int menu_height)
+{
+ struct m_queue *member;
+ struct saved_tree *retval;
+
+ if (!queue || !names || !FS ||
+ !height || !width || !menu_height)
+ return NULL;
+
+ if (!(member = queue->first))
+ return NULL;
+
+ while (member->next) {
+ retval = member->pointer;
+ if ((names == retval->names) &&
+ (size == retval->size) &&
+ (FS == retval->FS) &&
+ (height == retval->height) &&
+ (width == retval->width) &&
+ (menu_height == retval->menu_height))
+ return retval;
+ member = member->next;
+ }
+ retval = member->pointer;
+ if ((names == retval->names) &&
+ (size == retval->size) &&
+ (FS == retval->FS) &&
+ (height == retval->height) &&
+ (width == retval->width) &&
+ (menu_height == retval->menu_height))
+ return retval;
+ return NULL;
+}
+
+/* end of static utils for saved_tree */
diff --git a/gnu/lib/libdialog/ui_objects.c b/gnu/lib/libdialog/ui_objects.c
new file mode 100644
index 0000000..dde1513
--- /dev/null
+++ b/gnu/lib/libdialog/ui_objects.c
@@ -0,0 +1,829 @@
+/*
+ * Program: objects.c
+ * Author: Marc van Kempen
+ * Desc: Implementation of UI-objects:
+ * - String input fields
+ * - List selection
+ * - Buttons
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ */
+
+#include <stdlib.h>
+#include <sys/param.h>
+#include <ncurses.h>
+#include <dialog.h>
+#include "dialog.priv.h"
+#include "ui_objects.h"
+
+#define ESC 27
+
+/***********************************************************************
+ *
+ * Obj routines
+ *
+ ***********************************************************************/
+
+void
+AddObj(ComposeObj **Obj, int objtype, void *obj)
+/*
+ * Desc: Add the object <obj> to the list of objects <Obj>
+ */
+{
+ if (*Obj == NULL) {
+ /* Create the root object */
+ *Obj = (ComposeObj *) malloc( sizeof(ComposeObj) );
+ if (!Obj) {
+ printf("AddObj: Error malloc'ing ComposeObj\n");
+ exit(-1);
+ }
+ (*Obj)->objtype = objtype;
+ (*Obj)->obj = obj;
+ (*Obj)->next = NULL;
+ (*Obj)->prev = NULL;
+ } else {
+ ComposeObj *o = *Obj;
+
+ /* create the next object */
+ while (o->next) o = (ComposeObj *) o->next;
+ o->next = (struct ComposeObj *) malloc( sizeof(ComposeObj) );
+ if (!o->next) {
+ printf("AddObj: Error malloc'ing o->next\n");
+ exit(-1);
+ }
+ o->next->objtype = objtype;
+ o->next->obj = obj;
+ o->next->next = NULL;
+ o->next->prev = o;
+ }
+
+ return;
+} /* AddObj() */
+
+void
+FreeObj(ComposeObj *Obj)
+/*
+ * Desc: free the memory occupied by *Obj
+ */
+{
+ ComposeObj *o = Obj;
+
+ o = Obj;
+ while (o) {
+ o = Obj->next;
+ free(Obj);
+ Obj = o;
+ }
+
+ return;
+} /* FreeObj() */
+
+
+int
+ReadObj(ComposeObj *Obj)
+/*
+ * Desc: navigate through the different objects calling their
+ * respective navigation routines as necessary
+ * Pre: Obj != NULL
+ */
+{
+ ComposeObj *o;
+ ComposeObj *last; /* the last object in the list */
+ int ret; /* the return value from the selection routine */
+
+ /* find the last object in the list */
+ last = Obj;
+ while (last->next) last = last->next;
+
+ ret = 0;
+ o = Obj;
+ while ((ret != SEL_BUTTON) && (ret != SEL_ESC)) {
+ switch(o->objtype) {
+ case STRINGOBJ:
+ ret = SelectStringObj((StringObj *) o->obj);
+ break;
+ case LISTOBJ:
+ ret = SelectListObj((ListObj *) o->obj);
+ break;
+ case BUTTONOBJ:
+ ret = SelectButtonObj((ButtonObj *) o->obj);
+ break;
+ }
+ switch(ret) {
+ case KEY_DOWN:
+ case SEL_CR:
+ case SEL_TAB: /* move to the next object in the list */
+ if (o->next != NULL) {
+ o = o->next; /* next object */
+ } else {
+ o = Obj; /* beginning of the list */
+ }
+ break;
+
+ case KEY_UP:
+ case SEL_BACKTAB: /* move to the previous object in the list */
+ if (o->prev != NULL) {
+ o = o->prev; /* previous object */
+ } else {
+ o = last; /* end of the list */
+ }
+ break;
+
+ case KEY_F(1): /* display help_file */
+ case '?':
+ display_helpfile();
+ break;
+ }
+ }
+
+ return(ret);
+
+} /* ReadObj() */
+
+
+int
+PollObj(ComposeObj **Obj)
+{
+ ComposeObj *last; /* the last object in the list */
+ ComposeObj *first; /* the first object in the list */
+ int ret; /* the return value from the selection routine */
+
+ /* find the last object in the list */
+ last = *Obj;
+ while (last->next) last = last->next;
+
+ /* find the first object in the list */
+ first = *Obj;
+ while (first->prev) first = first->prev;
+
+ ret = 0;
+ switch((*Obj)->objtype) {
+ case STRINGOBJ:
+ ret = SelectStringObj((StringObj *) (*Obj)->obj);
+ break;
+ case LISTOBJ:
+ ret = SelectListObj((ListObj *) (*Obj)->obj);
+ break;
+ case BUTTONOBJ:
+ ret = SelectButtonObj((ButtonObj *) (*Obj)->obj);
+ break;
+ }
+ switch(ret) {
+ case KEY_DOWN:
+ case SEL_CR:
+ case SEL_TAB: /* move to the next object in the list */
+ if ((*Obj)->next != NULL) {
+ *Obj = (*Obj)->next; /* next object */
+ } else {
+ *Obj = first; /* beginning of the list */
+ }
+ break;
+
+ case KEY_UP:
+ case SEL_BACKTAB: /* move to the previous object in the list */
+ if ((*Obj)->prev != NULL) {
+ *Obj = (*Obj)->prev; /* previous object */
+ } else {
+ *Obj = last; /* end of the list */
+ }
+ break;
+ }
+
+ return(ret);
+
+} /* PollObj() */
+
+
+void
+DelObj(ComposeObj *Obj)
+/*
+ * Desc: Free all objects
+ */
+{
+ ComposeObj *o;
+
+ o = Obj;
+ while (Obj != NULL) {
+ switch(Obj->objtype) {
+ case STRINGOBJ:
+ DelStringObj((StringObj *) Obj->obj);
+ break;
+ case LISTOBJ:
+ DelListObj((ListObj *) Obj->obj);
+ break;
+ case BUTTONOBJ:
+ DelButtonObj((ButtonObj *) Obj->obj);
+ break;
+ }
+ Obj = Obj->next;
+ }
+
+ FreeObj(o);
+} /* DelObj() */
+
+/***********************************************************************
+ *
+ * StringObj routines
+ *
+ ***********************************************************************/
+
+static void
+outstr(WINDOW *win, char *str, int attrs)
+{
+ if (attrs & DITEM_NO_ECHO) {
+ char *cpy;
+ int n = strlen(str);
+
+ cpy = alloca(n + 1);
+ memset(cpy, '*', n);
+ cpy[n] = '\0';
+ waddstr(win, cpy);
+ }
+ else
+ waddstr(win, str);
+}
+
+void
+RefreshStringObj(StringObj *so)
+/*
+ * Desc: redraw the object
+ */
+{
+ char tmp[512];
+
+ wmove(so->win, so->y, so->x+1);
+ wattrset(so->win, dialog_attr);
+ waddstr(so->win, so->title);
+
+ draw_box(so->win, so->y+1, so->x, 3, so->w, dialog_attr, border_attr);
+ wattrset(so->win, item_attr);
+ wmove(so->win, so->y+2, so->x+1);
+ if (strlen(so->s) > so->w-2) {
+ strncpy(tmp, (char *) so->s + strlen(so->s) - so->w + 2, so->w - 1);
+ outstr(so->win, tmp, so->attr_mask);
+ } else {
+ outstr(so->win, so->s, so->attr_mask);
+ }
+
+ return;
+} /* RefreshStringObj() */
+
+StringObj *
+NewStringObj(WINDOW *win, char *title, char *s, int y, int x, int w, int len)
+/*
+ * Desc: Initialize a new stringobj and return a pointer to it.
+ * Draw the object on the screen at the specified coordinates
+ */
+{
+ StringObj *so;
+
+ /* Initialize a new object */
+ so = (StringObj *) malloc( sizeof(StringObj) );
+ if (!so) {
+ printf("NewStringObj: Error malloc'ing StringObj\n");
+ exit(-1);
+ }
+ so->title = (char *) malloc( strlen(title) + 1);
+ if (!so->title) {
+ printf("NewStringObj: Error malloc'ing so->title\n");
+ exit(-1);
+ }
+ strcpy(so->title, title);
+ so->s = s;
+ strcpy(so->s, s);
+ so->x = x;
+ so->y = y;
+ so->w = w;
+ so->len = len;
+ so->win = win;
+ so->attr_mask = DialogInputAttrs; /* Grossly use a global to avoid changing API */
+
+ /* Draw it on the screen */
+ RefreshStringObj(so);
+
+ return(so);
+} /* NewStringObj() */
+
+int
+SelectStringObj(StringObj *so)
+/*
+ * Desc: get input using the info in <so>
+ */
+{
+ int key;
+ char tmp[so->len+1];
+
+ strcpy(tmp, so->s);
+ key = line_edit(so->win, so->y+2, so->x+1,
+ so->len, so->w-2, inputbox_attr, TRUE, tmp, so->attr_mask);
+ if ((key == '\n') || (key == '\r') || (key == '\t') || key == (KEY_BTAB) ) {
+ strcpy(so->s, tmp);
+ }
+ RefreshStringObj(so);
+ if (key == ESC) {
+ return(SEL_ESC);
+ }
+ if (key == '\t') {
+ return(SEL_TAB);
+ }
+ if ( (key == KEY_BTAB) || (key == KEY_F(2)) ) {
+ return(SEL_BACKTAB);
+ }
+ if ((key == '\n') || (key == '\r')) {
+ return(SEL_CR);
+ }
+ return(key);
+} /* SelectStringObj() */
+
+
+void
+DelStringObj(StringObj *so)
+/*
+ * Desc: Free the space occupied by <so>
+ */
+{
+ free(so->title);
+ free(so);
+
+ return;
+}
+
+/***********************************************************************
+ *
+ * ListObj routines
+ *
+ ***********************************************************************/
+
+void
+DrawNames(ListObj *lo)
+/*
+ * Desc: Just refresh the names, not the surrounding box and title
+ */
+{
+ int i, j, h, x, y;
+ char tmp[MAXPATHLEN];
+
+ x = lo->x + 1;
+ y = lo->y + 2;
+ h = lo->h - 2;
+ for (i=lo->scroll; i<lo->n && i<lo->scroll+h; i++) {
+ wmove(lo->win, y+i-lo->scroll, x);
+ if (lo->seld[i]) {
+ wattrset(lo->win, A_BOLD);
+ } else {
+ wattrset(lo->win, item_attr);
+ }
+ if (strlen(lo->name[i]) > lo->w-2) {
+ strncpy(tmp, lo->name[i], lo->w-2);
+ tmp[lo->w - 2] = 0;
+ waddstr(lo->win, tmp);
+ } else {
+ waddstr(lo->win, lo->name[i]);
+ for (j=strlen(lo->name[i]); j<lo->w-2; j++) waddstr(lo->win, " ");
+ }
+ }
+ wattrset(lo->win, item_attr);
+ while (i<lo->scroll+h) {
+ wmove(lo->win, y+i-lo->scroll, x);
+ for (j=0; j<lo->w-2; j++) waddstr(lo->win, " ");
+ i++;
+ }
+
+ return;
+} /* DrawNames() */
+
+void
+RefreshListObj(ListObj *lo)
+/*
+ * Desc: redraw the list object
+ */
+{
+ char perc[7];
+
+ /* setup the box */
+ wmove(lo->win, lo->y, lo->x+1);
+ wattrset(lo->win, dialog_attr);
+ waddstr(lo->win, lo->title);
+ draw_box(lo->win, lo->y+1, lo->x, lo->h, lo->w, dialog_attr, border_attr);
+
+ /* draw the names */
+ DrawNames(lo);
+
+ /* Draw % indication */
+ sprintf(perc, "(%3d%%)", MIN(100, (int) (100 * (lo->sel+lo->h-2) / MAX(1, lo->n))));
+ wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8);
+ wattrset(lo->win, dialog_attr);
+ waddstr(lo->win, perc);
+
+
+ return;
+} /* RefreshListObj() */
+
+ListObj *
+NewListObj(WINDOW *win, char *title, char **list, char *listelt, int y, int x,
+ int h, int w, int n)
+/*
+ * Desc: create a listobj, draw it on the screen and return a pointer to it.
+ */
+{
+ ListObj *lo;
+ int i;
+
+ /* Initialize a new object */
+ lo = (ListObj *) malloc( sizeof(ListObj) );
+ if (!lo) {
+ fprintf(stderr, "NewListObj: Error malloc'ing ListObj\n");
+ exit(-1);
+ }
+ lo->title = (char *) malloc( strlen(title) + 1);
+ if (!lo->title) {
+ fprintf(stderr, "NewListObj: Error malloc'ing lo->title\n");
+ exit(-1);
+ }
+ strcpy(lo->title, title);
+ lo->name = list;
+ if (n>0) {
+ lo->seld = (int *) malloc( n * sizeof(int) );
+ if (!lo->seld) {
+ fprintf(stderr, "NewListObj: Error malloc'ing lo->seld\n");
+ exit(-1);
+ }
+ for (i=0; i<n; i++) {
+ lo->seld[i] = FALSE;
+ }
+ } else {
+ lo->seld = NULL;
+ }
+ lo->y = y;
+ lo->x = x;
+ lo->w = w;
+ lo->h = h;
+ lo->n = n;
+ lo->scroll = 0;
+ lo->sel = 0;
+ lo->elt = listelt;
+ lo->win = win;
+
+ /* Draw the object on the screen */
+ RefreshListObj(lo);
+
+ return(lo);
+} /* NewListObj() */
+
+void
+UpdateListObj(ListObj *lo, char **list, int n)
+/*
+ * Desc: Update the list in the listobject with the provided list
+ * Pre: lo->name "has been freed"
+ * "(A i: 0<=i<lo->n: "lo->name[i] has been freed")"
+ */
+{
+ int i;
+
+ if (lo->seld) {
+ free(lo->seld);
+ }
+
+ /* Rewrite the list in the object */
+ lo->name = list;
+ if (n>0) {
+ lo->seld = (int *) malloc( n * sizeof(int) );
+ if (!lo->seld) {
+ fprintf(stderr, "UpdateListObj: Error malloc'ing lo->seld\n");
+ exit(-1);
+ }
+ for (i=0; i<n; i++) {
+ lo->seld[i] = FALSE;
+ }
+ } else {
+ lo->seld = NULL;
+ }
+ lo->n = n;
+ lo->scroll = 0;
+ lo->sel = 0;
+
+ /* Draw the object on the screen */
+ RefreshListObj(lo);
+
+ return;
+} /* UpdateListObj() */
+
+int
+SelectListObj(ListObj *lo)
+/*
+ * Desc: get a listname (or listnames), TAB to move on, or ESC ESC to exit
+ * Pre: lo->n >= 1
+ */
+{
+ int key, sel_x, sel_y, quit;
+ char tmp[MAXPATHLEN];
+ char perc[4];
+
+ sel_x = lo->x+1;
+ sel_y = lo->y + 2 + lo->sel - lo->scroll;
+
+ if (lo->n == 0) return(SEL_TAB);
+
+ keypad(lo->win, TRUE);
+
+ /* Draw current selection in inverse video */
+ wmove(lo->win, sel_y, sel_x);
+ wattrset(lo->win, item_selected_attr);
+ waddstr(lo->win, lo->name[lo->sel]);
+
+ key = wgetch(lo->win);
+ quit = FALSE;
+ while ((key != '\t') && (key != '\n') && (key != '\r')
+ && (key != ESC) && (key != KEY_F(1)) && (key != '?') && !quit) {
+ /* first draw current item in normal video */
+ wmove(lo->win, sel_y, sel_x);
+ if (lo->seld[lo->sel]) {
+ wattrset(lo->win, A_BOLD);
+ } else {
+ wattrset(lo->win, item_attr);
+ }
+ if (strlen(lo->name[lo->sel]) > lo->w - 2) {
+ strncpy(tmp, lo->name[lo->sel], lo->w - 2);
+ tmp[lo->w - 2] = 0;
+ waddstr(lo->win, tmp);
+ } else {
+ waddstr(lo->win, lo->name[lo->sel]);
+ }
+
+ switch (key) {
+ case KEY_DOWN:
+ case ctrl('n'):
+ if (sel_y < lo->y + lo->h-1) {
+ if (lo->sel < lo->n-1) {
+ sel_y++;
+ lo->sel++;
+ }
+ } else {
+ if (lo->sel < lo->n-1) {
+ lo->sel++;
+ lo->scroll++;
+ DrawNames(lo);
+ wrefresh(lo->win);
+ }
+ }
+ break;
+ case KEY_UP:
+ case ctrl('p'):
+ if (sel_y > lo->y+2) {
+ if (lo->sel > 0) {
+ sel_y--;
+ lo->sel--;
+ }
+ } else {
+ if (lo->sel > 0) {
+ lo->sel--;
+ lo->scroll--;
+ DrawNames(lo);
+ wrefresh(lo->win);
+ }
+ }
+ break;
+ case KEY_HOME:
+ case ctrl('a'):
+ lo->sel = 0;
+ lo->scroll = 0;
+ sel_y = lo->y + 2;
+ DrawNames(lo);
+ wrefresh(lo->win);
+ break;
+ case KEY_END:
+ case ctrl('e'):
+ if (lo->n < lo->h - 3) {
+ lo->sel = lo->n-1;
+ lo->scroll = 0;
+ sel_y = lo->y + 2 + lo->sel - lo->scroll;
+ } else {
+ /* more than one page of list */
+ lo->sel = lo->n-1;
+ lo->scroll = lo->n-1 - (lo->h-3);
+ sel_y = lo->y + 2 + lo->sel - lo->scroll;
+ DrawNames(lo);
+ wrefresh(lo->win);
+ }
+ break;
+ case KEY_NPAGE:
+ case ctrl('f'):
+ lo->sel += lo->h - 2;
+ if (lo->sel >= lo->n) lo->sel = lo->n - 1;
+ lo->scroll += lo->h - 2;
+ if (lo->scroll >= lo->n - 1) lo->scroll = lo->n - 1;
+ if (lo->scroll < 0) lo->scroll = 0;
+ sel_y = lo->y + 2 + lo->sel - lo->scroll;
+ DrawNames(lo);
+ wrefresh(lo->win);
+ break;
+ case KEY_PPAGE:
+ case ctrl('b'):
+ lo->sel -= lo->h - 2;
+ if (lo->sel < 0) lo->sel = 0;
+ lo->scroll -= lo->h - 2;
+ if (lo->scroll < 0) lo->scroll = 0;
+ sel_y = lo->y + 2 + lo->sel - lo->scroll;
+ DrawNames(lo);
+ wrefresh(lo->win);
+ break;
+ default:
+ quit = TRUE;
+ break;
+ }
+ /* Draw % indication */
+ sprintf(perc, "(%3d%%)", MIN(100, (int)
+ (100 * (lo->sel+lo->h - 2) / MAX(1, lo->n))));
+ wmove(lo->win, lo->y + lo->h, lo->x + lo->w - 8);
+ wattrset(lo->win, dialog_attr);
+ waddstr(lo->win, perc);
+
+ /* draw current item in inverse */
+ wmove(lo->win, sel_y, sel_x);
+ wattrset(lo->win, item_selected_attr);
+ if (strlen(lo->name[lo->sel]) > lo->w - 2) {
+ /* when printing in inverse video show the last characters in the */
+ /* name that will fit in the window */
+ strncpy(tmp,
+ lo->name[lo->sel] + strlen(lo->name[lo->sel]) - (lo->w - 2),
+ lo->w - 2);
+ tmp[lo->w - 2] = 0;
+ waddstr(lo->win, tmp);
+ } else {
+ waddstr(lo->win, lo->name[lo->sel]);
+ }
+ if (!quit) key = wgetch(lo->win);
+ }
+
+ if (key == ESC) {
+ return(SEL_ESC);
+ }
+ if (key == '\t') {
+ return(SEL_TAB);
+ }
+ if ((key == KEY_BTAB) || (key == ctrl('b'))) {
+ return(SEL_BACKTAB);
+ }
+ if ((key == '\n') || (key == '\r')) {
+ strcpy(lo->elt, lo->name[lo->sel]);
+ return(SEL_CR);
+ }
+ return(key);
+} /* SelectListObj() */
+
+void
+DelListObj(ListObj *lo)
+/*
+ * Desc: Free the space occupied by the listobject
+ */
+{
+ free(lo->title);
+ if (lo->seld != NULL) free(lo->seld);
+ free(lo);
+
+ return;
+} /* DelListObj() */
+
+void
+MarkCurrentListObj(ListObj *lo)
+/*
+ * Desc: mark the current item for the selection list
+ */
+{
+ lo->seld[lo->sel] = !(lo->seld[lo->sel]);
+ DrawNames(lo);
+
+ return;
+} /* MarkCurrentListObj() */
+
+void
+MarkAllListObj(ListObj *lo)
+/*
+ * Desc: mark all items
+ */
+{
+ int i;
+
+ for (i=0; i<lo->n; i++) {
+ lo->seld[i] = TRUE;
+ }
+ DrawNames(lo);
+
+ return;
+} /* MarkAllListObj() */
+
+void
+UnMarkAllListObj(ListObj *lo)
+/*
+ * Desc: unmark all items
+ */
+{
+ int i;
+
+ for (i=0; i<lo->n; i++) {
+ lo->seld[i] = FALSE;
+ }
+ DrawNames(lo);
+
+ return;
+} /* UnMarkAllListObj() */
+
+
+/***********************************************************************
+ *
+ * ButtonObj routines
+ *
+ ***********************************************************************/
+
+
+void
+RefreshButtonObj(ButtonObj *bo)
+/*
+ * Desc: redraw the button
+ */
+{
+ draw_box(bo->win, bo->y, bo->x, 3, bo->w, dialog_attr, border_attr);
+ print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE);
+
+ return;
+} /* RefreshButtonObj() */
+
+ButtonObj *
+NewButtonObj(WINDOW *win, char *title, int *pushed, int y, int x)
+/*
+ * Desc: Create a new button object
+ */
+{
+ ButtonObj *bo;
+
+ bo = (ButtonObj *) malloc( sizeof(ButtonObj) );
+
+ bo->win = win;
+ bo->title = (char *) malloc( strlen(title) + 1);
+ strcpy(bo->title, title);
+ bo->x = x;
+ bo->y = y;
+ bo->w = strlen(title) + 6;
+ bo->h = 3;
+ bo->pushed = pushed;
+
+ RefreshButtonObj(bo);
+
+ return(bo);
+} /* NewButtonObj() */
+
+int
+SelectButtonObj(ButtonObj *bo)
+/*
+ * Desc: Wait for buttonpresses or TAB's to move on, or ESC ESC
+ */
+{
+ int key;
+
+ print_button(bo->win, bo->title, bo->y+1, bo->x+2, TRUE);
+ wmove(bo->win, bo->y+1, bo->x+(bo->w/2)-1);
+ key = wgetch(bo->win);
+ print_button(bo->win, bo->title, bo->y+1, bo->x+2, FALSE);
+ switch(key) {
+ case '\t':
+ return(SEL_TAB);
+ break;
+ case KEY_BTAB:
+ case ctrl('b'):
+ return(SEL_BACKTAB);
+ case '\n':
+ case '\r':
+ *(bo->pushed) = TRUE;
+ return(SEL_BUTTON);
+ break;
+ case ESC:
+ return(SEL_ESC);
+ break;
+ default:
+ return(key);
+ break;
+ }
+} /* SelectButtonObj() */
+
+void
+DelButtonObj(ButtonObj *bo)
+/*
+ * Desc: Free the space occupied by <bo>
+ */
+{
+ free(bo->title);
+ free(bo);
+
+ return;
+} /* DelButtonObj() */
diff --git a/gnu/lib/libdialog/ui_objects.h b/gnu/lib/libdialog/ui_objects.h
new file mode 100644
index 0000000..b30feb8
--- /dev/null
+++ b/gnu/lib/libdialog/ui_objects.h
@@ -0,0 +1,114 @@
+/*
+ * Author: Marc van Kempen
+ * Desc: include file for UI-objects
+ *
+ * Copyright (c) 1995, Marc van Kempen
+ *
+ * All rights reserved.
+ *
+ * This software may be used, modified, copied, distributed, and
+ * sold, in both source and binary form provided that the above
+ * copyright and these terms are retained, verbatim, as the first
+ * lines of this file. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with
+ * its use.
+ *
+ */
+
+#include "dialog.h"
+#include <ncurses.h>
+
+/***********************************************************************
+ *
+ * Defines
+ *
+ ***********************************************************************/
+
+#define ctrl(a) ((a) - 'a' + 1)
+
+/* the Object types */
+#define STRINGOBJ 1
+#define LISTOBJ 2
+#define BUTTONOBJ 3
+
+/* the return signals from the selection routines */
+/* 1000 and higher should avoid conflicts with keys pressed */
+#define SEL_CR 1001 /* return was pressed */
+#define SEL_ESC 1002 /* ESC pressed */
+#define SEL_TAB 1003 /* TAB pressed */
+#define SEL_BACKTAB 1004 /* SHIFT-TAB pressed */
+#define SEL_BUTTON 1005 /* a button was pressed */
+
+/***********************************************************************
+ *
+ * Typedefs
+ *
+ ***********************************************************************/
+
+typedef struct {
+ WINDOW *win; /* the window it's contained in */
+ char *title; /* the prompt for the input field */
+ char *s; /* initial value of the input field */
+ int x, y, w, len; /* the (y, x) position of the upperleft */
+ /* corner and the width <w> of the display */
+ /* and length <len> of the field */
+ int attr_mask; /* special attributes */
+} StringObj;
+
+typedef struct {
+ WINDOW *win; /* the windows it's contained in */
+ char *title; /* the title of the list */
+ char **name; /* the names of the list */
+ int *seld; /* the currently selected names */
+ char *elt; /* the current element in the list list[sel] */
+ int x, y, w, h, n; /* dimensions of list and # of elements (n) */
+ int scroll, sel; /* current position in the list */
+} ListObj;
+
+typedef struct {
+ WINDOW *win; /* the window it's contained in */
+ char *title; /* title for the button */
+ int x, y, w, h; /* its dimensions */
+ int *pushed; /* boolean that determines wether button was pushed */
+} ButtonObj;
+
+typedef struct ComposeObj {
+ int objtype;
+ void *obj;
+ struct ComposeObj *next, *prev;
+} ComposeObj;
+
+/**********************************************************************
+ *
+ * Prototypes
+ *
+ **********************************************************************/
+
+void RefreshStringObj(StringObj *so);
+StringObj *NewStringObj(WINDOW *win, char *title, char *s,
+ int y, int x, int w, int len);
+int SelectStringObj(StringObj *so);
+void DelStringObj(StringObj *so);
+
+void RefreshListObj(ListObj *lo);
+ListObj *NewListObj(WINDOW *win, char *title, char **list,
+ char *listelt, int y, int x, int h, int w, int n);
+void UpdateListObj(ListObj *lo, char **list, int n);
+int SelectListObj(ListObj *lo);
+void DelListObj(ListObj *obj);
+void MarkCurrentListObj(ListObj *lo);
+void MarkAllListObj(ListObj *lo);
+void UnMarkAllListObj(ListObj *lo);
+
+void RefreshButtonObj(ButtonObj *bo);
+ButtonObj *NewButtonObj(WINDOW *win, char *title, int *pushed,
+ int y, int x);
+int SelectButtonObj(ButtonObj *bo);
+void DelButtonObj(ButtonObj *bo);
+void AddObj(ComposeObj **Obj, int objtype, void *obj);
+void FreeObj(ComposeObj *Obj);
+int ReadObj(ComposeObj *Obj);
+int PollObj(ComposeObj **Obj);
+void DelObj(ComposeObj *Obj);
+
diff --git a/gnu/lib/libdialog/yesno.c b/gnu/lib/libdialog/yesno.c
new file mode 100644
index 0000000..d3dfb1e
--- /dev/null
+++ b/gnu/lib/libdialog/yesno.c
@@ -0,0 +1,171 @@
+/*
+ * yesno.c -- implements the yes/no box
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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 lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <dialog.h>
+#include "dialog.priv.h"
+
+/* Actual work function */
+static int dialog_yesno_proc(unsigned char *title, unsigned char *prompt,
+ int height, int width, int yesdefault);
+
+/*
+ * Display a dialog box with two buttons - Yes and No
+ */
+int
+dialog_yesno(unsigned char *title, unsigned char *prompt, int height, int width)
+{
+ return dialog_yesno_proc(title, prompt, height, width, TRUE);
+}
+
+/*
+ * Display a dialog box with two buttons - No and Yes
+ */
+int
+dialog_noyes(unsigned char *title, unsigned char *prompt, int height, int width)
+{
+ return dialog_yesno_proc(title, prompt, height, width, FALSE);
+}
+
+static int
+dialog_yesno_proc(unsigned char *title, unsigned char *prompt, int height, int width, int yesdefault)
+{
+ int i, j, x, y, key, button;
+ WINDOW *dialog;
+ char *tmphlp;
+
+ /* disable helpline */
+ tmphlp = get_helpline();
+ use_helpline(NULL);
+
+ if (height < 0)
+ height = strheight(prompt)+4;
+ if (width < 0) {
+ i = strwidth(prompt);
+ j = ((title != NULL) ? strwidth(title) : 0);
+ width = MAX(i,j)+4;
+ }
+ width = MAX(width,23);
+
+ if (width > COLS)
+ width = COLS;
+ if (height > LINES)
+ height = LINES;
+ /* center dialog box on screen */
+ x = DialogX ? DialogX : (COLS - width)/2;
+ y = DialogY ? DialogY : (LINES - height)/2;
+
+#ifdef HAVE_NCURSES
+ if (use_shadow)
+ draw_shadow(stdscr, y, x, height, width);
+#endif
+ dialog = newwin(height, width, y, x);
+ if (dialog == NULL) {
+ endwin();
+ fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
+ exit(1);
+ }
+ keypad(dialog, TRUE);
+
+ draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ wattrset(dialog, border_attr);
+ wmove(dialog, height-3, 0);
+ waddch(dialog, ACS_LTEE);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ACS_HLINE);
+ wattrset(dialog, dialog_attr);
+ waddch(dialog, ACS_RTEE);
+ wmove(dialog, height-2, 1);
+ for (i = 0; i < width-2; i++)
+ waddch(dialog, ' ');
+
+ if (title != NULL) {
+ wattrset(dialog, title_attr);
+ wmove(dialog, 0, (width - strlen(title))/2 - 1);
+ waddch(dialog, ' ');
+ waddstr(dialog, title);
+ waddch(dialog, ' ');
+ }
+ wattrset(dialog, dialog_attr);
+ wmove(dialog, 1, 2);
+ print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE);
+
+ display_helpline(dialog, height-1, width);
+
+ x = width/2-10;
+ y = height-2;
+
+ /* preset button 0 or 1 for YES or NO as the default */
+ key = 0;
+ button = !yesdefault;
+ while (key != ESC) {
+ print_button(dialog, " No ", y, x+13, button);
+ print_button(dialog, " Yes " , y, x, !button);
+ if (button)
+ wmove(dialog, y, x+16);
+ else
+ wmove(dialog, y, x+2);
+ wrefresh(dialog);
+
+ key = wgetch(dialog);
+ switch (key) {
+ case 'Y':
+ case 'y':
+ delwin(dialog);
+ restore_helpline(tmphlp);
+ return 0;
+ case 'N':
+ case 'n':
+ delwin(dialog);
+ restore_helpline(tmphlp);
+ return 1;
+ case KEY_BTAB:
+ case TAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_LEFT:
+ case KEY_RIGHT:
+ button = !button;
+ /* redrawn at the loop's entry */
+ break;
+ case ' ':
+ case '\r':
+ case '\n':
+ delwin(dialog);
+ restore_helpline(tmphlp);
+ return button;
+ case ESC:
+ break;
+ case KEY_F(1):
+ case '?':
+ display_helpfile();
+ break;
+ }
+ }
+
+ delwin(dialog);
+ restore_helpline(tmphlp);
+ return -1; /* ESC pressed */
+}
+/* End of dialog_yesno() */
diff --git a/gnu/lib/libg2c/MAIN.c b/gnu/lib/libg2c/MAIN.c
new file mode 100644
index 0000000..9c6f895
--- /dev/null
+++ b/gnu/lib/libg2c/MAIN.c
@@ -0,0 +1,4 @@
+/* $FreeBSD$ */
+
+int
+MAIN__(){ return 0; }
diff --git a/gnu/lib/libg2c/Makefile b/gnu/lib/libg2c/Makefile
new file mode 100644
index 0000000..264d5ff
--- /dev/null
+++ b/gnu/lib/libg2c/Makefile
@@ -0,0 +1,122 @@
+# $FreeBSD$
+
+SRCDIR= ${.CURDIR}/../../../contrib/libf2c
+
+.PATH: ${SRCDIR} ${SRCDIR}/libU77 ${SRCDIR}/libF77 ${SRCDIR}/libI77
+
+LIB= g2c
+SHLIB_MAJOR= 1
+SHLIB_MINOR= 0
+
+# Traditional FORTRAN Library members defined in libF77
+
+F77MISC= F77_aloc.c main.c s_rnge.c abort_.c getarg_.c \
+ iargc_.c getenv_.c signal_.c s_stop.c s_paus.c system_.c \
+ cabs.c derf_.c derfc_.c erf_.c erfc_.c sig_die.c exit_.c \
+ setarg.c setsig.c
+
+F77POW= pow_ci.c pow_dd.c pow_di.c pow_hh.c pow_ii.c pow_ri.c pow_zi.c \
+ pow_zz.c
+
+F77CX= c_abs.c c_cos.c c_div.c c_exp.c c_log.c c_sin.c c_sqrt.c
+F77DCX= ${F77CX:S/^c_/z_/g}
+
+F77INT= i_abs.c i_dim.c i_dnnt.c i_indx.c i_len.c i_mod.c i_nint.c \
+ i_sign.c
+
+F77HALF= h_abs.c h_dim.c h_dnnt.c h_indx.c h_len.c h_mod.c h_nint.c \
+ h_sign.c
+
+F77REAL= r_abs.c r_acos.c r_asin.c r_atan.c r_atn2.c r_cnjg.c r_cos.c \
+ r_cosh.c r_dim.c r_exp.c r_imag.c r_int.c r_lg10.c r_log.c \
+ r_mod.c r_nint.c r_sign.c r_sin.c r_sinh.c r_sqrt.c r_tan.c \
+ r_tanh.c
+F77DBL= ${F77REAL:S/^r_/d_/g} d_prod.c
+
+F77CMP= l_ge.c l_gt.c l_le.c l_lt.c hl_ge.c hl_gt.c hl_le.c hl_lt.c
+
+F77EFL= ef1asc_.c ef1cmc_.c
+
+F77CHAR= s_cat.c s_cmp.c s_copy.c
+
+F77F90BIT= lbitbits.c lbitshft.c qbitbits.c qbitshft.c
+
+F77SRCS= ${F77MISC} ${F77POW} ${F77CX} ${F77DCX} ${F77INT} ${F77HALF} \
+ ${F77REAL} ${F77DBL} ${F77CMP} ${F77EFL} ${F77CHAR} ${F77F90BIT}
+
+# I/O Library members defined in libI77
+
+I77SRCS= backspace.c close.c dfe.c dolio.c due.c endfile.c \
+ err.c fmt.c fmtlib.c iio.c ilnw.c inquire.c lread.c lwrite.c \
+ open.c rdfmt.c rewind.c rsfe.c rsli.c rsne.c sfe.c sue.c \
+ typesize.c uio.c util.c wref.c wrtfmt.c wsfe.c wsle.c wsne.c \
+ xwsne.c ftell_.c
+
+# UNIX Library members defined in libU77
+
+U77SRCS= gerror_.c perror_.c ierrno_.c itime_.c time_.c \
+ unlink_.c fnum_.c getpid_.c getuid_.c getgid_.c kill_.c \
+ rand_.c srand_.c irand_.c sleep_.c idate_.c ctime_.c \
+ etime_.c dtime_.c isatty_.c ltime_.c fstat_.c stat_.c \
+ lstat_.c access_.c link_.c getlog_.c ttynam_.c getcwd_.c \
+ symlnk_.c vxttime_.c vxtidate_.c gmtime_.c fdate_.c \
+ secnds_.c bes.c dbes.c chdir_.c chmod_.c lnblnk_.c \
+ hostnm_.c rename_.c fgetc_.c fputc_.c umask_.c \
+ sys_clock_.c date_.c second_.c flush1_.c mclock_.c \
+ alarm_.c datetime_.c
+
+# Library members refered to as libE77 by EGCS
+
+E77OBJS= abort.o access.o alarm.o besj0.o besj1.o besjn.o \
+ besy0.o besy1.o besyn.o chdir.o chmod.o ctime.o date.o \
+ dbesj0.o dbesj1.o dbesjn.o dbesy0.o dbesy1.o dbesyn.o derf.o \
+ derfc.o dtime.o ef1asc.o ef1cmc.o erf.o erfc.o etime.o exit.o \
+ fdate.o fget.o fgetc.o flush.o flush1.o fnum.o fput.o fputc.o \
+ fseek.o fstat.o ftell.o gerror.o getarg.o getcwd.o getenv.o \
+ getgid.o getlog.o getpid.o getuid.o gmtime.o hostnm.o iargc.o \
+ idate.o ierrno.o irand.o isatty.o itime.o kill.o link.o \
+ lnblnk.o lstat.o ltime.o mclock.o perror.o rand.o rename.o \
+ secnds.o second.o signal.o sleep.o srand.o stat.o symlnk.o \
+ system.o time.o ttynam.o umask.o unlink.o vxtidt.o vxttim.o
+
+LIBF77SRCS= ${F77SRCS} ${I77SRCS} ${U77SRCS} ${E77SRCS} MAIN.c
+
+SRCS= ${LIBF77SRCS}
+OBJS= ${E77OBJS}
+
+CFLAGS+= -DHAVE_CONFIG_H=1 -DSTDC_HEADERS=1 -DHAVE_TEMPNAM=1
+CFLAGS+= -DNO_EOF_CHAR_CHECK=1 -DRETSIGTYPE=void
+CFLAGS+= -DSkip_f2c_Undefs=1 -DIEEE_drem=1 -DAllow_TYQUAD -DPedantic
+CFLAGS+= -I${SRCDIR} -I${SRCDIR}/libF77 -I${SRCDIR}/libI77 -I${SRCDIR}/libU77
+CFLAGS+= -I${.CURDIR}
+
+.for x in F I U
+${x}77SRCS+= Version${x}.c
+CLEANFILES+= Version${x}.c
+Version${x}.c: ${SRCDIR}/lib${x}77/Version.c
+ ln -sf ${.ALLSRC} ${.TARGET}
+.endfor
+
+${E77OBJS}: f2cext.c
+ ${CC} ${CFLAGS} -c -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c}
+ @${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+.if !defined(NOPIC)
+${E77OBJS:.o=.So}: f2cext.c
+ ${CC} ${PICFLAG} -DPIC ${CFLAGS} -c -DL${.PREFIX} -o ${.TARGET} \
+ ${.ALLSRC:M*.c}
+ @${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+.endif
+
+.if !defined(NOPROFILE)
+${E77OBJS:.o=.po}: f2cext.c
+ ${CC} -p ${CFLAGS} -c -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c}
+ @${LD} -o ${.TARGET}.tmp -X -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+.endif
+
+INCS= g2c.h
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libg2c/config.h b/gnu/lib/libg2c/config.h
new file mode 100644
index 0000000..045a43f
--- /dev/null
+++ b/gnu/lib/libg2c/config.h
@@ -0,0 +1,107 @@
+/* config.h. Generated automatically by configure. */
+/* config.hin. Generated automatically from configure.in by autoheader. */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define if your struct stat has st_blksize. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define if your struct stat has st_blocks. */
+#define HAVE_ST_BLOCKS 1
+
+/* Define if your struct stat has st_rdev. */
+#define HAVE_ST_RDEV 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if your <sys/time.h> declares struct tm. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define as the path of the `chmod' program. */
+#define CHMOD_PATH "/bin/chmod"
+
+/* Define if you have the alarm function. */
+#define HAVE_ALARM 1
+
+/* Define if you have the clock function. */
+#define HAVE_CLOCK 1
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getgid function. */
+#define HAVE_GETGID 1
+
+/* Define if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the getlogin function. */
+#define HAVE_GETLOGIN 1
+
+/* Define if you have the getrusage function. */
+#define HAVE_GETRUSAGE 1
+
+/* Define if you have the gettimeofday function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the getuid function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the getwd function. */
+#define HAVE_GETWD 1
+
+/* Define if you have the kill function. */
+#define HAVE_KILL 1
+
+/* Define if you have the link function. */
+#define HAVE_LINK 1
+
+/* Define if you have the lstat function. */
+#define HAVE_LSTAT 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the symlink function. */
+#define HAVE_SYMLINK 1
+
+/* Define if you have the times function. */
+#define HAVE_TIMES 1
+
+/* Define if you have the ttyname function. */
+#define HAVE_TTYNAME 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/times.h> header file. */
+#define HAVE_SYS_TIMES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
diff --git a/gnu/lib/libg2c/g2c.h b/gnu/lib/libg2c/g2c.h
new file mode 100644
index 0000000..71e021d
--- /dev/null
+++ b/gnu/lib/libg2c/g2c.h
@@ -0,0 +1,236 @@
+/* g2c.h -- g77 version of f2c (Standard Fortran to C header file) */
+
+/* This file is generated by the g77 libg2c configuration process from a
+ file named g2c.hin. This process sets up the appropriate types,
+ defines the appropriate macros, and so on. The resulting g2c.h file
+ is used to build g77's copy of libf2c, named libg2c, and also can
+ be used when compiling C code produced by f2c to link the resulting
+ object file(s) with those produced by the same version of g77 that
+ produced this file, allowing inter-operability of f2c-compiled and
+ g77-compiled code. */
+
+/** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
+
+ - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */
+
+#ifndef F2C_INCLUDE
+#define F2C_INCLUDE
+
+/* F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems */
+/* we assume short, float are OK */
+typedef int /* long int */ integer;
+typedef unsigned long int /* long */ uinteger;
+typedef char *address;
+typedef short int shortint;
+typedef float real;
+typedef double doublereal;
+typedef struct { real r, i; } complex;
+typedef struct { doublereal r, i; } doublecomplex;
+typedef int /* long int */ logical;
+typedef short int shortlogical;
+typedef char logical1;
+typedef char integer1;
+typedef long long int /* long long */ longint; /* system-dependent */
+typedef unsigned long long int /* long long */ ulongint; /* system-dependent */
+#define qbit_clear(a,b) ((a) & ~((ulongint)1 << (b)))
+#define qbit_set(a,b) ((a) | ((ulongint)1 << (b)))
+
+#define TRUE_ (1)
+#define FALSE_ (0)
+
+/* Extern is for use with -E */
+#ifndef Extern
+#define Extern extern
+#endif
+
+/* I/O stuff */
+
+#ifdef f2c_i2
+#error "f2c_i2 will not work with g77!!!!"
+/* for -i2 */
+typedef short flag;
+typedef short ftnlen;
+typedef short ftnint;
+#else
+typedef int /* long int */ flag;
+typedef int /* long int */ ftnlen;
+typedef int /* long int */ ftnint;
+#endif
+
+/*external read, write*/
+typedef struct
+{ flag cierr;
+ ftnint ciunit;
+ flag ciend;
+ char *cifmt;
+ ftnint cirec;
+} cilist;
+
+/*internal read, write*/
+typedef struct
+{ flag icierr;
+ char *iciunit;
+ flag iciend;
+ char *icifmt;
+ ftnint icirlen;
+ ftnint icirnum;
+} icilist;
+
+/*open*/
+typedef struct
+{ flag oerr;
+ ftnint ounit;
+ char *ofnm;
+ ftnlen ofnmlen;
+ char *osta;
+ char *oacc;
+ char *ofm;
+ ftnint orl;
+ char *oblnk;
+} olist;
+
+/*close*/
+typedef struct
+{ flag cerr;
+ ftnint cunit;
+ char *csta;
+} cllist;
+
+/*rewind, backspace, endfile*/
+typedef struct
+{ flag aerr;
+ ftnint aunit;
+} alist;
+
+/* inquire */
+typedef struct
+{ flag inerr;
+ ftnint inunit;
+ char *infile;
+ ftnlen infilen;
+ ftnint *inex; /*parameters in standard's order*/
+ ftnint *inopen;
+ ftnint *innum;
+ ftnint *innamed;
+ char *inname;
+ ftnlen innamlen;
+ char *inacc;
+ ftnlen inacclen;
+ char *inseq;
+ ftnlen inseqlen;
+ char *indir;
+ ftnlen indirlen;
+ char *infmt;
+ ftnlen infmtlen;
+ char *inform;
+ ftnint informlen;
+ char *inunf;
+ ftnlen inunflen;
+ ftnint *inrecl;
+ ftnint *innrec;
+ char *inblank;
+ ftnlen inblanklen;
+} inlist;
+
+#define VOID void
+
+union Multitype { /* for multiple entry points */
+ integer1 g;
+ shortint h;
+ integer i;
+ /* longint j; */
+ real r;
+ doublereal d;
+ complex c;
+ doublecomplex z;
+ };
+
+typedef union Multitype Multitype;
+
+/*typedef long int Long;*/ /* No longer used; formerly in Namelist */
+
+struct Vardesc { /* for Namelist */
+ char *name;
+ char *addr;
+ ftnlen *dims;
+ int type;
+ };
+typedef struct Vardesc Vardesc;
+
+struct Namelist {
+ char *name;
+ Vardesc **vars;
+ int nvars;
+ };
+typedef struct Namelist Namelist;
+
+#define abs(x) ((x) >= 0 ? (x) : -(x))
+#define dabs(x) (doublereal)abs(x)
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+#define dmin(a,b) (doublereal)min(a,b)
+#define dmax(a,b) (doublereal)max(a,b)
+#define bit_test(a,b) ((a) >> (b) & 1)
+#define bit_clear(a,b) ((a) & ~((uinteger)1 << (b)))
+#define bit_set(a,b) ((a) | ((uinteger)1 << (b)))
+
+/* procedure parameter types for -A and -C++ */
+
+#define F2C_proc_par_types 1
+#ifdef __cplusplus
+typedef int /* Unknown procedure type */ (*U_fp)(...);
+typedef shortint (*J_fp)(...);
+typedef integer (*I_fp)(...);
+typedef real (*R_fp)(...);
+typedef doublereal (*D_fp)(...), (*E_fp)(...);
+typedef /* Complex */ VOID (*C_fp)(...);
+typedef /* Double Complex */ VOID (*Z_fp)(...);
+typedef logical (*L_fp)(...);
+typedef shortlogical (*K_fp)(...);
+typedef /* Character */ VOID (*H_fp)(...);
+typedef /* Subroutine */ int (*S_fp)(...);
+#else
+typedef int /* Unknown procedure type */ (*U_fp)();
+typedef shortint (*J_fp)();
+typedef integer (*I_fp)();
+typedef real (*R_fp)();
+typedef doublereal (*D_fp)(), (*E_fp)();
+typedef /* Complex */ VOID (*C_fp)();
+typedef /* Double Complex */ VOID (*Z_fp)();
+typedef logical (*L_fp)();
+typedef shortlogical (*K_fp)();
+typedef /* Character */ VOID (*H_fp)();
+typedef /* Subroutine */ int (*S_fp)();
+#endif
+/* E_fp is for real functions when -R is not specified */
+typedef VOID C_f; /* complex function */
+typedef VOID H_f; /* character function */
+typedef VOID Z_f; /* double complex function */
+typedef doublereal E_f; /* real function with -R not specified */
+
+/* undef any lower-case symbols that your C compiler predefines, e.g.: */
+
+#ifndef Skip_f2c_Undefs
+/* (No such symbols should be defined in a strict ANSI C compiler.
+ We can avoid trouble with f2c-translated code by using
+ gcc -ansi [-traditional].) */
+#undef cray
+#undef gcos
+#undef mc68010
+#undef mc68020
+#undef mips
+#undef pdp11
+#undef sgi
+#undef sparc
+#undef sun
+#undef sun2
+#undef sun3
+#undef sun4
+#undef u370
+#undef u3b
+#undef u3b2
+#undef u3b5
+#undef unix
+#undef vax
+#endif
+#endif
diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile
new file mode 100644
index 0000000..ed19ee2
--- /dev/null
+++ b/gnu/lib/libgcc/Makefile
@@ -0,0 +1,241 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../../usr.bin/cc/Makefile.tgt"
+
+GCCDIR= ${.CURDIR}/../../../contrib/gcc
+.PATH: ${GCCDIR}/config/${GCC_CPU} ${GCCDIR}
+
+# allow to be overridden for the a.out case
+.if !defined(LIB) || ${LIB} != "gcc_r"
+LIB= gcc
+.endif
+
+#SHLIB_MAJOR= 1
+#SHLIB_MINOR= 0
+
+.if ${OBJFORMAT} == aout
+# Install libgcc_pic.a, since ld.so uses it.
+INSTALL_PIC_ARCHIVE= yes
+.endif
+
+#
+# XXX This is a hack, but it seems to work.
+# libgcc2.a is meant to be compiled by *this* version of gcc.
+#
+# Normally, this does not make any difference, since we only have gcc, but
+# when bootstrapping from gcc-2.6.3, we have to use the freshly built 2.7.2
+# compiler for some of the libgcc2.c __attribute__ stuff.
+#
+# We now depend on a bootstrap pass (normally in `make world') to build
+# and install the new version of gcc before we get here. This makes
+# finding the new version (XCC) easy but may break finding the old version
+# (CC).
+#
+XCC= ${CC}
+XCXX= ${CXX}
+
+CFLAGS+= -fexceptions
+CFLAGS+= -DIN_GCC -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED \
+ -DFINE_GRAINED_LIBRARIES
+.if ${OBJFORMAT} != aout
+CFLAGS+= -D_PTHREADS -DGTHREAD_USE_WEAK
+.endif
+CFLAGS+= -I${.CURDIR}/../../usr.bin/cc/cc_tools \
+ -I${GCCDIR}/config -I${GCCDIR} -I.
+LDFLAGS= -nostdlib
+
+OBJS= # added to below in various ways depending on TARGET_ARCH
+
+#---------------------------------------------------------------------------
+#
+# When upgrading GCC, get the following defintions straight from Makefile.in
+#
+
+# Library members defined in libgcc2.c.
+# Variable length limited to 255 charactes when passed to a shell script.
+LIB2FUNCS_1 = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _ffsdi2 _clz \
+ _cmpdi2 _ucmpdi2 _floatdidf _floatdisf _fixunsdfsi _fixunssfsi \
+ _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _fixxfdi _fixunsxfdi
+
+LIB2FUNCS_2 = _floatdixf _fixunsxfsi _fixtfdi _fixunstfdi _floatditf \
+ _clear_cache _trampoline __main _exit _absvsi2 _absvdi2 _addvsi3 \
+ _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
+
+# Defined in libgcc2.c, included only in the static library.
+LIB2FUNCS_ST = _eprintf _bb __gcc_bcmp
+
+FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
+ _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
+ _lt_sf _le_sf _unord_sf _si_to_sf _sf_to_si _negate_sf _make_sf \
+ _sf_to_df _thenan_sf _sf_to_usi _usi_to_sf
+
+DPBIT_FUNCS = _pack_df _unpack_df _addsub_df _mul_df _div_df \
+ _fpcmp_parts_df _compare_df _eq_df _ne_df _gt_df _ge_df \
+ _lt_df _le_df _unord_df _si_to_df _df_to_si _negate_df _make_df \
+ _df_to_sf _thenan_df _df_to_usi _usi_to_df
+
+# These might cause a divide overflow trap and so are compiled with
+# unwinder info.
+LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udivdi3 _umoddi3 _udiv_w_sdiv _udivmoddi4
+
+MACHMODE_H = machmode.h machmode.def
+
+LIB2ADD = $(LIB2FUNCS_EXTRA)
+LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
+
+# Additional sources to handle exceptions; overridden on ia64.
+LIB2ADDEH = unwind-dw2.c unwind-dw2-fde.c unwind-sjlj.c
+
+#-----------------------------------------------------------------------
+#
+# Platform specific bits.
+# When upgrading GCC, get the following defintions from config/<cpu>/t-*
+#
+
+.if ${TARGET_ARCH} == "alpha"
+# from config/alpha/t-alpha
+LIB2FUNCS_EXTRA = qrnnd.asm
+.endif
+
+.if ${TARGET_ARCH} == "arm"
+# from config/arm/t-strongarm-elf
+LIB1ASMSRC = lib1funcs.asm
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+XXX fix this: NEED_FP_EMULATION set to "yes" with different rules per platform
+.endif
+
+.if ${TARGET_ARCH} == "ia64"
+# from config/ia64/t-ia64
+LIB1ASMSRC = lib1funcs.asm
+LIB1ASMFUNCS = __divtf3 __divdf3 __divsf3 \
+ __divdi3 __moddi3 __udivdi3 __umoddi3 \
+ __divsi3 __modsi3 __udivsi3 __umodsi3 __save_stack_nonlocal \
+ __nonlocal_goto __restore_stack_nonlocal __trampoline
+LIB2ADDEH = unwind-ia64.c unwind-sjlj.c
+.endif
+
+.if ${TARGET_ARCH} == "powerpc"
+# from config/rs6000/t-ppccomm
+LIB2FUNCS_EXTRA = tramp.asm
+# This one can't end up in shared libgcc
+LIB2FUNCS_STATIC_EXTRA = eabi.asm
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+OBJS+= dp-bit.o fp-bit.o
+.endif
+
+.if ${TARGET_ARCH} == "sparc64"
+# from config/sparc/t-elf
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+LIB1ASMSRC = lb1spc.asm
+LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
+OBJS+= dp-bit.o fp-bit.o
+.endif
+
+dp-bit.o: config/fp-bit.c
+ ${XCC} -c ${CFLAGS} -o ${.TARGET} ${.ALLSRC:M*fp-bit*}
+
+dp-bit.So: config/fp-bit.c
+ ${XCC} ${PICFLAG} -c ${CFLAGS} -o ${.TARGET} ${.ALLSRC:M*fp-bit*}
+
+dp-bit.po: config/fp-bit.c
+ ${XCC} -p -c ${CFLAGS} -o ${.TARGET} ${.ALLSRC:M*fp-bit*}
+
+fp-bit.o: config/fp-bit.c
+ ${XCC} -DFLOAT=1 -c ${CFLAGS} -o ${.TARGET} ${.ALLSRC:M*fp-bit*}
+
+fp-bit.So: config/fp-bit.c
+ ${XCC} ${PICFLAG} -DFLOAT=1 -c ${CFLAGS} -o ${.TARGET} ${.ALLSRC:M*fp-bit*}
+
+fp-bit.po: config/fp-bit.c
+ ${XCC} -p -DFLOAT=1 -c ${CFLAGS} -o ${.TARGET} ${.ALLSRC:M*fp-bit*}
+
+#-----------------------------------------------------------------------
+
+# Remove any objects from LIB2FUNCS and LIB2_DIVMOD_FUNCS that are
+# defined as optimized assembly code in LIB1ASMFUNCS.
+.if defined(LIB1ASMFUNCS)
+.for sym in ${LIB1ASMFUNCS}
+LIB2FUNCS_1:= ${LIB2FUNCS_1:S/${sym}//g}
+LIB2FUNCS_2:= ${LIB2FUNCS_2:S/${sym}//g}
+LIB2_DIVMOD_FUNCS:= ${LIB2_DIVMOD_FUNCS:S/${sym}//g}
+.endfor
+.endif
+
+ASM_T= ${LIB1ASMFUNCS:S/$/.o/}
+ASM_P= ${LIB1ASMFUNCS:S/$/.po/}
+ASM_S= ${LIB1ASMFUNCS:S/$/.So/}
+
+SYMS= ${LIB2FUNCS_1} \
+ ${LIB2FUNCS_2} \
+ ${LIB2_DIVMOD_FUNCS}
+.if ${TARGET_ARCH} == "arm" || ${TARGET_ARCH} == "powerpc" || ${TARGET_ARCH} == "sparc64"
+SYMS+= ${FPBIT_FUNCS} ${DPBIT_FUNCS}
+.endif
+SYMS_ST= ${LIB2FUNCS_ST} \
+ ${LIB2ADD_ST}
+OBJS+= ${SYMS:S/$/.o/} ${LIB1ASMFUNCS:S/$/.o/}
+OBJS_T= ${SYMS:S/$/.o/} ${SYMS_ST:S/$/.o/}
+OBJS_P= ${SYMS:S/$/.po/} ${SYMS_ST:S/$/.po/}
+OBJS_S= ${SYMS:S/$/.So/}
+STATICOBJS= ${SYMS_ST:S/$/.o/}
+SRCS= ${LIB2ADD} ${LIB2ADDEH}
+
+COMMONHDRS= tconfig.h
+SRCS+= ${COMMONHDRS}
+CLEANFILES+= ${COMMONHDRS}
+
+tconfig.h: ${.CURDIR}/../../usr.bin/cc/cc_tools/Makefile
+ ${MAKE} -f ${.ALLSRC} MFILE=${.ALLSRC} GCCDIR=${GCCDIR} ${.TARGET}
+
+${OBJS} beforedepend: ${COMMONHDRS}
+
+${OBJS_T}: libgcc2.c
+ ${XCC} -c ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c}
+ @${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+.if !defined(NOPIC)
+${OBJS_S}: libgcc2.c
+ ${XCC} -c ${PICFLAG} ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c}
+ @${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+.endif
+
+.if !defined(NOPROFILE)
+${OBJS_P}: libgcc2.c
+ ${XCC} -c -p ${CFLAGS} -DL${.PREFIX} -o ${.TARGET} ${.ALLSRC:M*.c}
+ @${LD} -o ${.TARGET}.tmp -X -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+.endif
+
+.if defined(LIB1ASMSRC)
+.for _lib1asmsrc in ${LIB1ASMSRC}
+${ASM_T}: ${_lib1asmsrc}
+ ${XCC} -x assembler-with-cpp -c ${CFLAGS} -DL${.PREFIX} \
+ -o ${.TARGET} ${.ALLSRC:N*.h}
+ @${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+
+.if !defined(NOPIC)
+${ASM_S}: ${_lib1asmsrc}
+ ${XCC} -x assembler-with-cpp -c ${PICFLAG} ${CFLAGS} -DL${.PREFIX} \
+ -o ${.TARGET} ${.ALLSRC:N*.h}
+ @${LD} -o ${.TARGET}.tmp -x -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+.endif
+
+.if !defined(NOPROFILE)
+${ASM_P}: ${_lib1asmsrc}
+ ${XCC} -x assembler-with-cpp -p -c ${CFLAGS} -DL${.PREFIX} \
+ -o ${.TARGET} ${.ALLSRC:N*.h}
+ @${LD} -o ${.TARGET}.tmp -X -r ${.TARGET}
+ @mv ${.TARGET}.tmp ${.TARGET}
+.endif
+.endfor
+.endif
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libgcc_r/Makefile b/gnu/lib/libgcc_r/Makefile
new file mode 100644
index 0000000..501549c
--- /dev/null
+++ b/gnu/lib/libgcc_r/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+LIB= gcc_r
+CFLAGS+=-D_PTHREADS
+CFLAGS+=-D'__GTHREAD_MUTEX_INIT_FUNCTION(m)=pthread_mutex_init(m, NULL)'
+
+.include "../libgcc/Makefile"
diff --git a/gnu/lib/libiberty/Makefile b/gnu/lib/libiberty/Makefile
new file mode 100644
index 0000000..17228f8
--- /dev/null
+++ b/gnu/lib/libiberty/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+SRCDIR= ${.CURDIR}/../../../contrib/binutils/libiberty
+
+.PATH: ${SRCDIR} ${SRCDIR}/../include
+
+#LIB= iberty
+
+# miniumally required sources
+SRCS= argv.c choose-temp.c concat.c cplus-dem.c fdmatch.c fnmatch.c getopt.c \
+ getopt1.c getruntime.c hex.c floatformat.c objalloc.c obstack.c \
+ pexecute.c spaces.c strerror.c strsignal.c xatexit.c xexit.c xmalloc.c \
+ xstrdup.c xstrerror.c
+
+CFLAGS+= -I${SRCDIR}/../include -I${.CURDIR}
+CFLAGS+= -DHAVE_CONFIG_H
+
+#INCS= alloca-conf.h ansidecl.h demangle.h floatformat.h fnmatch.h getopt.h \
+# libiberty.h objalloc.h obstack.h
+#INCSDIR=${INCLUDEDIR}/libiberty
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libiberty/config.h b/gnu/lib/libiberty/config.h
new file mode 100644
index 0000000..3db0e3e
--- /dev/null
+++ b/gnu/lib/libiberty/config.h
@@ -0,0 +1,255 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have <vfork.h>. */
+/* #undef HAVE_VFORK_H */
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define vfork as fork if vfork does not work. */
+/* #undef vfork */
+
+/* Define if you have the asprintf function. */
+#define HAVE_ASPRINTF 1
+
+/* Define if you have the atexit function. */
+#define HAVE_ATEXIT 1
+
+/* Define if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define if you have the bcmp function. */
+#define HAVE_BCMP 1
+
+/* Define if you have the bcopy function. */
+#define HAVE_BCOPY 1
+
+/* Define if you have the bsearch function. */
+#define HAVE_BSEARCH 1
+
+/* Define if you have the bzero function. */
+#define HAVE_BZERO 1
+
+/* Define if you have the calloc function. */
+#define HAVE_CALLOC 1
+
+/* Define if you have the clock function. */
+#define HAVE_CLOCK 1
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getrusage function. */
+#define HAVE_GETRUSAGE 1
+
+/* Define if you have the gettimeofday function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the index function. */
+#define HAVE_INDEX 1
+
+/* Define if you have the insque function. */
+/* #undef HAVE_INSQUE */
+
+/* Define if you have the memchr function. */
+#define HAVE_MEMCHR 1
+
+/* Define if you have the memcmp function. */
+#define HAVE_MEMCMP 1
+
+/* Define if you have the memcpy function. */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the memset function. */
+#define HAVE_MEMSET 1
+
+/* Define if you have the mkstemps function. */
+#define HAVE_MKSTEMPS 1
+
+/* Define if you have the on_exit function. */
+/* #undef HAVE_ON_EXIT */
+
+/* Define if you have the psignal function. */
+#define HAVE_PSIGNAL 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the random function. */
+#define HAVE_RANDOM 1
+
+/* Define if you have the rename function. */
+#define HAVE_RENAME 1
+
+/* Define if you have the rindex function. */
+#define HAVE_RINDEX 1
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the sigsetmask function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define if you have the strrchr function. */
+#define HAVE_STRRCHR 1
+
+/* Define if you have the strsignal function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtod function. */
+#define HAVE_STRTOD 1
+
+/* Define if you have the strtol function. */
+#define HAVE_STRTOL 1
+
+/* Define if you have the strtoul function. */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the sysconf function. */
+#define HAVE_SYSCONF 1
+
+/* Define if you have the times function. */
+#define HAVE_TIMES 1
+
+/* Define if you have the tmpnam function. */
+#define HAVE_TMPNAM 1
+
+/* Define if you have the vasprintf function. */
+#define HAVE_VASPRINTF 1
+
+/* Define if you have the vfprintf function. */
+#define HAVE_VFPRINTF 1
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
+/* Define if you have the vsprintf function. */
+#define HAVE_VSPRINTF 1
+
+/* Define if you have the waitpid function. */
+#define HAVE_WAITPID 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if errno must be declared even when <errno.h> is included. */
+/* #undef NEED_DECLARATION_ERRNO */
+
+/* Define if you have the sys_errlist variable. */
+#define HAVE_SYS_ERRLIST 1
+
+/* Define if you have the sys_nerr variable. */
+#define HAVE_SYS_NERR 1
+
+/* Define if you have the sys_siglist variable. */
+#define HAVE_SYS_SIGLIST 1
+
diff --git a/gnu/lib/libobjc/Makefile b/gnu/lib/libobjc/Makefile
new file mode 100644
index 0000000..35cf26a
--- /dev/null
+++ b/gnu/lib/libobjc/Makefile
@@ -0,0 +1,39 @@
+# $FreeBSD$
+
+OBJCDIR=${.CURDIR}/../../../contrib/libobjc
+GCCDIR= ${.CURDIR}/../../../contrib/gcc
+
+.PATH: ${OBJCDIR}/objc ${OBJCDIR}
+
+LIB= objc
+NOMAN= sorry
+NOPIC= works but method lookup slowdown is significant
+
+SRCS= archive.c class.c encoding.c gc.c hash.c init.c misc.c \
+ nil_method.c objects.c sarray.c selector.c sendmsg.c \
+ thr.c thr-single.c \
+ NXConstStr.m Object.m Protocol.m linking.m
+
+INCS= encoding.h hash.h objc-api.h objc-list.h objc.h runtime.h \
+ sarray.h thr.h typedstream.h NXConstStr.h Object.h Protocol.h
+INCSDIR=${INCLUDEDIR}/objc
+
+CFLAGS+= -fgnu-runtime -DHAVE_GTHR_DEFAULT -DIN_TARGET_LIBS
+CFLAGS+= -I. -I${.CURDIR}/../../usr.bin/cc/cc_tools
+CFLAGS+= -I${OBJCDIR}/objc -I${OBJCDIR}
+CFLAGS+= -I${GCCDIR}/config -I${GCCDIR}
+
+GENHDRS= runtime-info.h tconfig.h
+CLEANFILES+= ${GENHDRS}
+SRCS+= ${GENHDRS}
+
+${OBJS}: ${GENHDRS}
+
+runtime-info.h:
+ `${CC} --print-prog-name=cc1obj` -print-objc-runtime-info \
+ < /dev/null > ${.TARGET}
+
+tconfig.h: ${.CURDIR}/../../usr.bin/cc/cc_tools/Makefile
+ ${MAKE} -f ${.ALLSRC} MFILE=${.ALLSRC} GCCDIR=${GCCDIR} ${.TARGET}
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libreadline/Makefile b/gnu/lib/libreadline/Makefile
new file mode 100644
index 0000000..637dcc8
--- /dev/null
+++ b/gnu/lib/libreadline/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR = history readline
+
+.include <bsd.subdir.mk>
diff --git a/gnu/lib/libreadline/Makefile.inc b/gnu/lib/libreadline/Makefile.inc
new file mode 100644
index 0000000..58822ff
--- /dev/null
+++ b/gnu/lib/libreadline/Makefile.inc
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+SHLIB_MAJOR= 4
+SHLIB_MINOR= 2
+RL_LIBRARY_VERSION= 4.2
+
+SRCDIR= ${.CURDIR}/../../../../contrib/libreadline
+.PATH: ${SRCDIR} ${.CURDIR}/..
+
+LOCAL_CFLAGS= -DRL_LIBRARY_VERSION='"$(RL_LIBRARY_VERSION)"'
+CFLAGS+= -I${.CURDIR}/.. -I${SRCDIR} -DHAVE_CONFIG_H ${LOCAL_CFLAGS}
+
+HISTSRC= history.c histexpand.c histfile.c histsearch.c shell.c
diff --git a/gnu/lib/libreadline/config.h b/gnu/lib/libreadline/config.h
new file mode 100644
index 0000000..a470805
--- /dev/null
+++ b/gnu/lib/libreadline/config.h
@@ -0,0 +1,150 @@
+/* $FreeBSD$ */
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+#define VOID_SIGHANDLER 1
+
+/* Define if you have the lstat function. */
+#define HAVE_LSTAT 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the tcgetattr function. */
+#define HAVE_TCGETATTR 1
+
+/* Define if you have the strcoll function. */
+#define HAVE_STRCOLL 1
+
+/* #undef STRCOLL_BROKEN */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/pte.h> header file. */
+/* #undef HAVE_SYS_PTE_H */
+
+/* Define if you have the <sys/ptem.h> header file. */
+/* #undef HAVE_SYS_PTEM_H */
+
+/* Define if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/stream.h> header file. */
+/* #undef HAVE_SYS_STREAM_H */
+
+/* Define if you have the <termcap.h> header file. */
+#define HAVE_TERMCAP_H 1
+
+/* Define if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <varargs.h> header file. */
+#define HAVE_VARARGS_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+#define HAVE_LOCALE_H 1
+
+/* Definitions pulled in from aclocal.m4. */
+#define VOID_SIGHANDLER 1
+
+#define GWINSZ_IN_SYS_IOCTL 1
+
+#define STRUCT_WINSIZE_IN_SYS_IOCTL 1
+
+/* #undef STRUCT_WINSIZE_IN_TERMIOS */
+
+#define TIOCSTAT_IN_SYS_IOCTL 1
+
+#define FIONREAD_IN_SYS_IOCTL 1
+
+/* #undef SPEED_T_IN_SYS_TYPES */
+
+#define HAVE_GETPW_DECLS 1
+
+#define STRUCT_DIRENT_HAS_D_INO 1
+
+#define STRUCT_DIRENT_HAS_D_FILENO 1
+
+/* #undef HAVE_BSD_SIGNALS */
+
+#define HAVE_POSIX_SIGNALS 1
+
+/* #undef HAVE_USG_SIGHOLD */
+
+/* #undef MUST_REINSTALL_SIGHANDLERS */
+
+#define HAVE_POSIX_SIGSETJMP 1
+
+/* config.h.bot */
+/* modify settings or make new ones based on what autoconf tells us. */
+
+/* Ultrix botches type-ahead when switching from canonical to
+ non-canonical mode, at least through version 4.3 */
+#if !defined (HAVE_TERMIOS_H) || !defined (HAVE_TCGETATTR) || defined (ultrix)
+# define TERMIOS_MISSING
+#endif
+
+#if defined (STRCOLL_BROKEN)
+# define HAVE_STRCOLL 1
+#endif
+
+#if defined (__STDC__) && defined (HAVE_STDARG_H)
+# define PREFER_STDARG
+# define USE_VARARGS
+#else
+# if defined (HAVE_VARARGS_H)
+# define PREFER_VARARGS
+# define USE_VARARGS
+# endif
+#endif
diff --git a/gnu/lib/libreadline/history/Makefile b/gnu/lib/libreadline/history/Makefile
new file mode 100644
index 0000000..7c83496
--- /dev/null
+++ b/gnu/lib/libreadline/history/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+SUBDIR= doc
+
+LIB= history
+MAN= rlhistory.3
+
+SRCS= $(HISTSRC) xmalloc.c
+
+rlhistory.3: doc/history.3
+ cp ${.ALLSRC} ${.TARGET}
+
+CLEANFILES+= rlhistory.3
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libreadline/history/doc/Makefile b/gnu/lib/libreadline/history/doc/Makefile
new file mode 100644
index 0000000..4fdf229
--- /dev/null
+++ b/gnu/lib/libreadline/history/doc/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+SRCDIR= ${.CURDIR}/../../../../../contrib/libreadline/doc
+
+INFO = history
+
+INFOSECTION= "Programming & development tools."
+INFOENTRY_history= "* History: (history). The GNU History library."
+
+SRCS= hist.texinfo
+
+history.info: hist.texinfo hstech.texinfo hsuser.texinfo manvers.texinfo
+
+.include <bsd.info.mk>
diff --git a/gnu/lib/libreadline/readline/Makefile b/gnu/lib/libreadline/readline/Makefile
new file mode 100644
index 0000000..57fa012
--- /dev/null
+++ b/gnu/lib/libreadline/readline/Makefile
@@ -0,0 +1,26 @@
+# $FreeBSD$
+
+SUBDIR= doc
+
+LIB= readline
+MAN= doc/readline.3
+
+TILDESRC= tilde.c
+SRCS= readline.c vi_mode.c funmap.c keymaps.c parens.c search.c \
+ rltty.c complete.c bind.c isearch.c display.c signals.c \
+ util.c kill.c undo.c macro.c input.c callback.c terminal.c \
+ nls.c compat.c xmalloc.c $(HISTSRC) $(TILDESRC)
+
+INSTALLED_HEADERS= readline.h chardefs.h keymaps.h history.h tilde.h \
+ rlstdc.h rlconf.h rltypedefs.h
+
+DPADD= ${LIBNCURSES}
+LDADD= -lncurses
+
+INCSDIR=${INCLUDEDIR}/readline
+
+.for hdr in ${INSTALLED_HEADERS}
+INCS+= ${SRCDIR}/${hdr}
+.endfor
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libreadline/readline/doc/Makefile b/gnu/lib/libreadline/readline/doc/Makefile
new file mode 100644
index 0000000..6602de5
--- /dev/null
+++ b/gnu/lib/libreadline/readline/doc/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+SRCDIR= ${.CURDIR}/../../../../../contrib/libreadline/doc
+
+INFO = readline rluserman
+
+INFOSECTION= "Programming & development tools."
+INFOENTRY_readline= "* Readline: (readline). The GNU Readline library"
+INFOENTRY_rluserman= "* Readline: (readline). The GNU readline library API"
+
+CLEANFILES += readline.texinfo
+
+readline.info: rlman.texinfo rltech.texinfo rluser.texinfo manvers.texinfo
+
+readline.texinfo: rlman.texinfo
+ cp ${SRCDIR}/rlman.texinfo ${.TARGET}
+
+rluserman.info: rluser.texinfo manvers.texinfo
+
+.include <bsd.info.mk>
diff --git a/gnu/lib/libregex/AUTHORS b/gnu/lib/libregex/AUTHORS
new file mode 100644
index 0000000..058be99
--- /dev/null
+++ b/gnu/lib/libregex/AUTHORS
@@ -0,0 +1,10 @@
+Richard Stallman -- original version and continuing revisions of
+ regex.c and regex.h, and original version of the documentation.
+
+Karl Berry and Kathryn Hargreaves -- extensive modifications to above,
+ and all test files.
+
+Jim Blandy -- original version of re_set_registers, revisions to regex.c.
+
+Joe Arceneaux, David MacKenzie, Mike Haertel, Charles Hannum, and
+probably others -- revisions to regex.c.
diff --git a/gnu/lib/libregex/COPYING b/gnu/lib/libregex/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/gnu/lib/libregex/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/lib/libregex/ChangeLog b/gnu/lib/libregex/ChangeLog
new file mode 100644
index 0000000..ef919d2
--- /dev/null
+++ b/gnu/lib/libregex/ChangeLog
@@ -0,0 +1,3030 @@
+Fri Apr 2 17:31:59 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * Released version 0.12.
+
+ * regex.c (regerror): If errcode is zero, that's not a valid
+ error code, according to POSIX, but return "Success."
+
+ * regex.c (regerror): Remember to actually fetch the message
+ from re_error_msg.
+
+ * regex.c (regex_compile): Don't use the trick for ".*\n" on
+ ".+\n". Since the latter involves laying an extra choice
+ point, the backward jump isn't adjusted properly.
+
+Thu Mar 25 21:35:18 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * regex.c (regex_compile): In the handle_open and handle_close
+ sections, clear pending_exact to zero.
+
+Tue Mar 9 12:03:07 1993 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * regex.c (re_search_2): In the loop which searches forward
+ using fastmap, don't forget to cast the character from the
+ string to an unsigned before using it as an index into the
+ translate map.
+
+Thu Jan 14 15:41:46 1993 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu)
+
+ * regex.h: Never define const; let the callers do it.
+ configure.in: Don't define USING_AUTOCONF.
+
+Wed Jan 6 20:49:29 1993 Jim Blandy (jimb@geech.gnu.ai.mit.edu)
+
+ * regex.c (regerror): Abort if ERRCODE is out of range.
+
+Sun Dec 20 16:19:10 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * configure.in: Arrange to #define USING_AUTOCONF.
+ * regex.h: If USING_AUTOCONF is #defined, don't mess with
+ `const' at all; autoconf has taken care of it.
+
+Mon Dec 14 21:40:39 1992 David J. MacKenzie (djm@kropotkin.gnu.ai.mit.edu)
+
+ * regex.h (RE_SYNTAX_AWK): Fix typo. From Arnold Robbins.
+
+Sun Dec 13 20:35:39 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * regex.c (compile_range): Fetch the range start and end by
+ casting the pattern pointer to an `unsigned char *' before
+ fetching through it.
+
+Sat Dec 12 09:41:01 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * regex.c: Undo change of 12/7/92; it's better for Emacs to
+ #define HAVE_CONFIG_H.
+
+Fri Dec 11 22:00:34 1992 Jim Meyering (meyering@hal.gnu.ai.mit.edu)
+
+ * regex.c: Define and use isascii-protected ctype.h macros.
+
+Fri Dec 11 05:10:38 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * regex.c (re_match_2): Undo Karl's November 10th change; it
+ keeps the group in :\(.*\) from matching :/ properly.
+
+Mon Dec 7 19:44:56 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * regex.c: #include config.h if either HAVE_CONFIG_H or emacs
+ is #defined.
+
+Tue Dec 1 13:33:17 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
+
+ * regex.c [HAVE_CONFIG_H]: Include config.h.
+
+Wed Nov 25 23:46:02 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
+
+ * regex.c (regcomp): Add parens around bitwise & for clarity.
+ Initialize preg->allocated to prevent segv.
+
+Tue Nov 24 09:22:29 1992 David J. MacKenzie (djm@goldman.gnu.ai.mit.edu)
+
+ * regex.c: Use HAVE_STRING_H, not USG.
+ * configure.in: Check for string.h, not USG.
+
+Fri Nov 20 06:33:24 1992 Karl Berry (karl@cs.umb.edu)
+
+ * regex.c (SIGN_EXTEND_CHAR) [VMS]: Back out of this change,
+ since Roland Roberts now says it was a localism.
+
+Mon Nov 16 07:01:36 1992 Karl Berry (karl@cs.umb.edu)
+
+ * regex.h (const) [!HAVE_CONST]: Test another cpp symbol (from
+ Autoconf) before zapping const.
+
+Sun Nov 15 05:36:42 1992 Jim Blandy (jimb@wookumz.gnu.ai.mit.edu)
+
+ * regex.c, regex.h: Changes for VMS from Roland B Roberts
+ <roberts@nsrl31.nsrl.rochester.edu>.
+
+Thu Nov 12 11:31:15 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in (distfiles): Include INSTALL.
+
+Tue Nov 10 09:29:23 1992 Karl Berry (karl@cs.umb.edu)
+
+ * regex.c (re_match_2): At maybe_pop_jump, if at end of string
+ and pattern, just quit the matching loop.
+
+ * regex.c (LETTER_P): Rename to `WORDCHAR_P'.
+
+ * regex.c (AT_STRINGS_{BEG,END}): Take `d' as an arg; change
+ callers.
+
+ * regex.c (re_match_2) [!emacs]: In wordchar and notwordchar
+ cases, advance d.
+
+Wed Nov 4 15:43:58 1992 Karl Berry (karl@hal.gnu.ai.mit.edu)
+
+ * regex.h (const) [!__STDC__]: Don't define if it's already defined.
+
+Sat Oct 17 19:28:19 1992 Karl Berry (karl@cs.umb.edu)
+
+ * regex.c (bcmp, bcopy, bzero): Only #define if they are not
+ already #defined.
+
+ * configure.in: Use AC_CONST.
+
+Thu Oct 15 08:39:06 1992 Karl Berry (karl@cs.umb.edu)
+
+ * regex.h (const) [!const]: Conditionalize.
+
+Fri Oct 2 13:31:42 1992 Karl Berry (karl@cs.umb.edu)
+
+ * regex.h (RE_SYNTAX_ED): New definition.
+
+Sun Sep 20 12:53:39 1992 Karl Berry (karl@cs.umb.edu)
+
+ * regex.[ch]: remove traces of `longest_p' -- dumb idea to put
+ this into the pattern buffer, as it means parallelism loses.
+
+ * Makefile.in (config.status): use sh to run configure --no-create.
+
+ * Makefile.in (realclean): OK, don't remove configure.
+
+Sat Sep 19 09:05:08 1992 Karl Berry (karl@hayley)
+
+ * regex.c (PUSH_FAILURE_POINT, POP_FAILURE_POINT) [DEBUG]: keep
+ track of how many failure points we push and pop.
+ (re_match_2) [DEBUG]: declare variables for that, and print results.
+ (DEBUG_PRINT4): new macro.
+
+ * regex.h (re_pattern_buffer): new field `longest_p' (to
+ eliminate backtracking if the user doesn't need it).
+ * regex.c (re_compile_pattern): initialize it (to 1).
+ (re_search_2): set it to zero if register information is not needed.
+ (re_match_2): if it's set, don't backtrack.
+
+ * regex.c (re_search_2): update fastmap only after checking that
+ the pattern is anchored.
+
+ * regex.c (re_match_2): do more debugging at maybe_pop_jump.
+
+ * regex.c (re_search_2): cast result of TRANSLATE for use in
+ array subscript.
+
+Thu Sep 17 19:47:16 1992 Karl Berry (karl@geech.gnu.ai.mit.edu)
+
+ * Version 0.11.
+
+Wed Sep 16 08:17:10 1992 Karl Berry (karl@hayley)
+
+ * regex.c (INIT_FAIL_STACK): rewrite as statements instead of a
+ complicated comma expr, to avoid compiler warnings (and also
+ simplify).
+ (re_compile_fastmap, re_match_2): change callers.
+
+ * regex.c (POP_FAILURE_POINT): cast pop of regstart and regend
+ to avoid compiler warnings.
+
+ * regex.h (RE_NEWLINE_ORDINARY): remove this syntax bit, and
+ remove uses.
+ * regex.c (at_{beg,end}line_loc_p): go the last mile: remove
+ the RE_NEWLINE_ORDINARY case which made the ^ in \n^ be an anchor.
+
+Tue Sep 15 09:55:29 1992 Karl Berry (karl@hayley)
+
+ * regex.c (at_begline_loc_p): new fn.
+ (at_endline_loc_p): simplify at_endline_op_p.
+ (regex_compile): in ^/$ cases, call the above.
+
+ * regex.c (POP_FAILURE_POINT): rewrite the fn as a macro again,
+ as lord's profiling indicates the function is 20% of the time.
+ (re_match_2): callers changed.
+
+ * configure.in (AC_MEMORY_H): remove, since we never use memcpy et al.
+
+Mon Sep 14 17:49:27 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (makeargs): include MFLAGS.
+
+Sun Sep 13 07:41:45 1992 Karl Berry (karl@hayley)
+
+ * regex.c (regex_compile): in \1..\9 case, make it always
+ invalid to use \<digit> if there is no preceding <digit>th subexpr.
+ * regex.h (RE_NO_MISSING_BK_REF): remove this syntax bit.
+
+ * regex.c (regex_compile): remove support for invalid empty groups.
+ * regex.h (RE_NO_EMPTY_GROUPS): remove this syntax bit.
+
+ * regex.c (FREE_VARIABLES) [!REGEX_MALLOC]: define as alloca (0),
+ to reclaim memory.
+
+ * regex.h (RE_SYNTAX_POSIX_SED): don't bother with this.
+
+Sat Sep 12 13:37:21 1992 Karl Berry (karl@hayley)
+
+ * README: incorporate emacs.diff.
+
+ * regex.h (_RE_ARGS) [!__STDC__]: define as empty parens.
+
+ * configure.in: add AC_ALLOCA.
+
+ * Put test files in subdir test, documentation in subdir doc.
+ Adjust Makefile.in and configure.in accordingly.
+
+Thu Sep 10 10:29:11 1992 Karl Berry (karl@hayley)
+
+ * regex.h (RE_SYNTAX_{POSIX_,}SED): new definitions.
+
+Wed Sep 9 06:27:09 1992 Karl Berry (karl@hayley)
+
+ * Version 0.10.
+
+Tue Sep 8 07:32:30 1992 Karl Berry (karl@hayley)
+
+ * xregex.texinfo: put the day of month into the date.
+
+ * Makefile.in (realclean): remove Texinfo-generated files.
+ (distclean): remove empty sorted index files.
+ (clean): remove dvi files, etc.
+
+ * configure.in: test for more Unix variants.
+
+ * fileregex.c: new file.
+ Makefile.in (fileregex): new target.
+
+ * iregex.c (main): move variable decls to smallest scope.
+
+ * regex.c (FREE_VARIABLES): free reg_{,info_}dummy.
+ (re_match_2): check that the allocation for those two succeeded.
+
+ * regex.c (FREE_VAR): replace FREE_NONNULL with this.
+ (FREE_VARIABLES): call it.
+ (re_match_2) [REGEX_MALLOC]: initialize all our vars to NULL.
+
+ * tregress.c (do_match): generalize simple_match.
+ (SIMPLE_NONMATCH): new macro.
+ (SIMPLE_MATCH): change from routine.
+
+ * Makefile.in (regex.texinfo): make file readonly, so we don't
+ edit it by mistake.
+
+ * many files (re_default_syntax): rename to `re_syntax_options';
+ call re_set_syntax instead of assigning to the variable where
+ possible.
+
+Mon Sep 7 10:12:16 1992 Karl Berry (karl@hayley)
+
+ * syntax.skel: don't use prototypes.
+
+ * {configure,Makefile}.in: new files.
+
+ * regex.c: include <string.h> `#if USG || STDC_HEADERS'; remove
+ obsolete test for `POSIX', and test for BSRTING.
+ Include <strings.h> if we are not USG or STDC_HEADERS.
+ Do not include <unistd.h>. What did we ever need that for?
+
+ * regex.h (RE_NO_EMPTY_ALTS): remove this.
+ (RE_SYNTAX_AWK): remove from here, too.
+ * regex.c (regex_compile): remove the check.
+ * xregex.texinfo (Alternation Operator): update.
+ * other.c (test_others): remove tests for this.
+
+ * regex.h (RE_DUP_MAX): undefine if already defined.
+
+ * regex.h: (RE_SYNTAX_POSIX*): redo to allow more operators, and
+ define new syntaxes with the minimal set.
+
+ * syntax.skel (main): used sscanf instead of scanf.
+
+ * regex.h (RE_SYNTAX_*GREP): new definitions from mike.
+
+ * regex.c (regex_compile): initialize the upper bound of
+ intervals at the beginning of the interval, not the end.
+ (From pclink@qld.tne.oz.au.)
+
+ * regex.c (handle_bar): rename to `handle_alt', for consistency.
+
+ * regex.c ({store,insert}_{op1,op2}): new routines (except the last).
+ ({STORE,INSERT}_JUMP{,2}): macros to replace the old routines,
+ which took arguments in different orders, and were generally weird.
+
+ * regex.c (PAT_PUSH*): rename to `BUF_PUSH*' -- we're not
+ appending info to the pattern!
+
+Sun Sep 6 11:26:49 1992 Karl Berry (karl@hayley)
+
+ * regex.c (regex_compile): delete the variable
+ `following_left_brace', since we never use it.
+
+ * regex.c (print_compiled_pattern): don't print the fastmap if
+ it's null.
+
+ * regex.c (re_compile_fastmap): handle
+ `on_failure_keep_string_jump' like `on_failure_jump'.
+
+ * regex.c (re_match_2): in `charset{,_not' case, cast the bit
+ count to unsigned, not unsigned char, in case we have a full
+ 32-byte bit list.
+
+ * tregress.c (simple_match): remove.
+ (simple_test): rename as `simple_match'.
+ (simple_compile): print the error string if the compile failed.
+
+ * regex.c (DO_RANGE): rewrite as a function, `compile_range', so
+ we can debug it. Change pattern characters to unsigned char
+ *'s, and change the range variable to an unsigned.
+ (regex_compile): change calls.
+
+Sat Sep 5 17:40:49 1992 Karl Berry (karl@hayley)
+
+ * regex.h (_RE_ARGS): new macro to put in argument lists (if
+ ANSI) or omit them (if K&R); don't declare routines twice.
+
+ * many files (obscure_syntax): rename to `re_default_syntax'.
+
+Fri Sep 4 09:06:53 1992 Karl Berry (karl@hayley)
+
+ * GNUmakefile (extraclean): new target.
+ (realclean): delete the info files.
+
+Wed Sep 2 08:14:42 1992 Karl Berry (karl@hayley)
+
+ * regex.h: doc fix.
+
+Sun Aug 23 06:53:15 1992 Karl Berry (karl@hayley)
+
+ * regex.[ch] (re_comp): no const in the return type (from djm).
+
+Fri Aug 14 07:25:46 1992 Karl Berry (karl@hayley)
+
+ * regex.c (DO_RANGE): declare variables as unsigned chars, not
+ signed chars (from jimb).
+
+Wed Jul 29 18:33:53 1992 Karl Berry (karl@claude.cs.umb.edu)
+
+ * Version 0.9.
+
+ * GNUmakefile (distclean): do not remove regex.texinfo.
+ (realclean): remove it here.
+
+ * tregress.c (simple_test): initialize buf.buffer.
+
+Sun Jul 26 08:59:38 1992 Karl Berry (karl@hayley)
+
+ * regex.c (push_dummy_failure): new opcode and corresponding
+ case in the various routines. Pushed at the end of
+ alternatives.
+
+ * regex.c (jump_past_next_alt): rename to `jump_past_alt', for
+ brevity.
+ (no_pop_jump): rename to `jump'.
+
+ * regex.c (regex_compile) [DEBUG]: terminate printing of pattern
+ with a newline.
+
+ * NEWS: new file.
+
+ * tregress.c (simple_{compile,match,test}): routines to simplify all
+ these little tests.
+
+ * tregress.c: test for matching as much as possible.
+
+Fri Jul 10 06:53:32 1992 Karl Berry (karl@hayley)
+
+ * Version 0.8.
+
+Wed Jul 8 06:39:31 1992 Karl Berry (karl@hayley)
+
+ * regex.c (SIGN_EXTEND_CHAR): #undef any previous definition, as
+ ours should always work properly.
+
+Mon Jul 6 07:10:50 1992 Karl Berry (karl@hayley)
+
+ * iregex.c (main) [DEBUG]: conditionalize the call to
+ print_compiled_pattern.
+
+ * iregex.c (main): initialize buf.buffer to NULL.
+ * tregress (test_regress): likewise.
+
+ * regex.c (alloca) [sparc]: #if on HAVE_ALLOCA_H instead.
+
+ * tregress.c (test_regress): didn't have jla's test quite right.
+
+Sat Jul 4 09:02:12 1992 Karl Berry (karl@hayley)
+
+ * regex.c (re_match_2): only REGEX_ALLOCATE all the register
+ vectors if the pattern actually has registers.
+ (match_end): new variable to avoid having to use best_regend[0].
+
+ * regex.c (IS_IN_FIRST_STRING): rename to FIRST_STRING_P.
+
+ * regex.c: doc fixes.
+
+ * tregess.c (test_regress): new fastmap test forwarded by rms.
+
+ * tregress.c (test_regress): initialize the fastmap field.
+
+ * tregress.c (test_regress): new test from jla that aborted
+ in re_search_2.
+
+Fri Jul 3 09:10:05 1992 Karl Berry (karl@hayley)
+
+ * tregress.c (test_regress): add tests for translating charsets,
+ from kaoru.
+
+ * GNUmakefile (common): add alloca.o.
+ * alloca.c: new file, copied from bison.
+
+ * other.c (test_others): remove var `buf', since it's no longer used.
+
+ * Below changes from ro@TechFak.Uni-Bielefeld.DE.
+
+ * tregress.c (test_regress): initialize buf.allocated.
+
+ * regex.c (re_compile_fastmap): initialize `succeed_n_p'.
+
+ * GNUmakefile (regex): depend on $(common).
+
+Wed Jul 1 07:12:46 1992 Karl Berry (karl@hayley)
+
+ * Version 0.7.
+
+ * regex.c: doc fixes.
+
+Mon Jun 29 08:09:47 1992 Karl Berry (karl@fosse)
+
+ * regex.c (pop_failure_point): change string vars to
+ `const char *' from `unsigned char *'.
+
+ * regex.c: consolidate debugging stuff.
+ (print_partial_compiled_pattern): avoid enum clash.
+
+Mon Jun 29 07:50:27 1992 Karl Berry (karl@hayley)
+
+ * xmalloc.c: new file.
+ * GNUmakefile (common): add it.
+
+ * iregex.c (print_regs): new routine (from jimb).
+ (main): call it.
+
+Sat Jun 27 10:50:59 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * xregex.c (re_match_2): When we have accepted a match and
+ restored d from best_regend[0], we need to set dend
+ appropriately as well.
+
+Sun Jun 28 08:48:41 1992 Karl Berry (karl@hayley)
+
+ * tregress.c: rename from regress.c.
+
+ * regex.c (print_compiled_pattern): improve charset case to ease
+ byte-counting.
+ Also, don't distinguish between Emacs and non-Emacs
+ {not,}wordchar opcodes.
+
+ * regex.c (print_fastmap): move here.
+ * test.c: from here.
+ * regex.c (print_{{partial,}compiled_pattern,double_string}):
+ rename from ..._printer. Change calls here and in test.c.
+
+ * regex.c: create from xregex.c and regexinc.c for once and for
+ all, and change the debug fns to be extern, instead of static.
+ * GNUmakefile: remove traces of xregex.c.
+ * test.c: put in externs, instead of including regexinc.c.
+
+ * xregex.c: move interactive main program and scanstring to iregex.c.
+ * iregex.c: new file.
+ * upcase.c, printchar.c: new files.
+
+ * various doc fixes and other cosmetic changes throughout.
+
+ * regexinc.c (compiled_pattern_printer): change variable name,
+ for consistency.
+ (partial_compiled_pattern_printer): print other info about the
+ compiled pattern, besides just the opcodes.
+ * xregex.c (regex_compile) [DEBUG]: print the compiled pattern
+ when we're done.
+
+ * xregex.c (re_compile_fastmap): in the duplicate case, set
+ `can_be_null' and return.
+ Also, set `bufp->can_be_null' according to a new variable,
+ `path_can_be_null'.
+ Also, rewrite main while loop to not test `p != NULL', since
+ we never set it that way.
+ Also, eliminate special `can_be_null' value for the endline case.
+ (re_search_2): don't test for the special value.
+ * regex.h (struct re_pattern_buffer): remove the definition.
+
+Sat Jun 27 15:00:40 1992 Karl Berry (karl@hayley)
+
+ * xregex.c (re_compile_fastmap): remove the `RE_' from
+ `REG_RE_MATCH_NULL_AT_END'.
+ Also, assert the fastmap in the pattern buffer is non-null.
+ Also, reset `succeed_n_p' after we've
+ paid attention to it, instead of every time through the loop.
+ Also, in the `anychar' case, only clear fastmap['\n'] if the
+ syntax says to, and don't return prematurely.
+ Also, rearrange cases in some semblance of a rational order.
+ * regex.h (REG_RE_MATCH_NULL_AT_END): remove the `RE_' from the name.
+
+ * other.c: take bug reports from here.
+ * regress.c: new file for them.
+ * GNUmakefile (test): add it.
+ * main.c (main): new possible test.
+ * test.h (test_type): new value in enum.
+
+Thu Jun 25 17:37:43 1992 Karl Berry (karl@hayley)
+
+ * xregex.c (scanstring) [test]: new function from jimb to allow some
+ escapes.
+ (main) [test]: call it (on the string, not the pattern).
+
+ * xregex.c (main): make return type `int'.
+
+Wed Jun 24 10:43:03 1992 Karl Berry (karl@hayley)
+
+ * xregex.c (pattern_offset_t): change to `int', for the benefit
+ of patterns which compile to more than 2^15 bytes.
+
+ * xregex.c (GET_BUFFER_SPACE): remove spurious braces.
+
+ * xregex.texinfo (Using Registers): put in a stub to ``document''
+ the new function.
+ * regex.h (re_set_registers) [!__STDC__]: declare.
+ * xregex.c (re_set_registers): declare K&R style (also move to a
+ different place in the file).
+
+Mon Jun 8 18:03:28 1992 Jim Blandy (jimb@pogo.cs.oberlin.edu)
+
+ * regex.h (RE_NREGS): Doc fix.
+
+ * xregex.c (re_set_registers): New function.
+ * regex.h (re_set_registers): Declaration for new function.
+
+Fri Jun 5 06:55:18 1992 Karl Berry (karl@hayley)
+
+ * main.c (main): `return 0' instead of `exit (0)'. (From Paul Eggert)
+
+ * regexinc.c (SIGN_EXTEND_CHAR): cast to unsigned char.
+ (extract_number, EXTRACT_NUMBER): don't bother to cast here.
+
+Tue Jun 2 07:37:53 1992 Karl Berry (karl@hayley)
+
+ * Version 0.6.
+
+ * Change copyrights to `1985, 89, ...'.
+
+ * regex.h (REG_RE_MATCH_NULL_AT_END): new macro.
+ * xregex.c (re_compile_fastmap): initialize `can_be_null' to
+ `p==pend', instead of in the test at the top of the loop (as
+ it was, it was always being set).
+ Also, set `can_be_null'=1 if we would jump to the end of the
+ pattern in the `on_failure_jump' cases.
+ (re_search_2): check if `can_be_null' is 1, not nonzero. This
+ was the original test in rms' regex; why did we change this?
+
+ * xregex.c (re_compile_fastmap): rename `is_a_succeed_n' to
+ `succeed_n_p'.
+
+Sat May 30 08:09:08 1992 Karl Berry (karl@hayley)
+
+ * xregex.c (re_compile_pattern): declare `regnum' as `unsigned',
+ not `regnum_t', for the benefit of those patterns with more
+ than 255 groups.
+
+ * xregex.c: rename `failure_stack' to `fail_stack', for brevity;
+ likewise for `match_nothing' to `match_null'.
+
+ * regexinc.c (REGEX_REALLOCATE): take both the new and old
+ sizes, and copy only the old bytes.
+ * xregex.c (DOUBLE_FAILURE_STACK): pass both old and new.
+ * This change from Thorsten Ohl.
+
+Fri May 29 11:45:22 1992 Karl Berry (karl@hayley)
+
+ * regexinc.c (SIGN_EXTEND_CHAR): define as `(signed char) c'
+ instead of relying on __CHAR_UNSIGNED__, to work with
+ compilers other than GCC. From Per Bothner.
+
+ * main.c (main): change return type to `int'.
+
+Mon May 18 06:37:08 1992 Karl Berry (karl@hayley)
+
+ * regex.h (RE_SYNTAX_AWK): typo in RE_RE_UNMATCHED...
+
+Fri May 15 10:44:46 1992 Karl Berry (karl@hayley)
+
+ * Version 0.5.
+
+Sun May 3 13:54:00 1992 Karl Berry (karl@hayley)
+
+ * regex.h (struct re_pattern_buffer): now it's just `regs_allocated'.
+ (REGS_UNALLOCATED, REGS_REALLOCATE, REGS_FIXED): new constants.
+ * xregex.c (regexec, re_compile_pattern): set the field appropriately.
+ (re_match_2): and use it. bufp can't be const any more.
+
+Fri May 1 15:43:09 1992 Karl Berry (karl@hayley)
+
+ * regexinc.c: unconditionally include <sys/types.h>, first.
+
+ * regex.h (struct re_pattern_buffer): rename
+ `caller_allocated_regs' to `regs_allocated_p'.
+ * xregex.c (re_compile_pattern): same change here.
+ (regexec): and here.
+ (re_match_2): reallocate registers if necessary.
+
+Fri Apr 10 07:46:50 1992 Karl Berry (karl@hayley)
+
+ * regex.h (RE_SYNTAX{_POSIX,}_AWK): new definitions from Arnold.
+
+Sun Mar 15 07:34:30 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (dist): versionize regex.{c,h,texinfo}.
+
+Tue Mar 10 07:05:38 1992 Karl Berry (karl at hayley)
+
+ * Version 0.4.
+
+ * xregex.c (PUSH_FAILURE_POINT): always increment the failure id.
+ (DEBUG_STATEMENT) [DEBUG]: execute the statement even if `debug'==0.
+
+ * xregex.c (pop_failure_point): if the saved string location is
+ null, keep the current value.
+ (re_match_2): at fail, test for a dummy failure point by
+ checking the restored pattern value, not string value.
+ (re_match_2): new case, `on_failure_keep_string_jump'.
+ (regex_compile): output this opcode in the .*\n case.
+ * regexinc.c (re_opcode_t): define the opcode.
+ (partial_compiled_pattern_pattern): add the new case.
+
+Mon Mar 9 09:09:27 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (regex_compile): optimize .*\n to output an
+ unconditional jump to the ., instead of pushing failure points
+ each time through the loop.
+
+ * xregex.c (DOUBLE_FAILURE_STACK): compute the maximum size
+ ourselves (and correctly); change callers.
+
+Sun Mar 8 17:07:46 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (failure_stack_elt_t): change to `const char *', to
+ avoid warnings.
+
+ * regex.h (re_set_syntax): declare this.
+
+ * xregex.c (pop_failure_point) [DEBUG]: conditionally pass the
+ original strings and sizes; change callers.
+
+Thu Mar 5 16:35:35 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * xregex.c (regnum_t): new type for register/group numbers.
+ (compile_stack_elt_t, regex_compile): use it.
+
+ * xregex.c (regexec): declare len as `int' to match re_search.
+
+ * xregex.c (re_match_2): don't declare p1 twice.
+
+ * xregex.c: change `while (1)' to `for (;;)' to avoid silly
+ compiler warnings.
+
+ * regex.h [__STDC__]: use #if, not #ifdef.
+
+ * regexinc.c (REGEX_REALLOCATE): cast the result of alloca to
+ (char *), to avoid warnings.
+
+ * xregex.c (regerror): declare variable as const.
+
+ * xregex.c (re_compile_pattern, re_comp): define as returning a const
+ char *.
+ * regex.h (re_compile_pattern, re_comp): likewise.
+
+Thu Mar 5 15:57:56 1992 Karl Berry (karl@hal)
+
+ * xregex.c (regcomp): declare `syntax' as unsigned.
+
+ * xregex.c (re_match_2): try to avoid compiler warnings about
+ unsigned comparisons.
+
+ * GNUmakefile (test-xlc): new target.
+
+ * regex.h (reg_errcode_t): remove trailing comma from definition.
+ * regexinc.c (re_opcode_t): likewise.
+
+Thu Mar 5 06:56:07 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (dist): add version numbers automatically.
+ (versionfiles): new variable.
+ (regex.{c,texinfo}): don't add version numbers here.
+ * regex.h: put in placeholder instead of the version number.
+
+Fri Feb 28 07:11:33 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (re_error_msg): declare const, since it is.
+
+Sun Feb 23 05:41:57 1992 Karl Berry (karl at fosse)
+
+ * xregex.c (PAT_PUSH{,_2,_3}, ...): cast args to avoid warnings.
+ (regex_compile, regexec): return REG_NOERROR, instead
+ of 0, on success.
+ (boolean): define as char, and #define false and true.
+ * regexinc.c (STREQ): cast the result.
+
+Sun Feb 23 07:45:38 1992 Karl Berry (karl at hayley)
+
+ * GNUmakefile (test-cc, test-hc, test-pcc): new targets.
+
+ * regex.inc (extract_number, extract_number_and_incr) [DEBUG]:
+ only define if we are debugging.
+
+ * xregex.c [_AIX]: do #pragma alloca first if necessary.
+ * regexinc.c [_AIX]: remove the #pragma from here.
+
+ * regex.h (reg_syntax_t): declare as unsigned, and redo the enum
+ as #define's again. Some compilers do stupid things with enums.
+
+Thu Feb 20 07:19:47 1992 Karl Berry (karl at hayley)
+
+ * Version 0.3.
+
+ * xregex.c, regex.h (newline_anchor_match_p): rename to
+ `newline_anchor'; dumb idea to change the name.
+
+Tue Feb 18 07:09:02 1992 Karl Berry (karl at hayley)
+
+ * regexinc.c: go back to original, i.e., don't include
+ <string.h> or define strchr.
+ * xregex.c (regexec): don't bother with adding characters after
+ newlines to the fastmap; instead, just don't use a fastmap.
+ * xregex.c (regcomp): set the buffer and fastmap fields to zero.
+
+ * xregex.texinfo (GNU r.e. compiling): have to initialize more
+ than two fields.
+
+ * regex.h (struct re_pattern_buffer): rename `newline_anchor' to
+ `newline_anchor_match_p', as we're back to two cases.
+ * xregex.c (regcomp, re_compile_pattern, re_comp): change
+ accordingly.
+ (re_match_2): at begline and endline, POSIX is not a special
+ case anymore; just check newline_anchor_match_p.
+
+Thu Feb 13 16:29:33 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (*empty_string*): rename to *null_string*, for brevity.
+
+Wed Feb 12 06:36:22 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (re_compile_fastmap): at endline, don't set fastmap['\n'].
+ (re_match_2): rewrite the begline/endline cases to take account
+ of the new field newline_anchor.
+
+Tue Feb 11 14:34:55 1992 Karl Berry (karl at hayley)
+
+ * regexinc.c [!USG etc.]: include <strings.h> and define strchr
+ as index.
+
+ * xregex.c (re_search_2): when searching backwards, declare `c'
+ as a char and use casts when using it as an array subscript.
+
+ * xregex.c (regcomp): if REG_NEWLINE, set
+ RE_HAT_LISTS_NOT_NEWLINE. Set the `newline_anchor' field
+ appropriately.
+ (regex_compile): compile [^...] as matching a \n according to
+ the syntax bit.
+ (regexec): if doing REG_NEWLINE stuff, compile a fastmap and add
+ characters after any \n's to the newline.
+ * regex.h (RE_HAT_LISTS_NOT_NEWLINE): new syntax bit.
+ (struct re_pattern_buffer): rename `posix_newline' to
+ `newline_anchor', define constants for its values.
+
+Mon Feb 10 07:22:50 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (re_compile_fastmap): combine the code at the top and
+ bottom of the loop, as it's essentially identical.
+
+Sun Feb 9 10:02:19 1992 Karl Berry (karl at hayley)
+
+ * xregex.texinfo (POSIX Translate Tables): remove this, as it
+ doesn't match the spec.
+
+ * xregex.c (re_compile_fastmap): if we finish off a path, go
+ back to the top (to set can_be_null) instead of returning
+ immediately.
+
+ * xregex.texinfo: changes from bob.
+
+Sat Feb 1 07:03:25 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (re_search_2): doc fix (from rms).
+
+Fri Jan 31 09:52:04 1992 Karl Berry (karl at hayley)
+
+ * xregex.texinfo (GNU Searching): clarify the range arg.
+
+ * xregex.c (re_match_2, at_endline_op_p): add extra parens to
+ get rid of GCC 2's (silly, IMHO) warning about && within ||.
+
+ * xregex.c (common_op_match_empty_string_p): use
+ MATCH_NOTHING_UNSET_VALUE, not -1.
+
+Thu Jan 16 08:43:02 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (SET_REGS_MATCHED): only set the registers from
+ lowest to highest.
+
+ * regexinc.c (MIN): new macro.
+ * xregex.c (re_match_2): only check min (num_regs,
+ regs->num_regs) when we set the returned regs.
+
+ * xregex.c (re_match_2): set registers after the first
+ num_regs to -1 before we return.
+
+Tue Jan 14 16:01:42 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (re_match_2): initialize max (RE_NREGS, re_nsub + 1)
+ registers (from rms).
+
+ * xregex.c, regex.h: don't abbreviate `19xx' to `xx'.
+
+ * regexinc.c [!emacs]: include <sys/types.h> before <unistd.h>.
+ (from ro@thp.Uni-Koeln.DE).
+
+Thu Jan 9 07:23:00 1992 Karl Berry (karl at hayley)
+
+ * xregex.c (*unmatchable): rename to `match_empty_string_p'.
+ (CAN_MATCH_NOTHING): rename to `REG_MATCH_EMPTY_STRING_P'.
+
+ * regexinc.c (malloc, realloc): remove prototypes, as they can
+ cause clashes (from rms).
+
+Mon Jan 6 12:43:24 1992 Karl Berry (karl at claude.cs.umb.edu)
+
+ * Version 0.2.
+
+Sun Jan 5 10:50:38 1992 Karl Berry (karl at hayley)
+
+ * xregex.texinfo: bring more or less up-to-date.
+ * GNUmakefile (regex.texinfo): generate from regex.h and
+ xregex.texinfo.
+ * include.awk: new file.
+
+ * xregex.c: change all calls to the fn extract_number_and_incr
+ to the macro.
+
+ * xregex.c (re_match_2) [emacs]: in at_dot, use PTR_CHAR_POS + 1,
+ instead of bf_* and sl_*. Cast d to unsigned char *, to match
+ the declaration in Emacs' buffer.h.
+ [emacs19]: in before_dot, at_dot, and after_dot, likewise.
+
+ * regexinc.c: unconditionally include <sys/types.h>.
+
+ * regexinc.c (alloca) [!alloca]: Emacs config files sometimes
+ define this, so don't define it if it's already defined.
+
+Sun Jan 5 06:06:53 1992 Karl Berry (karl at fosse)
+
+ * xregex.c (re_comp): fix type conflicts with regex_compile (we
+ haven't been compiling this).
+
+ * regexinc.c (SIGN_EXTEND_CHAR): use `__CHAR_UNSIGNED__', not
+ `CHAR_UNSIGNED'.
+
+ * regexinc.c (NULL) [!NULL]: define it (as zero).
+
+ * regexinc.c (extract_number): remove the temporaries.
+
+Sun Jan 5 07:50:14 1992 Karl Berry (karl at hayley)
+
+ * regex.h (regerror) [!__STDC__]: return a size_t, not a size_t *.
+
+ * xregex.c (PUSH_FAILURE_POINT, ...): declare `destination' as
+ `char *' instead of `void *', to match alloca declaration.
+
+ * xregex.c (regerror): use `size_t' for the intermediate values
+ as well as the return type.
+
+ * xregex.c (regexec): cast the result of malloc.
+
+ * xregex.c (regexec): don't initialize `private_preg' in the
+ declaration, as old C compilers can't do that.
+
+ * xregex.c (main) [test]: declare printchar void.
+
+ * xregex.c (assert) [!DEBUG]: define this to do nothing, and
+ remove #ifdef DEBUG's from around asserts.
+
+ * xregex.c (re_match_2): remove error message when not debugging.
+
+Sat Jan 4 09:45:29 1992 Karl Berry (karl at hayley)
+
+ * other.c: test the bizarre duplicate case in re_compile_fastmap
+ that I just noticed.
+
+ * test.c (general_test): don't test registers beyond the end of
+ correct_regs, as well as regs.
+
+ * xregex.c (regex_compile): at handle_close, don't assign to
+ *inner_group_loc if we didn't push a start_memory (because the
+ group number was too big). In fact, don't push or pop the
+ inner_group_offset in that case.
+
+ * regex.c: rename to xregex.c, since it's not the whole thing.
+ * regex.texinfo: likewise.
+ * GNUmakefile: change to match.
+
+ * regex.c [DEBUG]: only include <stdio.h> if debugging.
+
+ * regexinc.c (SIGN_EXTEND_CHAR) [CHAR_UNSIGNED]: if it's already
+ defined, don't redefine it.
+
+ * regex.c: define _GNU_SOURCE at the beginning.
+ * regexinc.c (isblank) [!isblank]: define it.
+ (isgraph) [!isgraph]: change conditional to this, and remove the
+ sequent stuff.
+
+ * regex.c (regex_compile): add `blank' character class.
+
+ * regex.c (regex_compile): don't use a uchar variable to loop
+ through all characters.
+
+ * regex.c (regex_compile): at '[', improve logic for checking
+ that we have enough space for the charset.
+
+ * regex.h (struct re_pattern_buffer): declare translate as char
+ * again. We only use it as an array subscript once, I think.
+
+ * regex.c (TRANSLATE): new macro to cast the data character
+ before subscripting.
+ (num_internal_regs): rename to `num_regs'.
+
+Fri Jan 3 07:58:01 1992 Karl Berry (karl at hayley)
+
+ * regex.h (struct re_pattern_buffer): declare `allocated' and
+ `used' as unsigned long, since these are never negative.
+
+ * regex.c (compile_stack_element): rename to compile_stack_elt_t.
+ (failure_stack_element): similarly.
+
+ * regexinc.c (TALLOC, RETALLOC): new macros to simplify
+ allocation of arrays.
+
+ * regex.h (re_*) [__STDC__]: don't declare string args unsigned
+ char *; that makes them incompatible with string constants.
+ (struct re_pattern_buffer): declare the pattern and translate
+ table as unsigned char *.
+ * regex.c (most routines): use unsigned char vs. char consistently.
+
+ * regex.h (re_compile_pattern): do not declare the length arg as
+ const.
+ * regex.c (re_compile_pattern): likewise.
+
+ * regex.c (POINTER_TO_REG): rename to `POINTER_TO_OFFSET'.
+
+ * regex.h (re_registers): declare `start' and `end' as
+ `regoff_t', instead of `int'.
+
+ * regex.c (regexec): if either of the malloc's for the register
+ information fail, return failure.
+
+ * regex.h (RE_NREGS): define this again, as 30 (from jla).
+ (RE_ALLOCATE_REGISTERS): remove this.
+ (RE_SYNTAX_*): remove it from definitions.
+ (re_pattern_buffer): remove `return_default_num_regs', add
+ `caller_allocated_regs'.
+ * regex.c (re_compile_pattern): clear no_sub and
+ caller_allocated_regs in the pattern.
+ (regcomp): set caller_allocated_regs.
+ (re_match_2): do all register allocation at the end of the
+ match; implement new semantics.
+
+ * regex.c (MAX_REGNUM): new macro.
+ (regex_compile): at handle_open and handle_close, if the group
+ number is too large, don't push the start/stop memory.
+
+Thu Jan 2 07:56:10 1992 Karl Berry (karl at hayley)
+
+ * regex.c (re_match_2): if the back reference is to a group that
+ never matched, then goto fail, not really_fail. Also, don't
+ test if the pattern can match the empty string. Why did we
+ ever do that?
+ (really_fail): this label no longer needed.
+
+ * regexinc.c [STDC_HEADERS]: use only this to test if we should
+ include <stdlib.h>.
+
+ * regex.c (DO_RANGE, regex_compile): translate in all cases
+ except the single character after a \.
+
+ * regex.h (RE_AWK_CLASS_HACK): rename to
+ RE_BACKSLASH_ESCAPE_IN_LISTS.
+ * regex.c (regex_compile): change use.
+
+ * regex.c (re_compile_fastmap): do not translate the characters
+ again; we already translated them at compilation. (From ylo@ngs.fi.)
+
+ * regex.c (re_match_2): in case for at_dot, invert sense of
+ comparison and find the character number properly. (From
+ worley@compass.com.)
+ (re_match_2) [emacs]: remove the cases for before_dot and
+ after_dot, since there's no way to specify them, and the code
+ is wrong (judging from this change).
+
+Wed Jan 1 09:13:38 1992 Karl Berry (karl at hayley)
+
+ * psx-{interf,basic,extend}.c, other.c: set `t' as the first
+ thing, so that if we run them in sucession, general_test's
+ kludge to see if we're doing POSIX tests works.
+
+ * test.h (test_type): add `all_test'.
+ * main.c: add case for `all_test'.
+
+ * regexinc.c (partial_compiled_pattern_printer,
+ double_string_printer): don't print anything if we're passed null.
+
+ * regex.c (PUSH_FAILURE_POINT): do not scan for the highest and
+ lowest active registers.
+ (re_match_2): compute lowest/highest active regs at start_memory and
+ stop_memory.
+ (NO_{LOW,HIGH}EST_ACTIVE_REG): new sentinel values.
+ (pop_failure_point): return the lowest/highest active reg values
+ popped; change calls.
+
+ * regex.c [DEBUG]: include <assert.h>.
+ (various routines) [DEBUG]: change conditionals to assertions.
+
+ * regex.c (DEBUG_STATEMENT): new macro.
+ (PUSH_FAILURE_POINT): use it to increment num_regs_pushed.
+ (re_match_2) [DEBUG]: only declare num_regs_pushed if DEBUG.
+
+ * regex.c (*can_match_nothing): rename to *unmatchable.
+
+ * regex.c (re_match_2): at stop_memory, adjust argument reading.
+
+ * regex.h (re_pattern_buffer): declare `can_be_null' as a 2-bit
+ bit field.
+
+ * regex.h (re_pattern_buffer): declare `buffer' unsigned char *;
+ no, dumb idea. The pattern can have signed number.
+
+ * regex.c (re_match_2): in maybe_pop_jump case, skip over the
+ right number of args to the group operators, and don't do
+ anything with endline if posix_newline is not set.
+
+ * regex.c, regexinc.c (all the things we just changed): go back
+ to putting the inner group count after the start_memory,
+ because we need it in the on_failure_jump case in re_match_2.
+ But leave it after the stop_memory also, since we need it
+ there in re_match_2, and we don't have any way of getting back
+ to the start_memory.
+
+ * regexinc.c (partial_compiled_pattern_printer): adjust argument
+ reading for start/stop_memory.
+ * regex.c (re_compile_fastmap, group_can_match_nothing): likewise.
+
+Tue Dec 31 10:15:08 1991 Karl Berry (karl at hayley)
+
+ * regex.c (bits list routines): remove these.
+ (re_match_2): get the number of inner groups from the pattern,
+ instead of keeping track of it at start and stop_memory.
+ Put the count after the stop_memory, not after the
+ start_memory.
+ (compile_stack_element): remove `fixup_inner_group' member,
+ since we now put it in when we can compute it.
+ (regex_compile): at handle_open, don't push the inner group
+ offset, and at handle_close, don't pop it.
+
+ * regex.c (level routines): remove these, and their uses in
+ regex_compile. This was another manifestation of having to find
+ $'s that were endlines.
+
+ * regex.c (regexec): this does searching, not matching (a
+ well-disguised part of the standard). So rewrite to use
+ `re_search' instead of `re_match'.
+ * psx-interf.c (test_regexec): add tests to, uh, match.
+
+ * regex.h (RE_TIGHT_ALT): remove this; nobody uses it.
+ * regex.c: remove the code that was supposed to implement it.
+
+ * other.c (test_others): ^ and $ never match newline characters;
+ RE_CONTEXT_INVALID_OPS doesn't affect anchors.
+
+ * psx-interf.c (test_regerror): update for new error messages.
+
+ * psx-extend.c: it's now ok to have an alternative be just a $,
+ so remove all the tests which supposed that was invalid.
+
+Wed Dec 25 09:00:05 1991 Karl Berry (karl at hayley)
+
+ * regex.c (regex_compile): in handle_open, don't skip over ^ and
+ $ when checking for an empty group. POSIX has changed the
+ grammar.
+ * psx-extend.c (test_posix_extended): thus, move (^$) tests to
+ valid section.
+
+ * regexinc.c (boolean): move from here to test.h and regex.c.
+ * test files: declare verbose, omit_register_tests, and
+ test_should_match as boolean.
+
+ * psx-interf.c (test_posix_c_interface): remove the `c_'.
+ * main.c: likewise.
+
+ * psx-basic.c (test_posix_basic): ^ ($) is an anchor after
+ (before) an open (close) group.
+
+ * regex.c (re_match_2): in endline, correct precedence of
+ posix_newline condition.
+
+Tue Dec 24 06:45:11 1991 Karl Berry (karl at hayley)
+
+ * test.h: incorporate private-tst.h.
+ * test files: include test.h, not private-tst.h.
+
+ * test.c (general_test): set posix_newline to zero if we are
+ doing POSIX tests (unfortunately, it's difficult to call
+ regcomp in this case, which is what we should really be doing).
+
+ * regex.h (reg_syntax_t): make this an enumeration type which
+ defines the syntax bits; renames re_syntax_t.
+
+ * regex.c (at_endline_op_p): don't preincrement p; then if it's
+ not an empty string op, we lose.
+
+ * regex.h (reg_errcode_t): new enumeration type of the error
+ codes.
+ * regex.c (regex_compile): return that type.
+
+ * regex.c (regex_compile): in [, initialize
+ just_had_a_char_class to false; somehow I had changed this to
+ true.
+
+ * regex.h (RE_NO_CONSECUTIVE_REPEATS): remove this, since we
+ don't use it, and POSIX doesn't require this behavior anymore.
+ * regex.c (regex_compile): remove it from here.
+
+ * regex.c (regex_compile): remove the no_op insertions for
+ verify_and_adjust_endlines, since that doesn't exist anymore.
+
+ * regex.c (regex_compile) [DEBUG]: use printchar to print the
+ pattern, so unprintable bytes will print properly.
+
+ * regex.c: move re_error_msg back.
+ * test.c (general_test): print the compile error if the pattern
+ was invalid.
+
+Mon Dec 23 08:54:53 1991 Karl Berry (karl at hayley)
+
+ * regexinc.c: move re_error_msg here.
+
+ * regex.c (re_error_msg): the ``message'' for success must be
+ NULL, to keep the interface to re_compile_pattern the same.
+ (regerror): if the msg is null, use "Success".
+
+ * rename most test files for consistency. Change Makefile
+ correspondingly.
+
+ * test.c (most routines): add casts to (unsigned char *) when we
+ call re_{match,search}{,_2}.
+
+Sun Dec 22 09:26:06 1991 Karl Berry (karl at hayley)
+
+ * regex.c (re_match_2): declare string args as unsigned char *
+ again; don't declare non-pointer args const; declare the
+ pattern buffer const.
+ (re_match): likewise.
+ (re_search_2, re_search): likewise, except don't declare the
+ pattern const, since we make a fastmap.
+ * regex.h [__STDC__]: change prototypes.
+
+ * regex.c (regex_compile): return an error code, not a string.
+ (re_err_list): new table to map from error codes to string.
+ (re_compile_pattern): return an element of re_err_list.
+ (regcomp): don't test all the strings.
+ (regerror): just use the list.
+ (put_in_buffer): remove this.
+
+ * regex.c (equivalent_failure_points): remove this.
+
+ * regex.c (re_match_2): don't copy the string arguments into
+ non-const pointers. We never alter the data.
+
+ * regex.c (re_match_2): move assignment to `is_a_jump_n' out of
+ the main loop. Just initialize it right before we do
+ something with it.
+
+ * regex.[ch] (re_match_2): don't declare the int parameters const.
+
+Sat Dec 21 08:52:20 1991 Karl Berry (karl at hayley)
+
+ * regex.h (re_syntax_t): new type; declare to be unsigned
+ (previously we used int, but since we do bit operations on
+ this, unsigned is better, according to H&S).
+ (obscure_syntax, re_pattern_buffer): use that type.
+ * regex.c (re_set_syntax, regex_compile): likewise.
+
+ * regex.h (re_pattern_buffer): new field `posix_newline'.
+ * regex.c (re_comp, re_compile_pattern): set to zero.
+ (regcomp): set to REG_NEWLINE.
+ * regex.h (RE_HAT_LISTS_NOT_NEWLINE): remove this (we can just
+ check `posix_newline' instead.)
+
+ * regex.c (op_list_type, op_list, add_op): remove these.
+ (verify_and_adjust_endlines): remove this.
+ (pattern_offset_list_type, *pattern_offset* routines): and these.
+ These things all implemented the nonleading/nontrailing position
+ code, which was very long, had a few remaining problems, and
+ is no longer needed. So...
+
+ * regexinc.c (STREQ): new macro to abbreviate strcmp(,)==0, for
+ brevity. Change various places in regex.c to use it.
+
+ * regex{,inc}.c (enum regexpcode): change to a typedef
+ re_opcode_t, for brevity.
+
+ * regex.h (re_syntax_table) [SYNTAX_TABLE]: remove this; it
+ should only be in regex.c, I think, since we don't define it
+ in this case. Maybe it should be conditional on !SYNTAX_TABLE?
+
+ * regexinc.c (partial_compiled_pattern_printer): simplify and
+ distinguish the emacs/not-emacs (not)wordchar cases.
+
+Fri Dec 20 08:11:38 1991 Karl Berry (karl at hayley)
+
+ * regexinc.c (regexpcode) [emacs]: only define the Emacs opcodes
+ if we are ifdef emacs.
+
+ * regex.c (BUF_PUSH*): rename to PAT_PUSH*.
+
+ * regex.c (regex_compile): in $ case, go back to essentially the
+ original code for deciding endline op vs. normal char.
+ (at_endline_op_p): new routine.
+ * regex.h (RE_ANCHORS_ONLY_AT_ENDS, RE_CONTEXT_INVALID_ANCHORS,
+ RE_REPEATED_ANCHORS_AWAY, RE_NO_ANCHOR_AT_NEWLINE): remove
+ these. POSIX has simplified the rules for anchors in draft
+ 11.2.
+ (RE_NEWLINE_ORDINARY): new syntax bit.
+ (RE_CONTEXT_INDEP_ANCHORS): change description to be compatible
+ with POSIX.
+ * regex.texinfo (Syntax Bits): remove the descriptions.
+
+Mon Dec 16 08:12:40 1991 Karl Berry (karl at hayley)
+
+ * regex.c (re_match_2): in jump_past_next_alt, unconditionally
+ goto no_pop. The only register we were finding was one which
+ enclosed the whole alternative expression, not one around an
+ individual alternative. So we were never doing what we
+ thought we were doing, and this way makes (|a) against the
+ empty string fail.
+
+ * regex.c (regex_compile): remove `highest_ever_regnum', and
+ don't restore regnum from the stack; just put it into a
+ temporary to put into the stop_memory. Otherwise, groups
+ aren't numbered consecutively.
+
+ * regex.c (is_in_compile_stack): rename to
+ `group_in_compile_stack'; remove unnecessary test for the
+ stack being empty.
+
+ * regex.c (re_match_2): in on_failure_jump, skip no_op's before
+ checking for the start_memory, in case we were called from
+ succeed_n.
+
+Sun Dec 15 16:20:48 1991 Karl Berry (karl at hayley)
+
+ * regex.c (regex_compile): in duplicate case, use
+ highest_ever_regnum instead of regnum, since the latter is
+ reverted at stop_memory.
+
+ * regex.c (re_match_2): in on_failure_jump, if the * applied to
+ a group, save the information for that group and all inner
+ groups (by making it active), even though we're not inside it
+ yet.
+
+Sat Dec 14 09:50:59 1991 Karl Berry (karl at hayley)
+
+ * regex.c (PUSH_FAILURE_ITEM, POP_FAILURE_ITEM): new macros.
+ Use them instead of copying the stack manipulating a zillion
+ times.
+
+ * regex.c (PUSH_FAILURE_POINT, pop_failure_point) [DEBUG]: save
+ and restore a unique identification value for each failure point.
+
+ * regexinc.c (partial_compiled_pattern_printer): don't print an
+ extra / after duplicate commands.
+
+ * regex.c (regex_compile): in back-reference case, allow a back
+ reference to register `regnum'. Otherwise, even `\(\)\1'
+ fails, since regnum is 1 at the back-reference.
+
+ * regex.c (re_match_2): in fail, don't examine the pattern if we
+ restored to pend.
+
+ * test_private.h: rename to private_tst.h. Change includes.
+
+ * regex.c (extend_bits_list): compute existing size for realloc
+ in bytes, not blocks.
+
+ * regex.c (re_match_2): in jump_past_next_alt, the for loop was
+ missing its (empty) statement. Even so, some register tests
+ still fail, although in a different way than in the previous change.
+
+Fri Dec 13 15:55:08 1991 Karl Berry (karl at hayley)
+
+ * regex.c (re_match_2): in jump_past_next_alt, unconditionally
+ goto no_pop, since we weren't properly detecting if the
+ alternative matched something anyway. No, we need to not jump
+ to keep the register values correct; just change to not look at
+ register zero and not test RE_NO_EMPTY_ALTS (which is a
+ compile-time thing).
+
+ * regex.c (SET_REGS_MATCHED): start the loop at 1, since we never
+ care about register zero until the very end. (I think.)
+
+ * regex.c (PUSH_FAILURE_POINT, pop_failure_point): go back to
+ pushing and popping the active registers, instead of only doing
+ the registers before a group: (fooq|fo|o)*qbar against fooqbar
+ fails, since we restore back into the middle of group 1, yet it
+ isn't active, because the previous restore clobbered the active flag.
+
+Thu Dec 12 17:25:36 1991 Karl Berry (karl at hayley)
+
+ * regex.c (PUSH_FAILURE_POINT): do not call
+ `equivalent_failure_points' after all; it causes the registers
+ to be ``wrong'' (according to POSIX), and an infinite loop on
+ `((a*)*)*' against `ab'.
+
+ * regex.c (re_compile_fastmap): don't push `pend' on the failure
+ stack.
+
+Tue Dec 10 10:30:03 1991 Karl Berry (karl at hayley)
+
+ * regex.c (PUSH_FAILURE_POINT): if pushing same failure point that
+ is on the top of the stack, fail.
+ (equivalent_failure_points): new routine.
+
+ * regex.c (re_match_2): add debug statements for every opcode we
+ execute.
+
+ * regex.c (regex_compile/handle_close): restore
+ `fixup_inner_group_count' and `regnum' from the stack.
+
+Mon Dec 9 13:51:15 1991 Karl Berry (karl at hayley)
+
+ * regex.c (PUSH_FAILURE_POINT): declare `this_reg' as int, so
+ unsigned arithmetic doesn't happen when we don't want to save
+ the registers.
+
+Tue Dec 3 08:11:10 1991 Karl Berry (karl at hayley)
+
+ * regex.c (extend_bits_list): divide size by bits/block.
+
+ * regex.c (init_bits_list): remove redundant assignmen to
+ `bits_list_ptr'.
+
+ * regexinc.c (partial_compiled_pattern_printer): don't do *p++
+ twice in the same expr.
+
+ * regex.c (re_match_2): at on_failure_jump, use the correct
+ pattern positions for getting the stuff following the start_memory.
+
+ * regex.c (struct register_info): remove the bits_list for the
+ inner groups; make that a separate variable.
+
+Mon Dec 2 10:42:07 1991 Karl Berry (karl at hayley)
+
+ * regex.c (PUSH_FAILURE_POINT): don't pass `failure_stack' as an
+ arg; change callers.
+
+ * regex.c (PUSH_FAILURE_POINT): print items in order they are
+ pushed.
+ (pop_failure_point): likewise.
+
+ * regex.c (main): prompt for the pattern and string.
+
+ * regex.c (FREE_VARIABLES) [!REGEX_MALLOC]: declare as nothing;
+ remove #ifdefs from around calls.
+
+ * regex.c (extract_number, extract_number_and_incr): declare static.
+
+ * regex.c: remove the canned main program.
+ * main.c: new file.
+ * Makefile (COMMON): add main.o.
+
+Tue Sep 24 06:26:51 1991 Kathy Hargreaves (kathy at fosse)
+
+ * regex.c (re_match_2): Made `pend' and `dend' not register variables.
+ Only set string2 to string1 if string1 isn't null.
+ Send address of p, d, regstart, regend, and reg_info to
+ pop_failure_point.
+ Put in more debug statements.
+
+ * regex.c [debug]: Added global variable.
+ (DEBUG_*PRINT*): Only print if `debug' is true.
+ (DEBUG_DOUBLE_STRING_PRINTER): Changed DEBUG_STRING_PRINTER's
+ name to this.
+ Changed some comments.
+ (PUSH_FAILURE_POINT): Moved and added some debugging statements.
+ Was saving regstart on the stack twice instead of saving both
+ regstart and regend; remedied this.
+ [NUM_REGS_ITEMS]: Changed from 3 to 4, as now save lowest and
+ highest active registers instead of highest used one.
+ [NUM_NON_REG_ITEMS]: Changed name of NUM_OTHER_ITEMS to this.
+ (NUM_FAILURE_ITEMS): Use active registers instead of number 0
+ through highest used one.
+ (re_match_2): Have pop_failure_point put things in the variables.
+ (pop_failure_point): Have it do what the fail case in re_match_2
+ did with the failure stack, instead of throwing away the stuff
+ popped off. re_match_2 can ignore results when it doesn't
+ need them.
+
+
+Thu Sep 5 13:23:28 1991 Kathy Hargreaves (kathy at fosse)
+
+ * regex.c (banner): Changed copyright years to be separate.
+
+ * regex.c [CHAR_UNSIGNED]: Put __ at both ends of this name.
+ [DEBUG, debug_count, *debug_p, DEBUG_PRINT_1, DEBUG_PRINT_2,
+ DEBUG_COMPILED_PATTERN_PRINTER ,DEBUG_STRING_PRINTER]:
+ defined these for debugging.
+ (extract_number): Added this (debuggable) routine version of
+ the macro EXTRACT_NUMBER. Ditto for EXTRACT_NUMBER_AND_INCR.
+ (re_compile_pattern): Set return_default_num_regs if the
+ syntax bit RE_ALLOCATE_REGISTERS is set.
+ [REGEX_MALLOC]: Renamed USE_ALLOCA to this.
+ (BUF_POP): Got rid of this, as don't ever use it.
+ (regex_compile): Made the type of `pattern' not be register.
+ If DEBUG, print the pattern to compile.
+ (re_match_2): If had a `$' in the pattern before a `^' then
+ don't record the `^' as an anchor.
+ Put (enum regexpcode) before references to b, as suggested
+ [RE_NO_BK_BRACES]: Changed RE_NO_BK_CURLY_BRACES to this.
+ (remove_pattern_offset): Removed this unused routine.
+ (PUSH_FAILURE_POINT): Changed to only save active registers.
+ Put in debugging statements.
+ (re_compile_fastmap): Made `pattern' not a register variable.
+ Use routine for extracting numbers instead of macro.
+ (re_match_2): Made `p', `mcnt' and `mcnt2' not register variables.
+ Added `num_regs_pushed' for debugging.
+ Only malloc registers if the syntax bit RE_ALLOCATE_REGISTERS is set.
+ Put in debug statements.
+ Put the macro NOTE_INNER_GROUP's code inline, as it was the
+ only called in one place.
+ For debugging, extract numbers using routines instead of macros.
+ In case fail: only restore pushed active registers, and added
+ debugging statements.
+ (pop_failure_point): Test for underfull stack.
+ (group_can_match_nothing, common_op_can_match_nothing): For
+ debugging, extract numbers using routines instead of macros.
+ (regexec): Changed formal parameters to not be prototypes.
+ Don't initialize `regs' or `private_preg' in their declarations.
+
+Tue Jul 23 18:38:36 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h [RE_CONTEX_INDEP_OPS]: Moved the anchor stuff out of
+ this bit.
+ [RE_UNMATCHED_RIGHT_PAREN_ORD]: Defined this bit.
+ [RE_CONTEXT_INVALID_ANCHORS]: Defined this bit.
+ [RE_CONTEXT_INDEP_ANCHORS]: Defined this bit.
+ Added RE_CONTEXT_INDEP_ANCHORS to all syntaxes which had
+ RE_CONTEXT_INDEP_OPS.
+ Took RE_ANCHORS_ONLY_AT_ENDS out of the POSIX basic syntax.
+ Added RE_UNMATCHED_RIGHT_PAREN_ORD to the POSIX extended
+ syntax.
+ Took RE_REPEATED_ANCHORS_AWAY out of the POSIX extended syntax.
+ Defined REG_NOERROR (which will probably have to go away again).
+ Changed the type `off_t' to `regoff_t'.
+
+ * regex.c: Changed some commments.
+ (regex_compile): Added variable `had_an_endline' to keep track
+ of if hit a `$' since the beginning of the pattern or the last
+ alternative (if any).
+ Changed RE_CONTEXT_INVALID_OPS and RE_CONTEXT_INDEP_OPS to
+ RE_CONTEXT_INVALID_ANCHORS and RE_CONTEXT_INDEP_ANCHORS where
+ appropriate.
+ Put a `no_op' in the pattern if a repeat is only zero or one
+ times; in this case and if it is many times (whereupon a jump
+ backwards is pushed instead), keep track of the operator for
+ verify_and_adjust_endlines.
+ If RE_UNMATCHED_RIGHT_PAREN is set, make an unmatched
+ close-group operator match `)'.
+ Changed all error exits to exit (1).
+ (remove_pattern_offset): Added this routine, but don't use it.
+ (verify_and_adjust_endlines): At top of routine, if initialize
+ routines run out of memory, return true after setting
+ enough_memory false.
+ At end of endline, et al. case, don't set *p to no_op.
+ Repetition operators also set the level and active groups'
+ match statuses, unless RE_REPEATED_ANCHORS_AWAY is set.
+ (get_group_match_status): Put a return in front of call to get_bit.
+ (re_compile_fastmap): Changed is_a_succeed_n to a boolean.
+ If at end of pattern, then if the failure stack isn't empty,
+ go back to the failure point.
+ In *jump* case, only pop the stack if what's on top of it is
+ where we've just jumped to.
+ (re_search_2): Return -2 instead of val if val is -2.
+ (group_can_match_nothing, alternative_can_match_nothing,
+ common_op_can-match_nothing): Now pass in reg_info for the
+ `duplicate' case.
+ (re_match_2): Don't skip over the next alternative also if
+ empty alternatives aren't allowed.
+ In fail case, if failed to a backwards jump that's part of a
+ repetition loop, pop the current failure point and use the
+ next one.
+ (pop_failure_point): Check that there's as many register items
+ on the failure stack as the stack says there are.
+ (common_op_can_match_nothing): Added variables `ret' and
+ `reg_no' so can set reg_info for the group encountered.
+ Also break without doing anything if hit a no_op or the other
+ kinds of `endline's.
+ If not done already, set reg_info in start_memory case.
+ Put in no_pop_jump for an optimized succeed_n of zero repetitions.
+ In succeed_n case, if the number isn't zero, then return false.
+ Added `duplicate' case.
+
+Sat Jul 13 11:27:38 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (REG_NOERROR): Added this error code definition.
+
+ * regex.c: Took some redundant parens out of macros.
+ (enum regexpcode): Added jump_past_next_alt.
+ Wrapped some macros in `do..while (0)'.
+ Changed some comments.
+ (regex_compile): Use `fixup_alt_jump' instead of `fixup_jump'.
+ Use `maybe_pop_jump' instead of `maybe_pop_failure_jump'.
+ Use `jump_past_next_alt' instead of `no_pop_jump' when at the
+ end of an alternative.
+ (re_match_2): Used REGEX_ALLOCATE for the registers stuff.
+ In stop_memory case: Add more boolean tests to see if the
+ group is in a loop.
+ Added jump_past_next_alt case, which doesn't jump over the
+ next alternative if the last one didn't match anything.
+ Unfortunately, to make this work with, e.g., `(a+?*|b)*'
+ against `bb', I also had to pop the alternative's failure
+ point, which in turn broke backtracking!
+ In fail case: Detect a dummy failure point by looking at
+ failure_stack.avail - 2, not stack[-2].
+ (pop_failure_point): Only pop if the stack isn't empty; don't
+ give an error if it is. (Not sure yet this is correct.)
+ (group_can_match_nothing): Make it return a boolean instead of int.
+ Make it take an argument indicating the end of where it should look.
+ If find a group that can match nothing, set the pointer
+ argument to past the group in the pattern.
+ Took out cases which can share with alternative_can_match_nothing
+ and call common_op_can_match_nothing.
+ Took ++ out of switch, so could call common_op_can_match_nothing.
+ Wrote lots more for on_failure_jump case to handle alternatives.
+ Main loop now doesn't look for matching stop_memory, but
+ rather the argument END; return true if hit the matching
+ stop_memory; this way can call itself for inner groups.
+ (alternative_can_match_nothing): Added for alternatives.
+ (common_op_can_match_nothing): Added for previous two routines'
+ common operators.
+ (regerror): Returns a message saying there's no error if gets
+ sent REG_NOERROR.
+
+Wed Jul 3 10:43:15 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c: Removed unnecessary enclosing parens from several macros.
+ Put `do..while (0)' around a few.
+ Corrected some comments.
+ (INIT_FAILURE_STACK_SIZE): Deleted in favor of using
+ INIT_FAILURE_ALLOC.
+ (INIT_FAILURE_STACK, DOUBLE_FAILURE_STACK, PUSH_PATTERN_OP,
+ PUSH_FAILURE_POINT): Made routines of the same name (but with all
+ lowercase letters) into these macros, so could use `alloca'
+ when USE_ALLOCA is defined. The reason is stated below for
+ bits lists. Deleted analogous routines.
+ (re_compile_fastmap): Added variable void *destination for
+ PUSH_PATTERN_OP.
+ (re_match_2): Added variable void *destination for REGEX_REALLOCATE.
+ Used the failure stack macros in place of the routines.
+ Detected a dummy failure point by inspecting the failure stack's
+ (avail - 2)th element, not failure_stack.stack[-2]. This bug
+ arose when used the failure stack macros instead of the routines.
+
+ * regex.c [USE_ALLOCA]: Put this conditional around previous
+ alloca stuff and defined these to work differently depending
+ on whether or not USE_ALLOCA is defined:
+ (REGEX_ALLOCATE): Uses either `alloca' or `malloc'.
+ (REGEX_REALLOCATE): Uses either `alloca' or `realloc'.
+ (INIT_BITS_LIST, EXTEND_BITS_LIST, SET_BIT_TO_VALUE): Defined
+ macro versions of routines with the same name (only with all
+ lowercase letters) so could use `alloc' in re_match_2. This
+ is to prevent core leaks when C-g is used in Emacs and to make
+ things faster and avoid storage fragmentation. These things
+ have to be macros because the results of `alloca' go away with
+ the routine by which it's called.
+ (BITS_BLOCK_SIZE, BITS_BLOCK, BITS_MASK): Moved to above the
+ above-mentioned macros instead of before the routines defined
+ below regex_compile.
+ (set_bit_to_value): Compacted some code.
+ (reg_info_type): Changed inner_groups field to be bits_list_type
+ so could be arbitrarily long and thus handle arbitrary nesting.
+ (NOTE_INNER_GROUP): Put `do...while (0)' around it so could
+ use as a statement.
+ Changed code to use bits lists.
+ Added variable void *destination for REGEX_REALLOCATE (whose call
+ is several levels in).
+ Changed variable name of `this_bit' to `this_reg'.
+ (FREE_VARIABLES): Only define and use if USE_ALLOCA is defined.
+ (re_match_2): Use REGEX_ALLOCATE instead of malloc.
+ Instead of setting INNER_GROUPS of reg_info to zero, have to
+ use INIT_BITS_LIST and return -2 (and free variables if
+ USE_ALLOCA isn't defined) if it fails.
+
+Fri Jun 28 13:45:07 1991 Karl Berry (karl at hayley)
+
+ * regex.c (re_match_2): set value of `dend' when we restore `d'.
+
+ * regex.c: remove declaration of alloca.
+
+ * regex.c (MISSING_ISGRAPH): rename to `ISGRAPH_MISSING'.
+
+ * regex.h [_POSIX_SOURCE]: remove these conditionals; always
+ define POSIX stuff.
+ * regex.c (_POSIX_SOURCE): change conditionals to use `POSIX'
+ instead.
+
+Sat Jun 1 16:56:50 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.*: Changed RE_CONTEXTUAL_* to RE_CONTEXT_*,
+ RE_TIGHT_VBAR to RE_TIGHT_ALT, RE_NEWLINE_OR to
+ RE_NEWLINE_ALT, and RE_DOT_MATCHES_NEWLINE to RE_DOT_NEWLINE.
+
+Wed May 29 09:24:11 1991 Karl Berry (karl at hayley)
+
+ * regex.texinfo (POSIX Pattern Buffers): cross-reference the
+ correct node name (Match-beginning-of-line, not ..._line).
+ (Syntax Bits): put @code around all syntax bits.
+
+Sat May 18 16:29:58 1991 Karl Berry (karl at hayley)
+
+ * regex.c (global): add casts to keep broken compilers from
+ complaining about malloc and realloc calls.
+
+ * regex.c (isgraph) [MISSING_ISGRAPH]: change test to this,
+ instead of `#ifndef isgraph', since broken compilers can't
+ have both a macro and a symbol by the same name.
+
+ * regex.c (re_comp, re_exec) [_POSIX_SOURCE]: do not define.
+ (regcomp, regfree, regexec, regerror) [_POSIX_SOURCE && !emacs]:
+ only define in this case.
+
+Mon May 6 17:37:04 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (re_search, re_search_2): Changed BUFFER to not be const.
+
+ * regex.c (re_compile_pattern): `^' is in a leading position if
+ it precedes a newline.
+ (various routines): Added or changed header comments.
+ (double_pattern_offsets_list): Changed name from
+ `extend_pattern_offsets_list'.
+ (adjust_pattern_offsets_list): Changed return value from
+ unsigned to void.
+ (verify_and_adjust_endlines): Now returns `true' and `false'
+ instead of 1 and 0.
+ `$' is in a leading position if it follows a newline.
+ (set_bit_to_value, get_bit_value): Exit with error if POSITION < 0
+ so now calling routines don't have to.
+ (init_failure_stack, inspect_failure_stack_top,
+ pop_failure_stack_top, push_pattern_op, double_failure_stack):
+ Now return value unsigned instead of boolean.
+ (re_search, re_search_2): Changed BUFP to not be const.
+ (re_search_2): Added variable const `private_bufp' to send to
+ re_match_2.
+ (push_failure_point): Made return value unsigned instead of boolean.
+
+Sat May 4 15:32:22 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (re_compile_fastmap): Added extern for this.
+ Changed some comments.
+
+ * regex.c (re_compile_pattern): In case handle_bar: put invalid
+ pattern test before levels matching stuff.
+ Changed some commments.
+ Added optimizing test for detecting an empty alternative that
+ ends with a trailing '$' at the end of the pattern.
+ (re_compile_fastmap): Moved failure_stack stuff to before this
+ so could use it. Made its stack dynamic.
+ Made it return an int so that it could return -2 if its stack
+ couldn't be allocated.
+ Added to header comment (about the return values).
+ (init_failure_stack): Wrote so both re_match_2 and
+ re_compile_fastmap could use it similar stacks.
+ (double_failure_stack): Added for above reasons.
+ (push_pattern_op): Wrote for re_compile_fastmap.
+ (re_search_2): Now return -2 if re_compile_fastmap does.
+ (re_match_2): Made regstart and regend type failure_stack_element*.
+ (push_failure_point): Made pattern_place and string_place type
+ failure_stack_element*.
+ Call double_failure_stack now.
+ Return true instead of 1.
+
+Wed May 1 12:57:21 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (remove_intervening_anchors): Avoid erroneously making
+ ops into no_op's by making them no_op only when they're beglines.
+ (verify_and_adjust_endlines): Don't make '$' a normal character
+ if it's before a newline.
+ Look for the endline op in *p, not p[1].
+ (failure_stack_element): Added this declaration.
+ (failure_stack_type): Added this declaration.
+ (INIT_FAILURE_STACK_SIZE, FAILURE_STACK_EMPTY,
+ FAILURE_STACK_PTR_EMPTY, REMAINING_AVAIL_SLOTS): Added for
+ failure stack.
+ (FAILURE_ITEM_SIZE, PUSH_FAILURE_POINT): Deleted.
+ (FREE_VARIABLES): Now free failure_stack.stack instead of stackb.
+ (re_match_2): deleted variables `initial_stack', `stackb',
+ `stackp', and `stacke' and added `failure_stack' to replace them.
+ Replaced calls to PUSH_FAILURE_POINT with those to
+ push_failure_point.
+ (push_failure_point): Added for re_match_2.
+ (pop_failure_point): Rewrote to use a failure_stack_type of stack.
+ (can_match_nothing): Moved definition to below re_match_2.
+ (bcmp_translate): Moved definition to below re_match_2.
+
+Mon Apr 29 14:20:54 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (enum regexpcode): Added codes endline_before_newline
+ and repeated_endline_before_newline so could detect these
+ types of endlines in the intermediate stages of a compiled
+ pattern.
+ (INIT_FAILURE_ALLOC): Renamed NFAILURES to this and set it to 5.
+ (BUF_PUSH): Put `do {...} while 0' around this.
+ (BUF_PUSH_2): Defined this to cut down on expansion of EXTEND_BUFFER.
+ (regex_compile): Changed some comments.
+ Now push endline_before_newline if find a `$' before a newline
+ in the pattern.
+ If a `$' might turn into an ordinary character, set laststart
+ to point to it.
+ In '^' case, if syntax bit RE_TIGHT_VBAR is set, then for `^'
+ to be in a leading position, it must be first in the pattern.
+ Don't have to check in one of the else clauses that it's not set.
+ If RE_CONTEXTUAL_INDEP_OPS isn't set but RE_ANCHORS_ONLY_AT_ENDS
+ is, make '^' a normal character if it isn't first in the pattern.
+ Can only detect at the end if a '$' after an alternation op is a
+ trailing one, so can't immediately detect empty alternatives
+ if a '$' follows a vbar.
+ Added a picture of the ``success jumps'' in alternatives.
+ Have to set bufp->used before calling verify_and_adjust_endlines.
+ Also do it before returning all error strings.
+ (remove_intervening_anchors): Now replaces the anchor with
+ repeated_endline_before_newline if it's an endline_before_newline.
+ (verify_and_adjust_endlines): Deleted SYNTAX parameter (could
+ use bufp's) and added GROUP_FORWARD_MATCH_STATUS so could
+ detect back references referring to empty groups.
+ Added variable `bend' to point past the end of the pattern buffer.
+ Added variable `previous_p' so wouldn't have to reinspect the
+ pattern buffer to see what op we just looked at.
+ Added endline_before_newline and repeated_endline_before_newline
+ cases.
+ When checking if in a trailing position, added case where '$'
+ has to be at the pattern's end if either of the syntax bits
+ RE_ANCHORS_ONLY_AT_ENDS or RE_TIGHT_VBAR are set.
+ Since `endline' can have the intermediate form `endline_in_repeat',
+ have to change it to `endline' if RE_REPEATED_ANCHORS_AWAY
+ isn't set.
+ Now disallow empty alternatives with trailing endlines in them
+ if RE_NO_EMPTY_ALTS is set.
+ Now don't make '$' an ordinary character if it precedes a newline.
+ Don't make it an ordinary character if it's before a newline.
+ Back references now affect the level matching something only if
+ they refer to nonempty groups.
+ (can_match_nothing): Now increment p1 in the switch, which
+ changes many of the cases, but makes the code more like what
+ it was derived from.
+ Adjust the return statement to reflect above.
+ (struct register_info): Made `can_match_nothing' field an int
+ instead of a bit so could have -1 in it if never set.
+ (MAX_FAILURE_ITEMS): Changed name from MAX_NUM_FAILURE_ITEMS.
+ (FAILURE_ITEM_SIZE): Defined how much space a failure items uses.
+ (PUSH_FAILURE_POINT): Changed variable `last_used_reg's name
+ to `highest_used_reg'.
+ Added variable `num_stack_items' and changed `len's name to
+ `stack_length'.
+ Test failure stack limit in terms of number of items in it, not
+ in terms of its length. rms' fix tested length against number
+ of items, which was a misunderstanding.
+ Use `realloc' instead of `alloca' to extend the failure stack.
+ Use shifts instead of multiplying by 2.
+ (FREE_VARIABLES): Free `stackb' instead of `initial_stack', as
+ might may have been reallocated.
+ (re_match_2): When mallocing `initial_stack', now multiply
+ the number of items wanted (what was there before) by
+ FAILURE_ITEM_SIZE.
+ (pop_failure_point): Need this procedure form of the macro of
+ the same name for debugging, so left it in and deleted the
+ macro.
+ (recomp): Don't free the pattern buffer's translate field.
+
+Mon Apr 15 09:47:47 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_DUP_MAX): Moved to outside of #ifdef _POSIX_SOURCE.
+ * regex.c (#include <sys/types.h>): Removed #ifdef _POSIX_SOURCE
+ condition.
+ (malloc, realloc): Made return type void* #ifdef __STDC__.
+ (enum regexpcode): Added endline_in_repeat for the compiler's
+ use; this never ends up on the final compiled pattern.
+ (INIT_PATTERN_OFFSETS_LIST_SIZE): Initial size for
+ pattern_offsets_list_type.
+ (pattern_offset_type): Type for pattern offsets.
+ (pattern_offsets_list_type): Type for keeping a list of
+ pattern offsets.
+ (anchor_list_type): Changed to above type.
+ (PATTERN_OFFSETS_LIST_PTR_FULL): Tests if a pattern offsets
+ list is full.
+ (ANCHOR_LIST_PTR_FULL): Changed to above.
+ (BIT_BLOCK_SIZE): Changed to BITS_BLOCK_SIZE and moved to
+ above bits list routines below regex_compile.
+ (op_list_type): Defined to be pattern_offsets_list_type.
+ (compile_stack_type): Changed offsets to be
+ pattern_offset_type instead of unsigned.
+ (pointer): Changed the name of all structure fields from this
+ to `avail'.
+ (COMPILE_STACK_FULL): Changed so the stack is full if `avail'
+ is equal to `size' instead of `size' - 1.
+ (GET_BUFFER_SPACE): Changed `>=' to `>' in the while statement.
+ (regex_compile): Added variable `enough_memory' so could check
+ that routine that verifies '$' positions could return an
+ allocation error.
+ (group_count): Deleted this variable, as `regnum' already does
+ this work.
+ (op_list): Added this variable to keep track of operations
+ needed for verifying '$' positions.
+ (anchor_list): Now initialize using routine
+ `init_pattern_offsets_list'.
+ Consolidated the three bits_list initializations.
+ In case '$': Instead of trying to go past constructs which can
+ follow '$', merely detect the special case where it has to be
+ at the pattern's end, fix up any fixup jumps if necessary,
+ record the anchor if necessary and add an `endline' (and
+ possibly two `no-op's) to the pattern; will call a routine at
+ the end to verify if it's in a valid position or not.
+ (init_pattern_offsets_list): Added to initialize pattern
+ offsets lists.
+ (extend_anchor_list): Renamed this extend_pattern_offsets_list
+ and renamed parameters and internal variables appropriately.
+ (add_pattern_offset): Added this routine which both
+ record_anchor_position and add_op call.
+ (adjust_pattern_offsets_list): Add this routine to adjust by
+ some increment all the pattern offsets a list of such after a
+ given position.
+ (record_anchor_position): Now send in offset instead of
+ calculating it and just call add_pattern_offset.
+ (adjust_anchor_list): Replaced by above routine.
+ (remove_intervening_anchors): If the anchor is an `endline'
+ then replace it with `endline_in_repeat' instead of `no_op'.
+ (add_op): Added this routine to call in regex_compile
+ wherever push something relevant to verifying '$' positions.
+ (verify_and_adjust_endlines): Added routine to (1) verify that
+ '$'s in a pattern buffer (represented by `endline') were in
+ valid positions and (2) whether or not they were anchors.
+ (BITS_BLOCK_SIZE): Renamed BIT_BLOCK_SIZE and moved to right
+ above bits list routines.
+ (BITS_BLOCK): Defines which array element of a bits list the
+ bit corresponding to a given position is in.
+ (BITS_MASK): Has a 1 where the bit (in a bit list array element)
+ for a given position is.
+
+Mon Apr 1 12:09:06 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (BIT_BLOCK_SIZE): Defined this for using with
+ bits_list_type, abstracted from level_list_type so could use
+ for more things than just the level match status.
+ (regex_compile): Renamed `level_list' variable to
+ `level_match_status'.
+ Added variable `group_match_status' of type bits_list_type.
+ Kept track of whether or not for all groups any of them
+ matched other than the empty string, so detect if a back
+ reference in front of a '^' made it nonleading or not.
+ Do this by setting a match status bit for all active groups
+ whenever leave a group that matches other than the empty string.
+ Could detect which groups are active by going through the
+ stack each time, but or-ing a bits list of active groups with
+ a bits list of group match status is faster, so make a bits
+ list of active groups instead.
+ Have to check that '^' isn't in a leading position before
+ going to normal_char.
+ Whenever set level match status of the current level, also set
+ the match status of all active groups.
+ Increase the group count and make that group active whenever
+ open a group.
+ When close a group, only set the next level down if the
+ current level matches other than the empty string, and make
+ the current group inactive.
+ At a back reference, only set a level's match status if the
+ group to which the back reference refers matches other than
+ the empty string.
+ (init_bits_list): Added to initialize a bits list.
+ (get_level_value): Deleted this. (Made into
+ get_level_match_status.)
+ (extend_bits_list): Added to extend a bits list. (Made this
+ from deleted routine `extend_level_list'.)
+ (get_bit): Added to get a bit value from a bits list. (Made
+ this from deleted routine `get_level_value'.)
+ (set_bit_to_value): Added to set a bit in a bits list. (Made
+ this from deleted routine `set_level_value'.)
+ (get_level_match_status): Added this to get the match status
+ of a given level. (Made from get_level_value.)
+ (set_this_level, set_next_lower_level): Made all routines
+ which set bits extend the bits list if necessary, thus they
+ now return an unsigned value to indicate whether or not the
+ reallocation failed.
+ (increase_level): No longer extends the level list.
+ (make_group_active): Added to mark as active a given group in
+ an active groups list.
+ (make_group_inactive): Added to mark as inactive a given group
+ in an active groups list.
+ (set_match_status_of_active_groups): Added to set the match
+ status of all currently active groups.
+ (get_group_match_status): Added to get a given group's match status.
+ (no_levels_match_anything): Removed the paramenter LEVEL.
+ (PUSH_FAILURE_POINT): Added rms' bug fix and changed RE_NREGS
+ to num_internal_regs.
+
+Sun Mar 31 09:04:30 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_ANCHORS_ONLY_AT_ENDS): Added syntax so could
+ constrain '^' and '$' to only be anchors if at the beginning
+ and end of the pattern.
+ (RE_SYNTAX_POSIX_BASIC): Added the above bit.
+
+ * regex.c (enum regexcode): Changed `unused' to `no_op'.
+ (this_and_lower_levels_match_nothing): Deleted forward reference.
+ (regex_compile): case '^': if the syntax bit RE_ANCHORS_ONLY_AT_ENDS
+ is set, then '^' is only an anchor if at the beginning of the
+ pattern; only record anchor position if the syntax bit
+ RE_REPEATED_ANCHORS_AWAY is set; the '^' is a normal char if
+ the syntax bit RE_ANCHORS_ONLY_AT_END is set and we're not at
+ the beginning of the pattern (and neither RE_CONTEXTUAL_INDEP_OPS
+ nor RE_CONTEXTUAL_INDEP_OPS syntax bits are set).
+ Only adjust the anchor list if the syntax bit
+ RE_REPEATED_ANCHORS_AWAY is set.
+
+ * regex.c (level_list_type): Use to detect when '^' is
+ in a leading position.
+ (regex_compile): Added level_list_type level_list variable in
+ which we keep track of whether or not a grouping level (in its
+ current or most recent incarnation) matches anything besides the
+ empty string. Set the bit for the i-th level when detect it
+ should match something other than the empty string and the bit
+ for the (i-1)-th level when leave the i-th group. Clear all
+ bits for the i-th and higher levels if none of 0--(i - 1)-th's
+ bits are set when encounter an alternation operator on that
+ level. If no levels are set when hit a '^', then it is in a
+ leading position. We keep track of which level we're at by
+ increasing a variable current_level whenever we encounter an
+ open-group operator and decreasing it whenever we encounter a
+ close-group operator.
+ Have to adjust the anchor list contents whenever insert
+ something ahead of them (such as on_failure_jump's) in the
+ pattern.
+ (adjust_anchor_list): Adjusts the offsets in an anchor list by
+ a given increment starting at a given start position.
+ (get_level_value): Returns the bit setting of a given level.
+ (set_level_value): Sets the bit of a given level to a given value.
+ (set_this_level): Sets (to 1) the bit of a given level.
+ (set_next_lower_level): Sets (to 1) the bit of (LEVEL - 1) for a
+ given LEVEL.
+ (clear_this_and_higher_levels): Clears the bits for a given
+ level and any higher levels.
+ (extend_level_list): Adds sizeof(unsigned) more bits to a level list.
+ (increase_level): Increases by 1 the value of a given level variable.
+ (decrease_level): Decreases by 1 the value of a given level variable.
+ (lower_levels_match_nothing): Checks if any levels lower than
+ the given one match anything.
+ (no_levels_match_anything): Checks if any levels match anything.
+ (re_match_2): At case wordbeg: before looking at d-1, check that
+ we're not at the string's beginning.
+ At case wordend: Added some illuminating parentheses.
+
+Mon Mar 25 13:58:51 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_NO_ANCHOR_AT_NEWLINE): Changed syntax bit name
+ from RE_ANCHOR_NOT_NEWLINE because an anchor never matches the
+ newline itself, just the empty string either before or after it.
+ (RE_REPEATED_ANCHORS_AWAY): Added this syntax bit for ignoring
+ anchors inside groups which are operated on by repetition
+ operators.
+ (RE_DOT_MATCHES_NEWLINE): Added this bit so the match-any-character
+ operator could match a newline when it's set.
+ (RE_SYNTAX_POSIX_BASIC): Set RE_DOT_MATCHES_NEWLINE in this.
+ (RE_SYNTAX_POSIX_EXTENDED): Set RE_DOT_MATCHES_NEWLINE and
+ RE_REPEATED_ANCHORS_AWAY in this.
+ (regerror): Changed prototypes to new POSIX spec.
+
+ * regex.c (anchor_list_type): Added so could null out anchors inside
+ repeated groups.
+ (ANCHOR_LIST_PTR_FULL): Added for above type.
+ (compile_stack_element): Changed name from stack_element.
+ (compile_stack_type): Changed name from compile_stack.
+ (INIT_COMPILE_STACK_SIZE): Changed name from INIT_STACK_SIZE.
+ (COMPILE_STACK_EMPTY): Changed name from STACK_EMPTY.
+ (COMPILE_STACK_FULL): Changed name from STACK_FULL.
+ (regex_compile): Changed SYNTAX parameter to non-const.
+ Changed variable name `stack' to `compile_stack'.
+ If syntax bit RE_REPEATED_ANCHORS_AWAY is set, then naively put
+ anchors in a list when encounter them and then set them to
+ `unused' when detect they are within a group operated on by a
+ repetition operator. Need something more sophisticated than
+ this, as they should only get set to `unused' if they are in
+ positions where they would be anchors. Also need a better way to
+ detect contextually invalid anchors.
+ Changed some commments.
+ (is_in_compile_stack): Changed name from `is_in_stack'.
+ (extend_anchor_list): Added to do anchor stuff.
+ (record_anchor_position): Added to do anchor stuff.
+ (remove_intervening_anchors): Added to do anchor stuff.
+ (re_match_2): Now match a newline with the match-any-character
+ operator if RE_DOT_MATCHES_NEWLINE is set.
+ Compacted some code.
+ (regcomp): Added new POSIX newline information to the header
+ commment.
+ If REG_NEWLINE cflag is set, then now unset RE_DOT_MATCHES_NEWLINE
+ in syntax.
+ (put_in_buffer): Added to do new POSIX regerror spec. Called
+ by regerror.
+ (regerror): Changed to take a pattern buffer, error buffer and
+ its size, and return type `size_t', the size of the full error
+ message, and the first ERRBUF_SIZE - 1 characters of the full
+ error message in the error buffer.
+
+Wed Feb 27 16:38:33 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (#include <sys/types.h>): Removed this as new POSIX
+ standard has the user include it.
+ (RE_SYNTAX_POSIX_BASIC and RE_SYNTAX_POSIX_EXTENDED): Removed
+ RE_HAT_LISTS_NOT_NEWLINE as new POSIX standard has the cflag
+ REG_NEWLINE now set this. Similarly, added syntax bit
+ RE_ANCHOR_NOT_NEWLINE as this is now unset by REG_NEWLINE.
+ (RE_SYNTAX_POSIX_BASIC): Removed syntax bit
+ RE_NO_CONSECUTIVE_REPEATS as POSIX now allows them.
+
+ * regex.c (#include <sys/types.h>): Added this as new POSIX
+ standard has the user include it instead of us putting it in
+ regex.h.
+ (extern char *re_syntax_table): Made into an extern so the
+ user could allocate it.
+ (DO_RANGE): If don't find a range end, now goto invalid_range_end
+ instead of unmatched_left_bracket.
+ (regex_compile): Made variable SYNTAX non-const.????
+ Reformatted some code.
+ (re_compile_fastmap): Moved is_a_succeed_n's declaration to
+ inner braces.
+ Compacted some code.
+ (SET_NEWLINE_FLAG): Removed and put inline.
+ (regcomp): Made variable `syntax' non-const so can unset
+ RE_ANCHOR_NOT_NEWLINE syntax bit if cflag RE_NEWLINE is set.
+ If cflag RE_NEWLINE is set, set the RE_HAT_LISTS_NOT_NEWLINE
+ syntax bit and unset RE_ANCHOR_NOT_NEWLINE one of `syntax'.
+
+Wed Feb 20 16:33:38 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_NO_CONSECUTIVE_REPEATS): Changed name from
+ RE_NO_CONSEC_REPEATS.
+ (REG_ENESTING): Deleted this POSIX return value, as the stack
+ is now unbounded.
+ (struct re_pattern_buffer): Changed some comments.
+ (re_compile_pattern): Changed a comment.
+ Deleted check on stack upper bound and corresponding error.
+ Now when there's no interval contents and it's the end of the
+ pattern, go to unmatched_left_curly_brace instead of end_of_pattern.
+ Removed nesting_too_deep error, as the stack is now unbounded.
+ (regcomp): Removed REG_ENESTING case, as the stack is now unbounded.
+ (regerror): Removed REG_ENESTING case, as the stack is now unbounded.
+
+ * regex.c (MAX_STACK_SIZE): Deleted because don't need upper
+ bound on array indexed with an unsigned number.
+
+Sun Feb 17 15:50:24 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: Changed and added some comments.
+
+ * regex.c (init_syntax_once): Made `_' a word character.
+ (re_compile_pattern): Added a comment.
+ (re_match_2): Redid header comment.
+ (regexec): With header comment about PMATCH, corrected and
+ removed details found regex.h, adding a reference.
+
+Fri Feb 15 09:21:31 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (DO_RANGE): Removed argument parentheses.
+ Now get untranslated range start and end characters and set
+ list bits for the translated (if at all) versions of them and
+ all characters between them.
+ (re_match_2): Now use regs->num_regs instead of num_regs_wanted
+ wherever possible.
+ (regcomp): Now build case-fold translate table using isupper
+ and tolower facilities so will work on foreign language characters.
+
+Sat Feb 9 16:40:03 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_HAT_LISTS_NOT_NEWLINE): Changed syntax bit name
+ from RE_LISTS_NOT_NEWLINE as it only affects nonmatching lists.
+ Changed all references to the match-beginning-of-string
+ operator to match-beginning-of-line operator, as this is what
+ it does.
+ (RE_NO_CONSEC_REPEATS): Added this syntax bit.
+ (RE_SYNTAX_POSIX_BASIC): Added above bit to this.
+ (REG_PREMATURE_END): Changed name to REG_EEND.
+ (REG_EXCESS_NESTING): Changed name to REG_ENESTING.
+ (REG_TOO_BIG): Changed name to REG_ESIZE.
+ (REG_INVALID_PREV_RE): Deleted this return POSIX value.
+ Added and changed some comments.
+
+ * regex.c (re_compile_pattern): Now sets the pattern buffer's
+ `return_default_num_regs' field.
+ (typedef struct stack_element, stack_type, INIT_STACK_SIZE,
+ MAX_STACK_SIZE, STACK_EMPTY, STACK_FULL): Added for regex_compile.
+ (INIT_BUF_SIZE): Changed value from 28 to 32.
+ (BUF_PUSH): Changed name from BUFPUSH.
+ (MAX_BUF_SIZE): Added so could use in many places.
+ (IS_CHAR_CLASS_STRING): Replaced is_char_class with this.
+ (regex_compile): Added a stack which could grow dynamically
+ and which has struct elements.
+ Go back to initializing `zero_times_ok' and `many_time_ok' to
+ 0 and |=ing them inside the loop.
+ Now disallow consecutive repetition operators if the syntax
+ bit RE_NO_CONSEC_REPEATS is set.
+ Now detect trailing backslash when the compiler is expecting a
+ `?' or a `+'.
+ Changed calls to GET_BUFFER_SPACE which asked for 6 to ask for
+ 3, as that's all they needed.
+ Now check for trailing backslash inside lists.
+ Now disallow an empty alternative right before an end-of-line
+ operator.
+ Now get buffer space before leaving space for a fixup jump.
+ Now check if at pattern end when at open-interval operator.
+ Added some comments.
+ Now check if non-interval repetition operators follow an
+ interval one if the syntax bit RE_NO_CONSEC_REPEATS is set.
+ Now only check if what precedes an interval repetition
+ operator isn't a regular expression which matches one
+ character if the syntax bit RE_NO_CONSEC_REPEATS is set.
+ Now return "Unmatched [ or [^" instead of "Unmatched [".
+ (is_in_stack): Added to check if a given register number is in
+ the stack.
+ (re_match_2): If initial variable allocations fail, return -2,
+ instead of -1.
+ Now set reg's `num_regs' field when allocating regs.
+ Now before allocating them, free regs->start and end if they
+ aren't NULL and return -2 if either allocation fails.
+ Now use regs->num_regs instead of num_regs_wanted to control
+ regs loops.
+ Now increment past the newline when matching it with an
+ end-of-line operator.
+ (recomp): Added to the header comment.
+ Now return REG_ESUBREG if regex_compile returns "Unmatched [
+ or [^" instead of doing so if it returns "Unmatched [".
+ Now return REG_BADRPT if in addition to returning "Missing
+ preceding regular expression", regex_compile returns "Invalid
+ preceding regular expression".
+ Now return new return value names (see regex.h changes).
+ (regexec): Added to header comment.
+ Initialize regs structure.
+ Now match whole string.
+ Now always free regs.start and regs.end instead of just when
+ the string matched.
+ (regerror): Now return "Regex error: Unmatched [ or [^.\n"
+ instead of "Regex error: Unmatched [.\n".
+ Now return "Regex error: Preceding regular expression either
+ missing or not simple.\n" instead of "Regex error: Missing
+ preceding regular expression.\n".
+ Removed REG_INVALID_PREV_RE case (it got subsumed into the
+ REG_BADRPT case).
+
+Thu Jan 17 09:52:35 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: Changed a comment.
+
+ * regex.c: Changed and added large header comments.
+ (re_compile_pattern): Now if detect that `laststart' for an
+ interval points to a byte code for a regular expression which
+ matches more than one character, make it an internal error.
+ (regerror): Return error message, don't print it.
+
+Tue Jan 15 15:32:49 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (regcomp return codes): Added GNU ones.
+ Updated some comments.
+
+ * regex.c (DO_RANGE): Changed `obscure_syntax' to `syntax'.
+ (regex_compile): Added `following_left_brace' to keep track of
+ where pseudo interval following a valid interval starts.
+ Changed some instances that returned "Invalid regular
+ expression" to instead return error strings coinciding with
+ POSIX error codes.
+ Changed some comments.
+ Now consider only things between `[:' and `:]' to be possible
+ character class names.
+ Now a character class expression can't end a pattern; at
+ least a `]' must close the list.
+ Now if the syntax bit RE_NO_BK_CURLY_BRACES is set, then a
+ valid interval must be followed by yet another to get an error
+ for preceding an interval (in this case, the second one) with
+ a regular expression that matches more than one character.
+ Now if what follows a valid interval begins with a open
+ interval operator but doesn't begin a valid interval, then set
+ following_left_bracket to it, put it in C and go to
+ normal_char label.
+ Added some comments.
+ Return "Invalid character class name" instead of "Invalid
+ character class".
+ (regerror): Return messages for all POSIX error codes except
+ REG_ECOLLATE and REG_NEWLINE, along with all GNU error codes.
+ Added `break's after all cases.
+ (main): Call re_set_syntax instead of setting `obscure_syntax'
+ directly.
+
+Sat Jan 12 13:37:59 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (Copyright): Updated date.
+ (#include <sys/types.h>): Include unconditionally.
+ (RE_CANNOT_MATCH_NEWLINE): Deleted this syntax bit.
+ (RE_SYNTAX_POSIX_BASIC, RE_SYNTAX_POSIX_EXTENDED): Removed
+ setting the RE_ANCHOR_NOT_NEWLINE syntax bit from these.
+ Changed and added some comments.
+ (struct re_pattern_buffer): Changed some flags from chars to bits.
+ Added field `syntax'; holds which syntax pattern was compiled with.
+ Added bit flag `return_default_num_regs'.
+ (externs for GNU and Berkeley UNIX routines): Added `const's to
+ parameter types to be compatible with POSIX.
+ (#define const): Added to support old C compilers.
+
+ * regex.c (Copyright): Updated date.
+ (enum regexpcode): Deleted `newline'.
+ (regex_compile): Renamed re_compile_pattern to this, added a
+ syntax parameter so it can set the pattern buffer's `syntax'
+ field.
+ Made `pattern', and `size' `const's so could pass to POSIX
+ interface routines; also made `const' whatever interval
+ variables had to be to make this work.
+ Changed references to `obscure_syntax' to new parameter `syntax'.
+ Deleted putting `newline' in buffer when see `\n'.
+ Consider invalid character classes which have nothing wrong
+ except the character class name; if so, return character-class error.
+ (is_char_class): Added routine for regex_compile.
+ (re_compile_pattern): added a new one which calls
+ regex_compile with `obscure_syntax' as the actual parameter
+ for the formal `syntax'.
+ Gave this the old routine's header comments.
+ Made `pattern', and `size' `const's so could use POSIX interface
+ routine parameters.
+ (re_search, re_search_2, re_match, re_match_2): Changed
+ `pbufp' to `bufp'.
+ (re_search_2, re_match_2): Changed `mstop' to `stop'.
+ (re_search, re_search_2): Made all parameters except `regs'
+ `const's so could use POSIX interface routines parameters.
+ (re_search_2): Added private copies of `const' parameters so
+ could change their values.
+ (re_match_2): Made all parameters except `regs' `const's so
+ could use POSIX interface routines parameters.
+ Changed `size1' and `size2' parameters to `size1_arg' and
+ `size2_arg' and so could change; added local `size1' and
+ `size2' and set to these.
+ Added some comments.
+ Deleted `newline' case.
+ `begline' can also possibly match if `d' contains a newline;
+ if it does, we have to increment d to point past the newline.
+ Replaced references to `obscure_syntax' with `bufp->syntax'.
+ (re_comp, re_exec): Made parameter `s' a `const' so could use POSIX
+ interface routines parameters.
+ Now call regex_compile, passing `obscure_syntax' via the
+ `syntax' parameter.
+ (re_exec): Made local `len' a `const' so could pass to re_search.
+ (regcomp): Added header comment.
+ Added local `syntax' to set and pass to regex_compile rather
+ than setting global `obscure_syntax' and passing it.
+ Call regex_compile with its `syntax' parameter rather than
+ re_compile_pattern.
+ Return REG_ECTYPE if character-class error.
+ (regexec): Don't initialize `regs' to anything.
+ Made `private_preg' a nonpointer so could set to what the
+ constant `preg' points.
+ Initialize `private_preg's `return_default_num_regs' field to
+ zero because want to return `nmatch' registers, not however
+ many there are subexpressions in the pattern.
+ Also test if `nmatch' > 0 to see if should pass re_match `regs'.
+
+Tue Jan 8 15:57:17 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (struct re_pattern_buffer): Reworded comment.
+
+ * regex.c (EXTEND_BUFFER): Also reset beg_interval.
+ (re_search_2): Return val if val = -2.
+ (NUM_REG_ITEMS): Listed items in comment.
+ (NUM_OTHER_ITEMS): Defined this for using in > 1 definition.
+ (MAX_NUM_FAILURE_ITEMS): Replaced `+ 2' with NUM_OTHER_ITEMS.
+ (NUM_FAILURE_ITEMS): As with definition above and added to
+ comment.
+ (PUSH_FAILURE_POINT): Replaced `* 2's with `<< 1's.
+ (re_match_2): Test with equality with 1 to see pbufp->bol and
+ pbufp->eol are set.
+
+Fri Jan 4 15:07:22 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (struct re_pattern_buffer): Reordered some fields.
+ Updated some comments.
+ Added not_bol and not_eol fields.
+ (extern regcomp, regexec, regerror): Added return types.
+ (extern regfree): Added `extern'.
+
+ * regex.c (min): Deleted unused macro.
+ (re_match_2): Compacted some code.
+ Removed call to macro `min' from `for' loop.
+ Fixed so unused registers get filled with -1's.
+ Fail if the pattern buffer's `not_bol' field is set and
+ encounter a `begline'.
+ Fail if the pattern buffer's `not_eol' field is set and
+ encounter a `endline'.
+ Deleted redundant check for empty stack in fail case.
+ Don't free pattern buffer's components in re_comp.
+ (regexec): Initialize variable regs.
+ Added `private_preg' pattern buffer so could set `not_bol' and
+ `not_eol' fields and hand to re_match.
+ Deleted naive attempt to detect anchors.
+ Set private pattern buffer's `not_bol' and `not_eol' fields
+ according to eflags value.
+ `nmatch' must also be > 0 for us to bother allocating
+ registers to send to re_match and filling pmatch
+ with their results after the call to re_match.
+ Send private pattern buffer instead of argument to re_match.
+ If use the registers, always free them and then set them to NULL.
+ (regerror): Added this Posix routine.
+ (regfree): Added this Posix routine.
+
+Tue Jan 1 15:02:45 1991 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_NREGS): Deleted this definition, as now the user
+ can choose how many registers to have.
+ (REG_NOTBOL, REG_NOTEOL): Defined these Posix eflag bits.
+ (REG_NOMATCH, REG_BADPAT, REG_ECOLLATE, REG_ECTYPE,
+ REG_EESCAPE, REG_ESUBREG, REG_EBRACK, REG_EPAREN, REG_EBRACE,
+ REG_BADBR, REG_ERANGE, REG_ESPACE, REG_BADRPT, REG_ENEWLINE):
+ Defined these return values for Posix's regcomp and regexec.
+ Updated some comments.
+ (struct re_pattern_buffer): Now typedef this as regex_t
+ instead of the other way around.
+ (struct re_registers): Added num_regs field. Made start and
+ end fields pointers to char instead of fixed size arrays.
+ (regmatch_t): Added this Posix register type.
+ (regcomp, regexec, regerror, regfree): Added externs for these
+ Posix routines.
+
+ * regex.c (enum boolean): Typedefed this.
+ (re_pattern_buffer): Reformatted some comments.
+ (re_compile_pattern): Updated some comments.
+ Always push start_memory and its attendant number whenever
+ encounter a group, not just when its number is less than the
+ previous maximum number of registers; same for stop_memory.
+ Get 4 bytes of buffer space instead of 2 when pushing a
+ set_number_at.
+ (can_match_nothing): Added this to elaborate on and replace
+ code in re_match_2.
+ (reg_info_type): Made can_match_nothing field a bit instead of int.
+ (MIN): Added for re_match_2.
+ (re_match_2 macros): Changed all `for' loops which used
+ RE_NREGS to now use num_internal_regs as upper bounds.
+ (MAX_NUM_FAILURE_ITEMS): Use num_internal_regs instead of RE_NREGS.
+ (POP_FAILURE_POINT): Added check for empty stack.
+ (FREE_VARIABLES): Added this to free (and set to NULL)
+ variables allocated in re_match_2.
+ (re_match_2): Rearranged parameters to be in order.
+ Added variables num_regs_wanted (how many registers the user wants)
+ and num_internal_regs (how many groups there are).
+ Allocated initial_stack, regstart, regend, old_regstart,
+ old_regend, reginfo, best_regstart, and best_regend---all
+ which used to be fixed size arrays. Free them all and return
+ -1 if any fail.
+ Free above variables if starting position pos isn't valid.
+ Changed all `for' loops which used RE_NREGS to now use
+ num_internal_regs as upper bounds---except for the loops which
+ fill regs; then use num_regs_wanted.
+ Allocate regs if the user has passed it and wants more than 0
+ registers filled.
+ Set regs->start[i] and regs->end[i] to -1 if either
+ regstart[i] or regend[i] equals -1, not just the first.
+ Free allocated variables before returning.
+ Updated some comments.
+ (regcomp): Return REG_ESPACE, REG_BADPAT, REG_EPAREN when
+ appropriate.
+ Free translate array.
+ (regexec): Added this Posix interface routine.
+
+Mon Dec 24 14:21:13 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: If _POSIX_SOURCE is defined then #include <sys/types.h>.
+ Added syntax bit RE_CANNOT_MATCH_NEWLINE.
+ Defined Posix cflags: REG_EXTENDED, REG_NEWLINE, REG_ICASE, and
+ REG_NOSUB.
+ Added fields re_nsub and no_sub to struct re_pattern_buffer.
+ Typedefed regex_t to be `struct re_pattern_buffer'.
+
+ * regex.c (CHAR_SET_SIZE): Defined this to be 256 and replaced
+ incidences of this value with this constant.
+ (re_compile_pattern): Added switch case for `\n' and put
+ `newline' into the pattern buffer when encounter this.
+ Increment the pattern_buffer's `re_nsub' field whenever open a
+ group.
+ (re_match_2): Match a newline with `newline'---provided the
+ syntax bit RE_CANNOT_MATCH_NEWLINE isn't set.
+ (regcomp): Added this Posix interface routine.
+ (enum test_type): Added interface_test tag.
+ (main): Added Posix interface test.
+
+Tue Dec 18 12:58:12 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (struct re_pattern_buffer): reformatted so would fit
+ in texinfo documentation.
+
+Thu Nov 29 15:49:16 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_NO_EMPTY_ALTS): Added this bit.
+ (RE_SYNTAX_POSIX_EXTENDED): Added above bit.
+
+ * regex.c (re_compile_pattern): Disallow empty alternatives only
+ when RE_NO_EMPTY_ALTS is set, not when RE_CONTEXTUAL_INVALID_OPS is.
+ Changed RE_NO_BK_CURLY_BRACES to RE_NO_BK_PARENS when testing
+ for empty groups at label handle_open.
+ At label handle_bar: disallow empty alternatives if RE_NO_EMPTY_ALTS
+ is set.
+ Rewrote some comments.
+
+ (re_compile_fastmap): cleaned up code.
+
+ (re_search_2): Rewrote comment.
+
+ (struct register_info): Added field `inner_groups'; it records
+ which groups are inside of the current one.
+ Added field can_match_nothing; it's set if the current group
+ can match nothing.
+ Added field ever_match_something; it's set if current group
+ ever matched something.
+
+ (INNER_GROUPS): Added macro to access inner_groups field of
+ struct register_info.
+
+ (CAN_MATCH_NOTHING): Added macro to access can_match_nothing
+ field of struct register_info.
+
+ (EVER_MATCHED_SOMETHING): Added macro to access
+ ever_matched_something field of struct register_info.
+
+ (NOTE_INNER_GROUP): Defined macro to record that a given group
+ is inside of all currently active groups.
+
+ (re_match_2): Added variables *p1 and mcnt2 (multipurpose).
+ Added old_regstart and old_regend arrays to hold previous
+ register values if they need be restored.
+ Initialize added fields and variables.
+ case start_memory: Find out if the group can match nothing.
+ Save previous register values in old_restart and old_regend.
+ Record that current group is inside of all currently active
+ groups.
+ If the group is inside a loop and it ever matched anything,
+ restore its registers to values before the last failed match.
+ Restore the registers for the inner groups, too.
+ case duplicate: Can back reference to a group that never
+ matched if it can match nothing.
+
+Thu Nov 29 11:12:54 1990 Karl Berry (karl at hayley)
+
+ * regex.c (bcopy, ...): define these if either _POSIX_SOURCE or
+ STDC_HEADERS is defined; same for including <stdlib.h>.
+
+Sat Oct 6 16:04:55 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (struct re_pattern_buffer): Changed field comments.
+
+ * regex.c (re_compile_pattern): Allow a `$' to precede an
+ alternation operator (`|' or `\|').
+ Disallow `^' and/or `$' in empty groups if the syntax bit
+ RE_NO_EMPTY_GROUPS is set.
+ Wait until have parsed a valid `\{...\}' interval expression
+ before testing RE_CONTEXTUAL_INVALID_OPS to see if it's
+ invalidated by that.
+ Don't use RE_NO_BK_CURLY_BRACES to test whether or not a validly
+ parsed interval expression is invalid if it has no preceding re;
+ rather, use RE_CONTEXTUAL_INVALID_OPS.
+ If an interval parses, but there is no preceding regular
+ expression, yet the syntax bit RE_CONTEXTUAL_INDEP_OPS is set,
+ then that interval can match the empty regular expression; if
+ the bit isn't set, then the characters in the interval
+ expression are parsed as themselves (sans the backslashes).
+ In unfetch_interval case: Moved PATFETCH to above the test for
+ RE_NO_BK_CURLY_BRACES being set, which would force a goto
+ normal_backslash; the code at both normal_backsl and normal_char
+ expect a character in `c.'
+
+Sun Sep 30 11:13:48 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: Changed some comments to use the terms used in the
+ documentation.
+ (RE_CONTEXTUAL_INDEP_OPS): Changed name from `RE_CONTEXT_INDEP_OPS'.
+ (RE_LISTS_NOT_NEWLINE): Changed name from `RE_HAT_NOT_NEWLINE.'
+ (RE_ANCHOR_NOT_NEWLINE): Added this syntax bit.
+ (RE_NO_EMPTY_GROUPS): Added this syntax bit.
+ (RE_NO_HYPHEN_RANGE_END): Deleted this syntax bit.
+ (RE_SYNTAX_...): Reformatted.
+ (RE_SYNTAX_POSIX_BASIC, RE_SYNTAX_EXTENDED): Added syntax bits
+ RE_ANCHOR_NOT_NEWLINE and RE_NO_EMPTY_GROUPS, and deleted
+ RE_NO_HYPHEN_RANGE_END.
+ (RE_SYNTAX_POSIX_EXTENDED): Added syntax bit RE_DOT_NOT_NULL.
+
+ * regex.c (bcopy, bcmp, bzero): Define if _POSIX_SOURCE is defined.
+ (_POSIX_SOURCE): ifdef this, #include <stdlib.h>
+ (#ifdef emacs): Changed comment of the #endif for the its #else
+ clause to be `not emacs', not `emacs.'
+ (no_pop_jump): Changed name from `jump'.
+ (pop_failure_jump): Changed name from `finalize_jump.'
+ (maybe_pop_failure_jump): Changed name from `maybe_finalize_jump'.
+ (no_pop_jump_n): Changed name from `jump_n.'
+ (EXTEND_BUFFER): Use shift instead of multiplication to double
+ buf->allocated.
+ (DO_RANGE, recompile_pattern): Added macro to set the list bits
+ for a range.
+ (re_compile_pattern): Fixed grammar problems in some comments.
+ Checked that RE_NO_BK_VBAR is set to make `$' valid before a `|'
+ and not set to make it valid before a `\|'.
+ Checked that RE_NO_BK_PARENS is set to make `$' valid before a ')'
+ and not set to make it valid before a `\)'.
+ Disallow ranges starting with `-', unless the range is the
+ first item in a list, rather than disallowing ranges which end
+ with `-'.
+ Disallow empty groups if the syntax bit RE_NO_EMPTY_GROUPS is set.
+ Disallow nothing preceding `{' and `\{' if they represent the
+ open-interval operator and RE_CONTEXTUAL_INVALID_OPS is set.
+ (register_info_type): typedef-ed this using `struct register_info.'
+ (SET_REGS_MATCHED): Compacted the code.
+ (re_match_2): Made it fail if back reference a group which we've
+ never matched.
+ Made `^' not match a newline if the syntax bit
+ RE_ANCHOR_NOT_NEWLINE is set.
+ (really_fail): Added this label so could force a final fail that
+ would not try to use the failure stack to recover.
+
+Sat Aug 25 14:23:01 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_CONTEXTUAL_OPS): Changed name from RE_CONTEXT_OPS.
+ (global): Rewrote comments and rebroke some syntax #define lines.
+
+ * regex.c (isgraph): Added definition for sequents.
+ (global): Now refer to character set lists as ``lists.''
+ Rewrote comments containing ``\('' or ``\)'' to now refer to
+ ``groups.''
+ (RE_CONTEXTUAL_OPS): Changed name from RE_CONTEXT_OPS.
+
+ (re_compile_pattern): Expanded header comment.
+
+Sun Jul 15 14:50:25 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_CONTEX_INDEP_OPS): the comment's sense got turned
+ around when we changed how it read; changed it to be correct.
+
+Sat Jul 14 16:38:06 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_NO_EMPTY_BK_REF): changed name to
+ RE_NO_MISSING_BK_REF, as this describes it better.
+
+ * regex.c (re_compile_pattern): changed RE_NO_EMPTY_BK_REF
+ to RE_NO_MISSING_BK_REF, as above.
+
+Thu Jul 12 11:45:05 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h (RE_NO_EMPTY_BRACKETS): removed this syntax bit, as
+ bracket expressions should *never* be empty regardless of the
+ syntax. Removes this bit from RE_SYNTAX_POSIX_BASIC and
+ RE_SYNTAX_POSIX_EXTENDED.
+
+ * regex.c (SET_LIST_BIT): in the comment, now refer to character
+ sets as (non)matching sets, as bracket expressions can now match
+ other things in addition to characters.
+ (re_compile_pattern): refer to groups as such instead of `\(...\)'
+ or somesuch, because groups can now be enclosed in either plain
+ parens or backslashed ones, depending on the syntax.
+ In the '[' case, added a boolean just_had_a_char_class to detect
+ whether or not a character class begins a range (which is invalid).
+ Restore way of breaking out of a bracket expression to original way.
+ Add way to detect a range if the last thing in a bracket
+ expression was a character class.
+ Took out check for c != ']' at the end of a character class in
+ the else clause, as it had already been checked in the if part
+ that also checked the validity of the string.
+ Set or clear just_had_a_char_class as appropriate.
+ Added some comments. Changed references to character sets to
+ ``(non)matching lists.''
+
+Sun Jul 1 12:11:29 1990 Karl Berry (karl at hayley)
+
+ * regex.h (BYTEWIDTH): moved back to regex.c.
+
+ * regex.h (re_compile_fastmap): removed declaration; this
+ shouldn't be advertised.
+
+Mon May 28 15:27:53 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (ifndef Sword): Made comments more specific.
+ (global): include <stdio.h> so can write fatal messages on
+ standard error. Replaced calls to assert with fprintfs to
+ stderr and exit (1)'s.
+ (PREFETCH): Reformatted to make more readable.
+ (AT_STRINGS_BEG): Defined to test if we're at the beginning of
+ the virtual concatenation of string1 and string2.
+ (AT_STRINGS_END): Defined to test if at the end of the virtual
+ concatenation of string1 and string2.
+ (AT_WORD_BOUNDARY): Defined to test if are at a word boundary.
+ (IS_A_LETTER(d)): Defined to test if the contents of the pointer D
+ is a letter.
+ (re_match_2): Rewrote the wordbound, notwordbound, wordbeg, wordend,
+ begbuf, and endbuf cases in terms of the above four new macros.
+ Called SET_REGS_MATCHED in the matchsyntax, matchnotsyntax,
+ wordchar, and notwordchar cases.
+
+Mon May 14 14:49:13 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (re_search_2): Fixed RANGE to not ever take STARTPOS
+ outside of virtual concatenation of STRING1 and STRING2.
+ Updated header comment as to this.
+ (re_match_2): Clarified comment about MSTOP in header.
+
+Sat May 12 15:39:00 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (re_search_2): Checked for out-of-range STARTPOS.
+ Added comments.
+ When searching backwards, not only get the character with which
+ to compare to the fastmap from string2 if the starting position
+ >= size1, but also if size1 is zero; this is so won't get a
+ segmentation fault if string1 is null.
+ Reformatted code at label advance.
+
+Thu Apr 12 20:26:21 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: Added #pragma once and #ifdef...endif __REGEXP_LIBRARY.
+ (RE_EXACTN_VALUE): Added for search.c to use.
+ Reworded some comments.
+
+ regex.c: Punctuated some comments correctly.
+ (NULL): Removed this.
+ (RE_EXACTN_VALUE): Added for search.c to use.
+ (<ctype.h>): Moved this include to top of file.
+ (<assert.h>): Added this include.
+ (struct regexpcode): Assigned 0 to unused and 1 to exactn
+ because of RE_EXACTN_VALUE.
+ Added comment.
+ (various macros): Lined up backslashes near end of line.
+ (insert_jump): Cleaned up the header comment.
+ (re_search): Corrected the header comment.
+ (re_search_2): Cleaned up and completed the header comment.
+ (re_max_failures): Updated comment.
+ (struct register_info): Constructed as bits so as to save space
+ on the stack when pushing register information.
+ (IS_ACTIVE): Macro for struct register_info.
+ (MATCHED_SOMETHING): Macro for struct register_info.
+ (NUM_REG_ITEMS): How many register information items for each
+ register we have to push on the stack at each failure.
+ (MAX_NUM_FAILURE_ITEMS): If push all the registers on failure,
+ this is how many items we push on the stack.
+ (PUSH_FAILURE_POINT): Now pushes whether or not the register is
+ currently active, and whether or not it matched something.
+ Checks that there's enough space allocated to accomodate all the
+ items we currently want to push. (Before, a test for an empty
+ stack sufficed because we always pushed and popped the same
+ number of items).
+ Replaced ``2'' with MAX_NUM_FAILURE_POINTS when ``2'' refers
+ to how many things get pushed on the stack each time.
+ When copy the stack into the newly allocated storage, now only copy
+ the area in use.
+ Clarified comment.
+ (POP_FAILURE_POINT): Defined to use in places where put number
+ of registers on the stack into a variable before using it to
+ decrement the stack, so as to not confuse the compiler.
+ (IS_IN_FIRST_STRING): Defined to check if a pointer points into
+ the first string.
+ (SET_REGS_MATCHED): Changed to use the struct register_info
+ bits; also set the matched-something bit to false if the
+ register isn't currently active. (This is a redundant setting.)
+ (re_match_2): Cleaned up and completed the header comment.
+ Updated the failure stack comment.
+ Replaced the ``2'' with MAX_NUM_FAILURE_ITEMS in the static
+ allocation of initial_stack, because now more than two (now up
+ to MAX_FAILURE_ITEMS) items get pushed on the failure stack each
+ time.
+ Ditto for stackb.
+ Trashed restart_seg1, regend_seg1, best_regstart_seg1, and
+ best_regend_seg1 because they could have erroneous information
+ in them, such as when matching ``a'' (in string1) and ``ab'' (in
+ string2) with ``(a)*ab''; before using IS_IN_FIRST_STRING to see
+ whether or not the register starts or ends in string1,
+ regstart[1] pointed past the end of string1, yet regstart_seg1
+ was 0!
+ Added variable reg_info of type struct register_info to keep
+ track of currently active registers and whether or not they
+ currently match anything.
+ Commented best_regs_set.
+ Trashed reg_active and reg_matched_something and put the
+ information they held into reg_info; saves space on the stack.
+ Replaced NULL with '\000'.
+ In begline case, compacted the code.
+ Used assert to exit if had an internal error.
+ In begbuf case, because now force the string we're working on
+ into string2 if there aren't two strings, now allow d == string2
+ if there is no string1 (and the check for that is size1 == 0!);
+ also now succeeds if there aren't any strings at all.
+ (main, ifdef canned): Put test type into a variable so could
+ change it while debugging.
+
+Sat Mar 24 12:24:13 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (GET_UNSIGNED_NUMBER): Deleted references to num_fetches.
+ (re_compile_pattern): Deleted num_fetches because could keep
+ track of the number of fetches done by saving a pointer into the
+ pattern.
+ Added variable beg_interval to be used as a pointer, as above.
+ Assert that beg_interval points to something when it's used as above.
+ Initialize succeed_n's to lower_bound because re_compile_fastmap
+ needs to know it.
+ (re_compile_fastmap): Deleted unnecessary variable is_a_jump_n.
+ Added comment.
+ (re_match_2): Put number of registers on the stack into a
+ variable before using it to decrement the stack, so as to not
+ confuse the compiler.
+ Updated comments.
+ Used error routine instead of printf and exit.
+ In exactn case, restored longer code from ``original'' regex.c
+ which doesn't test translate inside a loop.
+
+ * regex.h: Moved #define NULL and the enum regexpcode definition
+ and to regex.c. Changed some comments.
+
+ regex.c (global): Updated comments about compiling and for the
+ re_compile_pattern jump routines.
+ Added #define NULL and the enum regexpcode definition (from
+ regex.h).
+ (enum regexpcode): Added set_number_at to reset the n's of
+ succeed_n's and jump_n's.
+ (re_set_syntax): Updated its comment.
+ (re_compile_pattern): Moved its heading comment to after its macros.
+ Moved its include statement to the top of the file.
+ Commented or added to comments of its macros.
+ In start_memory case: Push laststart value before adding
+ start_memory and its register number to the buffer, as they
+ might not get added.
+ Added code to put a set_number_at before each succeed_n and one
+ after each jump_n; rewrote code in what seemed a more
+ straightforward manner to put all these things in the pattern so
+ the succeed_n's would correctly jump to the set_number_at's of
+ the matching jump_n's, and so the jump_n's would correctly jump
+ to after the set_number_at's of the matching succeed_n's.
+ Initialize succeed_n n's to -1.
+ (insert_op_2): Added this to insert an operation followed by
+ two integers.
+ (re_compile_fastmap): Added set_number_at case.
+ (re_match_2): Moved heading comment to after macros.
+ Added mention of REGS to heading comment.
+ No longer turn a succeed_n with n = 0 into an on_failure_jump,
+ because n needs to be reset each time through a loop.
+ Check to see if a succeed_n's n is set by its set_number_at.
+ Added set_number_at case.
+ Updated some comments.
+ (main): Added another main to run posix tests, which is compiled
+ ifdef both test and canned. (Old main is still compiled ifdef
+ test only).
+
+Tue Mar 19 09:22:55 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.[hc]: Change all instances of the word ``legal'' to
+ ``valid'' and all instances of ``illegal'' to ``invalid.''
+
+Sun Mar 4 12:11:31 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: Added syntax bit RE_NO_EMPTY_RANGES which is set if
+ an ending range point has to collate higher or equal to the
+ starting range point.
+ Added syntax bit RE_NO_HYPHEN_RANGE_END which is set if a hyphen
+ can't be an ending range point.
+ Set to two above bits in RE_SYNTAX_POSIX_BASIC and
+ RE_SYNTAX_POSIX_EXTENDED.
+
+ regex.c: (re_compile_pattern): Don't allow empty ranges if the
+ RE_NO_EMPTY_RANGES syntax bit is set.
+ Don't let a hyphen be a range end if the RE_NO_HYPHEN_RANGE_END
+ syntax bit is set.
+ (ESTACK_PUSH_2): renamed this PUSH_FAILURE_POINT and made it
+ push all the used registers on the stack, as well as the number
+ of the highest numbered register used, and (as before) the two
+ failure points.
+ (re_match_2): Fixed up comments.
+ Added arrays best_regstart[], best_regstart_seg1[], best_regend[],
+ and best_regend_seg1[] to keep track of the best match so far
+ whenever reach the end of the pattern but not the end of the
+ string, and there are still failure points on the stack with
+ which to backtrack; if so, do the saving and force a fail.
+ If reach the end of the pattern but not the end of the string,
+ but there are no more failure points to try, restore the best
+ match so far, set the registers and return.
+ Compacted some code.
+ In stop_memory case, if the subexpression we've just left is in
+ a loop, push onto the stack the loop's on_failure_jump failure
+ point along with the current pointer into the string (d).
+ In finalize_jump case, in addition to popping the failure
+ points, pop the saved registers.
+ In the fail case, restore the registers, as well as the failure
+ points.
+
+Sun Feb 18 15:08:10 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c: (global): Defined a macro GET_BUFFER_SPACE which
+ makes sure you have a specified number of buffer bytes
+ allocated.
+ Redefined the macro BUFPUSH to use this.
+ Added comments.
+
+ (re_compile_pattern): Call GET_BUFFER_SPACE before storing or
+ inserting any jumps.
+
+ (re_match_2): Set d to string1 + pos and dend to end_match_1
+ only if string1 isn't null.
+ Force exit from a loop if it's around empty parentheses.
+ In stop_memory case, if found some jumps, increment p2 before
+ extracting address to which to jump. Also, don't need to know
+ how many more times can jump_n.
+ In begline case, d must equal string1 or string2, in that order,
+ only if they are not null.
+ In maybe_finalize_jump case, skip over start_memorys' and
+ stop_memorys' register numbers, too.
+
+Thu Feb 15 15:53:55 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (BUFPUSH): off by one goof in deciding whether to
+ EXTEND_BUFFER.
+
+Wed Jan 24 17:07:46 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: Moved definition of NULL to here.
+ Got rid of ``In other words...'' comment.
+ Added to some comments.
+
+ regex.c: (re_compile_pattern): Tried to bulletproof some code,
+ i.e., checked if backward references (e.g., p[-1]) were within
+ the range of pattern.
+
+ (re_compile_fastmap): Fixed a bug in succeed_n part where was
+ getting the amount to jump instead of how many times to jump.
+
+ (re_search_2): Changed the name of the variable ``total'' to
+ ``total_size.''
+ Condensed some code.
+
+ (re_match_2): Moved the comment about duplicate from above the
+ start_memory case to above duplicate case.
+
+ (global): Rewrote some comments.
+ Added commandline arguments to testing.
+
+Wed Jan 17 11:47:27 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c: (global): Defined a macro STORE_NUMBER which stores a
+ number into two contiguous bytes. Also defined STORE_NUMBER_AND_INCR
+ which does the same thing and then increments the pointer to the
+ storage place to point after the number.
+ Defined a macro EXTRACT_NUMBER which extracts a number from two
+ continguous bytes. Also defined EXTRACT_NUMBER_AND_INCR which
+ does the same thing and then increments the pointer to the
+ source to point to after where the number was.
+
+Tue Jan 16 12:09:19 1990 Kathy Hargreaves (kathy at hayley)
+
+ * regex.h: Incorporated rms' changes.
+ Defined RE_NO_BK_REFS syntax bit which is set when want to
+ interpret back reference patterns as literals.
+ Defined RE_NO_EMPTY_BRACKETS syntax bit which is set when want
+ empty bracket expressions to be illegal.
+ Defined RE_CONTEXTUAL_ILLEGAL_OPS syntax bit which is set when want
+ it to be illegal for *, +, ? and { to be first in an re or come
+ immediately after a | or a (, and for ^ not to appear in a
+ nonleading position and $ in a nontrailing position (outside of
+ bracket expressions, that is).
+ Defined RE_LIMITED_OPS syntax bit which is set when want +, ?
+ and | to always be literals instead of ops.
+ Fixed up the Posix syntax.
+ Changed the syntax bit comments from saying, e.g., ``0 means...''
+ to ``If this bit is set, it means...''.
+ Changed the syntax bit defines to use shifts instead of integers.
+
+ * regex.c: (global): Incorporated rms' changes.
+
+ (re_compile_pattern): Incorporated rms' changes
+ Made it illegal for a $ to appear anywhere but inside a bracket
+ expression or at the end of an re when RE_CONTEXTUAL_ILLEGAL_OPS
+ is set. Made the same hold for $ except it has to be at the
+ beginning of an re instead of the end.
+ Made the re "[]" illegal if RE_NO_EMPTY_BRACKETS is set.
+ Made it illegal for | to be first or last in an re, or immediately
+ follow another | or a (.
+ Added and embellished some comments.
+ Allowed \{ to be interpreted as a literal if RE_NO_BK_CURLY_BRACES
+ is set.
+ Made it illegal for *, +, ?, and { to appear first in an re, or
+ immediately follow a | or a ( when RE_CONTEXTUAL_ILLEGAL_OPS is set.
+ Made back references interpreted as literals if RE_NO_BK_REFS is set.
+ Made recursive intervals either illegal (if RE_NO_BK_CURLY_BRACES
+ isn't set) or interpreted as literals (if is set), if RE_INTERVALS
+ is set.
+ Made it treat +, ? and | as literals if RE_LIMITED_OPS is set.
+ Cleaned up some code.
+
+Thu Dec 21 15:31:32 1989 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c: (global): Moved RE_DUP_MAX to regex.h and made it
+ equal 2^15 - 1 instead of 1000.
+ Defined NULL to be zero.
+ Moved the definition of BYTEWIDTH to regex.h.
+ Made the global variable obscure_syntax nonstatic so the tests in
+ another file could use it.
+
+ (re_compile_pattern): Defined a maximum length (CHAR_CLASS_MAX_LENGTH)
+ for character class strings (i.e., what's between the [: and the
+ :]'s).
+ Defined a macro SET_LIST_BIT(c) which sets the bit for C in a
+ character set list.
+ Took out comments that EXTEND_BUFFER clobbers C.
+ Made the string "^" match itself, if not RE_CONTEXT_IND_OPS.
+ Added character classes to bracket expressions.
+ Change the laststart pointer saved with the start of each
+ subexpression to point to start_memory instead of after the
+ following register number. This is because the subexpression
+ might be in a loop.
+ Added comments and compacted some code.
+ Made intervals only work if preceded by an re matching a single
+ character or a subexpression.
+ Made back references to nonexistent subexpressions illegal if
+ using POSIX syntax.
+ Made intervals work on the last preceding character of a
+ concatenation of characters, e.g., ab{0,} matches abbb, not abab.
+ Moved macro PREFETCH to outside the routine.
+
+ (re_compile_fastmap): Added succeed_n to work analogously to
+ on_failure_jump if n is zero and jump_n to work analogously to
+ the other backward jumps.
+
+ (re_match_2): Defined macro SET_REGS_MATCHED to set which
+ current subexpressions had matches within them.
+ Changed some comments.
+ Added reg_active and reg_matched_something arrays to keep track
+ of in which subexpressions currently have matched something.
+ Defined MATCHING_IN_FIRST_STRING and replaced ``dend == end_match_1''
+ with it to make code easier to understand.
+ Fixed so can apply * and intervals to arbitrarily nested
+ subexpressions. (Lots of previous bugs here.)
+ Changed so won't match a newline if syntax bit RE_DOT_NOT_NULL is set.
+ Made the upcase array nonstatic so the testing file could use it also.
+
+ (main.c): Moved the tests out to another file.
+
+ (tests.c): Moved all the testing stuff here.
+
+Sat Nov 18 19:30:30 1989 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c: (re_compile_pattern): Defined RE_DUP_MAX, the maximum
+ number of times an interval can match a pattern.
+ Added macro GET_UNSIGNED_NUMBER (used to get below):
+ Added variables lower_bound and upper_bound for upper and lower
+ bounds of intervals.
+ Added variable num_fetches so intervals could do backtracking.
+ Added code to handle '{' and "\{" and intervals.
+ Added to comments.
+
+ (store_jump_n): (Added) Stores a jump with a number following the
+ relative address (for intervals).
+
+ (insert_jump_n): (Added) Inserts a jump_n.
+
+ (re_match_2): Defined a macro ESTACK_PUSH_2 for the error stack;
+ it checks for overflow and reallocates if necessary.
+
+ * regex.h: Added bits (RE_INTERVALS and RE_NO_BK_CURLY_BRACES)
+ to obscure syntax to indicate whether or not
+ a syntax handles intervals and recognizes either \{ and
+ \} or { and } as operators. Also added two syntaxes
+ RE_SYNTAX_POSIX_BASIC and RE_POSIX_EXTENDED and two command codes
+ to the enumeration regexpcode; they are succeed_n and jump_n.
+
+Sat Nov 18 19:30:30 1989 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c: (re_compile_pattern): Defined INIT_BUFF_SIZE to get rid
+ of repeated constants in code. Tested with value 1.
+ Renamed PATPUSH as BUFPUSH, since it pushes things onto the
+ buffer, not the pattern. Also made this macro extend the buffer
+ if it's full (so could do the following):
+ Took out code at top of loop that checks to see if buffer is going
+ to be full after 10 additions (and reallocates if necessary).
+
+ (insert_jump): Rearranged declaration lines so comments would read
+ better.
+
+ (re_match_2): Compacted exactn code and added more comments.
+
+ (main): Defined macros TEST_MATCH and MATCH_SELF to do
+ testing; took out loop so could use these instead.
+
+Tue Oct 24 20:57:18 1989 Kathy Hargreaves (kathy at hayley)
+
+ * regex.c (re_set_syntax): Gave argument `syntax' a type.
+ (store_jump, insert_jump): made them void functions.
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+version-control: never
+End:
diff --git a/gnu/lib/libregex/INSTALL b/gnu/lib/libregex/INSTALL
new file mode 100644
index 0000000..014e0f7
--- /dev/null
+++ b/gnu/lib/libregex/INSTALL
@@ -0,0 +1,117 @@
+This is a generic INSTALL file for utilities distributions.
+If this package does not come with, e.g., installable documentation or
+data files, please ignore the references to them below.
+
+To compile this package:
+
+1. Configure the package for your system. In the directory that this
+file is in, type `./configure'. If you're using `csh' on an old
+version of System V, you might need to type `sh configure' instead to
+prevent `csh' from trying to execute `configure' itself.
+
+The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation, and
+creates the Makefile(s) (one in each subdirectory of the source
+directory). In some packages it creates a C header file containing
+system-dependent definitions. It also creates a file `config.status'
+that you can run in the future to recreate the current configuration.
+
+Running `configure' takes a minute or two. While it is running, it
+prints some messages that tell what it is doing. If you don't want to
+see the messages, run `configure' with its standard output redirected
+to `/dev/null'; for example, `./configure >/dev/null'.
+
+To compile the package in a different directory from the one
+containing the source code, you must use a version of `make' that
+supports the VPATH variable, such as GNU `make'. `cd' to the directory
+where you want the object files and executables to go and run
+`configure'. `configure' automatically checks for the source code in
+the directory that `configure' is in and in `..'. If for some reason
+`configure' is not in the source code directory that you are
+configuring, then it will report that it can't find the source code.
+In that case, run `configure' with the option `--srcdir=DIR', where
+DIR is the directory that contains the source code.
+
+By default, `make install' will install the package's files in
+/usr/local/bin, /usr/local/lib, /usr/local/man, etc. You can specify
+an installation prefix other than /usr/local by giving `configure' the
+option `--prefix=PATH'. Alternately, you can do so by giving a value
+for the `prefix' variable when you run `make', e.g.,
+ make prefix=/usr/gnu
+
+You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If
+you give `configure' the option `--exec-prefix=PATH' or set the
+`make' variable `exec_prefix' to PATH, the package will use PATH as
+the prefix for installing programs and libraries. Data files and
+documentation will still use the regular prefix. Normally, all files
+are installed using the regular prefix.
+
+Another `configure' option is useful mainly in `Makefile' rules for
+updating `config.status' and `Makefile'. The `--no-create' option
+figures out the configuration for your system and records it in
+`config.status', without actually configuring the package (creating
+`Makefile's and perhaps a configuration header file). Later, you can
+run `./config.status' to actually configure the package. You can also
+give `config.status' the `--recheck' option, which makes it re-run
+`configure' with the same arguments you used before. This option is
+useful if you change `configure'.
+
+Some packages pay attention to `--with-PACKAGE' options to `configure',
+where PACKAGE is something like `gnu-libc' or `x' (for the X Window System).
+The README should mention any --with- options that the package recognizes.
+
+`configure' ignores any other arguments that you give it.
+
+If your system requires unusual options for compilation or linking
+that `configure' doesn't know about, you can give `configure' initial
+values for some variables by setting them in the environment. In
+Bourne-compatible shells, you can do that on the command line like
+this:
+ CC='gcc -traditional' DEFS=-D_POSIX_SOURCE ./configure
+
+The `make' variables that you might want to override with environment
+variables when running `configure' are:
+
+(For these variables, any value given in the environment overrides the
+value that `configure' would choose:)
+CC C compiler program.
+ Default is `cc', or `gcc' if `gcc' is in your PATH.
+INSTALL Program to use to install files.
+ Default is `install' if you have it, `cp' otherwise.
+
+(For these variables, any value given in the environment is added to
+the value that `configure' chooses:)
+DEFS Configuration options, in the form `-Dfoo -Dbar ...'
+ Do not use this variable in packages that create a
+ configuration header file.
+LIBS Libraries to link with, in the form `-lfoo -lbar ...'
+
+If you need to do unusual things to compile the package, we encourage
+you to figure out how `configure' could check whether to do them, and
+mail diffs or instructions to the address given in the README so we
+can include them in the next release.
+
+2. Type `make' to compile the package. If you want, you can override
+the `make' variables CFLAGS and LDFLAGS like this:
+
+ make CFLAGS=-O2 LDFLAGS=-s
+
+3. If the package comes with self-tests and you want to run them,
+type `make check'. If you're not sure whether there are any, try it;
+if `make' responds with something like
+ make: *** No way to make target `check'. Stop.
+then the package does not come with self-tests.
+
+4. Type `make install' to install programs, data files, and
+documentation.
+
+5. You can remove the program binaries and object files from the
+source directory by typing `make clean'. To also remove the
+Makefile(s), the header file containing system-dependent definitions
+(if the package uses one), and `config.status' (all the files that
+`configure' created), type `make distclean'.
+
+The file `configure.in' is used as a template to create `configure' by
+a program called `autoconf'. You will only need it if you want to
+regenerate `configure' using a newer version of `autoconf'.
diff --git a/gnu/lib/libregex/Makefile b/gnu/lib/libregex/Makefile
new file mode 100644
index 0000000..d351027
--- /dev/null
+++ b/gnu/lib/libregex/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+SUBDIR+= doc
+
+LIB= gnuregex
+SHLIB_MAJOR= 2
+SHLIB_MINOR= 0
+
+SRCS= regex.c
+INCS= regex.h
+INCSNAME= gnuregex.h
+NOMAN= noman
+
+CFLAGS+=-I${.CURDIR} -DHAVE_STRING_H=1 -DSTDC_HEADERS=1 -DNO_POSIX_COMPAT=1
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libregex/Makefile.gnu b/gnu/lib/libregex/Makefile.gnu
new file mode 100644
index 0000000..b8bc209
--- /dev/null
+++ b/gnu/lib/libregex/Makefile.gnu
@@ -0,0 +1,99 @@
+# Generated automatically from Makefile.in by configure.
+# Makefile for regex.
+#
+# Copyright (C) 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, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You 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.
+
+version = 0.12
+
+# You can define CPPFLAGS on the command line. Aside from system-specific
+# flags, you can define:
+# -DREGEX_MALLOC to use malloc/realloc/free instead of alloca.
+# -DDEBUG to enable the compiled pattern disassembler and execution
+# tracing; code runs substantially slower.
+# -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to
+# the corresponding C procedures). If not -DDEBUG, the macros
+# are used.
+CPPFLAGS =
+
+# Likewise, you can override CFLAGS to optimize, use -Wall, etc.
+CFLAGS = -g
+
+# Ditto for LDFLAGS and LOADLIBES.
+LDFLAGS =
+LOADLIBES =
+
+srcdir = .
+VPATH = .
+
+CC = gcc
+DEFS = -DHAVE_STRING_H=1
+
+SHELL = /bin/sh
+
+subdirs = doc test
+
+default all:: regex.o
+.PHONY: default all
+
+regex.o: regex.c regex.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $<
+
+clean mostlyclean::
+ rm -f *.o
+
+distclean:: clean
+ rm -f Makefile config.status
+
+extraclean:: distclean
+ rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out
+
+configure: configure.in
+ autoconf
+
+config.status: configure
+ sh configure --no-create
+
+Makefile: Makefile.in config.status
+ sh config.status
+
+makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \
+DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)'
+
+default all install \
+mostlyclean clean distclean extraclean realclean \
+TAGS check::
+ for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done
+.PHONY: install mostlyclean clean distclean extraclean realclean TAGS check
+
+# Prevent GNU make 3 from overflowing arg limit on system V.
+.NOEXPORT:
+
+distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \
+ *.in configure regex.c regex.h
+distdir = regex-$(version)
+distargs = version=$(version) distdir=../$(distdir)/$$d
+dist: TAGS configure
+ @echo "Version numbers in: Makefile.in, ChangeLog, NEWS,"
+ @echo " regex.c, regex.h,"
+ @echo " and doc/xregex.texi (if modified)."
+ rm -rf $(distdir)
+ mkdir $(distdir)
+ ln $(distfiles) $(distdir)
+ for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done
+ tar czhf $(distdir).tar.Z $(distdir)
+ rm -rf $(distdir)
+.PHONY: dist
diff --git a/gnu/lib/libregex/Makefile.in b/gnu/lib/libregex/Makefile.in
new file mode 100644
index 0000000..a21f970
--- /dev/null
+++ b/gnu/lib/libregex/Makefile.in
@@ -0,0 +1,98 @@
+# Makefile for regex.
+#
+# Copyright (C) 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, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You 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.
+
+version = 0.12
+
+# You can define CPPFLAGS on the command line. Aside from system-specific
+# flags, you can define:
+# -DREGEX_MALLOC to use malloc/realloc/free instead of alloca.
+# -DDEBUG to enable the compiled pattern disassembler and execution
+# tracing; code runs substantially slower.
+# -DEXTRACT_MACROS to use the macros EXTRACT_* (as opposed to
+# the corresponding C procedures). If not -DDEBUG, the macros
+# are used.
+CPPFLAGS =
+
+# Likewise, you can override CFLAGS to optimize, use -Wall, etc.
+CFLAGS = -g
+
+# Ditto for LDFLAGS and LOADLIBES.
+LDFLAGS =
+LOADLIBES =
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+DEFS = @DEFS@
+
+SHELL = /bin/sh
+
+subdirs = doc test
+
+default all:: regex.o
+.PHONY: default all
+
+regex.o: regex.c regex.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) -I. -I$(srcdir) -c $<
+
+clean mostlyclean::
+ rm -f *.o
+
+distclean:: clean
+ rm -f Makefile config.status
+
+extraclean:: distclean
+ rm -f patch* *~* *\#* *.orig *.rej *.bak core a.out
+
+configure: configure.in
+ autoconf
+
+config.status: configure
+ sh configure --no-create
+
+Makefile: Makefile.in config.status
+ sh config.status
+
+makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' \
+DEFS='$(DEFS)' LDFLAGS='$(LDFLAGS)' LOADLIBES='$(LOADLIBES)'
+
+default all install \
+mostlyclean clean distclean extraclean realclean \
+TAGS check::
+ for d in $(subdirs); do (cd $$d; $(MAKE) $(makeargs) $@); done
+.PHONY: install mostlyclean clean distclean extraclean realclean TAGS check
+
+# Prevent GNU make 3 from overflowing arg limit on system V.
+.NOEXPORT:
+
+distfiles = AUTHORS ChangeLog COPYING INSTALL NEWS README \
+ *.in configure regex.c regex.h
+distdir = regex-$(version)
+distargs = version=$(version) distdir=../$(distdir)/$$d
+dist: TAGS configure
+ @echo "Version numbers in: Makefile.in, ChangeLog, NEWS,"
+ @echo " regex.c, regex.h,"
+ @echo " and doc/xregex.texi (if modified)."
+ rm -rf $(distdir)
+ mkdir $(distdir)
+ ln $(distfiles) $(distdir)
+ for d in $(subdirs); do (cd $$d; $(MAKE) $(distargs) dist); done
+ tar czhf $(distdir).tar.Z $(distdir)
+ rm -rf $(distdir)
+.PHONY: dist
diff --git a/gnu/lib/libregex/NEWS b/gnu/lib/libregex/NEWS
new file mode 100644
index 0000000..b3a899b
--- /dev/null
+++ b/gnu/lib/libregex/NEWS
@@ -0,0 +1,62 @@
+Version 0.12
+
+* regex.c does not #define bcmp/bcopy/bzero if they already are.
+
+* regex.h does not redefine `const' if it is already defined, even if
+ __STDC__ is not defined.
+
+* RE_SYNTAX_ED added (same as POSIX BRE's).
+
+* The following bugs have been fixed, among others:
+ * The pattern \w+ doesn't infinite loop.
+ * The pattern ".+\n" is compiled correctly.
+ * Expressions with more than MAX_REGNUM groups are compiled correctly.
+
+* Patterns that end in a repetition operator (e.g., `*') match
+ slightly faster if no looping is actually necessary.
+
+Version 0.11 (17 Sep 92)
+
+* Back-references to nonexistent subexpressions, as in the r.e. `abc\1',
+ are always invalid. Previously, they could match the literal digit,
+ e.g., the stated r.e. might have matched `abc1'.
+
+* Empty subexpressions are always valid (POSIX leaves this undefined).
+
+* Simplified rules for ^ and $ being anchors.
+
+* One minor speedup (rewriting the C procedure `pop_failure_point' as a
+ macro again).
+
+* Bug fixes involving:
+ - Declarations in regex.h and non-ANSI compilers.
+ - Bracket expressions with characters between 0x80-0xff.
+ - Memory leak in re_match_2 on systems requiring `alloca (0)' to
+ free alloca'd storage.
+
+* Test and documentation files moved into subdirectories.
+
+Version 0.10 (9 Sep 92)
+
+* `obscure_syntax' is now called `re_default_syntax'.
+
+* `re_comp's return type is no longer `const', for compatibility with BSD.
+
+* POSIX syntaxes now include as much functionality as possible
+ (consistent with the standard).
+
+* Compilation conditionals normalized to what the rest of GNU is
+ migrating towards these days.
+
+* Bug fixes involving:
+ - Ranges with characters between 0x80 and 0xff, e.g., [\001-\377].
+ - `re_compile_fastmap' and the sequence `.*\n'.
+ - Intervals with exact counts, e.g., a{5}.
+
+* Changed distribution to use a standard Makefile, install the info
+ files, use a configure script, etc.
+
+Version 0.9
+
+* The longest match was not always chosen: `a*|ab' didn't match `aab'.
+
diff --git a/gnu/lib/libregex/README b/gnu/lib/libregex/README
new file mode 100644
index 0000000..918e1a0
--- /dev/null
+++ b/gnu/lib/libregex/README
@@ -0,0 +1,60 @@
+This directory contains the GNU regex library. It is compliant with
+POSIX.2, except for internationalization features.
+
+See the file NEWS for a list of major changes in the current release.
+
+See the file INSTALL for compilation instructions. (The only thing
+installed is the documentation; regex.c is compiled into regex.o, but
+not installed anywhere.)
+
+The subdirectory `doc' contains a (programmers') manual for the library.
+It's probably out-of-date. Improvements are welcome.
+
+The subdirectory `test' contains the various tests we've written.
+
+We know this code is not as fast as it might be. If you have specific
+suggestions, profiling results, or other such useful information to
+report, please do.
+
+Emacs 18 is not going use this revised regex (but Emacs 19 will). If
+you want to try it with Emacs 18, apply the patch at the end of this
+file first.
+
+Mail bug reports to bug-gnu-utils@prep.ai.mit.edu.
+
+Please include an actual regular expression that fails (and the syntax
+used to compile it); without that, there's no way to reproduce the bug,
+so there's no way we can fix it. Even if you include a patch, also
+include the regular expression in error; otherwise, we can't know for
+sure what you're trying to fix.
+
+Here is the patch to make this version of regex work with Emacs 18.
+
+*** ORIG/search.c Tue Jan 8 13:04:55 1991
+--- search.c Sun Jan 5 10:57:00 1992
+***************
+*** 25,26 ****
+--- 25,28 ----
+ #include "commands.h"
++
++ #include <sys/types.h>
+ #include "regex.h"
+***************
+*** 477,479 ****
+ /* really needed. */
+! && *(searchbuf.buffer) == (char) exactn /* first item is "exact match" */
+ && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */
+--- 479,482 ----
+ /* really needed. */
+! /* first item is "exact match" */
+! && *(searchbuf.buffer) == (char) RE_EXACTN_VALUE
+ && searchbuf.buffer[1] + 2 == searchbuf.used) /*first is ONLY item */
+***************
+*** 1273,1275 ****
+ searchbuf.allocated = 100;
+! searchbuf.buffer = (char *) malloc (searchbuf.allocated);
+ searchbuf.fastmap = search_fastmap;
+--- 1276,1278 ----
+ searchbuf.allocated = 100;
+! searchbuf.buffer = (unsigned char *) malloc (searchbuf.allocated);
+ searchbuf.fastmap = search_fastmap;
diff --git a/gnu/lib/libregex/VERSION b/gnu/lib/libregex/VERSION
new file mode 100644
index 0000000..7182be2
--- /dev/null
+++ b/gnu/lib/libregex/VERSION
@@ -0,0 +1,3 @@
+GNU regex version 0.12
+
+complete, unmodified regex sources are available from prep.ai.mit.edu.
diff --git a/gnu/lib/libregex/config.status b/gnu/lib/libregex/config.status
new file mode 100644
index 0000000..1b276aa
--- /dev/null
+++ b/gnu/lib/libregex/config.status
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host sun-lamp.cs.berkeley.edu:
+#
+# configure
+
+for arg
+do
+ case "$arg" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ exec /bin/sh configure ;;
+ *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;;
+ esac
+done
+
+trap 'rm -f Makefile doc/Makefile test/Makefile; exit 1' 1 3 15
+CC='gcc'
+INSTALL='/usr/bin/install -c'
+INSTALL_PROGRAM='$(INSTALL)'
+INSTALL_DATA='$(INSTALL) -m 644'
+CPP='${CC-cc} -E'
+ALLOCA=''
+LIBS=''
+srcdir='.'
+DEFS=' -DHAVE_STRING_H=1'
+prefix='/usr'
+exec_prefix='${prefix}'
+prsub='s%^prefix\([ ]*\)=\([ ]*\).*$%prefix\1=\2/usr%
+s%^exec_prefix\([ ]*\)=\([ ]*\).*$%exec_prefix\1=\2${prefix}%'
+
+top_srcdir=$srcdir
+for file in .. Makefile doc/Makefile test/Makefile; do if [ "x$file" != "x.." ]; then
+ srcdir=$top_srcdir
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ dir=`echo $file|sed 's%/[^/][^/]*$%%'`
+ if test "$dir" != "$file"; then
+ test "$top_srcdir" != . && srcdir=$top_srcdir/$dir
+ test ! -d $dir && mkdir $dir
+ fi
+ echo creating $file
+ rm -f $file
+ echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file
+ sed -e "
+$prsub
+s%@CC@%$CC%g
+s%@INSTALL@%$INSTALL%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@CPP@%$CPP%g
+s%@ALLOCA@%$ALLOCA%g
+s%@LIBS@%$LIBS%g
+s%@srcdir@%$srcdir%g
+s%@DEFS@%$DEFS%
+" $top_srcdir/${file}.in >> $file
+fi; done
+
+exit 0
diff --git a/gnu/lib/libregex/configure b/gnu/lib/libregex/configure
new file mode 100644
index 0000000..29c5b80
--- /dev/null
+++ b/gnu/lib/libregex/configure
@@ -0,0 +1,462 @@
+#!/bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf.
+# Copyright (C) 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, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You 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.
+
+# Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] [--no-create]
+# [--prefix=PREFIX] [--exec-prefix=PREFIX] [--with-PACKAGE] [TARGET]
+# Ignores all args except --srcdir, --prefix, --exec-prefix, --no-create, and
+# --with-PACKAGE unless this script has special code to handle it.
+
+
+for arg
+do
+ # Handle --exec-prefix with a space before the argument.
+ if test x$next_exec_prefix = xyes; then exec_prefix=$arg; next_exec_prefix=
+ # Handle --host with a space before the argument.
+ elif test x$next_host = xyes; then next_host=
+ # Handle --prefix with a space before the argument.
+ elif test x$next_prefix = xyes; then prefix=$arg; next_prefix=
+ # Handle --srcdir with a space before the argument.
+ elif test x$next_srcdir = xyes; then srcdir=$arg; next_srcdir=
+ else
+ case $arg in
+ # For backward compatibility, also recognize exact --exec_prefix.
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* | --exe=* | --ex=* | --e=*)
+ exec_prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e)
+ next_exec_prefix=yes ;;
+
+ -gas | --gas | --ga | --g) ;;
+
+ -host=* | --host=* | --hos=* | --ho=* | --h=*) ;;
+ -host | --host | --hos | --ho | --h)
+ next_host=yes ;;
+
+ -nfp | --nfp | --nf) ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre | --no-cr | --no-c | --no- | --no)
+ no_create=1 ;;
+
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ next_prefix=yes ;;
+
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*)
+ srcdir=`echo $arg | sed 's/[-a-z_]*=//'` ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s)
+ next_srcdir=yes ;;
+
+ -with-* | --with-*)
+ package=`echo $arg|sed 's/-*with-//'`
+ # Delete all the valid chars; see if any are left.
+ if test -n "`echo $package|sed 's/[-a-zA-Z0-9_]*//g'`"; then
+ echo "configure: $package: invalid package name" >&2; exit 1
+ fi
+ eval "with_`echo $package|sed s/-/_/g`=1" ;;
+
+ *) ;;
+ esac
+ fi
+done
+
+trap 'rm -f conftest* core; exit 1' 1 3 15
+
+rm -f conftest*
+compile='${CC-cc} $CFLAGS $DEFS conftest.c -o conftest $LIBS >/dev/null 2>&1'
+
+# 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.
+unique_file=regex.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ srcdirdefaulted=yes
+ # Try the directory containing this script, then `..'.
+ prog=$0
+ confdir=`echo $prog|sed 's%/[^/][^/]*$%%'`
+ test "X$confdir" = "X$prog" && confdir=.
+ srcdir=$confdir
+ if test ! -r $srcdir/$unique_file; then
+ srcdir=..
+ fi
+fi
+if test ! -r $srcdir/$unique_file; then
+ if test x$srcdirdefaulted = xyes; then
+ echo "configure: Can not find sources in \`${confdir}' or \`..'." 1>&2
+ else
+ echo "configure: Can not find sources in \`${srcdir}'." 1>&2
+ fi
+ exit 1
+fi
+# Preserve a srcdir of `.' to avoid automounter screwups with pwd.
+# But we can't avoid them for `..', to make subdirectories work.
+case $srcdir in
+ .|/*|~*) ;;
+ *) srcdir=`cd $srcdir; pwd` ;; # Make relative path absolute.
+esac
+
+
+if test -z "$CC"; then
+ echo checking for gcc
+ saveifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/gcc; then
+ CC="gcc"
+ break
+ fi
+ done
+ IFS="$saveifs"
+fi
+test -z "$CC" && CC="cc"
+
+# Find out if we are using GNU C, under whatever name.
+cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes
+#endif
+EOF
+${CC-cc} -E conftest.c > conftest.out 2>&1
+if egrep yes conftest.out >/dev/null 2>&1; then
+ GCC=1 # For later tests.
+fi
+rm -f conftest*
+
+# Make sure to not get the incompatible SysV /etc/install and
+# /usr/sbin/install, which might be in PATH before a BSD-like install,
+# or the SunOS /usr/etc/install directory, or the AIX /bin/install,
+# or the AFS install, which mishandles nonexistent args. (Sigh.)
+if test -z "$INSTALL"; then
+ echo checking for install
+ saveifs="$IFS"; IFS="${IFS}:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ case $dir in
+ /etc|/usr/sbin|/usr/etc|/usr/afsws/bin) ;;
+ *)
+ if test -f $dir/install; then
+ if grep dspmsg $dir/install >/dev/null 2>&1; then
+ : # AIX
+ else
+ INSTALL="$dir/install -c"
+ INSTALL_PROGRAM='$(INSTALL)'
+ INSTALL_DATA='$(INSTALL) -m 644'
+ break
+ fi
+ fi
+ ;;
+ esac
+ done
+ IFS="$saveifs"
+fi
+INSTALL=${INSTALL-cp}
+INSTALL_PROGRAM=${INSTALL_PROGRAM-'$(INSTALL)'}
+INSTALL_DATA=${INSTALL_DATA-'$(INSTALL)'}
+
+
+echo checking for AIX
+echo checking how to run the C preprocessor
+if test -z "$CPP"; then
+ CPP='${CC-cc} -E'
+ cat > conftest.c <<EOF
+#include <stdio.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ :
+else
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+
+cat > conftest.c <<EOF
+#ifdef _AIX
+ yes
+#endif
+
+EOF
+eval "$CPP $DEFS conftest.c > conftest.out 2>&1"
+if egrep "yes" conftest.out >/dev/null 2>&1; then
+ DEFS="$DEFS -D_ALL_SOURCE=1"
+fi
+rm -f conftest*
+
+
+echo checking for DYNIX/ptx libseq
+cat > conftest.c <<EOF
+#if defined(_SEQUENT_)
+ yes
+#endif
+
+EOF
+eval "$CPP $DEFS conftest.c > conftest.out 2>&1"
+if egrep "yes" conftest.out >/dev/null 2>&1; then
+ SEQUENT=1
+fi
+rm -f conftest*
+
+test -n "$SEQUENT" && test -f /usr/lib/libseq.a &&
+ LIBS="$LIBS -lseq"
+
+echo checking for POSIXized ISC
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ ISC=1 # If later tests want to check for ISC.
+ DEFS="$DEFS -D_POSIX_SOURCE=1"
+ if test -n "$GCC"; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+fi
+
+echo checking for minix/config.h
+cat > conftest.c <<EOF
+#include <minix/config.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ MINIX=1
+fi
+rm -f conftest*
+
+# The Minix shell can't assign to the same variable on the same line!
+if test -n "$MINIX"; then
+ DEFS="$DEFS -D_POSIX_SOURCE=1"
+ DEFS="$DEFS -D_POSIX_1_SOURCE=2"
+ DEFS="$DEFS -D_MINIX=1"
+fi
+
+
+echo checking for ANSI C header files
+cat > conftest.c <<EOF
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ # SunOS string.h does not declare mem*, contrary to ANSI.
+echo '#include <string.h>' > conftest.c
+eval "$CPP $DEFS conftest.c > conftest.out 2>&1"
+if egrep "memchr" conftest.out >/dev/null 2>&1; then
+ # SGI's /bin/cc from Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+cat > conftest.c <<EOF
+#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
+eval $compile
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ DEFS="$DEFS -DSTDC_HEADERS=1"
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+for hdr in string.h
+do
+trhdr=HAVE_`echo $hdr | tr '[a-z]./' '[A-Z]__'`
+echo checking for ${hdr}
+cat > conftest.c <<EOF
+#include <${hdr}>
+EOF
+err=`eval "$CPP $DEFS conftest.c 2>&1 >/dev/null"`
+if test -z "$err"; then
+ DEFS="$DEFS -D${trhdr}=1"
+fi
+rm -f conftest*
+done
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo checking for working alloca.h
+cat > conftest.c <<EOF
+#include <alloca.h>
+main() { exit(0); }
+t() { char *p = alloca(2 * sizeof(int)); }
+EOF
+if eval $compile; then
+ DEFS="$DEFS -DHAVE_ALLOCA_H=1"
+fi
+rm -f conftest*
+
+decl="#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else
+#ifdef _AIX
+ #pragma alloca
+#else
+char *alloca ();
+#endif
+#endif
+#endif
+"
+echo checking for alloca
+cat > conftest.c <<EOF
+$decl
+main() { exit(0); }
+t() { char *p = (char *) alloca(1); }
+EOF
+if eval $compile; then
+ :
+else
+ alloca_missing=1
+fi
+rm -f conftest*
+
+if test -n "$alloca_missing"; 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.o
+fi
+
+prog='/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *p;
+char **p2;
+/* HPUX 7.0 cc rejects these. */
+++p;
+p2 = (char const* const*) p;'
+echo checking for working const
+cat > conftest.c <<EOF
+
+main() { exit(0); }
+t() { $prog }
+EOF
+if eval $compile; then
+ :
+else
+ DEFS="$DEFS -Dconst="
+fi
+rm -f conftest*
+
+
+if test -z "$prefix"
+then
+ echo checking for gcc to derive installation directory prefix
+ saveifs="$IFS"; IFS="$IFS:"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test $dir != . && test -f $dir/gcc; then
+ # Not all systems have dirname.
+ prefix=`echo $dir|sed 's%/[^/][^/]*$%%'`
+ break
+ fi
+ done
+ IFS="$saveifs"
+fi
+
+
+if test -n "$prefix"; then
+ test -z "$exec_prefix" && exec_prefix='${prefix}'
+ prsub="s%^prefix\\([ ]*\\)=\\([ ]*\\).*$%prefix\\1=\\2$prefix%"
+fi
+if test -n "$exec_prefix"; then
+ prsub="$prsub
+s%^exec_prefix\\([ ]*\\)=\\([ ]*\\).*$%\
+exec_prefix\\1=\\2$exec_prefix%"
+fi
+
+trap 'rm -f config.status; exit 1' 1 3 15
+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`:
+#
+# $0 $*
+
+for arg
+do
+ case "\$arg" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ exec /bin/sh $0 $* ;;
+ *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;;
+ esac
+done
+
+trap 'rm -f Makefile doc/Makefile test/Makefile; exit 1' 1 3 15
+CC='$CC'
+INSTALL='$INSTALL'
+INSTALL_PROGRAM='$INSTALL_PROGRAM'
+INSTALL_DATA='$INSTALL_DATA'
+CPP='$CPP'
+ALLOCA='$ALLOCA'
+LIBS='$LIBS'
+srcdir='$srcdir'
+DEFS='$DEFS'
+prefix='$prefix'
+exec_prefix='$exec_prefix'
+prsub='$prsub'
+EOF
+cat >> config.status <<\EOF
+
+top_srcdir=$srcdir
+for file in .. Makefile doc/Makefile test/Makefile; do if [ "x$file" != "x.." ]; then
+ srcdir=$top_srcdir
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ dir=`echo $file|sed 's%/[^/][^/]*$%%'`
+ if test "$dir" != "$file"; then
+ test "$top_srcdir" != . && srcdir=$top_srcdir/$dir
+ test ! -d $dir && mkdir $dir
+ fi
+ echo creating $file
+ rm -f $file
+ echo "# Generated automatically from `echo $file|sed 's|.*/||'`.in by configure." > $file
+ sed -e "
+$prsub
+s%@CC@%$CC%g
+s%@INSTALL@%$INSTALL%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@CPP@%$CPP%g
+s%@ALLOCA@%$ALLOCA%g
+s%@LIBS@%$LIBS%g
+s%@srcdir@%$srcdir%g
+s%@DEFS@%$DEFS%
+" $top_srcdir/${file}.in >> $file
+fi; done
+
+exit 0
+EOF
+chmod +x config.status
+test -n "$no_create" || ./config.status
+
diff --git a/gnu/lib/libregex/configure.in b/gnu/lib/libregex/configure.in
new file mode 100644
index 0000000..f0fc780
--- /dev/null
+++ b/gnu/lib/libregex/configure.in
@@ -0,0 +1,23 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(regex.c)
+
+AC_PROG_CC
+AC_PROG_INSTALL
+
+dnl I'm not sure if AC_AIX and AC_DYNIX_SEQ are really necessary. The
+dnl Autoconf documentation isn't specific about which BSD functions they
+dnl provide.
+AC_AIX
+AC_DYNIX_SEQ
+AC_ISC_POSIX
+AC_MINIX
+
+AC_STDC_HEADERS
+AC_HAVE_HEADERS(string.h)
+
+AC_ALLOCA
+AC_CONST
+
+AC_PREFIX(gcc)
+
+AC_OUTPUT(Makefile doc/Makefile test/Makefile)
diff --git a/gnu/lib/libregex/doc/Makefile b/gnu/lib/libregex/doc/Makefile
new file mode 100644
index 0000000..b812f44
--- /dev/null
+++ b/gnu/lib/libregex/doc/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+INFO = regex
+INFOSECTION= "Programming & development tools."
+INFOENTRY_regex= "* Regex: (regex). Regular expression library."
+
+CLEANFILES += regex.texi
+
+regex.texi: xregex.texi ../regex.h
+ awk -f ${.CURDIR}/include.awk -v source=${.CURDIR}/../regex.h \
+ < ${.CURDIR}/xregex.texi \
+ | expand >$@
+
+.include <bsd.info.mk>
diff --git a/gnu/lib/libregex/doc/include.awk b/gnu/lib/libregex/doc/include.awk
new file mode 100644
index 0000000..a1df3f8
--- /dev/null
+++ b/gnu/lib/libregex/doc/include.awk
@@ -0,0 +1,19 @@
+# Assume `source' is set with -vsource=filename on the command line.
+#
+/^\[\[\[/ { inclusion = $2; # name of the thing to include.
+ printing = 0;
+ while ((getline line < source) > 0)
+ {
+ if (match (line, "\\[\\[\\[end " inclusion "\\]\\]\\]"))
+ printing = 0;
+
+ if (printing)
+ print line;
+
+ if (match (line,"\\[\\[\\[begin " inclusion "\\]\\]\\]"))
+ printing = 1;
+ }
+ close (source);
+ next;
+ }
+ { print }
diff --git a/gnu/lib/libregex/doc/xregex.texi b/gnu/lib/libregex/doc/xregex.texi
new file mode 100644
index 0000000..fe01e4e
--- /dev/null
+++ b/gnu/lib/libregex/doc/xregex.texi
@@ -0,0 +1,3021 @@
+\input texinfo
+@c %**start of header
+@setfilename regex.info
+@settitle Regex
+@c %**end of header
+
+@c \\{fill-paragraph} works better (for me, anyway) if the text in the
+@c source file isn't indented.
+@paragraphindent 2
+
+@c Define a new index for our magic constants.
+@defcodeindex cn
+
+@c Put everything in one index (arbitrarily chosen to be the concept index).
+@syncodeindex cn cp
+@syncodeindex ky cp
+@syncodeindex pg cp
+@syncodeindex tp cp
+@syncodeindex vr cp
+
+@c Here is what we use in the Info `dir' file:
+@c * Regex: (regex). Regular expression library.
+
+
+@ifinfo
+This file documents the GNU regular expression library.
+
+Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and provided that the entire resulting derived work is
+distributed under the terms of a permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' may be
+included in a translation approved by the Free Software Foundation
+instead of in the original English.
+@end ifinfo
+
+
+@titlepage
+
+@title Regex
+@subtitle edition 0.12a
+@subtitle 19 September 1992
+@author Kathryn A. Hargreaves
+@author Karl Berry
+
+@page
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992 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.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and provided that the entire resulting derived work is
+distributed under the terms of a permission notice identical to this
+one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' may be
+included in a translation approved by the Free Software Foundation
+instead of in the original English.
+
+@end titlepage
+
+
+@ifinfo
+@node Top, Overview, (dir), (dir)
+@top Regular Expression Library
+
+This manual documents how to program with the GNU regular expression
+library. This is edition 0.12a of the manual, 19 September 1992.
+
+The first part of this master menu lists the major nodes in this Info
+document, including the index. The rest of the menu lists all the
+lower level nodes in the document.
+
+@menu
+* Overview::
+* Regular Expression Syntax::
+* Common Operators::
+* GNU Operators::
+* GNU Emacs Operators::
+* What Gets Matched?::
+* Programming with Regex::
+* Copying:: Copying and sharing Regex.
+* Index:: General index.
+ --- The Detailed Node Listing ---
+
+Regular Expression Syntax
+
+* Syntax Bits::
+* Predefined Syntaxes::
+* Collating Elements vs. Characters::
+* The Backslash Character::
+
+Common Operators
+
+* Match-self Operator:: Ordinary characters.
+* Match-any-character Operator:: .
+* Concatenation Operator:: Juxtaposition.
+* Repetition Operators:: * + ? @{@}
+* Alternation Operator:: |
+* List Operators:: [...] [^...]
+* Grouping Operators:: (...)
+* Back-reference Operator:: \digit
+* Anchoring Operators:: ^ $
+
+Repetition Operators
+
+* Match-zero-or-more Operator:: *
+* Match-one-or-more Operator:: +
+* Match-zero-or-one Operator:: ?
+* Interval Operators:: @{@}
+
+List Operators (@code{[} @dots{} @code{]} and @code{[^} @dots{} @code{]})
+
+* Character Class Operators:: [:class:]
+* Range Operator:: start-end
+
+Anchoring Operators
+
+* Match-beginning-of-line Operator:: ^
+* Match-end-of-line Operator:: $
+
+GNU Operators
+
+* Word Operators::
+* Buffer Operators::
+
+Word Operators
+
+* Non-Emacs Syntax Tables::
+* Match-word-boundary Operator:: \b
+* Match-within-word Operator:: \B
+* Match-beginning-of-word Operator:: \<
+* Match-end-of-word Operator:: \>
+* Match-word-constituent Operator:: \w
+* Match-non-word-constituent Operator:: \W
+
+Buffer Operators
+
+* Match-beginning-of-buffer Operator:: \`
+* Match-end-of-buffer Operator:: \'
+
+GNU Emacs Operators
+
+* Syntactic Class Operators::
+
+Syntactic Class Operators
+
+* Emacs Syntax Tables::
+* Match-syntactic-class Operator:: \sCLASS
+* Match-not-syntactic-class Operator:: \SCLASS
+
+Programming with Regex
+
+* GNU Regex Functions::
+* POSIX Regex Functions::
+* BSD Regex Functions::
+
+GNU Regex Functions
+
+* GNU Pattern Buffers:: The re_pattern_buffer type.
+* GNU Regular Expression Compiling:: re_compile_pattern ()
+* GNU Matching:: re_match ()
+* GNU Searching:: re_search ()
+* Matching/Searching with Split Data:: re_match_2 (), re_search_2 ()
+* Searching with Fastmaps:: re_compile_fastmap ()
+* GNU Translate Tables:: The `translate' field.
+* Using Registers:: The re_registers type and related fns.
+* Freeing GNU Pattern Buffers:: regfree ()
+
+POSIX Regex Functions
+
+* POSIX Pattern Buffers:: The regex_t type.
+* POSIX Regular Expression Compiling:: regcomp ()
+* POSIX Matching:: regexec ()
+* Reporting Errors:: regerror ()
+* Using Byte Offsets:: The regmatch_t type.
+* Freeing POSIX Pattern Buffers:: regfree ()
+
+BSD Regex Functions
+
+* BSD Regular Expression Compiling:: re_comp ()
+* BSD Searching:: re_exec ()
+@end menu
+@end ifinfo
+@node Overview, Regular Expression Syntax, Top, Top
+@chapter Overview
+
+A @dfn{regular expression} (or @dfn{regexp}, or @dfn{pattern}) is a text
+string that describes some (mathematical) set of strings. A regexp
+@var{r} @dfn{matches} a string @var{s} if @var{s} is in the set of
+strings described by @var{r}.
+
+Using the Regex library, you can:
+
+@itemize @bullet
+
+@item
+see if a string matches a specified pattern as a whole, and
+
+@item
+search within a string for a substring matching a specified pattern.
+
+@end itemize
+
+Some regular expressions match only one string, i.e., the set they
+describe has only one member. For example, the regular expression
+@samp{foo} matches the string @samp{foo} and no others. Other regular
+expressions match more than one string, i.e., the set they describe has
+more than one member. For example, the regular expression @samp{f*}
+matches the set of strings made up of any number (including zero) of
+@samp{f}s. As you can see, some characters in regular expressions match
+themselves (such as @samp{f}) and some don't (such as @samp{*}); the
+ones that don't match themselves instead let you specify patterns that
+describe many different strings.
+
+To either match or search for a regular expression with the Regex
+library functions, you must first compile it with a Regex pattern
+compiling function. A @dfn{compiled pattern} is a regular expression
+converted to the internal format used by the library functions. Once
+you've compiled a pattern, you can use it for matching or searching any
+number of times.
+
+The Regex library consists of two source files: @file{regex.h} and
+@file{regex.c}.
+@pindex regex.h
+@pindex regex.c
+Regex provides three groups of functions with which you can operate on
+regular expressions. One group---the @sc{gnu} group---is more powerful
+but not completely compatible with the other two, namely the @sc{posix}
+and Berkeley @sc{unix} groups; its interface was designed specifically
+for @sc{gnu}. The other groups have the same interfaces as do the
+regular expression functions in @sc{posix} and Berkeley
+@sc{unix}.
+
+We wrote this chapter with programmers in mind, not users of
+programs---such as Emacs---that use Regex. We describe the Regex
+library in its entirety, not how to write regular expressions that a
+particular program understands.
+
+
+@node Regular Expression Syntax, Common Operators, Overview, Top
+@chapter Regular Expression Syntax
+
+@cindex regular expressions, syntax of
+@cindex syntax of regular expressions
+
+@dfn{Characters} are things you can type. @dfn{Operators} are things in
+a regular expression that match one or more characters. You compose
+regular expressions from operators, which in turn you specify using one
+or more characters.
+
+Most characters represent what we call the match-self operator, i.e.,
+they match themselves; we call these characters @dfn{ordinary}. Other
+characters represent either all or parts of fancier operators; e.g.,
+@samp{.} represents what we call the match-any-character operator
+(which, no surprise, matches (almost) any character); we call these
+characters @dfn{special}. Two different things determine what
+characters represent what operators:
+
+@enumerate
+@item
+the regular expression syntax your program has told the Regex library to
+recognize, and
+
+@item
+the context of the character in the regular expression.
+@end enumerate
+
+In the following sections, we describe these things in more detail.
+
+@menu
+* Syntax Bits::
+* Predefined Syntaxes::
+* Collating Elements vs. Characters::
+* The Backslash Character::
+@end menu
+
+
+@node Syntax Bits, Predefined Syntaxes, , Regular Expression Syntax
+@section Syntax Bits
+
+@cindex syntax bits
+
+In any particular syntax for regular expressions, some characters are
+always special, others are sometimes special, and others are never
+special. The particular syntax that Regex recognizes for a given
+regular expression depends on the value in the @code{syntax} field of
+the pattern buffer of that regular expression.
+
+You get a pattern buffer by compiling a regular expression. @xref{GNU
+Pattern Buffers}, and @ref{POSIX Pattern Buffers}, for more information
+on pattern buffers. @xref{GNU Regular Expression Compiling}, @ref{POSIX
+Regular Expression Compiling}, and @ref{BSD Regular Expression
+Compiling}, for more information on compiling.
+
+Regex considers the value of the @code{syntax} field to be a collection
+of bits; we refer to these bits as @dfn{syntax bits}. In most cases,
+they affect what characters represent what operators. We describe the
+meanings of the operators to which we refer in @ref{Common Operators},
+@ref{GNU Operators}, and @ref{GNU Emacs Operators}.
+
+For reference, here is the complete list of syntax bits, in alphabetical
+order:
+
+@table @code
+
+@cnindex RE_BACKSLASH_ESCAPE_IN_LIST
+@item RE_BACKSLASH_ESCAPE_IN_LISTS
+If this bit is set, then @samp{\} inside a list (@pxref{List Operators}
+quotes (makes ordinary, if it's special) the following character; if
+this bit isn't set, then @samp{\} is an ordinary character inside lists.
+(@xref{The Backslash Character}, for what `\' does outside of lists.)
+
+@cnindex RE_BK_PLUS_QM
+@item RE_BK_PLUS_QM
+If this bit is set, then @samp{\+} represents the match-one-or-more
+operator and @samp{\?} represents the match-zero-or-more operator; if
+this bit isn't set, then @samp{+} represents the match-one-or-more
+operator and @samp{?} represents the match-zero-or-one operator. This
+bit is irrelevant if @code{RE_LIMITED_OPS} is set.
+
+@cnindex RE_CHAR_CLASSES
+@item RE_CHAR_CLASSES
+If this bit is set, then you can use character classes in lists; if this
+bit isn't set, then you can't.
+
+@cnindex RE_CONTEXT_INDEP_ANCHORS
+@item RE_CONTEXT_INDEP_ANCHORS
+If this bit is set, then @samp{^} and @samp{$} are special anywhere outside
+a list; if this bit isn't set, then these characters are special only in
+certain contexts. @xref{Match-beginning-of-line Operator}, and
+@ref{Match-end-of-line Operator}.
+
+@cnindex RE_CONTEXT_INDEP_OPS
+@item RE_CONTEXT_INDEP_OPS
+If this bit is set, then certain characters are special anywhere outside
+a list; if this bit isn't set, then those characters are special only in
+some contexts and are ordinary elsewhere. Specifically, if this bit
+isn't set then @samp{*}, and (if the syntax bit @code{RE_LIMITED_OPS}
+isn't set) @samp{+} and @samp{?} (or @samp{\+} and @samp{\?}, depending
+on the syntax bit @code{RE_BK_PLUS_QM}) represent repetition operators
+only if they're not first in a regular expression or just after an
+open-group or alternation operator. The same holds for @samp{@{} (or
+@samp{\@{}, depending on the syntax bit @code{RE_NO_BK_BRACES}) if
+it is the beginning of a valid interval and the syntax bit
+@code{RE_INTERVALS} is set.
+
+@cnindex RE_CONTEXT_INVALID_OPS
+@item RE_CONTEXT_INVALID_OPS
+If this bit is set, then repetition and alternation operators can't be
+in certain positions within a regular expression. Specifically, the
+regular expression is invalid if it has:
+
+@itemize @bullet
+
+@item
+a repetition operator first in the regular expression or just after a
+match-beginning-of-line, open-group, or alternation operator; or
+
+@item
+an alternation operator first or last in the regular expression, just
+before a match-end-of-line operator, or just after an alternation or
+open-group operator.
+
+@end itemize
+
+If this bit isn't set, then you can put the characters representing the
+repetition and alternation characters anywhere in a regular expression.
+Whether or not they will in fact be operators in certain positions
+depends on other syntax bits.
+
+@cnindex RE_DOT_NEWLINE
+@item RE_DOT_NEWLINE
+If this bit is set, then the match-any-character operator matches
+a newline; if this bit isn't set, then it doesn't.
+
+@cnindex RE_DOT_NOT_NULL
+@item RE_DOT_NOT_NULL
+If this bit is set, then the match-any-character operator doesn't match
+a null character; if this bit isn't set, then it does.
+
+@cnindex RE_INTERVALS
+@item RE_INTERVALS
+If this bit is set, then Regex recognizes interval operators; if this bit
+isn't set, then it doesn't.
+
+@cnindex RE_LIMITED_OPS
+@item RE_LIMITED_OPS
+If this bit is set, then Regex doesn't recognize the match-one-or-more,
+match-zero-or-one or alternation operators; if this bit isn't set, then
+it does.
+
+@cnindex RE_NEWLINE_ALT
+@item RE_NEWLINE_ALT
+If this bit is set, then newline represents the alternation operator; if
+this bit isn't set, then newline is ordinary.
+
+@cnindex RE_NO_BK_BRACES
+@item RE_NO_BK_BRACES
+If this bit is set, then @samp{@{} represents the open-interval operator
+and @samp{@}} represents the close-interval operator; if this bit isn't
+set, then @samp{\@{} represents the open-interval operator and
+@samp{\@}} represents the close-interval operator. This bit is relevant
+only if @code{RE_INTERVALS} is set.
+
+@cnindex RE_NO_BK_PARENS
+@item RE_NO_BK_PARENS
+If this bit is set, then @samp{(} represents the open-group operator and
+@samp{)} represents the close-group operator; if this bit isn't set, then
+@samp{\(} represents the open-group operator and @samp{\)} represents
+the close-group operator.
+
+@cnindex RE_NO_BK_REFS
+@item RE_NO_BK_REFS
+If this bit is set, then Regex doesn't recognize @samp{\}@var{digit} as
+the back reference operator; if this bit isn't set, then it does.
+
+@cnindex RE_NO_BK_VBAR
+@item RE_NO_BK_VBAR
+If this bit is set, then @samp{|} represents the alternation operator;
+if this bit isn't set, then @samp{\|} represents the alternation
+operator. This bit is irrelevant if @code{RE_LIMITED_OPS} is set.
+
+@cnindex RE_NO_EMPTY_RANGES
+@item RE_NO_EMPTY_RANGES
+If this bit is set, then a regular expression with a range whose ending
+point collates lower than its starting point is invalid; if this bit
+isn't set, then Regex considers such a range to be empty.
+
+@cnindex RE_UNMATCHED_RIGHT_PAREN_ORD
+@item RE_UNMATCHED_RIGHT_PAREN_ORD
+If this bit is set and the regular expression has no matching open-group
+operator, then Regex considers what would otherwise be a close-group
+operator (based on how @code{RE_NO_BK_PARENS} is set) to match @samp{)}.
+
+@end table
+
+
+@node Predefined Syntaxes, Collating Elements vs. Characters, Syntax Bits, Regular Expression Syntax
+@section Predefined Syntaxes
+
+If you're programming with Regex, you can set a pattern buffer's
+(@pxref{GNU Pattern Buffers}, and @ref{POSIX Pattern Buffers})
+@code{syntax} field either to an arbitrary combination of syntax bits
+(@pxref{Syntax Bits}) or else to the configurations defined by Regex.
+These configurations define the syntaxes used by certain
+programs---@sc{gnu} Emacs,
+@cindex Emacs
+@sc{posix} Awk,
+@cindex POSIX Awk
+traditional Awk,
+@cindex Awk
+Grep,
+@cindex Grep
+@cindex Egrep
+Egrep---in addition to syntaxes for @sc{posix} basic and extended
+regular expressions.
+
+The predefined syntaxes--taken directly from @file{regex.h}---are:
+
+@example
+[[[ syntaxes ]]]
+@end example
+
+@node Collating Elements vs. Characters, The Backslash Character, Predefined Syntaxes, Regular Expression Syntax
+@section Collating Elements vs.@: Characters
+
+@sc{posix} generalizes the notion of a character to that of a
+collating element. It defines a @dfn{collating element} to be ``a
+sequence of one or more bytes defined in the current collating sequence
+as a unit of collation.''
+
+This generalizes the notion of a character in
+two ways. First, a single character can map into two or more collating
+elements. For example, the German
+@tex
+`\ss'
+@end tex
+@ifinfo
+``es-zet''
+@end ifinfo
+collates as the collating element @samp{s} followed by another collating
+element @samp{s}. Second, two or more characters can map into one
+collating element. For example, the Spanish @samp{ll} collates after
+@samp{l} and before @samp{m}.
+
+Since @sc{posix}'s ``collating element'' preserves the essential idea of
+a ``character,'' we use the latter, more familiar, term in this document.
+
+@node The Backslash Character, , Collating Elements vs. Characters, Regular Expression Syntax
+@section The Backslash Character
+
+@cindex \
+The @samp{\} character has one of four different meanings, depending on
+the context in which you use it and what syntax bits are set
+(@pxref{Syntax Bits}). It can: 1) stand for itself, 2) quote the next
+character, 3) introduce an operator, or 4) do nothing.
+
+@enumerate
+@item
+It stands for itself inside a list
+(@pxref{List Operators}) if the syntax bit
+@code{RE_BACKSLASH_ESCAPE_IN_LISTS} is not set. For example, @samp{[\]}
+would match @samp{\}.
+
+@item
+It quotes (makes ordinary, if it's special) the next character when you
+use it either:
+
+@itemize @bullet
+@item
+outside a list,@footnote{Sometimes
+you don't have to explicitly quote special characters to make
+them ordinary. For instance, most characters lose any special meaning
+inside a list (@pxref{List Operators}). In addition, if the syntax bits
+@code{RE_CONTEXT_INVALID_OPS} and @code{RE_CONTEXT_INDEP_OPS}
+aren't set, then (for historical reasons) the matcher considers special
+characters ordinary if they are in contexts where the operations they
+represent make no sense; for example, then the match-zero-or-more
+operator (represented by @samp{*}) matches itself in the regular
+expression @samp{*foo} because there is no preceding expression on which
+it can operate. It is poor practice, however, to depend on this
+behavior; if you want a special character to be ordinary outside a list,
+it's better to always quote it, regardless.} or
+
+@item
+inside a list and the syntax bit @code{RE_BACKSLASH_ESCAPE_IN_LISTS} is set.
+
+@end itemize
+
+@item
+It introduces an operator when followed by certain ordinary
+characters---sometimes only when certain syntax bits are set. See the
+cases @code{RE_BK_PLUS_QM}, @code{RE_NO_BK_BRACES}, @code{RE_NO_BK_VAR},
+@code{RE_NO_BK_PARENS}, @code{RE_NO_BK_REF} in @ref{Syntax Bits}. Also:
+
+@itemize @bullet
+@item
+@samp{\b} represents the match-word-boundary operator
+(@pxref{Match-word-boundary Operator}).
+
+@item
+@samp{\B} represents the match-within-word operator
+(@pxref{Match-within-word Operator}).
+
+@item
+@samp{\<} represents the match-beginning-of-word operator @*
+(@pxref{Match-beginning-of-word Operator}).
+
+@item
+@samp{\>} represents the match-end-of-word operator
+(@pxref{Match-end-of-word Operator}).
+
+@item
+@samp{\w} represents the match-word-constituent operator
+(@pxref{Match-word-constituent Operator}).
+
+@item
+@samp{\W} represents the match-non-word-constituent operator
+(@pxref{Match-non-word-constituent Operator}).
+
+@item
+@samp{\`} represents the match-beginning-of-buffer
+operator and @samp{\'} represents the match-end-of-buffer operator
+(@pxref{Buffer Operators}).
+
+@item
+If Regex was compiled with the C preprocessor symbol @code{emacs}
+defined, then @samp{\s@var{class}} represents the match-syntactic-class
+operator and @samp{\S@var{class}} represents the
+match-not-syntactic-class operator (@pxref{Syntactic Class Operators}).
+
+@end itemize
+
+@item
+In all other cases, Regex ignores @samp{\}. For example,
+@samp{\n} matches @samp{n}.
+
+@end enumerate
+
+@node Common Operators, GNU Operators, Regular Expression Syntax, Top
+@chapter Common Operators
+
+You compose regular expressions from operators. In the following
+sections, we describe the regular expression operators specified by
+@sc{posix}; @sc{gnu} also uses these. Most operators have more than one
+representation as characters. @xref{Regular Expression Syntax}, for
+what characters represent what operators under what circumstances.
+
+For most operators that can be represented in two ways, one
+representation is a single character and the other is that character
+preceded by @samp{\}. For example, either @samp{(} or @samp{\(}
+represents the open-group operator. Which one does depends on the
+setting of a syntax bit, in this case @code{RE_NO_BK_PARENS}. Why is
+this so? Historical reasons dictate some of the varying
+representations, while @sc{posix} dictates others.
+
+Finally, almost all characters lose any special meaning inside a list
+(@pxref{List Operators}).
+
+@menu
+* Match-self Operator:: Ordinary characters.
+* Match-any-character Operator:: .
+* Concatenation Operator:: Juxtaposition.
+* Repetition Operators:: * + ? @{@}
+* Alternation Operator:: |
+* List Operators:: [...] [^...]
+* Grouping Operators:: (...)
+* Back-reference Operator:: \digit
+* Anchoring Operators:: ^ $
+@end menu
+
+@node Match-self Operator, Match-any-character Operator, , Common Operators
+@section The Match-self Operator (@var{ordinary character})
+
+This operator matches the character itself. All ordinary characters
+(@pxref{Regular Expression Syntax}) represent this operator. For
+example, @samp{f} is always an ordinary character, so the regular
+expression @samp{f} matches only the string @samp{f}. In
+particular, it does @emph{not} match the string @samp{ff}.
+
+@node Match-any-character Operator, Concatenation Operator, Match-self Operator, Common Operators
+@section The Match-any-character Operator (@code{.})
+
+@cindex @samp{.}
+
+This operator matches any single printing or nonprinting character
+except it won't match a:
+
+@table @asis
+@item newline
+if the syntax bit @code{RE_DOT_NEWLINE} isn't set.
+
+@item null
+if the syntax bit @code{RE_DOT_NOT_NULL} is set.
+
+@end table
+
+The @samp{.} (period) character represents this operator. For example,
+@samp{a.b} matches any three-character string beginning with @samp{a}
+and ending with @samp{b}.
+
+@node Concatenation Operator, Repetition Operators, Match-any-character Operator, Common Operators
+@section The Concatenation Operator
+
+This operator concatenates two regular expressions @var{a} and @var{b}.
+No character represents this operator; you simply put @var{b} after
+@var{a}. The result is a regular expression that will match a string if
+@var{a} matches its first part and @var{b} matches the rest. For
+example, @samp{xy} (two match-self operators) matches @samp{xy}.
+
+@node Repetition Operators, Alternation Operator, Concatenation Operator, Common Operators
+@section Repetition Operators
+
+Repetition operators repeat the preceding regular expression a specified
+number of times.
+
+@menu
+* Match-zero-or-more Operator:: *
+* Match-one-or-more Operator:: +
+* Match-zero-or-one Operator:: ?
+* Interval Operators:: @{@}
+@end menu
+
+@node Match-zero-or-more Operator, Match-one-or-more Operator, , Repetition Operators
+@subsection The Match-zero-or-more Operator (@code{*})
+
+@cindex @samp{*}
+
+This operator repeats the smallest possible preceding regular expression
+as many times as necessary (including zero) to match the pattern.
+@samp{*} represents this operator. For example, @samp{o*}
+matches any string made up of zero or more @samp{o}s. Since this
+operator operates on the smallest preceding regular expression,
+@samp{fo*} has a repeating @samp{o}, not a repeating @samp{fo}. So,
+@samp{fo*} matches @samp{f}, @samp{fo}, @samp{foo}, and so on.
+
+Since the match-zero-or-more operator is a suffix operator, it may be
+useless as such when no regular expression precedes it. This is the
+case when it:
+
+@itemize @bullet
+@item
+is first in a regular expression, or
+
+@item
+follows a match-beginning-of-line, open-group, or alternation
+operator.
+
+@end itemize
+
+@noindent
+Three different things can happen in these cases:
+
+@enumerate
+@item
+If the syntax bit @code{RE_CONTEXT_INVALID_OPS} is set, then the
+regular expression is invalid.
+
+@item
+If @code{RE_CONTEXT_INVALID_OPS} isn't set, but
+@code{RE_CONTEXT_INDEP_OPS} is, then @samp{*} represents the
+match-zero-or-more operator (which then operates on the empty string).
+
+@item
+Otherwise, @samp{*} is ordinary.
+
+@end enumerate
+
+@cindex backtracking
+The matcher processes a match-zero-or-more operator by first matching as
+many repetitions of the smallest preceding regular expression as it can.
+Then it continues to match the rest of the pattern.
+
+If it can't match the rest of the pattern, it backtracks (as many times
+as necessary), each time discarding one of the matches until it can
+either match the entire pattern or be certain that it cannot get a
+match. For example, when matching @samp{ca*ar} against @samp{caaar},
+the matcher first matches all three @samp{a}s of the string with the
+@samp{a*} of the regular expression. However, it cannot then match the
+final @samp{ar} of the regular expression against the final @samp{r} of
+the string. So it backtracks, discarding the match of the last @samp{a}
+in the string. It can then match the remaining @samp{ar}.
+
+
+@node Match-one-or-more Operator, Match-zero-or-one Operator, Match-zero-or-more Operator, Repetition Operators
+@subsection The Match-one-or-more Operator (@code{+} or @code{\+})
+
+@cindex @samp{+}
+
+If the syntax bit @code{RE_LIMITED_OPS} is set, then Regex doesn't recognize
+this operator. Otherwise, if the syntax bit @code{RE_BK_PLUS_QM} isn't
+set, then @samp{+} represents this operator; if it is, then @samp{\+}
+does.
+
+This operator is similar to the match-zero-or-more operator except that
+it repeats the preceding regular expression at least once;
+@pxref{Match-zero-or-more Operator}, for what it operates on, how some
+syntax bits affect it, and how Regex backtracks to match it.
+
+For example, supposing that @samp{+} represents the match-one-or-more
+operator; then @samp{ca+r} matches, e.g., @samp{car} and
+@samp{caaaar}, but not @samp{cr}.
+
+@node Match-zero-or-one Operator, Interval Operators, Match-one-or-more Operator, Repetition Operators
+@subsection The Match-zero-or-one Operator (@code{?} or @code{\?})
+@cindex @samp{?}
+
+If the syntax bit @code{RE_LIMITED_OPS} is set, then Regex doesn't
+recognize this operator. Otherwise, if the syntax bit
+@code{RE_BK_PLUS_QM} isn't set, then @samp{?} represents this operator;
+if it is, then @samp{\?} does.
+
+This operator is similar to the match-zero-or-more operator except that
+it repeats the preceding regular expression once or not at all;
+@pxref{Match-zero-or-more Operator}, to see what it operates on, how
+some syntax bits affect it, and how Regex backtracks to match it.
+
+For example, supposing that @samp{?} represents the match-zero-or-one
+operator; then @samp{ca?r} matches both @samp{car} and @samp{cr}, but
+nothing else.
+
+@node Interval Operators, , Match-zero-or-one Operator, Repetition Operators
+@subsection Interval Operators (@code{@{} @dots{} @code{@}} or @code{\@{} @dots{} @code{\@}})
+
+@cindex interval expression
+@cindex @samp{@{}
+@cindex @samp{@}}
+@cindex @samp{\@{}
+@cindex @samp{\@}}
+
+If the syntax bit @code{RE_INTERVALS} is set, then Regex recognizes
+@dfn{interval expressions}. They repeat the smallest possible preceding
+regular expression a specified number of times.
+
+If the syntax bit @code{RE_NO_BK_BRACES} is set, @samp{@{} represents
+the @dfn{open-interval operator} and @samp{@}} represents the
+@dfn{close-interval operator} ; otherwise, @samp{\@{} and @samp{\@}} do.
+
+Specifically, supposing that @samp{@{} and @samp{@}} represent the
+open-interval and close-interval operators; then:
+
+@table @code
+@item @{@var{count}@}
+matches exactly @var{count} occurrences of the preceding regular
+expression.
+
+@item @{@var{min,}@}
+matches @var{min} or more occurrences of the preceding regular
+expression.
+
+@item @{@var{min, max}@}
+matches at least @var{min} but no more than @var{max} occurrences of
+the preceding regular expression.
+
+@end table
+
+The interval expression (but not necessarily the regular expression that
+contains it) is invalid if:
+
+@itemize @bullet
+@item
+@var{min} is greater than @var{max}, or
+
+@item
+any of @var{count}, @var{min}, or @var{max} are outside the range
+zero to @code{RE_DUP_MAX} (which symbol @file{regex.h}
+defines).
+
+@end itemize
+
+If the interval expression is invalid and the syntax bit
+@code{RE_NO_BK_BRACES} is set, then Regex considers all the
+characters in the would-be interval to be ordinary. If that bit
+isn't set, then the regular expression is invalid.
+
+If the interval expression is valid but there is no preceding regular
+expression on which to operate, then if the syntax bit
+@code{RE_CONTEXT_INVALID_OPS} is set, the regular expression is invalid.
+If that bit isn't set, then Regex considers all the characters---other
+than backslashes, which it ignores---in the would-be interval to be
+ordinary.
+
+
+@node Alternation Operator, List Operators, Repetition Operators, Common Operators
+@section The Alternation Operator (@code{|} or @code{\|})
+
+@kindex |
+@kindex \|
+@cindex alternation operator
+@cindex or operator
+
+If the syntax bit @code{RE_LIMITED_OPS} is set, then Regex doesn't
+recognize this operator. Otherwise, if the syntax bit
+@code{RE_NO_BK_VBAR} is set, then @samp{|} represents this operator;
+otherwise, @samp{\|} does.
+
+Alternatives match one of a choice of regular expressions:
+if you put the character(s) representing the alternation operator between
+any two regular expressions @var{a} and @var{b}, the result matches
+the union of the strings that @var{a} and @var{b} match. For
+example, supposing that @samp{|} is the alternation operator, then
+@samp{foo|bar|quux} would match any of @samp{foo}, @samp{bar} or
+@samp{quux}.
+
+@ignore
+@c Nobody needs to disallow empty alternatives any more.
+If the syntax bit @code{RE_NO_EMPTY_ALTS} is set, then if either of the regular
+expressions @var{a} or @var{b} is empty, the
+regular expression is invalid. More precisely, if this syntax bit is
+set, then the alternation operator can't:
+
+@itemize @bullet
+@item
+be first or last in a regular expression;
+
+@item
+follow either another alternation operator or an open-group operator
+(@pxref{Grouping Operators}); or
+
+@item
+precede a close-group operator.
+
+@end itemize
+
+@noindent
+For example, supposing @samp{(} and @samp{)} represent the open and
+close-group operators, then @samp{|foo}, @samp{foo|}, @samp{foo||bar},
+@samp{foo(|bar)}, and @samp{(foo|)bar} would all be invalid.
+@end ignore
+
+The alternation operator operates on the @emph{largest} possible
+surrounding regular expressions. (Put another way, it has the lowest
+precedence of any regular expression operator.)
+Thus, the only way you can
+delimit its arguments is to use grouping. For example, if @samp{(} and
+@samp{)} are the open and close-group operators, then @samp{fo(o|b)ar}
+would match either @samp{fooar} or @samp{fobar}. (@samp{foo|bar} would
+match @samp{foo} or @samp{bar}.)
+
+@cindex backtracking
+The matcher usually tries all combinations of alternatives so as to
+match the longest possible string. For example, when matching
+@samp{(fooq|foo)*(qbarquux|bar)} against @samp{fooqbarquux}, it cannot
+take, say, the first (``depth-first'') combination it could match, since
+then it would be content to match just @samp{fooqbar}.
+
+@comment xx something about leftmost-longest
+
+
+@node List Operators, Grouping Operators, Alternation Operator, Common Operators
+@section List Operators (@code{[} @dots{} @code{]} and @code{[^} @dots{} @code{]})
+
+@cindex matching list
+@cindex @samp{[}
+@cindex @samp{]}
+@cindex @samp{^}
+@cindex @samp{-}
+@cindex @samp{\}
+@cindex @samp{[^}
+@cindex nonmatching list
+@cindex matching newline
+@cindex bracket expression
+
+@dfn{Lists}, also called @dfn{bracket expressions}, are a set of one or
+more items. An @dfn{item} is a character,
+@ignore
+(These get added when they get implemented.)
+a collating symbol, an equivalence class expression,
+@end ignore
+a character class expression, or a range expression. The syntax bits
+affect which kinds of items you can put in a list. We explain the last
+two items in subsections below. Empty lists are invalid.
+
+A @dfn{matching list} matches a single character represented by one of
+the list items. You form a matching list by enclosing one or more items
+within an @dfn{open-matching-list operator} (represented by @samp{[})
+and a @dfn{close-list operator} (represented by @samp{]}).
+
+For example, @samp{[ab]} matches either @samp{a} or @samp{b}.
+@samp{[ad]*} matches the empty string and any string composed of just
+@samp{a}s and @samp{d}s in any order. Regex considers invalid a regular
+expression with a @samp{[} but no matching
+@samp{]}.
+
+@dfn{Nonmatching lists} are similar to matching lists except that they
+match a single character @emph{not} represented by one of the list
+items. You use an @dfn{open-nonmatching-list operator} (represented by
+@samp{[^}@footnote{Regex therefore doesn't consider the @samp{^} to be
+the first character in the list. If you put a @samp{^} character first
+in (what you think is) a matching list, you'll turn it into a
+nonmatching list.}) instead of an open-matching-list operator to start a
+nonmatching list.
+
+For example, @samp{[^ab]} matches any character except @samp{a} or
+@samp{b}.
+
+If the @code{posix_newline} field in the pattern buffer (@pxref{GNU
+Pattern Buffers} is set, then nonmatching lists do not match a newline.
+
+Most characters lose any special meaning inside a list. The special
+characters inside a list follow.
+
+@table @samp
+@item ]
+ends the list if it's not the first list item. So, if you want to make
+the @samp{]} character a list item, you must put it first.
+
+@item \
+quotes the next character if the syntax bit @code{RE_BACKSLASH_ESCAPE_IN_LISTS} is
+set.
+
+@ignore
+Put these in if they get implemented.
+
+@item [.
+represents the open-collating-symbol operator (@pxref{Collating Symbol
+Operators}).
+
+@item .]
+represents the close-collating-symbol operator.
+
+@item [=
+represents the open-equivalence-class operator (@pxref{Equivalence Class
+Operators}).
+
+@item =]
+represents the close-equivalence-class operator.
+
+@end ignore
+
+@item [:
+represents the open-character-class operator (@pxref{Character Class
+Operators}) if the syntax bit @code{RE_CHAR_CLASSES} is set and what
+follows is a valid character class expression.
+
+@item :]
+represents the close-character-class operator if the syntax bit
+@code{RE_CHAR_CLASSES} is set and what precedes it is an
+open-character-class operator followed by a valid character class name.
+
+@item -
+represents the range operator (@pxref{Range Operator}) if it's
+not first or last in a list or the ending point of a range.
+
+@end table
+
+@noindent
+All other characters are ordinary. For example, @samp{[.*]} matches
+@samp{.} and @samp{*}.
+
+@menu
+* Character Class Operators:: [:class:]
+* Range Operator:: start-end
+@end menu
+
+@ignore
+(If collating symbols and equivalence class expressions get implemented,
+then add this.)
+
+node Collating Symbol Operators
+subsubsection Collating Symbol Operators (@code{[.} @dots{} @code{.]})
+
+If the syntax bit @code{XX} is set, then you can represent
+collating symbols inside lists. You form a @dfn{collating symbol} by
+putting a collating element between an @dfn{open-collating-symbol
+operator} and an @dfn{close-collating-symbol operator}. @samp{[.}
+represents the open-collating-symbol operator and @samp{.]} represents
+the close-collating-symbol operator. For example, if @samp{ll} is a
+collating element, then @samp{[[.ll.]]} would match @samp{ll}.
+
+node Equivalence Class Operators
+subsubsection Equivalence Class Operators (@code{[=} @dots{} @code{=]})
+@cindex equivalence class expression in regex
+@cindex @samp{[=} in regex
+@cindex @samp{=]} in regex
+
+If the syntax bit @code{XX} is set, then Regex recognizes equivalence class
+expressions inside lists. A @dfn{equivalence class expression} is a set
+of collating elements which all belong to the same equivalence class.
+You form an equivalence class expression by putting a collating
+element between an @dfn{open-equivalence-class operator} and a
+@dfn{close-equivalence-class operator}. @samp{[=} represents the
+open-equivalence-class operator and @samp{=]} represents the
+close-equivalence-class operator. For example, if @samp{a} and @samp{A}
+were an equivalence class, then both @samp{[[=a=]]} and @samp{[[=A=]]}
+would match both @samp{a} and @samp{A}. If the collating element in an
+equivalence class expression isn't part of an equivalence class, then
+the matcher considers the equivalence class expression to be a collating
+symbol.
+
+@end ignore
+
+@node Character Class Operators, Range Operator, , List Operators
+@subsection Character Class Operators (@code{[:} @dots{} @code{:]})
+
+@cindex character classes
+@cindex @samp{[:} in regex
+@cindex @samp{:]} in regex
+
+If the syntax bit @code{RE_CHARACTER_CLASSES} is set, then Regex
+recognizes character class expressions inside lists. A @dfn{character
+class expression} matches one character from a given class. You form a
+character class expression by putting a character class name between an
+@dfn{open-character-class operator} (represented by @samp{[:}) and a
+@dfn{close-character-class operator} (represented by @samp{:]}). The
+character class names and their meanings are:
+
+@table @code
+
+@item alnum
+letters and digits
+
+@item alpha
+letters
+
+@item blank
+system-dependent; for @sc{gnu}, a space or tab
+
+@item cntrl
+control characters (in the @sc{ascii} encoding, code 0177 and codes
+less than 040)
+
+@item digit
+digits
+
+@item graph
+same as @code{print} except omits space
+
+@item lower
+lowercase letters
+
+@item print
+printable characters (in the @sc{ascii} encoding, space
+tilde---codes 040 through 0176)
+
+@item punct
+neither control nor alphanumeric characters
+
+@item space
+space, carriage return, newline, vertical tab, and form feed
+
+@item upper
+uppercase letters
+
+@item xdigit
+hexadecimal digits: @code{0}--@code{9}, @code{a}--@code{f}, @code{A}--@code{F}
+
+@end table
+
+@noindent
+These correspond to the definitions in the C library's @file{<ctype.h>}
+facility. For example, @samp{[:alpha:]} corresponds to the standard
+facility @code{isalpha}. Regex recognizes character class expressions
+only inside of lists; so @samp{[[:alpha:]]} matches any letter, but
+@samp{[:alpha:]} outside of a bracket expression and not followed by a
+repetition operator matches just itself.
+
+@node Range Operator, , Character Class Operators, List Operators
+@subsection The Range Operator (@code{-})
+
+Regex recognizes @dfn{range expressions} inside a list. They represent
+those characters
+that fall between two elements in the current collating sequence. You
+form a range expression by putting a @dfn{range operator} between two
+@ignore
+(If these get implemented, then substitute this for ``characters.'')
+of any of the following: characters, collating elements, collating symbols,
+and equivalence class expressions. The starting point of the range and
+the ending point of the range don't have to be the same kind of item,
+e.g., the starting point could be a collating element and the ending
+point could be an equivalence class expression. If a range's ending
+point is an equivalence class, then all the collating elements in that
+class will be in the range.
+@end ignore
+characters.@footnote{You can't use a character class for the starting
+or ending point of a range, since a character class is not a single
+character.} @samp{-} represents the range operator. For example,
+@samp{a-f} within a list represents all the characters from @samp{a}
+through @samp{f}
+inclusively.
+
+If the syntax bit @code{RE_NO_EMPTY_RANGES} is set, then if the range's
+ending point collates less than its starting point, the range (and the
+regular expression containing it) is invalid. For example, the regular
+expression @samp{[z-a]} would be invalid. If this bit isn't set, then
+Regex considers such a range to be empty.
+
+Since @samp{-} represents the range operator, if you want to make a
+@samp{-} character itself
+a list item, you must do one of the following:
+
+@itemize @bullet
+@item
+Put the @samp{-} either first or last in the list.
+
+@item
+Include a range whose starting point collates strictly lower than
+@samp{-} and whose ending point collates equal or higher. Unless a
+range is the first item in a list, a @samp{-} can't be its starting
+point, but @emph{can} be its ending point. That is because Regex
+considers @samp{-} to be the range operator unless it is preceded by
+another @samp{-}. For example, in the @sc{ascii} encoding, @samp{)},
+@samp{*}, @samp{+}, @samp{,}, @samp{-}, @samp{.}, and @samp{/} are
+contiguous characters in the collating sequence. You might think that
+@samp{[)-+--/]} has two ranges: @samp{)-+} and @samp{--/}. Rather, it
+has the ranges @samp{)-+} and @samp{+--}, plus the character @samp{/}, so
+it matches, e.g., @samp{,}, not @samp{.}.
+
+@item
+Put a range whose starting point is @samp{-} first in the list.
+
+@end itemize
+
+For example, @samp{[-a-z]} matches a lowercase letter or a hyphen (in
+English, in @sc{ascii}).
+
+
+@node Grouping Operators, Back-reference Operator, List Operators, Common Operators
+@section Grouping Operators (@code{(} @dots{} @code{)} or @code{\(} @dots{} @code{\)})
+
+@kindex (
+@kindex )
+@kindex \(
+@kindex \)
+@cindex grouping
+@cindex subexpressions
+@cindex parenthesizing
+
+A @dfn{group}, also known as a @dfn{subexpression}, consists of an
+@dfn{open-group operator}, any number of other operators, and a
+@dfn{close-group operator}. Regex treats this sequence as a unit, just
+as mathematics and programming languages treat a parenthesized
+expression as a unit.
+
+Therefore, using @dfn{groups}, you can:
+
+@itemize @bullet
+@item
+delimit the argument(s) to an alternation operator (@pxref{Alternation
+Operator}) or a repetition operator (@pxref{Repetition
+Operators}).
+
+@item
+keep track of the indices of the substring that matched a given group.
+@xref{Using Registers}, for a precise explanation.
+This lets you:
+
+@itemize @bullet
+@item
+use the back-reference operator (@pxref{Back-reference Operator}).
+
+@item
+use registers (@pxref{Using Registers}).
+
+@end itemize
+
+@end itemize
+
+If the syntax bit @code{RE_NO_BK_PARENS} is set, then @samp{(} represents
+the open-group operator and @samp{)} represents the
+close-group operator; otherwise, @samp{\(} and @samp{\)} do.
+
+If the syntax bit @code{RE_UNMATCHED_RIGHT_PAREN_ORD} is set and a
+close-group operator has no matching open-group operator, then Regex
+considers it to match @samp{)}.
+
+
+@node Back-reference Operator, Anchoring Operators, Grouping Operators, Common Operators
+@section The Back-reference Operator (@dfn{\}@var{digit})
+
+@cindex back references
+
+If the syntax bit @code{RE_NO_BK_REF} isn't set, then Regex recognizes
+back references. A back reference matches a specified preceding group.
+The back reference operator is represented by @samp{\@var{digit}}
+anywhere after the end of a regular expression's @w{@var{digit}-th}
+group (@pxref{Grouping Operators}).
+
+@var{digit} must be between @samp{1} and @samp{9}. The matcher assigns
+numbers 1 through 9 to the first nine groups it encounters. By using
+one of @samp{\1} through @samp{\9} after the corresponding group's
+close-group operator, you can match a substring identical to the
+one that the group does.
+
+Back references match according to the following (in all examples below,
+@samp{(} represents the open-group, @samp{)} the close-group, @samp{@{}
+the open-interval and @samp{@}} the close-interval operator):
+
+@itemize @bullet
+@item
+If the group matches a substring, the back reference matches an
+identical substring. For example, @samp{(a)\1} matches @samp{aa} and
+@samp{(bana)na\1bo\1} matches @samp{bananabanabobana}. Likewise,
+@samp{(.*)\1} matches any (newline-free if the syntax bit
+@code{RE_DOT_NEWLINE} isn't set) string that is composed of two
+identical halves; the @samp{(.*)} matches the first half and the
+@samp{\1} matches the second half.
+
+@item
+If the group matches more than once (as it might if followed
+by, e.g., a repetition operator), then the back reference matches the
+substring the group @emph{last} matched. For example,
+@samp{((a*)b)*\1\2} matches @samp{aabababa}; first @w{group 1} (the
+outer one) matches @samp{aab} and @w{group 2} (the inner one) matches
+@samp{aa}. Then @w{group 1} matches @samp{ab} and @w{group 2} matches
+@samp{a}. So, @samp{\1} matches @samp{ab} and @samp{\2} matches
+@samp{a}.
+
+@item
+If the group doesn't participate in a match, i.e., it is part of an
+alternative not taken or a repetition operator allows zero repetitions
+of it, then the back reference makes the whole match fail. For example,
+@samp{(one()|two())-and-(three\2|four\3)} matches @samp{one-and-three}
+and @samp{two-and-four}, but not @samp{one-and-four} or
+@samp{two-and-three}. For example, if the pattern matches
+@samp{one-and-}, then its @w{group 2} matches the empty string and its
+@w{group 3} doesn't participate in the match. So, if it then matches
+@samp{four}, then when it tries to back reference @w{group 3}---which it
+will attempt to do because @samp{\3} follows the @samp{four}---the match
+will fail because @w{group 3} didn't participate in the match.
+
+@end itemize
+
+You can use a back reference as an argument to a repetition operator. For
+example, @samp{(a(b))\2*} matches @samp{a} followed by two or more
+@samp{b}s. Similarly, @samp{(a(b))\2@{3@}} matches @samp{abbbb}.
+
+If there is no preceding @w{@var{digit}-th} subexpression, the regular
+expression is invalid.
+
+
+@node Anchoring Operators, , Back-reference Operator, Common Operators
+@section Anchoring Operators
+
+@cindex anchoring
+@cindex regexp anchoring
+
+These operators can constrain a pattern to match only at the beginning or
+end of the entire string or at the beginning or end of a line.
+
+@menu
+* Match-beginning-of-line Operator:: ^
+* Match-end-of-line Operator:: $
+@end menu
+
+
+@node Match-beginning-of-line Operator, Match-end-of-line Operator, , Anchoring Operators
+@subsection The Match-beginning-of-line Operator (@code{^})
+
+@kindex ^
+@cindex beginning-of-line operator
+@cindex anchors
+
+This operator can match the empty string either at the beginning of the
+string or after a newline character. Thus, it is said to @dfn{anchor}
+the pattern to the beginning of a line.
+
+In the cases following, @samp{^} represents this operator. (Otherwise,
+@samp{^} is ordinary.)
+
+@itemize @bullet
+
+@item
+It (the @samp{^}) is first in the pattern, as in @samp{^foo}.
+
+@cnindex RE_CONTEXT_INDEP_ANCHORS @r{(and @samp{^})}
+@item
+The syntax bit @code{RE_CONTEXT_INDEP_ANCHORS} is set, and it is outside
+a bracket expression.
+
+@cindex open-group operator and @samp{^}
+@cindex alternation operator and @samp{^}
+@item
+It follows an open-group or alternation operator, as in @samp{a\(^b\)}
+and @samp{a\|^b}. @xref{Grouping Operators}, and @ref{Alternation
+Operator}.
+
+@end itemize
+
+These rules imply that some valid patterns containing @samp{^} cannot be
+matched; for example, @samp{foo^bar} if @code{RE_CONTEXT_INDEP_ANCHORS}
+is set.
+
+@vindex not_bol @r{field in pattern buffer}
+If the @code{not_bol} field is set in the pattern buffer (@pxref{GNU
+Pattern Buffers}), then @samp{^} fails to match at the beginning of the
+string. @xref{POSIX Matching}, for when you might find this useful.
+
+@vindex newline_anchor @r{field in pattern buffer}
+If the @code{newline_anchor} field is set in the pattern buffer, then
+@samp{^} fails to match after a newline. This is useful when you do not
+regard the string to be matched as broken into lines.
+
+
+@node Match-end-of-line Operator, , Match-beginning-of-line Operator, Anchoring Operators
+@subsection The Match-end-of-line Operator (@code{$})
+
+@kindex $
+@cindex end-of-line operator
+@cindex anchors
+
+This operator can match the empty string either at the end of
+the string or before a newline character in the string. Thus, it is
+said to @dfn{anchor} the pattern to the end of a line.
+
+It is always represented by @samp{$}. For example, @samp{foo$} usually
+matches, e.g., @samp{foo} and, e.g., the first three characters of
+@samp{foo\nbar}.
+
+Its interaction with the syntax bits and pattern buffer fields is
+exactly the dual of @samp{^}'s; see the previous section. (That is,
+``beginning'' becomes ``end'', ``next'' becomes ``previous'', and
+``after'' becomes ``before''.)
+
+
+@node GNU Operators, GNU Emacs Operators, Common Operators, Top
+@chapter GNU Operators
+
+Following are operators that @sc{gnu} defines (and @sc{posix} doesn't).
+
+@menu
+* Word Operators::
+* Buffer Operators::
+@end menu
+
+@node Word Operators, Buffer Operators, , GNU Operators
+@section Word Operators
+
+The operators in this section require Regex to recognize parts of words.
+Regex uses a syntax table to determine whether or not a character is
+part of a word, i.e., whether or not it is @dfn{word-constituent}.
+
+@menu
+* Non-Emacs Syntax Tables::
+* Match-word-boundary Operator:: \b
+* Match-within-word Operator:: \B
+* Match-beginning-of-word Operator:: \<
+* Match-end-of-word Operator:: \>
+* Match-word-constituent Operator:: \w
+* Match-non-word-constituent Operator:: \W
+@end menu
+
+@node Non-Emacs Syntax Tables, Match-word-boundary Operator, , Word Operators
+@subsection Non-Emacs Syntax Tables
+
+A @dfn{syntax table} is an array indexed by the characters in your
+character set. In the @sc{ascii} encoding, therefore, a syntax table
+has 256 elements. Regex always uses a @code{char *} variable
+@code{re_syntax_table} as its syntax table. In some cases, it
+initializes this variable and in others it expects you to initialize it.
+
+@itemize @bullet
+@item
+If Regex is compiled with the preprocessor symbols @code{emacs} and
+@code{SYNTAX_TABLE} both undefined, then Regex allocates
+@code{re_syntax_table} and initializes an element @var{i} either to
+@code{Sword} (which it defines) if @var{i} is a letter, number, or
+@samp{_}, or to zero if it's not.
+
+@item
+If Regex is compiled with @code{emacs} undefined but @code{SYNTAX_TABLE}
+defined, then Regex expects you to define a @code{char *} variable
+@code{re_syntax_table} to be a valid syntax table.
+
+@item
+@xref{Emacs Syntax Tables}, for what happens when Regex is compiled with
+the preprocessor symbol @code{emacs} defined.
+
+@end itemize
+
+@node Match-word-boundary Operator, Match-within-word Operator, Non-Emacs Syntax Tables, Word Operators
+@subsection The Match-word-boundary Operator (@code{\b})
+
+@cindex @samp{\b}
+@cindex word boundaries, matching
+
+This operator (represented by @samp{\b}) matches the empty string at
+either the beginning or the end of a word. For example, @samp{\brat\b}
+matches the separate word @samp{rat}.
+
+@node Match-within-word Operator, Match-beginning-of-word Operator, Match-word-boundary Operator, Word Operators
+@subsection The Match-within-word Operator (@code{\B})
+
+@cindex @samp{\B}
+
+This operator (represented by @samp{\B}) matches the empty string within
+a word. For example, @samp{c\Brat\Be} matches @samp{crate}, but
+@samp{dirty \Brat} doesn't match @samp{dirty rat}.
+
+@node Match-beginning-of-word Operator, Match-end-of-word Operator, Match-within-word Operator, Word Operators
+@subsection The Match-beginning-of-word Operator (@code{\<})
+
+@cindex @samp{\<}
+
+This operator (represented by @samp{\<}) matches the empty string at the
+beginning of a word.
+
+@node Match-end-of-word Operator, Match-word-constituent Operator, Match-beginning-of-word Operator, Word Operators
+@subsection The Match-end-of-word Operator (@code{\>})
+
+@cindex @samp{\>}
+
+This operator (represented by @samp{\>}) matches the empty string at the
+end of a word.
+
+@node Match-word-constituent Operator, Match-non-word-constituent Operator, Match-end-of-word Operator, Word Operators
+@subsection The Match-word-constituent Operator (@code{\w})
+
+@cindex @samp{\w}
+
+This operator (represented by @samp{\w}) matches any word-constituent
+character.
+
+@node Match-non-word-constituent Operator, , Match-word-constituent Operator, Word Operators
+@subsection The Match-non-word-constituent Operator (@code{\W})
+
+@cindex @samp{\W}
+
+This operator (represented by @samp{\W}) matches any character that is
+not word-constituent.
+
+
+@node Buffer Operators, , Word Operators, GNU Operators
+@section Buffer Operators
+
+Following are operators which work on buffers. In Emacs, a @dfn{buffer}
+is, naturally, an Emacs buffer. For other programs, Regex considers the
+entire string to be matched as the buffer.
+
+@menu
+* Match-beginning-of-buffer Operator:: \`
+* Match-end-of-buffer Operator:: \'
+@end menu
+
+
+@node Match-beginning-of-buffer Operator, Match-end-of-buffer Operator, , Buffer Operators
+@subsection The Match-beginning-of-buffer Operator (@code{\`})
+
+@cindex @samp{\`}
+
+This operator (represented by @samp{\`}) matches the empty string at the
+beginning of the buffer.
+
+@node Match-end-of-buffer Operator, , Match-beginning-of-buffer Operator, Buffer Operators
+@subsection The Match-end-of-buffer Operator (@code{\'})
+
+@cindex @samp{\'}
+
+This operator (represented by @samp{\'}) matches the empty string at the
+end of the buffer.
+
+
+@node GNU Emacs Operators, What Gets Matched?, GNU Operators, Top
+@chapter GNU Emacs Operators
+
+Following are operators that @sc{gnu} defines (and @sc{posix} doesn't)
+that you can use only when Regex is compiled with the preprocessor
+symbol @code{emacs} defined.
+
+@menu
+* Syntactic Class Operators::
+@end menu
+
+
+@node Syntactic Class Operators, , , GNU Emacs Operators
+@section Syntactic Class Operators
+
+The operators in this section require Regex to recognize the syntactic
+classes of characters. Regex uses a syntax table to determine this.
+
+@menu
+* Emacs Syntax Tables::
+* Match-syntactic-class Operator:: \sCLASS
+* Match-not-syntactic-class Operator:: \SCLASS
+@end menu
+
+@node Emacs Syntax Tables, Match-syntactic-class Operator, , Syntactic Class Operators
+@subsection Emacs Syntax Tables
+
+A @dfn{syntax table} is an array indexed by the characters in your
+character set. In the @sc{ascii} encoding, therefore, a syntax table
+has 256 elements.
+
+If Regex is compiled with the preprocessor symbol @code{emacs} defined,
+then Regex expects you to define and initialize the variable
+@code{re_syntax_table} to be an Emacs syntax table. Emacs' syntax
+tables are more complicated than Regex's own (@pxref{Non-Emacs Syntax
+Tables}). @xref{Syntax, , Syntax, emacs, The GNU Emacs User's Manual},
+for a description of Emacs' syntax tables.
+
+@node Match-syntactic-class Operator, Match-not-syntactic-class Operator, Emacs Syntax Tables, Syntactic Class Operators
+@subsection The Match-syntactic-class Operator (@code{\s}@var{class})
+
+@cindex @samp{\s}
+
+This operator matches any character whose syntactic class is represented
+by a specified character. @samp{\s@var{class}} represents this operator
+where @var{class} is the character representing the syntactic class you
+want. For example, @samp{w} represents the syntactic
+class of word-constituent characters, so @samp{\sw} matches any
+word-constituent character.
+
+@node Match-not-syntactic-class Operator, , Match-syntactic-class Operator, Syntactic Class Operators
+@subsection The Match-not-syntactic-class Operator (@code{\S}@var{class})
+
+@cindex @samp{\S}
+
+This operator is similar to the match-syntactic-class operator except
+that it matches any character whose syntactic class is @emph{not}
+represented by the specified character. @samp{\S@var{class}} represents
+this operator. For example, @samp{w} represents the syntactic class of
+word-constituent characters, so @samp{\Sw} matches any character that is
+not word-constituent.
+
+
+@node What Gets Matched?, Programming with Regex, GNU Emacs Operators, Top
+@chapter What Gets Matched?
+
+Regex usually matches strings according to the ``leftmost longest''
+rule; that is, it chooses the longest of the leftmost matches. This
+does not mean that for a regular expression containing subexpressions
+that it simply chooses the longest match for each subexpression, left to
+right; the overall match must also be the longest possible one.
+
+For example, @samp{(ac*)(c*d[ac]*)\1} matches @samp{acdacaaa}, not
+@samp{acdac}, as it would if it were to choose the longest match for the
+first subexpression.
+
+
+@node Programming with Regex, Copying, What Gets Matched?, Top
+@chapter Programming with Regex
+
+Here we describe how you use the Regex data structures and functions in
+C programs. Regex has three interfaces: one designed for @sc{gnu}, one
+compatible with @sc{posix} and one compatible with Berkeley @sc{unix}.
+
+@menu
+* GNU Regex Functions::
+* POSIX Regex Functions::
+* BSD Regex Functions::
+@end menu
+
+
+@node GNU Regex Functions, POSIX Regex Functions, , Programming with Regex
+@section GNU Regex Functions
+
+If you're writing code that doesn't need to be compatible with either
+@sc{posix} or Berkeley @sc{unix}, you can use these functions. They
+provide more options than the other interfaces.
+
+@menu
+* GNU Pattern Buffers:: The re_pattern_buffer type.
+* GNU Regular Expression Compiling:: re_compile_pattern ()
+* GNU Matching:: re_match ()
+* GNU Searching:: re_search ()
+* Matching/Searching with Split Data:: re_match_2 (), re_search_2 ()
+* Searching with Fastmaps:: re_compile_fastmap ()
+* GNU Translate Tables:: The `translate' field.
+* Using Registers:: The re_registers type and related fns.
+* Freeing GNU Pattern Buffers:: regfree ()
+@end menu
+
+
+@node GNU Pattern Buffers, GNU Regular Expression Compiling, , GNU Regex Functions
+@subsection GNU Pattern Buffers
+
+@cindex pattern buffer, definition of
+@tindex re_pattern_buffer @r{definition}
+@tindex struct re_pattern_buffer @r{definition}
+
+To compile, match, or search for a given regular expression, you must
+supply a pattern buffer. A @dfn{pattern buffer} holds one compiled
+regular expression.@footnote{Regular expressions are also referred to as
+``patterns,'' hence the name ``pattern buffer.''}
+
+You can have several different pattern buffers simultaneously, each
+holding a compiled pattern for a different regular expression.
+
+@file{regex.h} defines the pattern buffer @code{struct} as follows:
+
+@example
+[[[ pattern_buffer ]]]
+@end example
+
+
+@node GNU Regular Expression Compiling, GNU Matching, GNU Pattern Buffers, GNU Regex Functions
+@subsection GNU Regular Expression Compiling
+
+In @sc{gnu}, you can both match and search for a given regular
+expression. To do either, you must first compile it in a pattern buffer
+(@pxref{GNU Pattern Buffers}).
+
+@cindex syntax initialization
+@vindex re_syntax_options @r{initialization}
+Regular expressions match according to the syntax with which they were
+compiled; with @sc{gnu}, you indicate what syntax you want by setting
+the variable @code{re_syntax_options} (declared in @file{regex.h} and
+defined in @file{regex.c}) before calling the compiling function,
+@code{re_compile_pattern} (see below). @xref{Syntax Bits}, and
+@ref{Predefined Syntaxes}.
+
+You can change the value of @code{re_syntax_options} at any time.
+Usually, however, you set its value once and then never change it.
+
+@cindex pattern buffer initialization
+@code{re_compile_pattern} takes a pattern buffer as an argument. You
+must initialize the following fields:
+
+@table @code
+
+@item translate @r{initialization}
+
+@item translate
+@vindex translate @r{initialization}
+Initialize this to point to a translate table if you want one, or to
+zero if you don't. We explain translate tables in @ref{GNU Translate
+Tables}.
+
+@item fastmap
+@vindex fastmap @r{initialization}
+Initialize this to nonzero if you want a fastmap, or to zero if you
+don't.
+
+@item buffer
+@itemx allocated
+@vindex buffer @r{initialization}
+@vindex allocated @r{initialization}
+@findex malloc
+If you want @code{re_compile_pattern} to allocate memory for the
+compiled pattern, set both of these to zero. If you have an existing
+block of memory (allocated with @code{malloc}) you want Regex to use,
+set @code{buffer} to its address and @code{allocated} to its size (in
+bytes).
+
+@code{re_compile_pattern} uses @code{realloc} to extend the space for
+the compiled pattern as necessary.
+
+@end table
+
+To compile a pattern buffer, use:
+
+@findex re_compile_pattern
+@example
+char *
+re_compile_pattern (const char *@var{regex}, const int @var{regex_size},
+ struct re_pattern_buffer *@var{pattern_buffer})
+@end example
+
+@noindent
+@var{regex} is the regular expression's address, @var{regex_size} is its
+length, and @var{pattern_buffer} is the pattern buffer's address.
+
+If @code{re_compile_pattern} successfully compiles the regular
+expression, it returns zero and sets @code{*@var{pattern_buffer}} to the
+compiled pattern. It sets the pattern buffer's fields as follows:
+
+@table @code
+@item buffer
+@vindex buffer @r{field, set by @code{re_compile_pattern}}
+to the compiled pattern.
+
+@item used
+@vindex used @r{field, set by @code{re_compile_pattern}}
+to the number of bytes the compiled pattern in @code{buffer} occupies.
+
+@item syntax
+@vindex syntax @r{field, set by @code{re_compile_pattern}}
+to the current value of @code{re_syntax_options}.
+
+@item re_nsub
+@vindex re_nsub @r{field, set by @code{re_compile_pattern}}
+to the number of subexpressions in @var{regex}.
+
+@item fastmap_accurate
+@vindex fastmap_accurate @r{field, set by @code{re_compile_pattern}}
+to zero on the theory that the pattern you're compiling is different
+than the one previously compiled into @code{buffer}; in that case (since
+you can't make a fastmap without a compiled pattern),
+@code{fastmap} would either contain an incompatible fastmap, or nothing
+at all.
+
+@c xx what else?
+@end table
+
+If @code{re_compile_pattern} can't compile @var{regex}, it returns an
+error string corresponding to one of the errors listed in @ref{POSIX
+Regular Expression Compiling}.
+
+
+@node GNU Matching, GNU Searching, GNU Regular Expression Compiling, GNU Regex Functions
+@subsection GNU Matching
+
+@cindex matching with GNU functions
+
+Matching the @sc{gnu} way means trying to match as much of a string as
+possible starting at a position within it you specify. Once you've compiled
+a pattern into a pattern buffer (@pxref{GNU Regular Expression
+Compiling}), you can ask the matcher to match that pattern against a
+string using:
+
+@findex re_match
+@example
+int
+re_match (struct re_pattern_buffer *@var{pattern_buffer},
+ const char *@var{string}, const int @var{size},
+ const int @var{start}, struct re_registers *@var{regs})
+@end example
+
+@noindent
+@var{pattern_buffer} is the address of a pattern buffer containing a
+compiled pattern. @var{string} is the string you want to match; it can
+contain newline and null characters. @var{size} is the length of that
+string. @var{start} is the string index at which you want to
+begin matching; the first character of @var{string} is at index zero.
+@xref{Using Registers}, for a explanation of @var{regs}; you can safely
+pass zero.
+
+@code{re_match} matches the regular expression in @var{pattern_buffer}
+against the string @var{string} according to the syntax in
+@var{pattern_buffers}'s @code{syntax} field. (@xref{GNU Regular
+Expression Compiling}, for how to set it.) The function returns
+@math{-1} if the compiled pattern does not match any part of
+@var{string} and @math{-2} if an internal error happens; otherwise, it
+returns how many (possibly zero) characters of @var{string} the pattern
+matched.
+
+An example: suppose @var{pattern_buffer} points to a pattern buffer
+containing the compiled pattern for @samp{a*}, and @var{string} points
+to @samp{aaaaab} (whereupon @var{size} should be 6). Then if @var{start}
+is 2, @code{re_match} returns 3, i.e., @samp{a*} would have matched the
+last three @samp{a}s in @var{string}. If @var{start} is 0,
+@code{re_match} returns 5, i.e., @samp{a*} would have matched all the
+@samp{a}s in @var{string}. If @var{start} is either 5 or 6, it returns
+zero.
+
+If @var{start} is not between zero and @var{size}, then
+@code{re_match} returns @math{-1}.
+
+
+@node GNU Searching, Matching/Searching with Split Data, GNU Matching, GNU Regex Functions
+@subsection GNU Searching
+
+@cindex searching with GNU functions
+
+@dfn{Searching} means trying to match starting at successive positions
+within a string. The function @code{re_search} does this.
+
+Before calling @code{re_search}, you must compile your regular
+expression. @xref{GNU Regular Expression Compiling}.
+
+Here is the function declaration:
+
+@findex re_search
+@example
+int
+re_search (struct re_pattern_buffer *@var{pattern_buffer},
+ const char *@var{string}, const int @var{size},
+ const int @var{start}, const int @var{range},
+ struct re_registers *@var{regs})
+@end example
+
+@noindent
+@vindex start @r{argument to @code{re_search}}
+@vindex range @r{argument to @code{re_search}}
+whose arguments are the same as those to @code{re_match} (@pxref{GNU
+Matching}) except that the two arguments @var{start} and @var{range}
+replace @code{re_match}'s argument @var{start}.
+
+If @var{range} is positive, then @code{re_search} attempts a match
+starting first at index @var{start}, then at @math{@var{start} + 1} if
+that fails, and so on, up to @math{@var{start} + @var{range}}; if
+@var{range} is negative, then it attempts a match starting first at
+index @var{start}, then at @math{@var{start} -1} if that fails, and so
+on.
+
+If @var{start} is not between zero and @var{size}, then @code{re_search}
+returns @math{-1}. When @var{range} is positive, @code{re_search}
+adjusts @var{range} so that @math{@var{start} + @var{range} - 1} is
+between zero and @var{size}, if necessary; that way it won't search
+outside of @var{string}. Similarly, when @var{range} is negative,
+@code{re_search} adjusts @var{range} so that @math{@var{start} +
+@var{range} + 1} is between zero and @var{size}, if necessary.
+
+If the @code{fastmap} field of @var{pattern_buffer} is zero,
+@code{re_search} matches starting at consecutive positions; otherwise,
+it uses @code{fastmap} to make the search more efficient.
+@xref{Searching with Fastmaps}.
+
+If no match is found, @code{re_search} returns @math{-1}. If
+a match is found, it returns the index where the match began. If an
+internal error happens, it returns @math{-2}.
+
+
+@node Matching/Searching with Split Data, Searching with Fastmaps, GNU Searching, GNU Regex Functions
+@subsection Matching and Searching with Split Data
+
+Using the functions @code{re_match_2} and @code{re_search_2}, you can
+match or search in data that is divided into two strings.
+
+The function:
+
+@findex re_match_2
+@example
+int
+re_match_2 (struct re_pattern_buffer *@var{buffer},
+ const char *@var{string1}, const int @var{size1},
+ const char *@var{string2}, const int @var{size2},
+ const int @var{start},
+ struct re_registers *@var{regs},
+ const int @var{stop})
+@end example
+
+@noindent
+is similar to @code{re_match} (@pxref{GNU Matching}) except that you
+pass @emph{two} data strings and sizes, and an index @var{stop} beyond
+which you don't want the matcher to try matching. As with
+@code{re_match}, if it succeeds, @code{re_match_2} returns how many
+characters of @var{string} it matched. Regard @var{string1} and
+@var{string2} as concatenated when you set the arguments @var{start} and
+@var{stop} and use the contents of @var{regs}; @code{re_match_2} never
+returns a value larger than @math{@var{size1} + @var{size2}}.
+
+The function:
+
+@findex re_search_2
+@example
+int
+re_search_2 (struct re_pattern_buffer *@var{buffer},
+ const char *@var{string1}, const int @var{size1},
+ const char *@var{string2}, const int @var{size2},
+ const int @var{start}, const int @var{range},
+ struct re_registers *@var{regs},
+ const int @var{stop})
+@end example
+
+@noindent
+is similarly related to @code{re_search}.
+
+
+@node Searching with Fastmaps, GNU Translate Tables, Matching/Searching with Split Data, GNU Regex Functions
+@subsection Searching with Fastmaps
+
+@cindex fastmaps
+If you're searching through a long string, you should use a fastmap.
+Without one, the searcher tries to match at consecutive positions in the
+string. Generally, most of the characters in the string could not start
+a match. It takes much longer to try matching at a given position in the
+string than it does to check in a table whether or not the character at
+that position could start a match. A @dfn{fastmap} is such a table.
+
+More specifically, a fastmap is an array indexed by the characters in
+your character set. Under the @sc{ascii} encoding, therefore, a fastmap
+has 256 elements. If you want the searcher to use a fastmap with a
+given pattern buffer, you must allocate the array and assign the array's
+address to the pattern buffer's @code{fastmap} field. You either can
+compile the fastmap yourself or have @code{re_search} do it for you;
+when @code{fastmap} is nonzero, it automatically compiles a fastmap the
+first time you search using a particular compiled pattern.
+
+To compile a fastmap yourself, use:
+
+@findex re_compile_fastmap
+@example
+int
+re_compile_fastmap (struct re_pattern_buffer *@var{pattern_buffer})
+@end example
+
+@noindent
+@var{pattern_buffer} is the address of a pattern buffer. If the
+character @var{c} could start a match for the pattern,
+@code{re_compile_fastmap} makes
+@code{@var{pattern_buffer}->fastmap[@var{c}]} nonzero. It returns
+@math{0} if it can compile a fastmap and @math{-2} if there is an
+internal error. For example, if @samp{|} is the alternation operator
+and @var{pattern_buffer} holds the compiled pattern for @samp{a|b}, then
+@code{re_compile_fastmap} sets @code{fastmap['a']} and
+@code{fastmap['b']} (and no others).
+
+@code{re_search} uses a fastmap as it moves along in the string: it
+checks the string's characters until it finds one that's in the fastmap.
+Then it tries matching at that character. If the match fails, it
+repeats the process. So, by using a fastmap, @code{re_search} doesn't
+waste time trying to match at positions in the string that couldn't
+start a match.
+
+If you don't want @code{re_search} to use a fastmap,
+store zero in the @code{fastmap} field of the pattern buffer before
+calling @code{re_search}.
+
+Once you've initialized a pattern buffer's @code{fastmap} field, you
+need never do so again---even if you compile a new pattern in
+it---provided the way the field is set still reflects whether or not you
+want a fastmap. @code{re_search} will still either do nothing if
+@code{fastmap} is null or, if it isn't, compile a new fastmap for the
+new pattern.
+
+@node GNU Translate Tables, Using Registers, Searching with Fastmaps, GNU Regex Functions
+@subsection GNU Translate Tables
+
+If you set the @code{translate} field of a pattern buffer to a translate
+table, then the @sc{gnu} Regex functions to which you've passed that
+pattern buffer use it to apply a simple transformation
+to all the regular expression and string characters at which they look.
+
+A @dfn{translate table} is an array indexed by the characters in your
+character set. Under the @sc{ascii} encoding, therefore, a translate
+table has 256 elements. The array's elements are also characters in
+your character set. When the Regex functions see a character @var{c},
+they use @code{translate[@var{c}]} in its place, with one exception: the
+character after a @samp{\} is not translated. (This ensures that, the
+operators, e.g., @samp{\B} and @samp{\b}, are always distinguishable.)
+
+For example, a table that maps all lowercase letters to the
+corresponding uppercase ones would cause the matcher to ignore
+differences in case.@footnote{A table that maps all uppercase letters to
+the corresponding lowercase ones would work just as well for this
+purpose.} Such a table would map all characters except lowercase letters
+to themselves, and lowercase letters to the corresponding uppercase
+ones. Under the @sc{ascii} encoding, here's how you could initialize
+such a table (we'll call it @code{case_fold}):
+
+@example
+for (i = 0; i < 256; i++)
+ case_fold[i] = i;
+for (i = 'a'; i <= 'z'; i++)
+ case_fold[i] = i - ('a' - 'A');
+@end example
+
+You tell Regex to use a translate table on a given pattern buffer by
+assigning that table's address to the @code{translate} field of that
+buffer. If you don't want Regex to do any translation, put zero into
+this field. You'll get weird results if you change the table's contents
+anytime between compiling the pattern buffer, compiling its fastmap, and
+matching or searching with the pattern buffer.
+
+@node Using Registers, Freeing GNU Pattern Buffers, GNU Translate Tables, GNU Regex Functions
+@subsection Using Registers
+
+A group in a regular expression can match a (posssibly empty) substring
+of the string that regular expression as a whole matched. The matcher
+remembers the beginning and end of the substring matched by
+each group.
+
+To find out what they matched, pass a nonzero @var{regs} argument to a
+@sc{gnu} matching or searching function (@pxref{GNU Matching} and
+@ref{GNU Searching}), i.e., the address of a structure of this type, as
+defined in @file{regex.h}:
+
+@c We don't bother to include this directly from regex.h,
+@c since it changes so rarely.
+@example
+@tindex re_registers
+@vindex num_regs @r{in @code{struct re_registers}}
+@vindex start @r{in @code{struct re_registers}}
+@vindex end @r{in @code{struct re_registers}}
+struct re_registers
+@{
+ unsigned num_regs;
+ regoff_t *start;
+ regoff_t *end;
+@};
+@end example
+
+Except for (possibly) the @var{num_regs}'th element (see below), the
+@var{i}th element of the @code{start} and @code{end} arrays records
+information about the @var{i}th group in the pattern. (They're declared
+as C pointers, but this is only because not all C compilers accept
+zero-length arrays; conceptually, it is simplest to think of them as
+arrays.)
+
+The @code{start} and @code{end} arrays are allocated in various ways,
+depending on the value of the @code{regs_allocated}
+@vindex regs_allocated
+field in the pattern buffer passed to the matcher.
+
+The simplest and perhaps most useful is to let the matcher (re)allocate
+enough space to record information for all the groups in the regular
+expression. If @code{regs_allocated} is @code{REGS_UNALLOCATED},
+@vindex REGS_UNALLOCATED
+the matcher allocates @math{1 + @var{re_nsub}} (another field in the
+pattern buffer; @pxref{GNU Pattern Buffers}). The extra element is set
+to @math{-1}, and sets @code{regs_allocated} to @code{REGS_REALLOCATE}.
+@vindex REGS_REALLOCATE
+Then on subsequent calls with the same pattern buffer and @var{regs}
+arguments, the matcher reallocates more space if necessary.
+
+It would perhaps be more logical to make the @code{regs_allocated} field
+part of the @code{re_registers} structure, instead of part of the
+pattern buffer. But in that case the caller would be forced to
+initialize the structure before passing it. Much existing code doesn't
+do this initialization, and it's arguably better to avoid it anyway.
+
+@code{re_compile_pattern} sets @code{regs_allocated} to
+@code{REGS_UNALLOCATED},
+so if you use the GNU regular expression
+functions, you get this behavior by default.
+
+xx document re_set_registers
+
+@sc{posix}, on the other hand, requires a different interface: the
+caller is supposed to pass in a fixed-length array which the matcher
+fills. Therefore, if @code{regs_allocated} is @code{REGS_FIXED}
+@vindex REGS_FIXED
+the matcher simply fills that array.
+
+The following examples illustrate the information recorded in the
+@code{re_registers} structure. (In all of them, @samp{(} represents the
+open-group and @samp{)} the close-group operator. The first character
+in the string @var{string} is at index 0.)
+
+@c xx i'm not sure this is all true anymore.
+
+@itemize @bullet
+
+@item
+If the regular expression has an @w{@var{i}-th}
+group not contained within another group that matches a
+substring of @var{string}, then the function sets
+@code{@w{@var{regs}->}start[@var{i}]} to the index in @var{string} where
+the substring matched by the @w{@var{i}-th} group begins, and
+@code{@w{@var{regs}->}end[@var{i}]} to the index just beyond that
+substring's end. The function sets @code{@w{@var{regs}->}start[0]} and
+@code{@w{@var{regs}->}end[0]} to analogous information about the entire
+pattern.
+
+For example, when you match @samp{((a)(b))} against @samp{ab}, you get:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 2 in @code{@w{@var{regs}->}end[0]}
+
+@item
+0 in @code{@w{@var{regs}->}start[1]} and 2 in @code{@w{@var{regs}->}end[1]}
+
+@item
+0 in @code{@w{@var{regs}->}start[2]} and 1 in @code{@w{@var{regs}->}end[2]}
+
+@item
+1 in @code{@w{@var{regs}->}start[3]} and 2 in @code{@w{@var{regs}->}end[3]}
+@end itemize
+
+@item
+If a group matches more than once (as it might if followed by,
+e.g., a repetition operator), then the function reports the information
+about what the group @emph{last} matched.
+
+For example, when you match the pattern @samp{(a)*} against the string
+@samp{aa}, you get:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 2 in @code{@w{@var{regs}->}end[0]}
+
+@item
+1 in @code{@w{@var{regs}->}start[1]} and 2 in @code{@w{@var{regs}->}end[1]}
+@end itemize
+
+@item
+If the @w{@var{i}-th} group does not participate in a
+successful match, e.g., it is an alternative not taken or a
+repetition operator allows zero repetitions of it, then the function
+sets @code{@w{@var{regs}->}start[@var{i}]} and
+@code{@w{@var{regs}->}end[@var{i}]} to @math{-1}.
+
+For example, when you match the pattern @samp{(a)*b} against
+the string @samp{b}, you get:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 1 in @code{@w{@var{regs}->}end[0]}
+
+@item
+@math{-1} in @code{@w{@var{regs}->}start[1]} and @math{-1} in @code{@w{@var{regs}->}end[1]}
+@end itemize
+
+@item
+If the @w{@var{i}-th} group matches a zero-length string, then the
+function sets @code{@w{@var{regs}->}start[@var{i}]} and
+@code{@w{@var{regs}->}end[@var{i}]} to the index just beyond that
+zero-length string.
+
+For example, when you match the pattern @samp{(a*)b} against the string
+@samp{b}, you get:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 1 in @code{@w{@var{regs}->}end[0]}
+
+@item
+0 in @code{@w{@var{regs}->}start[1]} and 0 in @code{@w{@var{regs}->}end[1]}
+@end itemize
+
+@ignore
+The function sets @code{@w{@var{regs}->}start[0]} and
+@code{@w{@var{regs}->}end[0]} to analogous information about the entire
+pattern.
+
+For example, when you match the pattern @samp{(a*)} against the empty
+string, you get:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 0 in @code{@w{@var{regs}->}end[0]}
+
+@item
+0 in @code{@w{@var{regs}->}start[1]} and 0 in @code{@w{@var{regs}->}end[1]}
+@end itemize
+@end ignore
+
+@item
+If an @w{@var{i}-th} group contains a @w{@var{j}-th} group
+in turn not contained within any other group within group @var{i} and
+the function reports a match of the @w{@var{i}-th} group, then it
+records in @code{@w{@var{regs}->}start[@var{j}]} and
+@code{@w{@var{regs}->}end[@var{j}]} the last match (if it matched) of
+the @w{@var{j}-th} group.
+
+For example, when you match the pattern @samp{((a*)b)*} against the
+string @samp{abb}, @w{group 2} last matches the empty string, so you
+get what it previously matched:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 3 in @code{@w{@var{regs}->}end[0]}
+
+@item
+2 in @code{@w{@var{regs}->}start[1]} and 3 in @code{@w{@var{regs}->}end[1]}
+
+@item
+2 in @code{@w{@var{regs}->}start[2]} and 2 in @code{@w{@var{regs}->}end[2]}
+@end itemize
+
+When you match the pattern @samp{((a)*b)*} against the string
+@samp{abb}, @w{group 2} doesn't participate in the last match, so you
+get:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 3 in @code{@w{@var{regs}->}end[0]}
+
+@item
+2 in @code{@w{@var{regs}->}start[1]} and 3 in @code{@w{@var{regs}->}end[1]}
+
+@item
+0 in @code{@w{@var{regs}->}start[2]} and 1 in @code{@w{@var{regs}->}end[2]}
+@end itemize
+
+@item
+If an @w{@var{i}-th} group contains a @w{@var{j}-th} group
+in turn not contained within any other group within group @var{i}
+and the function sets
+@code{@w{@var{regs}->}start[@var{i}]} and
+@code{@w{@var{regs}->}end[@var{i}]} to @math{-1}, then it also sets
+@code{@w{@var{regs}->}start[@var{j}]} and
+@code{@w{@var{regs}->}end[@var{j}]} to @math{-1}.
+
+For example, when you match the pattern @samp{((a)*b)*c} against the
+string @samp{c}, you get:
+
+@itemize @bullet
+@item
+0 in @code{@w{@var{regs}->}start[0]} and 1 in @code{@w{@var{regs}->}end[0]}
+
+@item
+@math{-1} in @code{@w{@var{regs}->}start[1]} and @math{-1} in @code{@w{@var{regs}->}end[1]}
+
+@item
+@math{-1} in @code{@w{@var{regs}->}start[2]} and @math{-1} in @code{@w{@var{regs}->}end[2]}
+@end itemize
+
+@end itemize
+
+@node Freeing GNU Pattern Buffers, , Using Registers, GNU Regex Functions
+@subsection Freeing GNU Pattern Buffers
+
+To free any allocated fields of a pattern buffer, you can use the
+@sc{posix} function described in @ref{Freeing POSIX Pattern Buffers},
+since the type @code{regex_t}---the type for @sc{posix} pattern
+buffers---is equivalent to the type @code{re_pattern_buffer}. After
+freeing a pattern buffer, you need to again compile a regular expression
+in it (@pxref{GNU Regular Expression Compiling}) before passing it to
+a matching or searching function.
+
+
+@node POSIX Regex Functions, BSD Regex Functions, GNU Regex Functions, Programming with Regex
+@section POSIX Regex Functions
+
+If you're writing code that has to be @sc{posix} compatible, you'll need
+to use these functions. Their interfaces are as specified by @sc{posix},
+draft 1003.2/D11.2.
+
+@menu
+* POSIX Pattern Buffers:: The regex_t type.
+* POSIX Regular Expression Compiling:: regcomp ()
+* POSIX Matching:: regexec ()
+* Reporting Errors:: regerror ()
+* Using Byte Offsets:: The regmatch_t type.
+* Freeing POSIX Pattern Buffers:: regfree ()
+@end menu
+
+
+@node POSIX Pattern Buffers, POSIX Regular Expression Compiling, , POSIX Regex Functions
+@subsection POSIX Pattern Buffers
+
+To compile or match a given regular expression the @sc{posix} way, you
+must supply a pattern buffer exactly the way you do for @sc{gnu}
+(@pxref{GNU Pattern Buffers}). @sc{posix} pattern buffers have type
+@code{regex_t}, which is equivalent to the @sc{gnu} pattern buffer
+type @code{re_pattern_buffer}.
+
+
+@node POSIX Regular Expression Compiling, POSIX Matching, POSIX Pattern Buffers, POSIX Regex Functions
+@subsection POSIX Regular Expression Compiling
+
+With @sc{posix}, you can only search for a given regular expression; you
+can't match it. To do this, you must first compile it in a
+pattern buffer, using @code{regcomp}.
+
+@ignore
+Before calling @code{regcomp}, you must initialize this pattern buffer
+as you do for @sc{gnu} (@pxref{GNU Regular Expression Compiling}). See
+below, however, for how to choose a syntax with which to compile.
+@end ignore
+
+To compile a pattern buffer, use:
+
+@findex regcomp
+@example
+int
+regcomp (regex_t *@var{preg}, const char *@var{regex}, int @var{cflags})
+@end example
+
+@noindent
+@var{preg} is the initialized pattern buffer's address, @var{regex} is
+the regular expression's address, and @var{cflags} is the compilation
+flags, which Regex considers as a collection of bits. Here are the
+valid bits, as defined in @file{regex.h}:
+
+@table @code
+
+@item REG_EXTENDED
+@vindex REG_EXTENDED
+says to use @sc{posix} Extended Regular Expression syntax; if this isn't
+set, then says to use @sc{posix} Basic Regular Expression syntax.
+@code{regcomp} sets @var{preg}'s @code{syntax} field accordingly.
+
+@item REG_ICASE
+@vindex REG_ICASE
+@cindex ignoring case
+says to ignore case; @code{regcomp} sets @var{preg}'s @code{translate}
+field to a translate table which ignores case, replacing anything you've
+put there before.
+
+@item REG_NOSUB
+@vindex REG_NOSUB
+says to set @var{preg}'s @code{no_sub} field; @pxref{POSIX Matching},
+for what this means.
+
+@item REG_NEWLINE
+@vindex REG_NEWLINE
+says that a:
+
+@itemize @bullet
+
+@item
+match-any-character operator (@pxref{Match-any-character
+Operator}) doesn't match a newline.
+
+@item
+nonmatching list not containing a newline (@pxref{List
+Operators}) matches a newline.
+
+@item
+match-beginning-of-line operator (@pxref{Match-beginning-of-line
+Operator}) matches the empty string immediately after a newline,
+regardless of how @code{REG_NOTBOL} is set (@pxref{POSIX Matching}, for
+an explanation of @code{REG_NOTBOL}).
+
+@item
+match-end-of-line operator (@pxref{Match-beginning-of-line
+Operator}) matches the empty string immediately before a newline,
+regardless of how @code{REG_NOTEOL} is set (@pxref{POSIX Matching},
+for an explanation of @code{REG_NOTEOL}).
+
+@end itemize
+
+@end table
+
+If @code{regcomp} successfully compiles the regular expression, it
+returns zero and sets @code{*@var{pattern_buffer}} to the compiled
+pattern. Except for @code{syntax} (which it sets as explained above), it
+also sets the same fields the same way as does the @sc{gnu} compiling
+function (@pxref{GNU Regular Expression Compiling}).
+
+If @code{regcomp} can't compile the regular expression, it returns one
+of the error codes listed here. (Except when noted differently, the
+syntax of in all examples below is basic regular expression syntax.)
+
+@table @code
+
+@comment repetitions
+@item REG_BADRPT
+For example, the consecutive repetition operators @samp{**} in
+@samp{a**} are invalid. As another example, if the syntax is extended
+regular expression syntax, then the repetition operator @samp{*} with
+nothing on which to operate in @samp{*} is invalid.
+
+@item REG_BADBR
+For example, the @var{count} @samp{-1} in @samp{a\@{-1} is invalid.
+
+@item REG_EBRACE
+For example, @samp{a\@{1} is missing a close-interval operator.
+
+@comment lists
+@item REG_EBRACK
+For example, @samp{[a} is missing a close-list operator.
+
+@item REG_ERANGE
+For example, the range ending point @samp{z} that collates lower than
+does its starting point @samp{a} in @samp{[z-a]} is invalid. Also, the
+range with the character class @samp{[:alpha:]} as its starting point in
+@samp{[[:alpha:]-|]}.
+
+@item REG_ECTYPE
+For example, the character class name @samp{foo} in @samp{[[:foo:]} is
+invalid.
+
+@comment groups
+@item REG_EPAREN
+For example, @samp{a\)} is missing an open-group operator and @samp{\(a}
+is missing a close-group operator.
+
+@item REG_ESUBREG
+For example, the back reference @samp{\2} that refers to a nonexistent
+subexpression in @samp{\(a\)\2} is invalid.
+
+@comment unfinished business
+
+@item REG_EEND
+Returned when a regular expression causes no other more specific error.
+
+@item REG_EESCAPE
+For example, the trailing backslash @samp{\} in @samp{a\} is invalid, as is the
+one in @samp{\}.
+
+@comment kitchen sink
+@item REG_BADPAT
+For example, in the extended regular expression syntax, the empty group
+@samp{()} in @samp{a()b} is invalid.
+
+@comment internal
+@item REG_ESIZE
+Returned when a regular expression needs a pattern buffer larger than
+65536 bytes.
+
+@item REG_ESPACE
+Returned when a regular expression makes Regex to run out of memory.
+
+@end table
+
+
+@node POSIX Matching, Reporting Errors, POSIX Regular Expression Compiling, POSIX Regex Functions
+@subsection POSIX Matching
+
+Matching the @sc{posix} way means trying to match a null-terminated
+string starting at its first character. Once you've compiled a pattern
+into a pattern buffer (@pxref{POSIX Regular Expression Compiling}), you
+can ask the matcher to match that pattern against a string using:
+
+@findex regexec
+@example
+int
+regexec (const regex_t *@var{preg}, const char *@var{string},
+ size_t @var{nmatch}, regmatch_t @var{pmatch}[], int @var{eflags})
+@end example
+
+@noindent
+@var{preg} is the address of a pattern buffer for a compiled pattern.
+@var{string} is the string you want to match.
+
+@xref{Using Byte Offsets}, for an explanation of @var{pmatch}. If you
+pass zero for @var{nmatch} or you compiled @var{preg} with the
+compilation flag @code{REG_NOSUB} set, then @code{regexec} will ignore
+@var{pmatch}; otherwise, you must allocate it to have at least
+@var{nmatch} elements. @code{regexec} will record @var{nmatch} byte
+offsets in @var{pmatch}, and set to @math{-1} any unused elements up to
+@math{@var{pmatch}@code{[@var{nmatch}]} - 1}.
+
+@var{eflags} specifies @dfn{execution flags}---namely, the two bits
+@code{REG_NOTBOL} and @code{REG_NOTEOL} (defined in @file{regex.h}). If
+you set @code{REG_NOTBOL}, then the match-beginning-of-line operator
+(@pxref{Match-beginning-of-line Operator}) always fails to match.
+This lets you match against pieces of a line, as you would need to if,
+say, searching for repeated instances of a given pattern in a line; it
+would work correctly for patterns both with and without
+match-beginning-of-line operators. @code{REG_NOTEOL} works analogously
+for the match-end-of-line operator (@pxref{Match-end-of-line
+Operator}); it exists for symmetry.
+
+@code{regexec} tries to find a match for @var{preg} in @var{string}
+according to the syntax in @var{preg}'s @code{syntax} field.
+(@xref{POSIX Regular Expression Compiling}, for how to set it.) The
+function returns zero if the compiled pattern matches @var{string} and
+@code{REG_NOMATCH} (defined in @file{regex.h}) if it doesn't.
+
+@node Reporting Errors, Using Byte Offsets, POSIX Matching, POSIX Regex Functions
+@subsection Reporting Errors
+
+If either @code{regcomp} or @code{regexec} fail, they return a nonzero
+error code, the possibilities for which are defined in @file{regex.h}.
+@xref{POSIX Regular Expression Compiling}, and @ref{POSIX Matching}, for
+what these codes mean. To get an error string corresponding to these
+codes, you can use:
+
+@findex regerror
+@example
+size_t
+regerror (int @var{errcode},
+ const regex_t *@var{preg},
+ char *@var{errbuf},
+ size_t @var{errbuf_size})
+@end example
+
+@noindent
+@var{errcode} is an error code, @var{preg} is the address of the pattern
+buffer which provoked the error, @var{errbuf} is the error buffer, and
+@var{errbuf_size} is @var{errbuf}'s size.
+
+@code{regerror} returns the size in bytes of the error string
+corresponding to @var{errcode} (including its terminating null). If
+@var{errbuf} and @var{errbuf_size} are nonzero, it also returns in
+@var{errbuf} the first @math{@var{errbuf_size} - 1} characters of the
+error string, followed by a null.
+@var{errbuf_size} must be a nonnegative number less than or equal to the
+size in bytes of @var{errbuf}.
+
+You can call @code{regerror} with a null @var{errbuf} and a zero
+@var{errbuf_size} to determine how large @var{errbuf} need be to
+accommodate @code{regerror}'s error string.
+
+@node Using Byte Offsets, Freeing POSIX Pattern Buffers, Reporting Errors, POSIX Regex Functions
+@subsection Using Byte Offsets
+
+In @sc{posix}, variables of type @code{regmatch_t} hold analogous
+information, but are not identical to, @sc{gnu}'s registers (@pxref{Using
+Registers}). To get information about registers in @sc{posix}, pass to
+@code{regexec} a nonzero @var{pmatch} of type @code{regmatch_t}, i.e.,
+the address of a structure of this type, defined in
+@file{regex.h}:
+
+@tindex regmatch_t
+@example
+typedef struct
+@{
+ regoff_t rm_so;
+ regoff_t rm_eo;
+@} regmatch_t;
+@end example
+
+When reading in @ref{Using Registers}, about how the matching function
+stores the information into the registers, substitute @var{pmatch} for
+@var{regs}, @code{@w{@var{pmatch}[@var{i}]->}rm_so} for
+@code{@w{@var{regs}->}start[@var{i}]} and
+@code{@w{@var{pmatch}[@var{i}]->}rm_eo} for
+@code{@w{@var{regs}->}end[@var{i}]}.
+
+@node Freeing POSIX Pattern Buffers, , Using Byte Offsets, POSIX Regex Functions
+@subsection Freeing POSIX Pattern Buffers
+
+To free any allocated fields of a pattern buffer, use:
+
+@findex regfree
+@example
+void
+regfree (regex_t *@var{preg})
+@end example
+
+@noindent
+@var{preg} is the pattern buffer whose allocated fields you want freed.
+@code{regfree} also sets @var{preg}'s @code{allocated} and @code{used}
+fields to zero. After freeing a pattern buffer, you need to again
+compile a regular expression in it (@pxref{POSIX Regular Expression
+Compiling}) before passing it to the matching function (@pxref{POSIX
+Matching}).
+
+
+@node BSD Regex Functions, , POSIX Regex Functions, Programming with Regex
+@section BSD Regex Functions
+
+If you're writing code that has to be Berkeley @sc{unix} compatible,
+you'll need to use these functions whose interfaces are the same as those
+in Berkeley @sc{unix}.
+
+@menu
+* BSD Regular Expression Compiling:: re_comp ()
+* BSD Searching:: re_exec ()
+@end menu
+
+@node BSD Regular Expression Compiling, BSD Searching, , BSD Regex Functions
+@subsection BSD Regular Expression Compiling
+
+With Berkeley @sc{unix}, you can only search for a given regular
+expression; you can't match one. To search for it, you must first
+compile it. Before you compile it, you must indicate the regular
+expression syntax you want it compiled according to by setting the
+variable @code{re_syntax_options} (declared in @file{regex.h} to some
+syntax (@pxref{Regular Expression Syntax}).
+
+To compile a regular expression use:
+
+@findex re_comp
+@example
+char *
+re_comp (char *@var{regex})
+@end example
+
+@noindent
+@var{regex} is the address of a null-terminated regular expression.
+@code{re_comp} uses an internal pattern buffer, so you can use only the
+most recently compiled pattern buffer. This means that if you want to
+use a given regular expression that you've already compiled---but it
+isn't the latest one you've compiled---you'll have to recompile it. If
+you call @code{re_comp} with the null string (@emph{not} the empty
+string) as the argument, it doesn't change the contents of the pattern
+buffer.
+
+If @code{re_comp} successfully compiles the regular expression, it
+returns zero. If it can't compile the regular expression, it returns
+an error string. @code{re_comp}'s error messages are identical to those
+of @code{re_compile_pattern} (@pxref{GNU Regular Expression
+Compiling}).
+
+@node BSD Searching, , BSD Regular Expression Compiling, BSD Regex Functions
+@subsection BSD Searching
+
+Searching the Berkeley @sc{unix} way means searching in a string
+starting at its first character and trying successive positions within
+it to find a match. Once you've compiled a pattern using @code{re_comp}
+(@pxref{BSD Regular Expression Compiling}), you can ask Regex
+to search for that pattern in a string using:
+
+@findex re_exec
+@example
+int
+re_exec (char *@var{string})
+@end example
+
+@noindent
+@var{string} is the address of the null-terminated string in which you
+want to search.
+
+@code{re_exec} returns either 1 for success or 0 for failure. It
+automatically uses a @sc{gnu} fastmap (@pxref{Searching with Fastmaps}).
+
+
+@node Copying, Index, Programming with Regex, Top
+@appendix GNU GENERAL PUBLIC LICENSE
+@center Version 2, June 1991
+
+@display
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec 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.
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end ifinfo
+
+@enumerate
+@item
+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.
+
+@item
+You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this 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.
+
+@item
+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:
+
+@enumerate a
+@item
+You must cause the modified files to carry prominent notices
+stating that you changed the files and the date of any change.
+
+@item
+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.
+
+@item
+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.)
+@end enumerate
+
+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.
+
+@item
+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:
+
+@enumerate a
+@item
+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,
+
+@item
+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,
+
+@item
+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.)
+@end enumerate
+
+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.
+
+@item
+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.
+
+@item
+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.
+
+@item
+Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+@item
+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.
+
+@item
+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.
+
+@item
+The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of 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.
+
+@item
+If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+@item
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+@end enumerate
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+@page
+@unnumberedsec Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the ``copyright'' line and a pointer to where the full notice is found.
+
+@smallexample
+@var{one line to give the program's name and a brief idea of what it does.}
+Copyright (C) 19@var{yy} @var{name of author}
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+@end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than @samp{show w} and
+@samp{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:
+
+@example
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+`Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end example
+
+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.
+
+
+@node Index, , Copying, Top
+@unnumbered Index
+
+@printindex cp
+
+@contents
+
+@bye
diff --git a/gnu/lib/libregex/regex.c b/gnu/lib/libregex/regex.c
new file mode 100644
index 0000000..335e5d3
--- /dev/null
+++ b/gnu/lib/libregex/regex.c
@@ -0,0 +1,5101 @@
+/* Extended regular expression matching and search library,
+ version 0.12.
+ (Implements POSIX draft P10003.2/D11.2, except for
+ internationalization features.)
+
+ 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You 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. */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined (_AIX) && !defined (REGEX_MALLOC)
+ #pragma alloca
+#endif
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(STDC_HEADERS) && !defined(emacs)
+#include <stddef.h>
+#else
+/* We need this for `regex.h', and perhaps for the Emacs include files. */
+#include <sys/types.h>
+#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"
+
+/* Emacs uses `NULL' as a predicate. */
+#undef NULL
+
+#else /* not emacs */
+
+/* We used to test for `BSTRING' here, but only GCC and Emacs define
+ `BSTRING', as far as I know, and neither of them use this code. */
+#if HAVE_STRING_H || STDC_HEADERS
+#include <string.h>
+#ifndef bcmp
+#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
+#endif
+#ifndef bcopy
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n) memset ((s), 0, (n))
+#endif
+#else
+#include <strings.h>
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+char *malloc ();
+char *realloc ();
+#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 SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+#else /* not SYNTAX_TABLE */
+
+/* How many characters in the character set. */
+#define CHAR_SET_SIZE 256
+
+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. */
+#include "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." */
+#if ! defined (isascii) || defined (STDC_HEADERS)
+#undef isascii
+#define isascii(c) 1
+#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
+
+#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 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)
+
+#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>
+#else /* not __GNUC__ or HAVE_ALLOCA_H */
+#ifndef _AIX /* Already did AIX, up at the top. */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not 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), \
+ bcopy (source, destination, osize), \
+ destination)
+
+#endif /* not REGEX_MALLOC */
+
+
+/* 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 REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits. */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#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
+
+/* 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.
+
+ The value of `exactn' is needed in search.c (search_buffer) in Emacs.
+ So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
+ `exactn' we use here must also be 1. */
+
+typedef enum
+{
+ no_op = 0,
+
+ /* Followed by one byte giving n, then by n literal bytes. */
+ exactn = 1,
+
+ /* 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)
+
+
+extern void printchar ();
+
+/* 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;
+ printchar (i - 1);
+ while (i < (1 << BYTEWIDTH) && fastmap[i])
+ {
+ was_a_range = 1;
+ i++;
+ }
+ if (was_a_range)
+ {
+ printf ("-");
+ printchar (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 *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 ('/');
+ printchar (*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)
+ {
+ printchar (last);
+ in_range = 0;
+ }
+
+ if (! in_range)
+ printchar (c);
+
+ last = c;
+ }
+
+ if (in_range)
+ printchar (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);
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/succeed_n to %d, %d times", p + mcnt - start, mcnt2);
+ break;
+
+ case jump_n:
+ extract_number_and_incr (&mcnt, &p);
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/jump_n to %d, %d times", p + mcnt - start, mcnt2);
+ break;
+
+ case set_number_at:
+ extract_number_and_incr (&mcnt, &p);
+ extract_number_and_incr (&mcnt2, &p);
+ printf ("/set_number_at location %d to %d", p + mcnt - 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 ("%d bytes used/%d 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: %d\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;
+{
+ unsigned this_char;
+
+ if (where == NULL)
+ printf ("(null)");
+ else
+ {
+ if (FIRST_STRING_P (where))
+ {
+ for (this_char = where - string1; this_char < size1; this_char++)
+ printchar (string1[this_char]);
+
+ where = string2;
+ }
+
+ for (this_char = where - string2; this_char < size2; this_char++)
+ printchar (string2[this_char]);
+ }
+}
+
+#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. */
+reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
+
+
+/* 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 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;
+ return ret;
+}
+
+/* This table gives an error message for each of the error codes listed
+ in regex.h. Obviously the order here has to be same as there. */
+
+static const char *re_error_msg[] =
+ { NULL, /* REG_NOERROR */
+ "No match", /* REG_NOMATCH */
+ "Invalid regular expression", /* REG_BADPAT */
+ "Invalid collation character", /* REG_ECOLLATE */
+ "Invalid character class name", /* REG_ECTYPE */
+ "Trailing backslash", /* REG_EESCAPE */
+ "Invalid back reference", /* REG_ESUBREG */
+ "Unmatched [ or [^", /* REG_EBRACK */
+ "Unmatched ( or \\(", /* REG_EPAREN */
+ "Unmatched \\{", /* REG_EBRACE */
+ "Invalid content of \\{\\}", /* REG_BADBR */
+ "Invalid range end", /* REG_ERANGE */
+ "Memory exhausted", /* REG_ESPACE */
+ "Invalid preceding regular expression", /* REG_BADRPT */
+ "Premature end of regular expression", /* REG_EEND */
+ "Regular expression too big", /* REG_ESIZE */
+ "Unmatched ) or \\)", /* REG_ERPAREN */
+ };
+
+/* 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'). */
+#define PATFETCH(c) \
+ do {if (p == pend) return REG_EEND; \
+ c = (unsigned char) *p++; \
+ if (translate) c = translate[c]; \
+ } while (0)
+
+/* 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. */
+#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
+
+
+/* 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 (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!! */
+#ifdef _MSC_VER
+/* 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 realloc
+#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); \
+ } \
+ } \
+ }
+
+#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"))
+
+static boolean group_in_compile_stack _RE_ARGS((compile_stack_type
+ compile_stack,
+ regnum_t regnum));
+
+#ifdef __FreeBSD__
+static int collate_range_cmp (a, b)
+ int a, b;
+{
+ int r;
+ static char s[2][2];
+
+ if ((unsigned char)a == (unsigned char)b)
+ return 0;
+ s[0][0] = a;
+ s[1][0] = b;
+ if ((r = strcoll(s[0], s[1])) == 0)
+ r = (unsigned char)a - (unsigned char)b;
+ return r;
+}
+#endif
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+ Returns one of error codes defined in `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. */
+
+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 tempory 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. */
+ char *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++)
+ printchar (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) 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)
+ 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) 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) 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) return REG_EBRACK;
+
+ PATFETCH (c);
+
+ /* \ might escape characters inside [...] and [^...]. */
+ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+ {
+ if (p == pend) 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 != ']')
+ 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) 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) 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) return REG_EBRACK;
+
+ for (;;)
+ {
+ PATFETCH (c);
+ if (c == ':' || c == ']' || 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 == ']')
+ {
+ 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)) return REG_ECTYPE;
+
+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) return REG_EBRACK;
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+ {
+ if ( (is_alnum && ISALNUM (ch))
+ || (is_alpha && ISALPHA (ch))
+ || (is_blank && ISBLANK (ch))
+ || (is_cntrl && ISCNTRL (ch))
+ || (is_digit && ISDIGIT (ch))
+ || (is_graph && ISGRAPH (ch))
+ || (is_lower && ISLOWER (ch))
+ || (is_print && ISPRINT (ch))
+ || (is_punct && ISPUNCT (ch))
+ || (is_space && ISSPACE (ch))
+ || (is_upper && ISUPPER (ch))
+ || (is_xdigit && ISXDIGIT (ch)))
+ SET_LIST_BIT (ch);
+ }
+ had_char_class = true;
+ }
+ 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) 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
+ 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
+ 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
+ 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
+ return REG_BADBR;
+ }
+
+ if (!(syntax & RE_NO_BK_BRACES))
+ {
+ if (c != '\\') return REG_EBRACE;
+
+ PATFETCH (c);
+ }
+
+ if (c != '}')
+ {
+ if (syntax & RE_NO_BK_BRACES)
+ goto unfetch_interval;
+ else
+ 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)
+ 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> <succed_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 (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (wordchar);
+ break;
+
+
+ case 'W':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ laststart = b;
+ BUF_PUSH (notwordchar);
+ break;
+
+
+ case '<':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbeg);
+ break;
+
+ case '>':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordend);
+ break;
+
+ case 'b':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (wordbound);
+ break;
+
+ case 'B':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (notwordbound);
+ break;
+
+ case '`':
+ if (re_syntax_options & RE_NO_GNU_OPS)
+ goto normal_char;
+ BUF_PUSH (begbuf);
+ break;
+
+ case '\'':
+ if (re_syntax_options & 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)
+ 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)
+ return REG_EPAREN;
+
+ 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 */
+
+ 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 : NULL;
+
+ 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;
+ char *translate;
+ reg_syntax_t syntax;
+ unsigned char *b;
+{
+ unsigned this_char;
+
+ const char *p = *p_ptr;
+ 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. */
+ range_start = ((unsigned char *) p)[-2];
+ range_end = ((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. */
+#ifdef __FreeBSD__
+ if (collate_range_cmp (range_start, range_end) > 0)
+#else
+ if (range_start > range_end)
+#endif
+ return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+#ifdef __FreeBSD__
+ for (this_char = 0; this_char < 1 << BYTEWIDTH; this_char++)
+ if ( collate_range_cmp (range_start, this_char) <= 0
+ && collate_range_cmp (this_char, range_end) <= 0
+ ) {
+ SET_LIST_BIT (TRANSLATE (this_char));
+ }
+#else
+ /* 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));
+ }
+#endif
+ return REG_NOERROR;
+}
+
+/* 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. */
+
+
+/* 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_SPACE each time we failed.
+ This is a variable only so users of regex can assign to it; we never
+ change it ourselves. */
+int re_max_failures = 2000;
+
+typedef const unsigned char *fail_stack_elt_t;
+
+typedef struct
+{
+ fail_stack_elt_t *stack;
+ unsigned size;
+ unsigned avail; /* Offset of next open position. */
+} fail_stack_type;
+
+#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 FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail])
+
+
+/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */
+
+#define INIT_FAIL_STACK() \
+ do { \
+ fail_stack.stack = (fail_stack_elt_t *) \
+ REGEX_ALLOCATE (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)
+
+
+/* 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 requires `destination' be declared. */
+
+#define DOUBLE_FAIL_STACK(fail_stack) \
+ ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \
+ ? 0 \
+ : ((fail_stack).stack = (fail_stack_elt_t *) \
+ REGEX_REALLOCATE ((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 PATTERN_OP 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(pattern_op, fail_stack) \
+ ((FAIL_STACK_FULL () \
+ && !DOUBLE_FAIL_STACK (fail_stack)) \
+ ? 0 \
+ : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \
+ 1))
+
+/* This pushes an item onto the failure stack. Must be a four-byte
+ value. Assumes the variable `fail_stack'. Probably should only
+ be called from within `PUSH_FAILURE_POINT'. */
+#define PUSH_FAILURE_ITEM(item) \
+ fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
+
+/* The complement operation. Assumes `fail_stack' is nonempty. */
+#define POP_FAILURE_ITEM() 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_ITEM
+#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM ()
+#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 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 */ \
+ s_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: %d\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);\
+ }
+
+#define PUSH_FAILURE_POINT2(pattern_place, string_place, failure_code) \
+ /* Push the info, starting with the registers. */ \
+ DEBUG_PRINT1 ("\n"); \
+ \
+ PUSH_FAILURE_POINT_LOOP (); \
+ \
+ DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\
+ PUSH_FAILURE_ITEM (lowest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\
+ PUSH_FAILURE_ITEM (highest_active_reg); \
+ \
+ DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \
+ PUSH_FAILURE_ITEM (pattern_place); \
+ \
+ DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \
+ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
+ size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ PUSH_FAILURE_ITEM (string_place); \
+ \
+ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \
+ DEBUG_PUSH (failure_id); \
+ } while (0)
+
+/* Pulled out of PUSH_FAILURE_POINT() to shorten the definition
+ of that macro. (for VAX C) */
+#define PUSH_FAILURE_POINT_LOOP() \
+ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
+ this_reg++) \
+ { \
+ DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \
+ DEBUG_STATEMENT (num_regs_pushed++); \
+ \
+ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
+ PUSH_FAILURE_ITEM (regstart[this_reg]); \
+ \
+ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
+ PUSH_FAILURE_ITEM (regend[this_reg]); \
+ \
+ DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \
+ 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_ITEM (reg_info[this_reg].word); \
+ }
+
+/* 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. */
+#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items. */
+#define NUM_FAILURE_ITEMS \
+ ((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 (fail_stack_elt_t failure_id;) \
+ s_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_ITEM (); \
+ if (string_temp != NULL) \
+ str = (const char *) string_temp; \
+ \
+ DEBUG_PRINT2 (" Popping string 0x%x: `", str); \
+ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \
+ DEBUG_PRINT1 ("'\n"); \
+ \
+ pat = (unsigned char *) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \
+ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \
+ \
+ POP_FAILURE_POINT2 (low_reg, high_reg, regstart, regend, reg_info);
+
+/* Pulled out of POP_FAILURE_POINT() to shorten the definition
+ of that macro. (for MSC 5.1) */
+#define POP_FAILURE_POINT2(low_reg, high_reg, regstart, regend, reg_info) \
+ \
+ /* Restore register info. */ \
+ high_reg = (active_reg_t) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \
+ \
+ low_reg = (active_reg_t) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \
+ \
+ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \
+ { \
+ DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \
+ \
+ reg_info[this_reg].word = POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \
+ \
+ regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \
+ \
+ regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \
+ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \
+ } \
+ \
+ DEBUG_STATEMENT (nfailure_points_popped++); \
+} /* POP_FAILURE_POINT */
+
+
+/* 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;
+ fail_stack_type fail_stack;
+#ifndef REGEX_MALLOC
+ char *destination;
+#endif
+ /* We don't push any register information onto the failure stack. */
+ unsigned num_regs = 0;
+
+ register char *fastmap = bufp->fastmap;
+ unsigned char *pattern = bufp->buffer;
+ const unsigned char *p = pattern;
+ register unsigned char *pend = pattern + bufp->used;
+
+ /* 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 (p != pend || !FAIL_STACK_EMPTY ())
+ {
+ if (p == pend)
+ {
+ bufp->can_be_null |= path_can_be_null;
+
+ /* Reset for next path. */
+ path_can_be_null = true;
+
+ p = fail_stack.stack[--fail_stack.avail];
+ }
+
+ /* We should never be about to go beyond the end of the pattern. */
+ assert (p < pend);
+
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((re_opcode_t) *p++))
+#else
+ switch ((re_opcode_t) *p++)
+#endif
+ {
+
+ /* 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;
+ return 0;
+
+
+ /* 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:
+ /* `.' matches anything ... */
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ fastmap[j] = 1;
+
+ /* ... except perhaps newline. */
+ if (!(bufp->syntax & RE_DOT_NEWLINE))
+ fastmap['\n'] = 0;
+
+ /* 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)
+ return 0;
+
+ /* 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 /* not 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] == 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))
+ 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;
+ return 0;
+} /* re_compile_fastmap */
+
+/* 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 = 0;
+ }
+}
+
+/* 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);
+}
+
+
+/* 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 char *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. */
+ if (endpos < -1)
+ range = -1 - 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;
+ }
+
+ /* 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 (bufp, string1, size1, string2, size2,
+ startpos, regs, stop);
+ 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 */
+
+/* Structure for per-register (a.k.a. per-group) information.
+ This must not be longer than one word, because we push this value
+ onto the failure stack. 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)
+
+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));
+
+/* 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 \
+ { \
+ active_reg_t r; \
+ for (r = lowest_active_reg; r <= highest_active_reg; r++) \
+ { \
+ MATCHED_SOMETHING (reg_info[r]) \
+ = EVER_MATCHED_SOMETHING (reg_info[r]) \
+ = 1; \
+ } \
+ } \
+ while (0)
+
+
+/* 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) ? (ptr) - string1 : (ptr) - string2 + size1)
+
+/* Registers are set to a sentinel when they haven't yet matched. */
+#define REG_UNSET_VALUE ((char *) -1)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+
+/* 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)
+
+/* 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))
+
+
+/* Free everything we malloc. */
+#ifdef REGEX_MALLOC
+#define FREE_VAR(var) if (var) free (var); var = NULL
+#define FREE_VARIABLES() \
+ do { \
+ FREE_VAR (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 /* not REGEX_MALLOC */
+/* Some MIPS systems (at least) want this to free alloca'd storage. */
+#define FREE_VARIABLES() alloca (0)
+#endif /* not REGEX_MALLOC */
+
+
+/* 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;
+ {
+ return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size);
+}
+#endif /* not emacs */
+
+
+/* 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;
+{
+ /* 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;
+
+ /* We use this to map every character in the string. */
+ char *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. */
+ fail_stack_type fail_stack;
+#ifdef DEBUG
+ static unsigned failure_id = 0;
+ unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#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.) */
+ const char **regstart = 0, **regend = 0;
+
+ /* 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. */
+ const char **old_regstart = 0, **old_regend = 0;
+
+ /* 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. */
+ register_info_type *reg_info = 0;
+
+ /* 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;
+ const char **best_regstart = 0, **best_regend = 0;
+
+ /* 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;
+
+ /* Used when we pop values we don't care about. */
+ const char **reg_dummy = 0;
+ register_info_type *reg_info_dummy = 0;
+
+#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 ();
+
+ /* 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;
+ }
+ }
+#ifdef REGEX_MALLOC
+ 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 /* REGEX_MALLOC */
+
+ /* 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; 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: ");
+ 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 (;;)
+ {
+ DEBUG_PRINT2 ("\n0x%x: ", p);
+
+ 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)
+ {
+ DEBUG_PRINT1 ("backtracking.\n");
+
+ if (!FAIL_STACK_EMPTY ())
+ { /* More failure points to try. */
+ boolean same_str_p = (FIRST_STRING_P (match_end)
+ == MATCHING_IN_FIRST_STRING);
+
+ /* If exceeds best match so far, save it. */
+ if (!best_regs_set
+ || (same_str_p && d > match_end)
+ || (!same_str_p && !MATCHING_IN_FIRST_STRING))
+ {
+ best_regs_set = true;
+ match_end = d;
+
+ DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+ for (mcnt = 1; mcnt < num_regs; mcnt++)
+ {
+ best_regstart[mcnt] = regstart[mcnt];
+ best_regend[mcnt] = regend[mcnt];
+ }
+ }
+ goto fail;
+ }
+
+ /* If no failure points, don't restore garbage. */
+ else if (best_regs_set)
+ {
+ 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; mcnt < num_regs; mcnt++)
+ {
+ regstart[mcnt] = best_regstart[mcnt];
+ regend[mcnt] = best_regend[mcnt];
+ }
+ }
+ } /* d != end_match_2 */
+
+ 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)
+ 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)
+ 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 ? d - string1
+ : d - string2 + size1);
+ }
+
+ /* Go through the first `min (num_regs, regs->num_regs)'
+ registers, since that is all we initialized. */
+ for (mcnt = 1; 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] = POINTER_TO_OFFSET (regstart[mcnt]);
+ regs->end[mcnt] = 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; mcnt < regs->num_regs; mcnt++)
+ regs->start[mcnt] = regs->end[mcnt] = -1;
+ } /* regs && !bufp->no_sub */
+
+ FREE_VARIABLES ();
+ 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);
+
+ return mcnt;
+ }
+
+ /* Otherwise match next pattern command. */
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((re_opcode_t) *p++))
+#else
+ switch ((re_opcode_t) *p++)
+#endif
+ {
+ /* 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;
+
+
+ /* 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 (translate[(unsigned char) *d++] != (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;
+
+ /* 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;
+ 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;
+
+ /* 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])
+ || (re_opcode_t) p[-3] == start_memory)
+ && (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 < *p + *(p + 1); r++)
+ {
+ regstart[r] = old_regstart[r];
+
+ /* xx why this test? */
+ if ((s_reg_t) old_regend[r] >= (s_reg_t) regstart[r])
+ regend[r] = old_regend[r];
+ }
+ }
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+ PUSH_FAILURE_POINT2(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)
+ : bcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+ }
+ }
+ 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);
+ DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+
+ PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+ PUSH_FAILURE_POINT2(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);
+ DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+
+ /* 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 \(\(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);
+ PUSH_FAILURE_POINT2(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. */
+ while (p2 + 2 < pend
+ && ((re_opcode_t) *p2 == stop_memory
+ || (re_opcode_t) *p2 == start_memory))
+ p2 += 3; /* Skip over args, too. */
+
+ /* 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];
+ 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 ((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");
+ }
+ }
+ }
+ }
+ 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. */
+
+
+ /* Unconditionally jump (without popping any failure points). */
+ case jump:
+ unconditional_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */
+ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+ p += mcnt; /* Do the jump. */
+ DEBUG_PRINT2 ("(to 0x%x).\n", p);
+ 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 (0, 0, -2);
+ PUSH_FAILURE_POINT2(0, 0, -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 (0, 0, -2);
+ PUSH_FAILURE_POINT2(0, 0, -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);
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt);
+ }
+ else if (mcnt == 0)
+ {
+ DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2);
+ 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);
+ 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);
+ DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt);
+ STORE_NUMBER (p1, mcnt);
+ break;
+ }
+
+ 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;
+
+ 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
+#ifdef emacs19
+ 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;
+#else /* not emacs19 */
+ case at_dot:
+ DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+ if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
+ goto fail;
+ break;
+#endif /* not emacs19 */
+
+ 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 ();
+ if (SYNTAX (*d++) != (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 ();
+ if (SYNTAX (*d++) == (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;
+ char *translate;
+{
+ register const unsigned char *p1 = (const unsigned char *) s1,
+ *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);
+
+ return re_error_msg[(int) ret];
+}
+
+/* Entry points compatible with 4.2 BSD regex library. We don't define
+ them if this is an Emacs or POSIX compilation. */
+
+#if !defined (emacs) && !defined (_POSIX_SOURCE)
+
+/* BSD has one and only one pattern buffer. */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+ const char *s;
+{
+ reg_errcode_t ret;
+
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return "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 "Memory exhausted";
+ re_comp_buf.allocated = 200;
+
+ re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+ if (re_comp_buf.fastmap == NULL)
+ return "Memory exhausted";
+ }
+
+ /* 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);
+
+ /* Yes, we're discarding `const' here. */
+ return (char *) re_error_msg[(int) ret];
+}
+
+
+int
+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 /* not emacs and not _POSIX_SOURCE */
+
+/* POSIX.2 functions. Don't define these for Emacs. */
+
+#ifndef emacs
+#if !NO_POSIX_COMPAT
+
+/* 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 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 = (char *) malloc (CHAR_SET_SIZE);
+ 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;
+}
+
+
+/* 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;
+}
+
+
+/* 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 >= (sizeof (re_error_msg) / sizeof (re_error_msg[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 = re_error_msg[errcode];
+
+ /* POSIX doesn't require that we do anything in this case, but why
+ not be nice. */
+ if (! msg)
+ msg = "Success";
+
+ msg_size = strlen (msg) + 1; /* Includes the null. */
+
+ if (errbuf_size != 0)
+ {
+ if (msg_size > errbuf_size)
+ {
+ strncpy (errbuf, msg, errbuf_size - 1);
+ errbuf[errbuf_size - 1] = 0;
+ }
+ else
+ strcpy (errbuf, msg);
+ }
+
+ return msg_size;
+}
+
+
+/* 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;
+}
+
+#endif /* !NO_POSIX_COMPAT */
+#endif /* not emacs */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/regex.h b/gnu/lib/libregex/regex.h
new file mode 100644
index 0000000..e42c810
--- /dev/null
+++ b/gnu/lib/libregex/regex.h
@@ -0,0 +1,517 @@
+/* Definitions for data structures and routines for the regular
+ expression library, version 0.12.
+
+ Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU 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. */
+
+#ifndef __REGEXP_LIBRARY_H__
+#define __REGEXP_LIBRARY_H__
+
+/* 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>. */
+
+#ifdef VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+ should be there. */
+#include <stddef.h>
+#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 s_reg_t;
+typedef unsigned long 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 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 (1L)
+
+/* 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, do not process the GNU regex operators.
+ IF not set, then the GNU regex operators are recognized. */
+#define RE_NO_GNU_OPS (RE_UNMATCHED_RIGHT_PAREN_ORD << 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_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
+{
+ 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. */
+
+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 allocated;
+
+ /* Number of bytes actually used in `buffer'. */
+ unsigned long 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. */
+ char *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;
+
+
+/* search.c (search_buffer) in Emacs needs this one opcode value. It is
+ defined both in `regex.c' and here. */
+#define RE_EXACTN_VALUE 1
+
+/* 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. */
+
+#ifdef __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));
+
+/* 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));
+
+
+/* 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));
+
+
+/* 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));
+
+
+/* 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));
+
+
+/* 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));
+
+
+/* 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));
+
+
+/* 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));
+
+/* 4.2 bsd compatibility. */
+extern char *re_comp _RE_ARGS ((const char *));
+extern int re_exec _RE_ARGS ((const char *));
+
+/* POSIX compatibility. */
+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 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));
+
+#ifdef __cplusplus
+}
+#endif /* C++ */
+
+#endif /* not __REGEXP_LIBRARY_H__ */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/test/ChangeLog b/gnu/lib/libregex/test/ChangeLog
new file mode 100644
index 0000000..f0265bb
--- /dev/null
+++ b/gnu/lib/libregex/test/ChangeLog
@@ -0,0 +1,77 @@
+Thu Mar 25 21:23:43 1993 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * debugmalloc.c: #include <string.h>, and remove declaration of
+ memcpy.
+
+Sun Dec 13 20:59:32 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * tregress.c (test_regress): Add regression test for matching
+ "[a-a]" against "a" with the upcase translation map.
+
+ * iregex.c (print_regs): Don't print a newline after the register
+ contents.
+ (main): Instead, write out newlines here after printing match and
+ search results; this way, we get a newline whether or not the
+ pattern matched.
+
+Fri Dec 11 03:30:50 1992 Jim Blandy (jimb@totoro.cs.oberlin.edu)
+
+ * tregress.c (test_regress): Add new test to catch bug fixed by
+ change to regex.c today.
+
+ * Makefile.in (dregex.o): Depend on `../regex.[ch]', not `regex.[ch]'.
+
+Sun Nov 15 07:51:40 1992 Karl Berry (karl@cs.umb.edu)
+
+ * debugmalloc.c (memcpy): Declare; also, include <assert.h>.
+
+ * psx-interf.c (fill_pmatch): Declare offsets as `regoff_t'
+ instead of `off_t'.
+
+Thu Nov 12 11:29:58 1992 Karl Berry (karl@cs.umb.edu)
+
+ * iregex.c (main): Remove unused variable `c'; initialize
+ the char array in C code; only call print_regs if the match and
+ search succeeded.
+ (strlen): Declare.
+
+ * tregress.c (test_regress): Bug from enami.
+
+Tue Nov 10 10:36:53 1992 Karl Berry (karl@cs.umb.edu)
+
+ * tregress.c (test_regress): Remove Emacs 19 diff bug from rms, as
+ it was never the right thing to test anyway, and the test itself
+ had bugs in it.
+
+Mon Nov 9 10:09:40 1992 Karl Berry (karl@cs.umb.edu)
+
+ * tregress.c (test_regress): Bug from meyering.
+
+Thu Sep 24 10:48:34 1992 Karl Berry (karl@cs.umb.edu)
+
+ * Makefile.in: avoid $< (except in implicit rule).
+
+Sat Sep 19 15:38:29 1992 Karl Berry (karl@hayley)
+
+ * Makefile.in (TAGS): include regex.c and regex.h.
+
+Wed Sep 16 09:29:27 1992 Karl Berry (karl@hayley)
+
+ * xmalloc.c (xmalloc): use char *, not void *, as some compilers
+ bomb out on the latter.
+
+ * Makefile.in (LOADLIBES): use LIBS instead, as that what's
+ Autoconf wants to define.
+
+ * other.c: remove tests for ^/$ around newlines.
+
+Tue Sep 15 11:01:15 1992 Karl Berry (karl@hayley)
+
+ * fileregex.c (main): call re_search_2 instead of re_search.
+
+ * Makefile.in (regex.o): make target dregex.o, so VPATH doesn't
+ find ../regex.o.
+
+Sun Sep 13 06:50:03 1992 Karl Berry (karl@hayley)
+
+ * Created.
diff --git a/gnu/lib/libregex/test/Makefile b/gnu/lib/libregex/test/Makefile
new file mode 100644
index 0000000..218d2a1
--- /dev/null
+++ b/gnu/lib/libregex/test/Makefile
@@ -0,0 +1,171 @@
+# $FreeBSD$
+
+# Generated automatically from Makefile.in by configure.
+# Makefile for regex testing.
+#
+# 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, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You 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.
+
+CPPFLAGS =
+CFLAGS = -g
+LDFLAGS =
+
+srcdir = .
+VPATH = .:../.
+
+CC = gcc
+DEFS = -DHAVE_STRING_H=1
+LIBS = $(LOADLIBES)
+
+ETAGS = etags
+SHELL = /bin/sh
+
+debug = -DDEBUG
+ALL_CPPFLAGS = -I. -I$(srcdir) -I../$(srcdir) $(DEFS) $(CPPFLAGS) $(debug)
+
+.c.o:
+ $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c $<
+
+
+# Define this as `../regex.o' to get the optimized version.
+regex_o = dregex.o
+test_h = test.h
+test_o = test.o bsd-interf.o other.o tregress.o psx-basic.o psx-extend.o \
+ psx-generic.o psx-group.o psx-interf.o psx-interv.o
+common_o = printchar.o upcase.o xmalloc.o $(malloc)
+
+# We have a lot of mallocs we can try when we run afoul of strange bugs.
+malloc =
+#malloc = # the libc malloc
+#malloc = g++malloc.o
+#malloc = debugmalloc.o
+#malloc = emacsmalloc.o
+emacsmallocflags = -Drcheck -Dbotch=abort -DUSG
+
+# default is to do nothing.
+default:
+
+all: regex syntax
+
+regex: $(regex_o) $(common_o) $(test_o) main.o
+ $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
+
+# As long as we're doing tests, we enable debugging.
+dregex.o: ../regex.c ../regex.h
+ rm -f $@
+ $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c ../$(srcdir)/regex.c
+ mv -f regex.o $@
+
+# iregex is the interactive regex.
+iregex: $(common_o) $(regex_o) iregex.o
+ $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
+
+# fileregex searches for an r.e. in every line of a given file.
+fileregex_o = fileregex.o printchar.o $(regex_o)
+fileregex: $(fileregex_o)
+ $(CC) -o $@ $(LDFLAGS) $(fileregex_o) $(LIBS)
+
+# cppregex is regex with a preprocessed regex.c. Useful when the
+# problem is inside some macro.
+cppregex: regexcpp.o $(common_o) $(test_o) main.o
+ $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
+
+regexcpp.o: regexcpp.c
+
+regexcpp.c: regex.c regexcpp.sed
+ rm -f regexcpp.c
+ $(CC) -E $(ALL_CPPFLAGS) ../$(srcdir)/regex.c \
+ | egrep -v '^#|^ *$$' \
+ | sed -f regexcpp.sed \
+ > regexcpp.c
+ chmod a-w regexcpp.c
+
+# Have to give this malloc special flags.
+emacsmalloc.o: emacsmalloc.c
+ $(CC) -c $(CFLAGS) $(ALL_CPPFLAGS) $(emacsmallocflags) \
+ ../$(srcdir)/test/emacsmalloc.c
+
+syntax: syntax.o
+ $(CC) $(CFLAGS) -o $@ syntax.o
+
+syntax.c: syntax.skel bits
+ sed '/\[\[\[replace.*\]\]\]/r bits' syntax.skel > $@
+
+bits: regex.h
+ sed -n 1,/RE_SYNTAX_EMACS/p ../$(srcdir)/regex.h \
+ | grep "#define RE_.*1" \
+ | sed 's/^#define \(RE_[A-Z_]*\) .*/ TEST_BIT (\1);/' > $@
+
+check: regex
+ ./regex
+
+TAGS: regex.c regex.h *.h *.c
+ $(ETAGS) -t $^
+
+depend:
+ gcc -MM $(ALL_CPPFLAGS) *.c > /tmp/depend
+.PHONY: depend
+
+install:
+.PHONY: install
+
+clean mostlyclean:
+ rm -f *.o regex cppregex iregex fileregex regexcpp.c syntax
+
+distclean: clean
+ rm -f bits syntax.c Makefile
+
+extraclean: distclean
+ rm -f *~* *\#* patch* *.orig *.rej *.bak core a.out
+
+realclean: distclean
+ rm -f TAGS
+
+Makefile: Makefile.in ../config.status
+ (cd ..; sh config.status)
+
+# Prevent GNU make 3 from overflowing arg limit on system V.
+.NOEXPORT:
+
+# Assumes $(distdir) is the place to put our files.
+distfiles = ChangeLog TAGS *.in *.c *.h regexcpp.sed syntax.skel
+dist: Makefile TAGS
+ mkdir $(distdir)
+ ln $(distfiles) $(distdir)
+
+# Automatically-generated dependencies below here.
+alloca.o : alloca.c
+bsd-interf.o : bsd-interf.c
+debugmalloc.o : debugmalloc.c
+emacsmalloc.o : emacsmalloc.c getpagesize.h
+fileregex.o : fileregex.c .././regex.h
+g++malloc.o : g++malloc.c //usr/include/stdio.h getpagesize.h
+iregex.o : iregex.c .././regex.h
+main.o : main.c test.h .././regex.h
+malloc-test.o : malloc-test.c
+other.o : other.c test.h .././regex.h
+printchar.o : printchar.c
+psx-basic.o : psx-basic.c test.h .././regex.h
+psx-extend.o : psx-extend.c test.h .././regex.h
+psx-generic.o : psx-generic.c test.h .././regex.h
+psx-group.o : psx-group.c test.h .././regex.h
+psx-interf.o : psx-interf.c test.h .././regex.h
+psx-interv.o : psx-interv.c test.h .././regex.h
+syntax.o : syntax.c .././regex.h
+test.o : test.c test.h .././regex.h
+tregress.o : tregress.c test.h .././regex.h
+upcase.o : upcase.c
+xmalloc.o : xmalloc.c
diff --git a/gnu/lib/libregex/test/Makefile.in b/gnu/lib/libregex/test/Makefile.in
new file mode 100644
index 0000000..80ec09c
--- /dev/null
+++ b/gnu/lib/libregex/test/Makefile.in
@@ -0,0 +1,170 @@
+# $FreeBSD$
+
+# Makefile for regex testing.
+#
+# 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, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You 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.
+
+CPPFLAGS =
+CFLAGS = -g
+LDFLAGS =
+
+srcdir = @srcdir@
+VPATH = @srcdir@:../@srcdir@
+
+CC = @CC@
+DEFS = @DEFS@
+LIBS = @LIBS@ $(LOADLIBES)
+
+ETAGS = etags
+SHELL = /bin/sh
+
+debug = -DDEBUG
+ALL_CPPFLAGS = -I. -I$(srcdir) -I../$(srcdir) $(DEFS) $(CPPFLAGS) $(debug)
+
+.c.o:
+ $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c $<
+
+
+# Define this as `../regex.o' to get the optimized version.
+regex_o = dregex.o
+test_h = test.h
+test_o = test.o bsd-interf.o other.o tregress.o psx-basic.o psx-extend.o \
+ psx-generic.o psx-group.o psx-interf.o psx-interv.o
+common_o = printchar.o upcase.o xmalloc.o $(malloc)
+
+# We have a lot of mallocs we can try when we run afoul of strange bugs.
+malloc = @ALLOCA@
+#malloc = # the libc malloc
+#malloc = g++malloc.o
+#malloc = debugmalloc.o
+#malloc = emacsmalloc.o
+emacsmallocflags = -Drcheck -Dbotch=abort -DUSG
+
+# default is to do nothing.
+default:
+
+all: regex syntax
+
+regex: $(regex_o) $(common_o) $(test_o) main.o
+ $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
+
+# As long as we're doing tests, we enable debugging.
+dregex.o: ../regex.c ../regex.h
+ rm -f $@
+ $(CC) $(ALL_CPPFLAGS) $(CFLAGS) -c ../$(srcdir)/regex.c
+ mv -f regex.o $@
+
+# iregex is the interactive regex.
+iregex: $(common_o) $(regex_o) iregex.o
+ $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
+
+# fileregex searches for an r.e. in every line of a given file.
+fileregex_o = fileregex.o printchar.o $(regex_o)
+fileregex: $(fileregex_o)
+ $(CC) -o $@ $(LDFLAGS) $(fileregex_o) $(LIBS)
+
+# cppregex is regex with a preprocessed regex.c. Useful when the
+# problem is inside some macro.
+cppregex: regexcpp.o $(common_o) $(test_o) main.o
+ $(CC) -o $@ $(LDFLAGS) $^ $(LIBS)
+
+regexcpp.o: regexcpp.c
+
+regexcpp.c: regex.c regexcpp.sed
+ rm -f regexcpp.c
+ $(CC) -E $(ALL_CPPFLAGS) ../$(srcdir)/regex.c \
+ | egrep -v '^#|^ *$$' \
+ | sed -f regexcpp.sed \
+ > regexcpp.c
+ chmod a-w regexcpp.c
+
+# Have to give this malloc special flags.
+emacsmalloc.o: emacsmalloc.c
+ $(CC) -c $(CFLAGS) $(ALL_CPPFLAGS) $(emacsmallocflags) \
+ ../$(srcdir)/test/emacsmalloc.c
+
+syntax: syntax.o
+ $(CC) $(CFLAGS) -o $@ syntax.o
+
+syntax.c: syntax.skel bits
+ sed '/\[\[\[replace.*\]\]\]/r bits' syntax.skel > $@
+
+bits: regex.h
+ sed -n 1,/RE_SYNTAX_EMACS/p ../$(srcdir)/regex.h \
+ | grep "#define RE_.*1" \
+ | sed 's/^#define \(RE_[A-Z_]*\) .*/ TEST_BIT (\1);/' > $@
+
+check: regex
+ ./regex
+
+TAGS: regex.c regex.h *.h *.c
+ $(ETAGS) -t $^
+
+depend:
+ gcc -MM $(ALL_CPPFLAGS) *.c > /tmp/depend
+.PHONY: depend
+
+install:
+.PHONY: install
+
+clean mostlyclean:
+ rm -f *.o regex cppregex iregex fileregex regexcpp.c syntax
+
+distclean: clean
+ rm -f bits syntax.c Makefile
+
+extraclean: distclean
+ rm -f *~* *\#* patch* *.orig *.rej *.bak core a.out
+
+realclean: distclean
+ rm -f TAGS
+
+Makefile: Makefile.in ../config.status
+ (cd ..; sh config.status)
+
+# Prevent GNU make 3 from overflowing arg limit on system V.
+.NOEXPORT:
+
+# Assumes $(distdir) is the place to put our files.
+distfiles = ChangeLog TAGS *.in *.c *.h regexcpp.sed syntax.skel
+dist: Makefile TAGS
+ mkdir $(distdir)
+ ln $(distfiles) $(distdir)
+
+# Automatically-generated dependencies below here.
+alloca.o : alloca.c
+bsd-interf.o : bsd-interf.c
+debugmalloc.o : debugmalloc.c
+emacsmalloc.o : emacsmalloc.c getpagesize.h
+fileregex.o : fileregex.c .././regex.h
+g++malloc.o : g++malloc.c //usr/include/stdio.h getpagesize.h
+iregex.o : iregex.c .././regex.h
+main.o : main.c test.h .././regex.h
+malloc-test.o : malloc-test.c
+other.o : other.c test.h .././regex.h
+printchar.o : printchar.c
+psx-basic.o : psx-basic.c test.h .././regex.h
+psx-extend.o : psx-extend.c test.h .././regex.h
+psx-generic.o : psx-generic.c test.h .././regex.h
+psx-group.o : psx-group.c test.h .././regex.h
+psx-interf.o : psx-interf.c test.h .././regex.h
+psx-interv.o : psx-interv.c test.h .././regex.h
+syntax.o : syntax.c .././regex.h
+test.o : test.c test.h .././regex.h
+tregress.o : tregress.c test.h .././regex.h
+upcase.o : upcase.c
+xmalloc.o : xmalloc.c
diff --git a/gnu/lib/libregex/test/alloca.c b/gnu/lib/libregex/test/alloca.c
new file mode 100644
index 0000000..d8b6748
--- /dev/null
+++ b/gnu/lib/libregex/test/alloca.c
@@ -0,0 +1,194 @@
+/*
+ alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+ last edit: 86/05/30 rms
+ include config.h, since on VMS it renames some symbols.
+ Use xmalloc instead of malloc.
+
+ This implementation of the PWB library alloca() function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+
+ It should work under any C implementation that uses an
+ actual procedure stack (as opposed to a linked list of
+ frames). There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca()-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+#ifndef alloca /* If compiling with GCC, this file's not needed. */
+
+#ifdef __STDC__
+typedef void *pointer; /* generic pointer type */
+#else
+typedef char *pointer; /* generic pointer type */
+#endif
+
+#define NULL 0 /* null pointer constant */
+
+extern void free();
+extern pointer xmalloc();
+
+/*
+ Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+*/
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* known at compile-time */
+
+#else /* STACK_DIRECTION == 0; need run-time code */
+
+static int stack_dir; /* 1 or -1 once known */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+ static char *addr = NULL; /* address of first
+ `dummy', once known */
+ auto char dummy; /* to get stack address */
+
+ if (addr == NULL)
+ { /* initial entry */
+ addr = &dummy;
+
+ find_stack_direction (); /* recurse once */
+ }
+ else /* second entry */
+ if (&dummy > addr)
+ stack_dir = 1; /* stack grew upward */
+ else
+ stack_dir = -1; /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+ An "alloca header" is used to:
+ (a) chain together all alloca()ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc()
+ alignment chunk size. The following default should work okay.
+*/
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* to force sizeof(header) */
+ struct
+ {
+ union hdr *next; /* for chaining headers */
+ char *deep; /* for stack depth measure */
+ } h;
+} header;
+
+/*
+ alloca( size ) returns a pointer to at least `size' bytes of
+ storage which will be automatically reclaimed upon exit from
+ the procedure that called alloca(). Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size) /* returns pointer to storage */
+ unsigned size; /* # bytes to allocate */
+{
+ auto char probe; /* probes stack depth: */
+ register char *depth = &probe;
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* unknown growth direction */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca()ed storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* traverses linked list */
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* collect garbage */
+
+ hp = np; /* -> next header */
+ }
+ else
+ break; /* rest are not deeper */
+
+ last_alloca_header = hp; /* -> last valid storage */
+ }
+
+ if (size == 0)
+ return NULL; /* no allocation required */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = xmalloc (sizeof (header) + size);
+ /* address of header */
+
+ ((header *)new)->h.next = last_alloca_header;
+ ((header *)new)->h.deep = depth;
+
+ last_alloca_header = (header *)new;
+
+ /* User storage begins just after header. */
+
+ return (pointer)((char *)new + sizeof(header));
+ }
+}
+
+#endif /* no alloca */
diff --git a/gnu/lib/libregex/test/bsd-interf.c b/gnu/lib/libregex/test/bsd-interf.c
new file mode 100644
index 0000000..226a513
--- /dev/null
+++ b/gnu/lib/libregex/test/bsd-interf.c
@@ -0,0 +1,38 @@
+/* bsd-interf.c: test BSD interface. */
+
+#ifndef _POSIX_SOURCE /* whole file */
+
+#include "test.h"
+
+void
+test_berk_search (pattern, string)
+ const char *pattern;
+ char *string;
+{
+ const char *return_value = re_comp (pattern);
+
+ if (return_value != 0)
+ {
+ printf ("This didn't compile: `%s'.\n", pattern);
+ printf (" The error message was: `%s'.\n", return_value);
+ }
+ else
+ if (test_should_match && re_exec (string) != strlen (string))
+ {
+ printf ("Should have matched but didn't:\n");
+ printf (" The pattern was: %s.\n", pattern);
+ if (string)
+ printf (" The string was: `%s'.'n", string);
+ else
+ printf (" The string was empty.\n");
+ }
+}
+
+
+void
+test_bsd_interface ()
+{
+ test_berk_search ("a", "ab");
+}
+
+#endif /* _POSIX_SOURCE */
diff --git a/gnu/lib/libregex/test/debugmalloc.c b/gnu/lib/libregex/test/debugmalloc.c
new file mode 100644
index 0000000..6caeb65
--- /dev/null
+++ b/gnu/lib/libregex/test/debugmalloc.c
@@ -0,0 +1,273 @@
+/* debugmalloc.c: a malloc for debugging purposes. */
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+static unsigned trace = 0;
+#define TRACE(s) if (trace) fprintf (stderr, "%s", s)
+#define TRACE1(s, e1) if (trace) fprintf (stderr, s, e1)
+#define TRACE2(s, e1, e2) if (trace) fprintf (stderr, s, e1, e2)
+#define TRACE3(s, e1, e2, e3) if (trace) fprintf (stderr, s, e1, e2, e3)
+#define TRACE4(s, e1, e2, e3, e4) \
+ if (trace) fprintf (stderr, s, e1, e2, e3, e4)
+
+typedef char *address;
+
+
+/* Wrap our calls to sbrk. */
+
+address
+xsbrk (incr)
+ int incr;
+{
+ extern char *sbrk ();
+ address ret = sbrk (incr);
+
+ if (ret == (address) -1)
+ {
+ perror ("sbrk"); /* Actually, we should return NULL, not quit. */
+ abort ();
+ }
+
+ return ret;
+}
+
+
+
+typedef struct chunk_struct
+{
+ /* This is the size (in bytes) that has actually been actually
+ allocated, not the size that the user requested. */
+ unsigned alloc_size;
+
+ /* This is the size the user requested. */
+ unsigned user_size;
+
+ /* Points to the next block in one of the lists. */
+ struct chunk_struct *next;
+
+ /* Now comes the user's memory. */
+ address user_mem;
+
+ /* After the user's memory is a constant. */
+} *chunk;
+
+#define MALLOC_OVERHEAD 16
+
+/* We might play around with the `user_size' field, but the amount of
+ memory that is actually available in the chunk is always the size
+ allocated minus the overhead. */
+#define USER_ALLOC(c) ((c)->alloc_size - MALLOC_OVERHEAD)
+
+/* Given a pointer to a malloc-allocated block, the beginning of the
+ chunk should always be MALLOC_OVERHEAD - 4 bytes back, since the only
+ overhead after the user memory is the constant. */
+
+chunk
+mem_to_chunk (mem)
+ address mem;
+{
+ return (chunk) (mem - (MALLOC_OVERHEAD - 4));
+}
+
+
+/* The other direction is even easier, since the user's memory starts at
+ the `user_mem' member in the chunk. */
+
+address
+chunk_to_mem (c)
+ chunk c;
+{
+ return (address) &(c->user_mem);
+}
+
+
+
+/* We keep both all the allocated chunks and all the free chunks on
+ lists. Since we put the next pointers in the chunk structure, we
+ don't need a separate chunk_list structure. */
+chunk alloc_list = NULL, free_list = NULL;
+
+
+/* We always append the new chunk at the beginning of the list. */
+
+void
+chunk_insert (chunk_list, new_c)
+ chunk *chunk_list;
+ chunk new_c;
+{
+ chunk c = *chunk_list; /* old beginning of list */
+
+ TRACE3 (" Inserting 0x%x at the beginning of 0x%x, before 0x%x.\n",
+ new_c, chunk_list, c);
+
+ *chunk_list = new_c;
+ new_c->next = c;
+}
+
+
+/* Thus, removing an element means we have to search until we find it.
+ Have to delete before we insert, since insertion changes the next
+ pointer, which we need to put it on the other list. */
+
+void
+chunk_delete (chunk_list, dead_c)
+ chunk *chunk_list;
+ chunk dead_c;
+{
+ chunk c = *chunk_list;
+ chunk prev_c = NULL;
+
+ TRACE2 (" Deleting 0x%x from 0x%x:", dead_c, chunk_list);
+
+ while (c != dead_c && c != NULL)
+ {
+ TRACE1 (" 0x%x", c);
+ prev_c = c;
+ c = c->next;
+ }
+
+ if (c == NULL)
+ {
+ fprintf (stderr, "Chunk at 0x%x not found on list.\n", dead_c);
+ abort ();
+ }
+
+ if (prev_c == NULL)
+ {
+ TRACE1 (".\n Setting head to 0x%x.\n", c->next);
+ *chunk_list = c->next;
+ }
+ else
+ {
+ TRACE2 (".\n Linking next(0x%x) to 0x%x.\n", prev_c, c->next);
+ prev_c->next = c->next;
+ }
+}
+
+
+/* See if a list is hunky-dory. */
+
+void
+validate_list (chunk_list)
+ chunk *chunk_list;
+{
+ chunk c;
+
+ TRACE1 (" Validating list at 0x%x:", chunk_list);
+
+ for (c = *chunk_list; c != NULL; c = c->next)
+ {
+ assert (c->user_size < c->alloc_size);
+ assert (memcmp (chunk_to_mem (c) + c->user_size, "Karl", 4));
+ TRACE2 (" 0x%x/%d", c, c->user_size);
+ }
+
+ TRACE (".\n");
+}
+
+
+/* See if we have a free chunk of a given size. We'll take the first
+ one that is big enough. */
+
+chunk
+free_list_available (needed)
+ unsigned needed;
+{
+ chunk c;
+
+ TRACE1 (" Checking free list for %d bytes:", needed);
+
+ if (free_list == NULL)
+ {
+ return NULL;
+ }
+
+ c = free_list;
+
+ while (c != NULL && USER_ALLOC (c) < needed)
+ {
+ TRACE2 (" 0x%x/%d", c, USER_ALLOC (c));
+ c = c->next;
+ }
+
+ TRACE1 ("\n Returning 0x%x.\n", c);
+ return c;
+}
+
+
+
+
+address
+malloc (n)
+ unsigned n;
+{
+ address new_mem;
+ chunk c;
+
+ TRACE1 ("Mallocing %d bytes.\n", n);
+
+ validate_list (&free_list);
+ validate_list (&alloc_list);
+
+ c = free_list_available (n);
+
+ if (c == NULL)
+ { /* Nothing suitable on free list. Allocate a new chunk. */
+ TRACE (" not on free list.\n");
+ c = (chunk) xsbrk (n + MALLOC_OVERHEAD);
+ c->alloc_size = n + MALLOC_OVERHEAD;
+ }
+ else
+ { /* Found something on free list. Don't split it, just use as is. */
+ TRACE (" found on free list.\n");
+ chunk_delete (&free_list, c);
+ }
+
+ /* If we took this from the free list, then the user size might be
+ different now, and consequently the constant at the end might be in
+ the wrong place. */
+ c->user_size = n;
+ new_mem = chunk_to_mem (c);
+ memcpy (new_mem + n, "Karl", 4);
+ chunk_insert (&alloc_list, c);
+
+ TRACE2 ("Malloc returning 0x%x (chunk 0x%x).\n", new_mem, c);
+ return new_mem;
+}
+
+
+address
+realloc (mem, n)
+ address mem;
+ unsigned n;
+{
+ void free ();
+ chunk c = mem_to_chunk (mem);
+ address new_mem;
+
+ TRACE3 ("Reallocing %d bytes at 0x%x (chunk 0x%x).\n", n, mem, c);
+
+ new_mem = malloc (n);
+ memcpy (new_mem, mem, c->user_size);
+ free (mem);
+
+ return new_mem;
+}
+
+
+void
+free (mem)
+ address mem;
+{
+ chunk c = mem_to_chunk (mem);
+
+ TRACE2 ("Freeing memory at 0x%x (chunk at 0x%x).\n", mem, c);
+
+ validate_list (&free_list);
+ validate_list (&alloc_list);
+
+ chunk_delete (&alloc_list, c);
+ chunk_insert (&free_list, c);
+}
diff --git a/gnu/lib/libregex/test/emacsmalloc.c b/gnu/lib/libregex/test/emacsmalloc.c
new file mode 100644
index 0000000..ad7c4da
--- /dev/null
+++ b/gnu/lib/libregex/test/emacsmalloc.c
@@ -0,0 +1,844 @@
+/* dynamic memory allocation for GNU.
+ Copyright (C) 1985, 1987 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In other words, you are welcome to use, share and improve this program.
+You are forbidden to forbid anyone else to use, share and improve
+what you give them. Help stamp out software-hoarding! */
+
+
+/*
+ * @(#)nmalloc.c 1 (Caltech) 2/21/82
+ *
+ * U of M Modified: 20 Jun 1983 ACT: strange hacks for Emacs
+ *
+ * Nov 1983, Mike@BRL, Added support for 4.1C/4.2 BSD.
+ *
+ * This is a very fast storage allocator. It allocates blocks of a small
+ * number of different sizes, and keeps free lists of each size. Blocks
+ * that don't exactly fit are passed up to the next larger size. In this
+ * implementation, the available sizes are (2^n)-4 (or -16) bytes long.
+ * This is designed for use in a program that uses vast quantities of
+ * memory, but bombs when it runs out. To make it a little better, it
+ * warns the user when he starts to get near the end.
+ *
+ * June 84, ACT: modified rcheck code to check the range given to malloc,
+ * rather than the range determined by the 2-power used.
+ *
+ * Jan 85, RMS: calls malloc_warning to issue warning on nearly full.
+ * No longer Emacs-specific; can serve as all-purpose malloc for GNU.
+ * You should call malloc_init to reinitialize after loading dumped Emacs.
+ * Call malloc_stats to get info on memory stats if MSTATS turned on.
+ * realloc knows how to return same block given, just changing its size,
+ * if the power of 2 is correct.
+ */
+
+/*
+ * nextf[i] is the pointer to the next free block of size 2^(i+3). The
+ * smallest allocatable block is 8 bytes. The overhead information will
+ * go in the first int of the block, and the returned pointer will point
+ * to the second.
+ *
+#ifdef MSTATS
+ * nmalloc[i] is the difference between the number of mallocs and frees
+ * for a given block size.
+#endif MSTATS
+ */
+
+#ifdef emacs
+/* config.h specifies which kind of system this is. */
+#include "config.h"
+#include <signal.h>
+#else
+
+/* Determine which kind of system this is. */
+#include <sys/types.h>
+#include <signal.h>
+
+#include <string.h>
+#define bcopy(s,d,n) memcpy ((d), (s), (n))
+#define bcmp(s1,s2,n) memcmp ((s1), (s2), (n))
+#define bzero(s,n) memset ((s), 0, (n))
+
+#ifndef SIGTSTP
+#ifndef VMS
+#ifndef USG
+#define USG
+#endif
+#endif /* not VMS */
+#else /* SIGTSTP */
+#ifdef SIGIO
+#define BSD4_2
+#endif /* SIGIO */
+#endif /* SIGTSTP */
+
+#endif /* not emacs */
+
+/* Define getpagesize () if the system does not. */
+#include "getpagesize.h"
+
+#ifdef BSD
+#ifdef BSD4_1
+#include <sys/vlimit.h> /* warn the user when near the end */
+#else /* if 4.2 or newer */
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* if 4.2 or newer */
+#endif
+
+#ifdef VMS
+#include "vlimit.h"
+#endif
+
+extern char *start_of_data ();
+
+#ifdef BSD
+#ifndef DATA_SEG_BITS
+#define start_of_data() &etext
+#endif
+#endif
+
+#ifndef emacs
+#define start_of_data() &etext
+#endif
+
+#define ISALLOC ((char) 0xf7) /* magic byte that implies allocation */
+#define ISFREE ((char) 0x54) /* magic byte that implies free block */
+ /* this is for error checking only */
+#define ISMEMALIGN ((char) 0xd6) /* Stored before the value returned by
+ memalign, with the rest of the word
+ being the distance to the true
+ beginning of the block. */
+
+extern char etext;
+
+/* These two are for user programs to look at, when they are interested. */
+
+unsigned int malloc_sbrk_used; /* amount of data space used now */
+unsigned int malloc_sbrk_unused; /* amount more we can have */
+
+/* start of data space; can be changed by calling init_malloc */
+static char *data_space_start;
+
+#ifdef MSTATS
+static int nmalloc[30];
+static int nmal, nfre;
+#endif /* MSTATS */
+
+/* If range checking is not turned on, all we have is a flag indicating
+ whether memory is allocated, an index in nextf[], and a size field; to
+ realloc() memory we copy either size bytes or 1<<(index+3) bytes depending
+ on whether the former can hold the exact size (given the value of
+ 'index'). If range checking is on, we always need to know how much space
+ is allocated, so the 'size' field is never used. */
+
+struct mhead {
+ char mh_alloc; /* ISALLOC or ISFREE */
+ char mh_index; /* index in nextf[] */
+/* Remainder are valid only when block is allocated */
+ unsigned short mh_size; /* size, if < 0x10000 */
+#ifdef rcheck
+ unsigned mh_nbytes; /* number of bytes allocated */
+ int mh_magic4; /* should be == MAGIC4 */
+#endif /* rcheck */
+};
+
+/* Access free-list pointer of a block.
+ It is stored at block + 4.
+ This is not a field in the mhead structure
+ because we want sizeof (struct mhead)
+ to describe the overhead for when the block is in use,
+ and we do not want the free-list pointer to count in that. */
+
+#define CHAIN(a) \
+ (*(struct mhead **) (sizeof (char *) + (char *) (a)))
+
+#ifdef rcheck
+
+/* To implement range checking, we write magic values in at the beginning and
+ end of each allocated block, and make sure they are undisturbed whenever a
+ free or a realloc occurs. */
+/* Written in each of the 4 bytes following the block's real space */
+#define MAGIC1 0x55
+/* Written in the 4 bytes before the block's real space */
+#define MAGIC4 0x55555555
+#define ASSERT(p) if (!(p)) botch("p"); else
+#define EXTRA 4 /* 4 bytes extra for MAGIC1s */
+#else
+#define ASSERT(p) if (!(p)) abort (); else
+#define EXTRA 0
+#endif /* rcheck */
+
+
+/* nextf[i] is free list of blocks of size 2**(i + 3) */
+
+static struct mhead *nextf[30];
+
+/* busy[i] is nonzero while allocation of block size i is in progress. */
+
+static char busy[30];
+
+/* Number of bytes of writable memory we can expect to be able to get */
+static unsigned int lim_data;
+
+/* Level number of warnings already issued.
+ 0 -- no warnings issued.
+ 1 -- 75% warning already issued.
+ 2 -- 85% warning already issued.
+*/
+static int warnlevel;
+
+/* Function to call to issue a warning;
+ 0 means don't issue them. */
+static void (*warnfunction) ();
+
+/* nonzero once initial bunch of free blocks made */
+static int gotpool;
+
+char *_malloc_base;
+
+static void getpool ();
+
+/* Cause reinitialization based on job parameters;
+ also declare where the end of pure storage is. */
+void
+malloc_init (start, warnfun)
+ char *start;
+ void (*warnfun) ();
+{
+ if (start)
+ data_space_start = start;
+ lim_data = 0;
+ warnlevel = 0;
+ warnfunction = warnfun;
+}
+
+/* Return the maximum size to which MEM can be realloc'd
+ without actually requiring copying. */
+
+int
+malloc_usable_size (mem)
+ char *mem;
+{
+ struct mhead *p
+ = (struct mhead *) (mem - ((sizeof (struct mhead) + 7) & ~7));
+ int blocksize = 8 << p->mh_index;
+
+ return blocksize - sizeof (struct mhead) - EXTRA;
+}
+
+static void
+morecore (nu) /* ask system for more memory */
+ register int nu; /* size index to get more of */
+{
+ char *sbrk ();
+ register char *cp;
+ register int nblks;
+ register unsigned int siz;
+ int oldmask;
+
+#ifdef BSD
+#ifndef BSD4_1
+ int newmask = -1;
+ /* Blocking these signals interferes with debugging, at least on BSD on
+ the HP 9000/300. */
+#ifdef SIGTRAP
+ newmask &= ~(1 << SIGTRAP);
+#endif
+#ifdef SIGILL
+ newmask &= ~(1 << SIGILL);
+#endif
+#ifdef SIGTSTP
+ newmask &= ~(1 << SIGTSTP);
+#endif
+#ifdef SIGSTOP
+ newmask &= ~(1 << SIGSTOP);
+#endif
+ oldmask = sigsetmask (newmask);
+#endif
+#endif
+
+ if (!data_space_start)
+ {
+ data_space_start = start_of_data ();
+ }
+
+ if (lim_data == 0)
+ get_lim_data ();
+
+ /* On initial startup, get two blocks of each size up to 1k bytes */
+ if (!gotpool)
+ { getpool (); getpool (); gotpool = 1; }
+
+ /* Find current end of memory and issue warning if getting near max */
+
+#ifndef VMS
+ /* Maximum virtual memory on VMS is difficult to calculate since it
+ * depends on several dynmacially changing things. Also, alignment
+ * isn't that important. That is why much of the code here is ifdef'ed
+ * out for VMS systems.
+ */
+ cp = sbrk (0);
+ siz = cp - data_space_start;
+
+ if (warnfunction)
+ switch (warnlevel)
+ {
+ case 0:
+ if (siz > (lim_data / 4) * 3)
+ {
+ warnlevel++;
+ (*warnfunction) ("Warning: past 75% of memory limit");
+ }
+ break;
+ case 1:
+ if (siz > (lim_data / 20) * 17)
+ {
+ warnlevel++;
+ (*warnfunction) ("Warning: past 85% of memory limit");
+ }
+ break;
+ case 2:
+ if (siz > (lim_data / 20) * 19)
+ {
+ warnlevel++;
+ (*warnfunction) ("Warning: past 95% of memory limit");
+ }
+ break;
+ }
+
+ if ((int) cp & 0x3ff) /* land on 1K boundaries */
+ sbrk (1024 - ((int) cp & 0x3ff));
+#endif /* not VMS */
+
+ /* Take at least 2k, and figure out how many blocks of the desired size
+ we're about to get */
+ nblks = 1;
+ if ((siz = nu) < 8)
+ nblks = 1 << ((siz = 8) - nu);
+
+ if ((cp = sbrk (1 << (siz + 3))) == (char *) -1)
+ {
+#ifdef BSD
+#ifndef BSD4_1
+ sigsetmask (oldmask);
+#endif
+#endif
+ return; /* no more room! */
+ }
+ malloc_sbrk_used = siz;
+ malloc_sbrk_unused = lim_data - siz;
+
+#ifndef VMS
+ if ((int) cp & 7)
+ { /* shouldn't happen, but just in case */
+ cp = (char *) (((int) cp + 8) & ~7);
+ nblks--;
+ }
+#endif /* not VMS */
+
+ /* save new header and link the nblks blocks together */
+ nextf[nu] = (struct mhead *) cp;
+ siz = 1 << (nu + 3);
+ while (1)
+ {
+ ((struct mhead *) cp) -> mh_alloc = ISFREE;
+ ((struct mhead *) cp) -> mh_index = nu;
+ if (--nblks <= 0) break;
+ CHAIN ((struct mhead *) cp) = (struct mhead *) (cp + siz);
+ cp += siz;
+ }
+ CHAIN ((struct mhead *) cp) = 0;
+
+#ifdef BSD
+#ifndef BSD4_1
+ sigsetmask (oldmask);
+#endif
+#endif
+}
+
+static void
+getpool ()
+{
+ register int nu;
+ char * sbrk ();
+ register char *cp = sbrk (0);
+
+ if ((int) cp & 0x3ff) /* land on 1K boundaries */
+ sbrk (1024 - ((int) cp & 0x3ff));
+
+ /* Record address of start of space allocated by malloc. */
+ if (_malloc_base == 0)
+ _malloc_base = cp;
+
+ /* Get 2k of storage */
+
+ cp = sbrk (04000);
+ if (cp == (char *) -1)
+ return;
+
+ /* Divide it into an initial 8-word block
+ plus one block of size 2**nu for nu = 3 ... 10. */
+
+ CHAIN (cp) = nextf[0];
+ nextf[0] = (struct mhead *) cp;
+ ((struct mhead *) cp) -> mh_alloc = ISFREE;
+ ((struct mhead *) cp) -> mh_index = 0;
+ cp += 8;
+
+ for (nu = 0; nu < 7; nu++)
+ {
+ CHAIN (cp) = nextf[nu];
+ nextf[nu] = (struct mhead *) cp;
+ ((struct mhead *) cp) -> mh_alloc = ISFREE;
+ ((struct mhead *) cp) -> mh_index = nu;
+ cp += 8 << nu;
+ }
+}
+
+char *
+malloc (n) /* get a block */
+ unsigned n;
+{
+ register struct mhead *p;
+ register unsigned int nbytes;
+ register int nunits = 0;
+
+ /* Figure out how many bytes are required, rounding up to the nearest
+ multiple of 8, then figure out which nestf[] area to use.
+ Both the beginning of the header and the beginning of the
+ block should be on an eight byte boundary. */
+ nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
+ {
+ register unsigned int shiftr = (nbytes - 1) >> 2;
+
+ while (shiftr >>= 1)
+ nunits++;
+ }
+
+ /* In case this is reentrant use of malloc from signal handler,
+ pick a block size that no other malloc level is currently
+ trying to allocate. That's the easiest harmless way not to
+ interfere with the other level of execution. */
+ while (busy[nunits]) nunits++;
+ busy[nunits] = 1;
+
+ /* If there are no blocks of the appropriate size, go get some */
+ /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */
+ if (nextf[nunits] == 0)
+ morecore (nunits);
+
+ /* Get one block off the list, and set the new list head */
+ if ((p = nextf[nunits]) == 0)
+ {
+ busy[nunits] = 0;
+ return 0;
+ }
+ nextf[nunits] = CHAIN (p);
+ busy[nunits] = 0;
+
+ /* Check for free block clobbered */
+ /* If not for this check, we would gobble a clobbered free chain ptr */
+ /* and bomb out on the NEXT allocate of this size block */
+ if (p -> mh_alloc != ISFREE || p -> mh_index != nunits)
+#ifdef rcheck
+ botch ("block on free list clobbered");
+#else /* not rcheck */
+ abort ();
+#endif /* not rcheck */
+
+ /* Fill in the info, and if range checking, set up the magic numbers */
+ p -> mh_alloc = ISALLOC;
+#ifdef rcheck
+ p -> mh_nbytes = n;
+ p -> mh_magic4 = MAGIC4;
+ {
+ /* Get the location n after the beginning of the user's space. */
+ register char *m = (char *) p + ((sizeof *p + 7) & ~7) + n;
+
+ *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1;
+ }
+#else /* not rcheck */
+ p -> mh_size = n;
+#endif /* not rcheck */
+#ifdef MSTATS
+ nmalloc[nunits]++;
+ nmal++;
+#endif /* MSTATS */
+ return (char *) p + ((sizeof *p + 7) & ~7);
+}
+
+free (mem)
+ char *mem;
+{
+ register struct mhead *p;
+ {
+ register char *ap = mem;
+
+ if (ap == 0)
+ return;
+
+ p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
+ if (p -> mh_alloc == ISMEMALIGN)
+ {
+ ap -= p->mh_size;
+ p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7));
+ }
+
+#ifndef rcheck
+ if (p -> mh_alloc != ISALLOC)
+ abort ();
+
+#else rcheck
+ if (p -> mh_alloc != ISALLOC)
+ {
+ if (p -> mh_alloc == ISFREE)
+ botch ("free: Called with already freed block argument\n");
+ else
+ botch ("free: Called with bad argument\n");
+ }
+
+ ASSERT (p -> mh_magic4 == MAGIC4);
+ ap += p -> mh_nbytes;
+ ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1);
+ ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1);
+#endif /* rcheck */
+ }
+ {
+ register int nunits = p -> mh_index;
+
+ ASSERT (nunits <= 29);
+ p -> mh_alloc = ISFREE;
+
+ /* Protect against signal handlers calling malloc. */
+ busy[nunits] = 1;
+ /* Put this block on the free list. */
+ CHAIN (p) = nextf[nunits];
+ nextf[nunits] = p;
+ busy[nunits] = 0;
+
+#ifdef MSTATS
+ nmalloc[nunits]--;
+ nfre++;
+#endif /* MSTATS */
+ }
+}
+
+char *
+realloc (mem, n)
+ char *mem;
+ register unsigned n;
+{
+ register struct mhead *p;
+ register unsigned int tocopy;
+ register unsigned int nbytes;
+ register int nunits;
+
+ if (mem == 0)
+ return malloc (n);
+ p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7));
+ nunits = p -> mh_index;
+ ASSERT (p -> mh_alloc == ISALLOC);
+#ifdef rcheck
+ ASSERT (p -> mh_magic4 == MAGIC4);
+ {
+ register char *m = mem + (tocopy = p -> mh_nbytes);
+ ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1);
+ ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1);
+ }
+#else /* not rcheck */
+ if (p -> mh_index >= 13)
+ tocopy = (1 << (p -> mh_index + 3)) - ((sizeof *p + 7) & ~7);
+ else
+ tocopy = p -> mh_size;
+#endif /* not rcheck */
+
+ /* See if desired size rounds to same power of 2 as actual size. */
+ nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7;
+
+ /* If ok, use the same block, just marking its size as changed. */
+ if (nbytes > (4 << nunits) && nbytes <= (8 << nunits))
+ {
+#ifdef rcheck
+ register char *m = mem + tocopy;
+ *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0;
+ p-> mh_nbytes = n;
+ m = mem + n;
+ *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1;
+#else /* not rcheck */
+ p -> mh_size = n;
+#endif /* not rcheck */
+ return mem;
+ }
+
+ if (n < tocopy)
+ tocopy = n;
+ {
+ register char *new;
+
+ if ((new = malloc (n)) == 0)
+ return 0;
+ bcopy (mem, new, tocopy);
+ free (mem);
+ return new;
+ }
+}
+
+/* This is in case something linked with Emacs calls calloc. */
+
+char *
+calloc (num, size)
+ unsigned num, size;
+{
+ register char *mem;
+
+ num *= size;
+ mem = malloc (num);
+ if (mem != 0)
+ bzero (mem, num);
+ return mem;
+}
+
+#ifndef VMS
+
+char *
+memalign (alignment, size)
+ unsigned alignment, size;
+{
+ register char *ptr = malloc (size + alignment);
+ register char *aligned;
+ register struct mhead *p;
+
+ if (ptr == 0)
+ return 0;
+ /* If entire block has the desired alignment, just accept it. */
+ if (((int) ptr & (alignment - 1)) == 0)
+ return ptr;
+ /* Otherwise, get address of byte in the block that has that alignment. */
+ aligned = (char *) (((int) ptr + alignment - 1) & -alignment);
+
+ /* Store a suitable indication of how to free the block,
+ so that free can find the true beginning of it. */
+ p = (struct mhead *) (aligned - ((7 + sizeof (struct mhead)) & ~7));
+ p -> mh_size = aligned - ptr;
+ p -> mh_alloc = ISMEMALIGN;
+ return aligned;
+}
+
+#ifndef HPUX
+/* This runs into trouble with getpagesize on HPUX.
+ Patching out seems cleaner than the ugly fix needed. */
+char *
+valloc (size)
+{
+ return memalign (getpagesize (), size);
+}
+#endif /* not HPUX */
+#endif /* not VMS */
+
+#ifdef MSTATS
+/* Return statistics describing allocation of blocks of size 2**n. */
+
+struct mstats_value
+ {
+ int blocksize;
+ int nfree;
+ int nused;
+ };
+
+struct mstats_value
+malloc_stats (size)
+ int size;
+{
+ struct mstats_value v;
+ register int i;
+ register struct mhead *p;
+
+ v.nfree = 0;
+
+ if (size < 0 || size >= 30)
+ {
+ v.blocksize = 0;
+ v.nused = 0;
+ return v;
+ }
+
+ v.blocksize = 1 << (size + 3);
+ v.nused = nmalloc[size];
+
+ for (p = nextf[size]; p; p = CHAIN (p))
+ v.nfree++;
+
+ return v;
+}
+int
+malloc_mem_used ()
+{
+ int i;
+ int size_used;
+
+ size_used = 0;
+
+ for (i = 0; i < 30; i++)
+ {
+ int allocation_size = 1 << (i + 3);
+ struct mhead *p;
+
+ size_used += nmalloc[i] * allocation_size;
+ }
+
+ return size_used;
+}
+
+int
+malloc_mem_free ()
+{
+ int i;
+ int size_unused;
+
+ size_unused = 0;
+
+ for (i = 0; i < 30; i++)
+ {
+ int allocation_size = 1 << (i + 3);
+ struct mhead *p;
+
+ for (p = nextf[i]; p ; p = CHAIN (p))
+ size_unused += allocation_size;
+ }
+
+ return size_unused;
+}
+#endif /* MSTATS */
+
+/*
+ * This function returns the total number of bytes that the process
+ * will be allowed to allocate via the sbrk(2) system call. On
+ * BSD systems this is the total space allocatable to stack and
+ * data. On USG systems this is the data space only.
+ */
+
+#ifdef USG
+
+get_lim_data ()
+{
+ extern long ulimit ();
+
+#ifdef ULIMIT_BREAK_VALUE
+ lim_data = ULIMIT_BREAK_VALUE;
+#else
+ lim_data = ulimit (3, 0);
+#endif
+
+ lim_data -= (long) data_space_start;
+}
+
+#else /* not USG */
+#if defined (BSD4_1) || defined (VMS)
+
+get_lim_data ()
+{
+ lim_data = vlimit (LIM_DATA, -1);
+}
+
+#else /* not BSD4_1 and not VMS */
+
+get_lim_data ()
+{
+ struct rlimit XXrlimit;
+
+ getrlimit (RLIMIT_DATA, &XXrlimit);
+#ifdef RLIM_INFINITY
+ lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */
+#else
+ lim_data = XXrlimit.rlim_cur; /* soft limit */
+#endif
+}
+
+#endif /* not BSD4_1 and not VMS */
+#endif /* not USG */
+
+#ifdef VMS
+/* There is a problem when dumping and restoring things on VMS. Calls
+ * to SBRK don't necessarily result in contiguous allocation. Dumping
+ * doesn't work when it isn't. Therefore, we make the initial
+ * allocation contiguous by allocating a big chunk, and do SBRKs from
+ * there. Once Emacs has dumped there is no reason to continue
+ * contiguous allocation, malloc doesn't depend on it.
+ *
+ * There is a further problem of using brk and sbrk while using VMS C
+ * run time library routines malloc, calloc, etc. The documentation
+ * says that this is a no-no, although I'm not sure why this would be
+ * a problem. In any case, we remove the necessity to call brk and
+ * sbrk, by calling calloc (to assure zero filled data) rather than
+ * sbrk.
+ *
+ * VMS_ALLOCATION_SIZE is the size of the allocation array. This
+ * should be larger than the malloc size before dumping. Making this
+ * too large will result in the startup procedure slowing down since
+ * it will require more space and time to map it in.
+ *
+ * The value for VMS_ALLOCATION_SIZE in the following define was determined
+ * by running emacs linked (and a large allocation) with the debugger and
+ * looking to see how much storage was used. The allocation was 201 pages,
+ * so I rounded it up to a power of two.
+ */
+#ifndef VMS_ALLOCATION_SIZE
+#define VMS_ALLOCATION_SIZE (512*256)
+#endif
+
+/* Use VMS RTL definitions */
+#undef sbrk
+#undef brk
+#undef malloc
+int vms_out_initial = 0;
+char vms_initial_buffer[VMS_ALLOCATION_SIZE];
+static char *vms_current_brk = &vms_initial_buffer;
+static char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1];
+
+#include <stdio.h>
+
+char *
+sys_sbrk (incr)
+ int incr;
+{
+ char *sbrk(), *temp, *ptr;
+
+ if (vms_out_initial)
+ {
+ /* out of initial allocation... */
+ if (!(temp = malloc (incr)))
+ temp = (char *) -1;
+ }
+ else
+ {
+ /* otherwise, go out of our area */
+ ptr = vms_current_brk + incr; /* new current_brk */
+ if (ptr <= vms_end_brk)
+ {
+ temp = vms_current_brk;
+ vms_current_brk = ptr;
+ }
+ else
+ {
+ vms_out_initial = 1; /* mark as out of initial allocation */
+ if (!(temp = malloc (incr)))
+ temp = (char *) -1;
+ }
+ }
+ return temp;
+}
+#endif /* VMS */
diff --git a/gnu/lib/libregex/test/fileregex.c b/gnu/lib/libregex/test/fileregex.c
new file mode 100644
index 0000000..ba81062
--- /dev/null
+++ b/gnu/lib/libregex/test/fileregex.c
@@ -0,0 +1,77 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include "regex.h"
+
+#define BYTEWIDTH 8
+
+/* Sorry, but this is just a test program. */
+#define LINE_MAX 500
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ FILE *f;
+ char *filename;
+ char pat[500]; /* Sorry for that maximum size, too. */
+ char line[LINE_MAX];
+ struct re_pattern_buffer buf;
+ char fastmap[(1 << BYTEWIDTH)];
+ const char *compile_ret;
+ unsigned lineno = 1;
+ unsigned nfound = 0;
+
+ /* Actually, it might be useful to allow the data file to be standard
+ input, and to specify the pattern on the command line. */
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage: %s <filename>.\n", argv[0]);
+ exit (1);
+ }
+
+ filename = argv[1];
+ f = fopen (filename, "r");
+ if (f == NULL)
+ perror (filename);
+
+ buf.allocated = 0;
+ buf.buffer = NULL;
+ buf.fastmap = fastmap;
+
+ printf ("Pattern = ", pat);
+ gets (pat);
+
+ if (feof (stdin))
+ {
+ putchar ('\n');
+ exit (0);
+ }
+
+ compile_ret = re_compile_pattern (pat, strlen (pat), &buf);
+ if (compile_ret != NULL)
+ {
+ fprintf (stderr, "%s: %s\n", pat, compile_ret);
+ exit (1);
+ }
+
+ while (fgets (line, LINE_MAX, f) != NULL)
+ {
+ size_t len = strlen (line);
+ struct re_registers regs;
+ int search_ret
+ = re_search_2 (&buf, NULL, 0, line, len, 0, len, &regs, len);
+
+ if (search_ret == -2)
+ {
+ fprintf (stderr, "%s:%d: re_search failed.\n", filename, lineno);
+ exit (1);
+ }
+
+ nfound += search_ret != -1;
+ lineno++;
+ }
+
+ printf ("Matches found: %u (out of %u lines).\n", nfound, lineno - 1);
+ return 0;
+}
diff --git a/gnu/lib/libregex/test/g++malloc.c b/gnu/lib/libregex/test/g++malloc.c
new file mode 100644
index 0000000..88c181c5
--- /dev/null
+++ b/gnu/lib/libregex/test/g++malloc.c
@@ -0,0 +1,1288 @@
+#define inline
+
+/*
+Copyright (C) 1989 Free Software Foundation
+ written by Doug Lea (dl@oswego.edu)
+
+This file is part of GNU CC.
+
+GNU CC 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 GNU CC General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+GNU CC, but only under the conditions described in the
+GNU CC General Public License. A copy of this license is
+supposed to have been given to you along with GNU CC 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.
+*/
+
+
+
+#ifndef NO_LIBGXX_MALLOC /* ignore whole file otherwise */
+
+/* compile with -DMALLOC_STATS to collect statistics */
+/* collecting statistics slows down malloc by at least 15% */
+
+#ifdef MALLOC_STATS
+#define UPDATE_STATS(ARGS) {ARGS;}
+#else
+#define UPDATE_STATS(ARGS)
+#endif
+
+/* History
+
+
+ Tue Jan 16 04:54:27 1990 Doug Lea (dl at g.oswego.edu)
+
+ version 1 released in libg++
+
+ Sun Jan 21 05:52:47 1990 Doug Lea (dl at g.oswego.edu)
+
+ bins are now own struct for, sanity.
+
+ new victim search strategy: scan up and consolidate.
+ Both faster and less fragmentation.
+
+ refined when to scan bins for consolidation, via consollink, etc.
+
+ realloc: always try to expand chunk, avoiding some fragmentation.
+
+ changed a few inlines into macros
+
+ hardwired SBRK_UNIT to 4096 for uniformity across systems
+
+ Tue Mar 20 14:18:23 1990 Doug Lea (dl at g.oswego.edu)
+
+ calloc and cfree now correctly parameterized.
+
+ Sun Apr 1 10:00:48 1990 Doug Lea (dl at g.oswego.edu)
+
+ added memalign and valloc.
+
+ Sun Jun 24 05:46:48 1990 Doug Lea (dl at g.oswego.edu)
+
+ #include gepagesize.h only ifndef sun
+ cache pagesize after first call
+
+ Wed Jul 25 08:35:19 1990 Doug Lea (dl at g.oswego.edu)
+
+ No longer rely on a `designated victim':
+
+ 1. It sometimes caused splits of large chunks
+ when smaller ones would do, leading to
+ bad worst-case fragmentation.
+
+ 2. Scanning through the av array fast anyway,
+ so the overhead isn't worth it.
+
+ To compensate, several other minor changes:
+
+ 1. Unusable chunks are checked for consolidation during
+ searches inside bins, better distributing chunks
+ across bins.
+
+ 2. Chunks are returned when found in malloc_find_space,
+ rather than finishing cleaning everything up, to
+ avoid wasted iterations due to (1).
+*/
+
+/*
+ A version of malloc/free/realloc tuned for C++ applications.
+
+ Here's what you probably want to know first:
+
+ In various tests, this appears to be about as fast as,
+ and usually substantially less memory-wasteful than BSD/GNUemacs malloc.
+
+ Generally, it is slower (by perhaps 20%) than bsd-style malloc
+ only when bsd malloc would waste a great deal of space in
+ fragmented blocks, which this malloc recovers; or when, by
+ chance or design, nearly all requests are near the bsd malloc
+ power-of-2 allocation bin boundaries, and as many chunks are
+ used as are allocated.
+
+ It uses more space than bsd malloc only when, again by chance
+ or design, only bsdmalloc bin-sized requests are malloced, or when
+ little dynamic space is malloced, since this malloc may grab larger
+ chunks from the system at a time than bsd.
+
+ In other words, this malloc seems generally superior to bsd
+ except perhaps for programs that are specially tuned to
+ deal with bsdmalloc's characteristics. But even here, the
+ performance differences are slight.
+
+
+ This malloc, like any other, is a compromised design.
+
+
+ Chunks of memory are maintained using a `boundary tag' method as
+ described in e.g., Knuth or Standish. This means that the size of
+ the chunk is stored both in the front of the chunk and at the end.
+ This makes consolidating fragmented chunks into bigger chunks very fast.
+ The size field is also used to hold bits representing whether a
+ chunk is free or in use.
+
+ Malloced chunks have space overhead of 8 bytes: The preceding
+ and trailing size fields. When they are freed, the list pointer
+ fields are also needed.
+
+ Available chunks are kept in doubly linked lists. The lists are
+ maintained in an array of bins using a power-of-two method, except
+ that instead of 32 bins (one for each 1 << i), there are 128: each
+ power of two is split in quarters. The use of very fine bin sizes
+ closely approximates the use of one bin per actually used size,
+ without necessitating the overhead of locating such bins. It is
+ especially desirable in common C++ applications where large numbers
+ of identically-sized blocks are malloced/freed in some dynamic
+ manner, and then later are all freed. The finer bin sizes make
+ finding blocks fast, with little wasted overallocation. The
+ consolidation methods ensure that once the collection of blocks is
+ no longer useful, fragments are gathered into bigger chunks awaiting new
+ roles.
+
+ The bins av[i] serve as heads of the lists. Bins contain a dummy
+ header for the chunk lists, and a `dirty' field used to indicate
+ whether the list may need to be scanned for consolidation.
+
+ On allocation, the bin corresponding to the request size is
+ scanned, and if there is a chunk with size >= requested, it
+ is split, if too big, and used. Chunks on the list which are
+ too small are examined for consolidation during this traversal.
+
+ If no chunk exists in the list bigger bins are scanned in search of
+ a victim.
+
+ If no victim can be found, then smaller bins are examined for
+ consolidation in order to construct a victim.
+
+ Finally, if consolidation fails to come up with a usable chunk,
+ more space is obtained from the system.
+
+ After a split, the remainder is placed on
+ the back of the appropriate bin list. (All freed chunks are placed
+ on fronts of lists. All remaindered or consolidated chunks are
+ placed on the rear. Correspondingly, searching within a bin
+ starts at the front, but finding victims is from the back. All
+ of this approximates the effect of having 2 kinds of lists per
+ bin: returned chunks vs unallocated chunks, but without the overhead
+ of maintaining 2 lists.)
+
+ Deallocation (free) consists only of placing the chunk on
+ a list.
+
+ Reallocation proceeds in the usual way. If a chunk can be extended,
+ it is, else a malloc-copy-free sequence is taken.
+
+ memalign requests more than enough space from malloc, finds a
+ spot within that chunk that meets the alignment request, and
+ then possibly frees the leading and trailing space. Overreliance
+ on memalign is a sure way to fragment space.
+
+
+ Some other implementation matters:
+
+ 8 byte alignment is currently hardwired into the design. Calling
+ memalign will return a chunk that is both 8-byte aligned, and
+ meets the requested alignment.
+
+ The basic overhead of a used chunk is 8 bytes: 4 at the front and
+ 4 at the end.
+
+ When a chunk is free, 8 additional bytes are needed for free list
+ pointers. Thus, the minimum allocatable size is 16 bytes.
+
+ The existence of front and back overhead permits some reasonably
+ effective fence-bashing checks: The front and back fields must
+ be identical. This is checked only within free() and realloc().
+ The checks are fast enough to be made non-optional.
+
+ The overwriting of parts of freed memory with the freelist pointers
+ can also be very effective (albeit in an annoying way) in helping
+ users track down dangling pointers.
+
+ User overwriting of freed space will often result in crashes
+ within malloc or free.
+
+ These routines are also tuned to C++ in that free(0) is a noop and
+ a failed malloc automatically calls (*new_handler)().
+
+ malloc(0) returns a pointer to something of the minimum allocatable size.
+
+ Additional memory is gathered from the system (via sbrk) in a
+ way that allows chunks obtained across different sbrk calls to
+ be consolidated, but does not require contiguous memory: Thus,
+ it should be safe to intersperse mallocs with other sbrk calls.
+
+ This malloc is NOT designed to work in multiprocessing applications.
+ No semaphores or other concurrency control are provided to ensure
+ that multiple malloc or free calls don't run at the same time,
+ which could be disasterous.
+
+ VERY heavy use of inlines is made, for clarity. If this malloc
+ is ported via a compiler without inlining capabilities, all
+ inlines should be transformed into macros -- making them non-inline
+ makes malloc at least twice as slow.
+
+
+*/
+
+
+/* preliminaries */
+
+#ifdef __cplusplus
+#include <stdio.h>
+#else
+#include "//usr/include/stdio.h" /* needed for error reporting */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef USG
+extern void* memset(void*, int, int);
+extern void* memcpy(void*, const void*, int);
+/*inline void bzero(void* s, int l) { memset(s, 0, l); }*/
+#else
+/*extern void bzero(void*, unsigned int);*/
+#endif
+
+/*extern void bcopy(void*, void*, unsigned int);*/
+
+extern void* sbrk(unsigned int);
+
+/* Put this in instead of commmented out stuff above. */
+#define bcopy(s,d,n) memcpy((d),(s),(n))
+#define bcmp(s1,s2,n) memcmp((s1),(s2),(n))
+#define bzero(s,n) memset((s),0,(n))
+
+
+#ifdef __GNUC__
+extern volatile void abort();
+#else
+extern void abort();
+#endif
+
+#ifdef __cplusplus
+}; /* end of extern "C" */
+#endif
+
+
+/* A good multiple to call sbrk with */
+
+#define SBRK_UNIT 4096
+
+
+
+/* how to die on detected error */
+
+#ifdef __GNUC__
+static volatile void malloc_user_error()
+#else
+static void malloc_user_error()
+#endif
+{
+ fputs("malloc/free/realloc: clobbered space detected\n", stderr); abort();
+}
+
+
+
+/* Basic overhead for each malloc'ed chunk */
+
+
+struct malloc_chunk
+{
+ unsigned int size; /* Size in bytes, including overhead. */
+ /* Or'ed with INUSE if in use. */
+
+ struct malloc_chunk* fd; /* double links -- used only if free. */
+ struct malloc_chunk* bk;
+
+};
+
+typedef struct malloc_chunk* mchunkptr;
+
+struct malloc_bin
+{
+ struct malloc_chunk hd; /* dummy list header */
+ unsigned int dirty; /* True if maybe consolidatable */
+ /* Wasting a word here makes */
+ /* sizeof(bin) a power of 2, */
+ /* which makes size2bin() faster */
+};
+
+typedef struct malloc_bin* mbinptr;
+
+
+/* sizes, alignments */
+
+
+#define SIZE_SZ (sizeof(unsigned int))
+#define MALLOC_MIN_OVERHEAD (SIZE_SZ + SIZE_SZ)
+#define MALLOC_ALIGN_MASK (MALLOC_MIN_OVERHEAD - 1)
+
+#define MINSIZE (sizeof(struct malloc_chunk) + SIZE_SZ) /* MUST == 16! */
+
+
+/* pad request bytes into a usable size */
+
+static inline unsigned int request2size(unsigned int request)
+{
+ return (request == 0) ? MINSIZE :
+ ((request + MALLOC_MIN_OVERHEAD + MALLOC_ALIGN_MASK)
+ & ~(MALLOC_ALIGN_MASK));
+}
+
+
+static inline int aligned_OK(void* m)
+{
+ return ((unsigned int)(m) & (MALLOC_ALIGN_MASK)) == 0;
+}
+
+
+/* size field or'd with INUSE when in use */
+#define INUSE 0x1
+
+
+
+/* the bins, initialized to have null double linked lists */
+
+#define MAXBIN 120 /* 1 more than needed for 32 bit addresses */
+
+#define FIRSTBIN (&(av[0]))
+
+static struct malloc_bin av[MAXBIN] =
+{
+ { { 0, &(av[0].hd), &(av[0].hd) }, 0 },
+ { { 0, &(av[1].hd), &(av[1].hd) }, 0 },
+ { { 0, &(av[2].hd), &(av[2].hd) }, 0 },
+ { { 0, &(av[3].hd), &(av[3].hd) }, 0 },
+ { { 0, &(av[4].hd), &(av[4].hd) }, 0 },
+ { { 0, &(av[5].hd), &(av[5].hd) }, 0 },
+ { { 0, &(av[6].hd), &(av[6].hd) }, 0 },
+ { { 0, &(av[7].hd), &(av[7].hd) }, 0 },
+ { { 0, &(av[8].hd), &(av[8].hd) }, 0 },
+ { { 0, &(av[9].hd), &(av[9].hd) }, 0 },
+
+ { { 0, &(av[10].hd), &(av[10].hd) }, 0 },
+ { { 0, &(av[11].hd), &(av[11].hd) }, 0 },
+ { { 0, &(av[12].hd), &(av[12].hd) }, 0 },
+ { { 0, &(av[13].hd), &(av[13].hd) }, 0 },
+ { { 0, &(av[14].hd), &(av[14].hd) }, 0 },
+ { { 0, &(av[15].hd), &(av[15].hd) }, 0 },
+ { { 0, &(av[16].hd), &(av[16].hd) }, 0 },
+ { { 0, &(av[17].hd), &(av[17].hd) }, 0 },
+ { { 0, &(av[18].hd), &(av[18].hd) }, 0 },
+ { { 0, &(av[19].hd), &(av[19].hd) }, 0 },
+
+ { { 0, &(av[20].hd), &(av[20].hd) }, 0 },
+ { { 0, &(av[21].hd), &(av[21].hd) }, 0 },
+ { { 0, &(av[22].hd), &(av[22].hd) }, 0 },
+ { { 0, &(av[23].hd), &(av[23].hd) }, 0 },
+ { { 0, &(av[24].hd), &(av[24].hd) }, 0 },
+ { { 0, &(av[25].hd), &(av[25].hd) }, 0 },
+ { { 0, &(av[26].hd), &(av[26].hd) }, 0 },
+ { { 0, &(av[27].hd), &(av[27].hd) }, 0 },
+ { { 0, &(av[28].hd), &(av[28].hd) }, 0 },
+ { { 0, &(av[29].hd), &(av[29].hd) }, 0 },
+
+ { { 0, &(av[30].hd), &(av[30].hd) }, 0 },
+ { { 0, &(av[31].hd), &(av[31].hd) }, 0 },
+ { { 0, &(av[32].hd), &(av[32].hd) }, 0 },
+ { { 0, &(av[33].hd), &(av[33].hd) }, 0 },
+ { { 0, &(av[34].hd), &(av[34].hd) }, 0 },
+ { { 0, &(av[35].hd), &(av[35].hd) }, 0 },
+ { { 0, &(av[36].hd), &(av[36].hd) }, 0 },
+ { { 0, &(av[37].hd), &(av[37].hd) }, 0 },
+ { { 0, &(av[38].hd), &(av[38].hd) }, 0 },
+ { { 0, &(av[39].hd), &(av[39].hd) }, 0 },
+
+ { { 0, &(av[40].hd), &(av[40].hd) }, 0 },
+ { { 0, &(av[41].hd), &(av[41].hd) }, 0 },
+ { { 0, &(av[42].hd), &(av[42].hd) }, 0 },
+ { { 0, &(av[43].hd), &(av[43].hd) }, 0 },
+ { { 0, &(av[44].hd), &(av[44].hd) }, 0 },
+ { { 0, &(av[45].hd), &(av[45].hd) }, 0 },
+ { { 0, &(av[46].hd), &(av[46].hd) }, 0 },
+ { { 0, &(av[47].hd), &(av[47].hd) }, 0 },
+ { { 0, &(av[48].hd), &(av[48].hd) }, 0 },
+ { { 0, &(av[49].hd), &(av[49].hd) }, 0 },
+
+ { { 0, &(av[50].hd), &(av[50].hd) }, 0 },
+ { { 0, &(av[51].hd), &(av[51].hd) }, 0 },
+ { { 0, &(av[52].hd), &(av[52].hd) }, 0 },
+ { { 0, &(av[53].hd), &(av[53].hd) }, 0 },
+ { { 0, &(av[54].hd), &(av[54].hd) }, 0 },
+ { { 0, &(av[55].hd), &(av[55].hd) }, 0 },
+ { { 0, &(av[56].hd), &(av[56].hd) }, 0 },
+ { { 0, &(av[57].hd), &(av[57].hd) }, 0 },
+ { { 0, &(av[58].hd), &(av[58].hd) }, 0 },
+ { { 0, &(av[59].hd), &(av[59].hd) }, 0 },
+
+ { { 0, &(av[60].hd), &(av[60].hd) }, 0 },
+ { { 0, &(av[61].hd), &(av[61].hd) }, 0 },
+ { { 0, &(av[62].hd), &(av[62].hd) }, 0 },
+ { { 0, &(av[63].hd), &(av[63].hd) }, 0 },
+ { { 0, &(av[64].hd), &(av[64].hd) }, 0 },
+ { { 0, &(av[65].hd), &(av[65].hd) }, 0 },
+ { { 0, &(av[66].hd), &(av[66].hd) }, 0 },
+ { { 0, &(av[67].hd), &(av[67].hd) }, 0 },
+ { { 0, &(av[68].hd), &(av[68].hd) }, 0 },
+ { { 0, &(av[69].hd), &(av[69].hd) }, 0 },
+
+ { { 0, &(av[70].hd), &(av[70].hd) }, 0 },
+ { { 0, &(av[71].hd), &(av[71].hd) }, 0 },
+ { { 0, &(av[72].hd), &(av[72].hd) }, 0 },
+ { { 0, &(av[73].hd), &(av[73].hd) }, 0 },
+ { { 0, &(av[74].hd), &(av[74].hd) }, 0 },
+ { { 0, &(av[75].hd), &(av[75].hd) }, 0 },
+ { { 0, &(av[76].hd), &(av[76].hd) }, 0 },
+ { { 0, &(av[77].hd), &(av[77].hd) }, 0 },
+ { { 0, &(av[78].hd), &(av[78].hd) }, 0 },
+ { { 0, &(av[79].hd), &(av[79].hd) }, 0 },
+
+ { { 0, &(av[80].hd), &(av[80].hd) }, 0 },
+ { { 0, &(av[81].hd), &(av[81].hd) }, 0 },
+ { { 0, &(av[82].hd), &(av[82].hd) }, 0 },
+ { { 0, &(av[83].hd), &(av[83].hd) }, 0 },
+ { { 0, &(av[84].hd), &(av[84].hd) }, 0 },
+ { { 0, &(av[85].hd), &(av[85].hd) }, 0 },
+ { { 0, &(av[86].hd), &(av[86].hd) }, 0 },
+ { { 0, &(av[87].hd), &(av[87].hd) }, 0 },
+ { { 0, &(av[88].hd), &(av[88].hd) }, 0 },
+ { { 0, &(av[89].hd), &(av[89].hd) }, 0 },
+
+ { { 0, &(av[90].hd), &(av[90].hd) }, 0 },
+ { { 0, &(av[91].hd), &(av[91].hd) }, 0 },
+ { { 0, &(av[92].hd), &(av[92].hd) }, 0 },
+ { { 0, &(av[93].hd), &(av[93].hd) }, 0 },
+ { { 0, &(av[94].hd), &(av[94].hd) }, 0 },
+ { { 0, &(av[95].hd), &(av[95].hd) }, 0 },
+ { { 0, &(av[96].hd), &(av[96].hd) }, 0 },
+ { { 0, &(av[97].hd), &(av[97].hd) }, 0 },
+ { { 0, &(av[98].hd), &(av[98].hd) }, 0 },
+ { { 0, &(av[99].hd), &(av[99].hd) }, 0 },
+
+ { { 0, &(av[100].hd), &(av[100].hd) }, 0 },
+ { { 0, &(av[101].hd), &(av[101].hd) }, 0 },
+ { { 0, &(av[102].hd), &(av[102].hd) }, 0 },
+ { { 0, &(av[103].hd), &(av[103].hd) }, 0 },
+ { { 0, &(av[104].hd), &(av[104].hd) }, 0 },
+ { { 0, &(av[105].hd), &(av[105].hd) }, 0 },
+ { { 0, &(av[106].hd), &(av[106].hd) }, 0 },
+ { { 0, &(av[107].hd), &(av[107].hd) }, 0 },
+ { { 0, &(av[108].hd), &(av[108].hd) }, 0 },
+ { { 0, &(av[109].hd), &(av[109].hd) }, 0 },
+
+ { { 0, &(av[110].hd), &(av[110].hd) }, 0 },
+ { { 0, &(av[111].hd), &(av[111].hd) }, 0 },
+ { { 0, &(av[112].hd), &(av[112].hd) }, 0 },
+ { { 0, &(av[113].hd), &(av[113].hd) }, 0 },
+ { { 0, &(av[114].hd), &(av[114].hd) }, 0 },
+ { { 0, &(av[115].hd), &(av[115].hd) }, 0 },
+ { { 0, &(av[116].hd), &(av[116].hd) }, 0 },
+ { { 0, &(av[117].hd), &(av[117].hd) }, 0 },
+ { { 0, &(av[118].hd), &(av[118].hd) }, 0 },
+ { { 0, &(av[119].hd), &(av[119].hd) }, 0 }
+};
+
+/*
+ indexing into bins
+*/
+
+static inline mbinptr size2bin(unsigned int sz)
+{
+ mbinptr b = av;
+ while (sz >= (MINSIZE * 2)) { b += 4; sz >>= 1; } /* find power of 2 */
+ b += (sz - MINSIZE) >> 2; /* find quadrant */
+ return b;
+}
+
+
+
+/* counts maintained if MALLOC_STATS defined */
+
+#ifdef MALLOC_STATS
+
+static unsigned int sbrked_mem;
+static unsigned int requested_mem;
+static unsigned int malloced_mem;
+static unsigned int freed_mem;
+static unsigned int max_used_mem;
+
+static unsigned int n_sbrks;
+static unsigned int n_mallocs;
+static unsigned int n_frees;
+static unsigned int n_reallocs;
+static unsigned int n_reallocs_with_copy;
+static unsigned int n_avail;
+static unsigned int max_inuse;
+
+static unsigned int n_malloc_chunks;
+static unsigned int n_malloc_bins;
+
+static unsigned int n_split;
+static unsigned int n_consol;
+
+
+static void do_malloc_stats(const mchunkptr p)
+{
+ ++n_mallocs;
+ if ((n_mallocs-n_frees) > max_inuse)
+ max_inuse = n_mallocs - n_frees;
+ malloced_mem += (p->size & ~(INUSE));
+ if (malloced_mem - freed_mem > max_used_mem)
+ max_used_mem = malloced_mem - freed_mem;
+}
+
+static void do_free_stats(const mchunkptr p)
+{
+ ++n_frees;
+ freed_mem += (p->size & ~(INUSE));
+}
+
+#endif
+
+
+
+/* Utilities needed below for memalign */
+/* This is redundant with libg++ support, but not if used stand-alone */
+
+static unsigned int gcd(unsigned int a, unsigned int b)
+{
+ unsigned int tmp;
+
+ if (b > a)
+ {
+ tmp = a; a = b; b = tmp;
+ }
+ for(;;)
+ {
+ if (b == 0)
+ return a;
+ else if (b == 1)
+ return b;
+ else
+ {
+ tmp = b;
+ b = a % b;
+ a = tmp;
+ }
+ }
+}
+
+static inline unsigned int lcm(unsigned int x, unsigned int y)
+{
+ return x / gcd(x, y) * y;
+}
+
+
+
+/* maintaining INUSE via size field */
+
+
+#define inuse(p) ((p)->size & INUSE)
+#define set_inuse(p) ((p)->size |= INUSE)
+#define clear_inuse(b) ((p)->size &= ~INUSE)
+
+
+/* operations on malloc_chunk addresses */
+
+
+/* return ptr to next physical malloc_chunk */
+
+#define next_chunk(p) ((mchunkptr)((char*)(p) + (p)->size))
+
+/* return ptr to previous physical malloc_chunk */
+
+#define prev_chunk(p) ((mchunkptr)((char*)(p)-((((int*)(p))[-1]) & ~(INUSE))))
+
+/* place size at front and back of chunk */
+
+
+static inline void set_size(mchunkptr p, unsigned int sz)
+{
+ p->size = *((int*)((char*)(p) + sz - SIZE_SZ)) = sz;
+}
+
+
+
+
+/* conversion from malloc headers to user pointers, and back */
+
+static inline void* chunk2mem(mchunkptr p)
+{
+ void *mem;
+ set_inuse(p);
+mem = (void*)((char*)(p) + SIZE_SZ);
+ return mem;
+}
+
+/* xxxx my own */
+mchunkptr sanity_check(void* mem)
+{
+ mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ);
+
+ /* a quick sanity check */
+ unsigned int sz = p->size & ~(INUSE);
+ if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ)))
+ malloc_user_error();
+
+ return p;
+}
+
+
+
+
+static inline mchunkptr mem2chunk(void* mem)
+{
+ mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ);
+
+ /* a quick sanity check */
+ unsigned int sz = p->size & ~(INUSE);
+ if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ)))
+ malloc_user_error();
+
+ p->size = sz; /* clears INUSE */
+ return p;
+}
+
+
+
+/* maintaining bins & pointers */
+
+
+/* maximum bin actually used */
+
+static mbinptr malloc_maxbin = FIRSTBIN;
+
+
+/* operations on lists inside bins */
+
+
+/* take a chunk off a list */
+
+static inline void unlink(mchunkptr p)
+{
+ mchunkptr b = p->bk;
+ mchunkptr f = p->fd;
+
+ f->bk = b; b->fd = f;
+
+ UPDATE_STATS (--n_avail);
+}
+
+
+
+/* split a chunk and place on the back of a list */
+
+static inline void split(mchunkptr p, unsigned int offset)
+{
+ unsigned int room = p->size - offset;
+ if (room >= MINSIZE)
+ {
+ mbinptr bn = size2bin(room); /* new bin */
+ mchunkptr h = &(bn->hd); /* its head */
+ mchunkptr b = h->bk; /* old back element */
+ mchunkptr t = (mchunkptr)((char*)(p) + offset); /* remaindered chunk */
+
+ /* set size */
+ t->size = *((int*)((char*)(t) + room - SIZE_SZ)) = room;
+
+ /* link up */
+ t->bk = b; t->fd = h; h->bk = b->fd = t;
+
+ /* adjust maxbin (h == b means was empty) */
+ if (h == b && bn > malloc_maxbin) malloc_maxbin = bn;
+
+ /* adjust size of chunk to be returned */
+ p->size = *((int*)((char*)(p) + offset - SIZE_SZ)) = offset;
+
+ UPDATE_STATS ((++n_split, ++n_avail));
+ }
+}
+
+
+
+/* place a consolidated chunk on the back of a list */
+/* like above, except no split */
+
+static inline void consollink(mchunkptr p)
+{
+ mbinptr bn = size2bin(p->size);
+ mchunkptr h = &(bn->hd);
+ mchunkptr b = h->bk;
+
+ p->bk = b; p->fd = h; h->bk = b->fd = p;
+
+ if (h == b && bn > malloc_maxbin) malloc_maxbin = bn;
+
+ UPDATE_STATS(++n_avail);
+}
+
+
+/* place a freed chunk on the front of a list */
+
+static inline void frontlink(mchunkptr p)
+{
+ mbinptr bn = size2bin(p->size);
+ mchunkptr h = &(bn->hd);
+ mchunkptr f = h->fd;
+
+ p->bk = h; p->fd = f; f->bk = h->fd = p;
+
+ if (h == f && bn > malloc_maxbin) malloc_maxbin = bn;
+
+ bn->dirty = 1;
+
+ UPDATE_STATS(++n_avail);
+}
+
+
+
+/* Dealing with sbrk */
+
+
+/* To link consecutive sbrk regions when possible */
+
+static int* last_sbrk_end;
+
+
+/* who to call when sbrk returns failure */
+
+#ifndef NO_NEW_HANDLER
+typedef volatile void (*vfp)();
+#ifdef __cplusplus
+extern "C" vfp __new_handler;
+#else
+extern vfp __new_handler;
+#endif
+#endif
+
+static mchunkptr malloc_from_sys(unsigned nb)
+{
+ mchunkptr p;
+ unsigned int sbrk_size;
+ int* ip;
+
+ /* Minimally, we need to pad with enough space */
+ /* to place dummy size/use fields to ends if needed */
+
+ sbrk_size = ((nb + SBRK_UNIT - 1 + SIZE_SZ + SIZE_SZ)
+ / SBRK_UNIT) * SBRK_UNIT;
+
+ ip = (int*)(sbrk(sbrk_size));
+ if ((char*)ip == (char*)(-1)) /* sbrk returns -1 on failure */
+ {
+#ifndef NO_NEW_HANDLER
+ (*__new_handler) ();
+#endif
+ return 0;
+ }
+
+ UPDATE_STATS ((++n_sbrks, sbrked_mem += sbrk_size));
+
+
+ if (last_sbrk_end != &ip[-1])
+ {
+ /* It's either first time through or someone else called sbrk. */
+ /* Arrange end-markers at front & back */
+
+ /* Shouldn't be necessary, but better to be safe */
+ while (!aligned_OK(ip)) { ++ip; sbrk_size -= SIZE_SZ; }
+
+
+ /* Mark the front as in use to prevent merging. */
+ /* Note we can get away with only 1 word, not MINSIZE overhead here */
+
+ *ip++ = SIZE_SZ | INUSE;
+
+ p = (mchunkptr)ip;
+ set_size(p,sbrk_size - (SIZE_SZ + SIZE_SZ));
+
+ }
+ else
+ {
+ mchunkptr l;
+
+ /* We can safely make the header start at end of prev sbrked chunk. */
+ /* We will still have space left at the end from a previous call */
+ /* to place the end marker, below */
+
+ p = (mchunkptr)(last_sbrk_end);
+ set_size(p, sbrk_size);
+
+
+ /* Even better, maybe we can merge with last fragment: */
+
+ l = prev_chunk(p);
+ if (!inuse(l))
+ {
+ unlink(l);
+ set_size(l, p->size + l->size);
+ p = l;
+ }
+
+ }
+
+ /* mark the end of sbrked space as in use to prevent merging */
+
+ last_sbrk_end = (int*)((char*)p + p->size);
+ *last_sbrk_end = SIZE_SZ | INUSE;
+
+ UPDATE_STATS((++n_avail, ++n_malloc_chunks));
+
+ /* make it safe to unlink in malloc */
+ UPDATE_STATS(++n_avail);
+ p->fd = p->bk = p;
+
+ return p;
+}
+
+
+
+/* Consolidate dirty bins. */
+/* Stop if found a chunk big enough to satisfy current malloc request */
+
+/* (It requires much less bookkeeping to consolidate entire bins */
+/* at once than to keep records of which chunks might be */
+/* consolidatable. So long as the lists are short, which we */
+/* try to ensure via small bin ranges, there is little wasted effort.) */
+
+static mchunkptr malloc_find_space(unsigned int nb)
+{
+ mbinptr b;
+
+ /* first, re-adjust max used bin */
+
+ while (malloc_maxbin >= FIRSTBIN &&
+ malloc_maxbin->hd.bk == &(malloc_maxbin->hd))
+ {
+ malloc_maxbin->dirty = 0;
+ --malloc_maxbin;
+ }
+
+ for (b = malloc_maxbin; b >= FIRSTBIN; --b)
+ {
+ UPDATE_STATS(++n_malloc_bins);
+
+ if (b->dirty)
+ {
+ mchunkptr h = &(b->hd); /* head of list */
+ mchunkptr p = h->fd; /* chunk traverser */
+
+ while (p != h)
+ {
+ mchunkptr nextp = p->fd; /* save, in case of relinks */
+ int consolidated = 0; /* only unlink/relink if consolidated */
+
+ mchunkptr t;
+
+ UPDATE_STATS(++n_malloc_chunks);
+
+ while (!inuse(t = prev_chunk(p))) /* consolidate backward */
+ {
+ if (!consolidated) { consolidated = 1; unlink(p); }
+ if (t == nextp) nextp = t->fd;
+ unlink(t);
+ set_size(t, t->size + p->size);
+ p = t;
+ UPDATE_STATS (++n_consol);
+ }
+
+ while (!inuse(t = next_chunk(p))) /* consolidate forward */
+ {
+ if (!consolidated) { consolidated = 1; unlink(p); }
+ if (t == nextp) nextp = t->fd;
+ unlink(t);
+ set_size(p, p->size + t->size);
+ UPDATE_STATS (++n_consol);
+ }
+
+ if (consolidated)
+ {
+ if (p->size >= nb)
+ {
+ /* make it safe to unlink in malloc */
+ UPDATE_STATS(++n_avail);
+ p->fd = p->bk = p;
+ return p;
+ }
+ else
+ consollink(p);
+ }
+
+ p = nextp;
+
+ }
+
+ b->dirty = 0;
+
+ }
+ }
+
+ /* nothing available - sbrk some more */
+
+ return malloc_from_sys(nb);
+}
+
+
+
+/* Finally, the user-level functions */
+
+void* malloc(unsigned int bytes)
+{
+ unsigned int nb = request2size(bytes); /* padded request size */
+ mbinptr b = size2bin(nb); /* corresponding bin */
+ mchunkptr hd = &(b->hd); /* head of its list */
+ mchunkptr p = hd->fd; /* chunk traverser */
+
+ UPDATE_STATS((requested_mem+=bytes, ++n_malloc_bins));
+
+ /* Try a (near) exact match in own bin */
+ /* clean out unusable but consolidatable chunks in bin while traversing */
+
+ while (p != hd)
+ {
+ UPDATE_STATS(++n_malloc_chunks);
+ if (p->size >= nb)
+ goto found;
+ else /* try to consolidate; same code as malloc_find_space */
+ {
+ mchunkptr nextp = p->fd; /* save, in case of relinks */
+ int consolidated = 0; /* only unlink/relink if consolidated */
+
+ mchunkptr t;
+
+ while (!inuse(t = prev_chunk(p))) /* consolidate backward */
+ {
+ if (!consolidated) { consolidated = 1; unlink(p); }
+ if (t == nextp) nextp = t->fd;
+ unlink(t);
+ set_size(t, t->size + p->size);
+ p = t;
+ UPDATE_STATS (++n_consol);
+ }
+
+ while (!inuse(t = next_chunk(p))) /* consolidate forward */
+ {
+ if (!consolidated) { consolidated = 1; unlink(p); }
+ if (t == nextp) nextp = t->fd;
+ unlink(t);
+ set_size(p, p->size + t->size);
+ UPDATE_STATS (++n_consol);
+ }
+
+ if (consolidated)
+ {
+ if (p->size >= nb)
+ {
+ /* make it safe to unlink again below */
+ UPDATE_STATS(++n_avail);
+ p->fd = p->bk = p;
+ goto found;
+ }
+ else
+ consollink(p);
+ }
+
+ p = nextp;
+
+ }
+ }
+
+ b->dirty = 0; /* true if got here */
+
+ /* Scan bigger bins for a victim */
+
+ while (++b <= malloc_maxbin)
+ {
+ UPDATE_STATS(++n_malloc_bins);
+ if ((p = b->hd.bk) != &(b->hd)) /* no need to check size */
+ goto found;
+ }
+
+ /* Consolidate or sbrk */
+
+ p = malloc_find_space(nb);
+
+ if (p == 0) return 0; /* allocation failure */
+
+ found: /* Use what we found */
+
+ unlink(p);
+ split(p, nb);
+ UPDATE_STATS(do_malloc_stats(p));
+ return chunk2mem(p);
+}
+
+
+
+
+void free(void* mem)
+{
+ if (mem != 0)
+ {
+ mchunkptr p = mem2chunk(mem);
+ UPDATE_STATS(do_free_stats(p));
+ frontlink(p);
+ }
+}
+
+
+void* calloc(unsigned int n, unsigned int elem_size)
+{
+ unsigned int sz = n * elem_size;
+ void* p = malloc(sz);
+ bzero(p, sz);
+ return p;
+};
+
+/* This is here for compatibility with older systems */
+void cfree(void *mem)
+{
+ free(mem);
+}
+
+
+unsigned int malloc_usable_size(void* mem)
+{
+ if (mem == 0)
+ return 0;
+ else
+ {
+ mchunkptr p = (mchunkptr)((char*)(mem) - SIZE_SZ);
+ unsigned int sz = p->size & ~(INUSE);
+ if (p->size == sz || sz != *((int*)((char*)(p) + sz - SIZE_SZ)))
+ return 0;
+ else
+ return sz - MALLOC_MIN_OVERHEAD;
+ }
+}
+
+
+
+void* realloc(void* mem, unsigned int bytes)
+{
+ if (mem == 0)
+ return malloc(bytes);
+ else
+ {
+ unsigned int nb = request2size(bytes);
+ mchunkptr p = mem2chunk(mem);
+ unsigned int oldsize = p->size;
+ int room;
+ mchunkptr nxt;
+
+ UPDATE_STATS((++n_reallocs, requested_mem += bytes-oldsize));
+
+ /* try to expand (even if already big enough), to clean up chunk */
+
+ while (!inuse(nxt = next_chunk(p)))
+ {
+ UPDATE_STATS ((malloced_mem += nxt->size, ++n_consol));
+ unlink(nxt);
+ set_size(p, p->size + nxt->size);
+ }
+
+ room = p->size - nb;
+ if (room >= 0)
+ {
+ split(p, nb);
+ UPDATE_STATS(malloced_mem -= room);
+ return chunk2mem(p);
+ }
+ else /* do the obvious */
+ {
+ void* newmem;
+ set_inuse(p); /* don't let malloc consolidate us yet! */
+ newmem = malloc(nb);
+ bcopy(mem, newmem, oldsize - SIZE_SZ);
+ free(mem);
+ UPDATE_STATS(++n_reallocs_with_copy);
+ return newmem;
+ }
+ }
+}
+
+
+
+/* return a pointer to space with at least the alignment requested */
+
+void* memalign(unsigned int alignment, unsigned int bytes)
+{
+ mchunkptr p;
+ unsigned int nb = request2size(bytes);
+
+ /* find an alignment that both we and the user can live with: */
+ /* least common multiple guarantees mutual happiness */
+ unsigned int align = lcm(alignment, MALLOC_MIN_OVERHEAD);
+ unsigned int mask = align - 1;
+
+ /* call malloc with worst case padding to hit alignment; */
+ /* we will give back extra */
+
+ unsigned int req = nb + align + MINSIZE;
+ void* m = malloc(req);
+
+ if (m == 0) return m;
+
+ p = mem2chunk(m);
+
+ /* keep statistics on track */
+
+ UPDATE_STATS(--n_mallocs);
+ UPDATE_STATS(malloced_mem -= p->size);
+ UPDATE_STATS(requested_mem -= req);
+ UPDATE_STATS(requested_mem += bytes);
+
+ if (((int)(m) & (mask)) != 0) /* misaligned */
+ {
+
+ /* find an aligned spot inside chunk */
+
+ mchunkptr ap = (mchunkptr)(( ((int)(m) + mask) & -align) - SIZE_SZ);
+
+ unsigned int gap = (unsigned int)(ap) - (unsigned int)(p);
+ unsigned int room;
+
+ /* we need to give back leading space in a chunk of at least MINSIZE */
+
+ if (gap < MINSIZE)
+ {
+ /* This works since align >= MINSIZE */
+ /* and we've malloc'd enough total room */
+
+ ap = (mchunkptr)( (int)(ap) + align );
+ gap += align;
+ }
+
+ if (gap + nb > p->size) /* can't happen unless chunk sizes corrupted */
+ malloc_user_error();
+
+ room = p->size - gap;
+
+ /* give back leader */
+ set_size(p, gap);
+ consollink(p);
+
+ /* use the rest */
+ p = ap;
+ set_size(p, room);
+ }
+
+ /* also give back spare room at the end */
+
+ split(p, nb);
+ UPDATE_STATS(do_malloc_stats(p));
+ return chunk2mem(p);
+
+}
+
+#ifndef sun
+#include "getpagesize.h"
+#endif
+
+static unsigned int malloc_pagesize = 0;
+
+void* valloc(unsigned int bytes)
+{
+ if (malloc_pagesize == 0) malloc_pagesize = getpagesize();
+ return memalign (malloc_pagesize, bytes);
+}
+
+
+void malloc_stats()
+{
+#ifndef MALLOC_STATS
+}
+#else
+ int i;
+ mchunkptr p;
+ double nm = (double)(n_mallocs + n_reallocs);
+
+ fprintf(stderr, "\nmalloc statistics\n\n");
+
+ if (n_mallocs != 0)
+ fprintf(stderr, "requests = %10u total size = %10u\tave = %10u\n",
+ n_mallocs, requested_mem, requested_mem/n_mallocs);
+
+ if (n_mallocs != 0)
+ fprintf(stderr, "mallocs = %10u total size = %10u\tave = %10u\n",
+ n_mallocs, malloced_mem, malloced_mem/n_mallocs);
+
+ if (n_frees != 0)
+ fprintf(stderr, "frees = %10u total size = %10u\tave = %10u\n",
+ n_frees, freed_mem, freed_mem/n_frees);
+
+ if (n_mallocs-n_frees != 0)
+ fprintf(stderr, "in use = %10u total size = %10u\tave = %10u\n",
+ n_mallocs-n_frees, malloced_mem-freed_mem,
+ (malloced_mem-freed_mem) / (n_mallocs-n_frees));
+
+ if (max_inuse != 0)
+ fprintf(stderr, "max in use= %10u total size = %10u\tave = %10u\n",
+ max_inuse, max_used_mem, max_used_mem / max_inuse);
+
+ if (n_avail != 0)
+ fprintf(stderr, "available = %10u total size = %10u\tave = %10u\n",
+ n_avail, sbrked_mem - (malloced_mem-freed_mem),
+ (sbrked_mem - (malloced_mem-freed_mem)) / n_avail);
+
+ if (n_sbrks != 0)
+ fprintf(stderr, "sbrks = %10u total size = %10u\tave = %10u\n\n",
+ n_sbrks, sbrked_mem, sbrked_mem/ n_sbrks);
+
+ if (n_reallocs != 0)
+ fprintf(stderr, "reallocs = %10u with copy = %10u\n\n",
+ n_reallocs, n_reallocs_with_copy);
+
+
+ if (nm != 0)
+ {
+ fprintf(stderr, "chunks scanned per malloc = %6.3f\n",
+ n_malloc_chunks / nm);
+ fprintf(stderr, "bins scanned per malloc = %6.3f\n",
+ n_malloc_bins / nm);
+ fprintf(stderr, "splits per malloc = %6.3f\n",
+ n_split / nm);
+ fprintf(stderr, "consolidations per malloc = %6.3f\n",
+ n_consol / nm);
+ }
+
+ fprintf(stderr, "\nfree chunks:\n");
+ for (i = 0; i < MAXBIN; ++i)
+ {
+ p = av[i].hd.fd;
+ if (p != &(av[i].hd))
+ {
+ unsigned int count = 1;
+ unsigned int sz = p->size;
+ for (p = p->fd; p != &(av[i].hd); p = p->fd)
+ {
+ if (p->size == sz)
+ ++count;
+ else
+ {
+ fprintf(stderr, "\tsize = %10u count = %5u\n", sz, count);
+ count = 1;
+ sz = p->size;
+ }
+ }
+
+ fprintf(stderr, "\tsize = %10u count = %5u\n", sz, count);
+
+ }
+ }
+}
+#endif /* MALLOC_STATS */
+
+#endif /* NO_LIBGXX_MALLOC */
+
+
diff --git a/gnu/lib/libregex/test/getpagesize.h b/gnu/lib/libregex/test/getpagesize.h
new file mode 100644
index 0000000..32adae6
--- /dev/null
+++ b/gnu/lib/libregex/test/getpagesize.h
@@ -0,0 +1,25 @@
+#ifdef BSD
+#ifndef BSD4_1
+#define HAVE_GETPAGESIZE
+#endif
+#endif
+
+#ifndef HAVE_GETPAGESIZE
+
+#include <sys/param.h>
+
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#define getpagesize() NBPC
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+
+#endif /* not HAVE_GETPAGESIZE */
+
diff --git a/gnu/lib/libregex/test/iregex.c b/gnu/lib/libregex/test/iregex.c
new file mode 100644
index 0000000..1ff12b6
--- /dev/null
+++ b/gnu/lib/libregex/test/iregex.c
@@ -0,0 +1,164 @@
+/* Main program for interactive testing. For maximum output, compile
+ this and regex.c with -DDEBUG. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "regex.h"
+
+/* Don't bother to guess about <string.h> vs <strings.h>, etc. */
+extern int strlen ();
+
+#define BYTEWIDTH 8
+
+extern void printchar ();
+extern char upcase[];
+
+static void scanstring ();
+static void print_regs ();
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int i;
+ struct re_pattern_buffer buf;
+ char fastmap[(1 << BYTEWIDTH)];
+
+ /* Allow a command argument to specify the style of syntax. You can
+ use the `syntax' program to decode integer syntax values. */
+ if (argc > 1)
+ re_set_syntax (atoi (argv[1]));
+
+ buf.allocated = 0;
+ buf.buffer = NULL;
+ buf.fastmap = fastmap;
+ buf.translate = upcase;
+
+ for (;;)
+ {
+ char pat[500], str[500];
+ struct re_registers regs;
+
+ /* Some C compilers don't like `char pat[500] = ""'. */
+ pat[0] = 0;
+
+ printf ("Pattern (%s) = ", pat);
+ gets (pat);
+ scanstring (pat);
+
+ if (feof (stdin))
+ {
+ putchar ('\n');
+ exit (0);
+ }
+
+ if (*pat)
+ {
+ re_compile_pattern (pat, strlen (pat), &buf);
+ re_compile_fastmap (&buf);
+#ifdef DEBUG
+ print_compiled_pattern (&buf);
+#endif
+ }
+
+ printf ("String = ");
+ gets (str); /* Now read the string to match against */
+ scanstring (str);
+
+ i = re_match (&buf, str, strlen (str), 0, &regs);
+ printf ("Match value %d.\t", i);
+ if (i >= 0)
+ print_regs (regs);
+ putchar ('\n');
+
+ i = re_search (&buf, str, strlen (str), 0, strlen (str), &regs);
+ printf ("Search value %d.\t", i);
+ if (i >= 0)
+ print_regs (regs);
+ putchar ('\n');
+ }
+
+ /* We never get here, but what the heck. */
+ return 0;
+}
+
+void
+scanstring (s)
+ char *s;
+{
+ char *write = s;
+
+ while (*s != '\0')
+ {
+ if (*s == '\\')
+ {
+ s++;
+
+ switch (*s)
+ {
+ case '\0':
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ *write = *s++ - '0';
+
+ if ('0' <= *s && *s <= '9')
+ {
+ *write = (*write << 3) + (*s++ - '0');
+ if ('0' <= *s && *s <= '9')
+ *write = (*write << 3) + (*s++ - '0');
+ }
+ write++;
+ break;
+
+ case 'n':
+ *write++ = '\n';
+ s++;
+ break;
+
+ case 't':
+ *write++ = '\t';
+ s++;
+ break;
+
+ default:
+ *write++ = *s++;
+ break;
+ }
+ }
+ else
+ *write++ = *s++;
+ }
+
+ *write++ = '\0';
+}
+
+/* Print REGS in human-readable form. */
+
+void
+print_regs (regs)
+ struct re_registers regs;
+{
+ int i, end;
+
+ printf ("Registers: ");
+
+ if (regs.num_regs == 0 || regs.start[0] == -1)
+ {
+ printf ("(none)");
+ }
+ else
+ {
+ /* Find the last register pair that matched. */
+ for (end = regs.num_regs - 1; end >= 0; end--)
+ if (regs.start[end] != -1)
+ break;
+
+ printf ("[%d ", regs.start[0]);
+ for (i = 1; i <= end; i++)
+ printf ("(%d %d) ", regs.start[i], regs.end[i]);
+ printf ("%d]", regs.end[0]);
+ }
+}
diff --git a/gnu/lib/libregex/test/main.c b/gnu/lib/libregex/test/main.c
new file mode 100644
index 0000000..da4536d
--- /dev/null
+++ b/gnu/lib/libregex/test/main.c
@@ -0,0 +1,49 @@
+/* Main routine for running various tests. Meant only to be linked with
+ all the auxiliary test source files, with `test' undefined. */
+
+#include "test.h"
+
+test_type t = all_test;
+
+
+/* Use this to run the tests we've thought of. */
+
+int
+main ()
+{
+ switch (t)
+ {
+ case all_test:
+ test_regress ();
+ test_others ();
+ test_posix_basic ();
+ test_posix_extended ();
+ test_posix_interface ();
+ break;
+
+ case other_test:
+ test_others ();
+ break;
+
+ case posix_basic_test:
+ test_posix_basic ();
+ break;
+
+ case posix_extended_test:
+ test_posix_extended ();
+ break;
+
+ case posix_interface_test:
+ test_posix_interface ();
+ break;
+
+ case regress_test:
+ test_regress ();
+ break;
+
+ default:
+ fprintf (stderr, "Unknown test %d.\n", t);
+ }
+
+ return 0;
+}
diff --git a/gnu/lib/libregex/test/malloc-test.c b/gnu/lib/libregex/test/malloc-test.c
new file mode 100644
index 0000000..7e27a15
--- /dev/null
+++ b/gnu/lib/libregex/test/malloc-test.c
@@ -0,0 +1,47 @@
+
+
+typedef struct {
+ unsigned *bits;
+ unsigned size;
+} bits_list_type;
+
+#define BYTEWIDTH 8
+#define NULL 0
+
+#define BITS_BLOCK_SIZE (sizeof (unsigned) * BYTEWIDTH)
+#define BITS_BLOCK(position) ((position) / BITS_BLOCK_SIZE)
+#define BITS_MASK(position) (1 << ((position) % BITS_BLOCK_SIZE))
+
+static unsigned
+init_bits_list (bits_list_ptr)
+ bits_list_type *bits_list_ptr;
+{
+ bits_list_ptr->bits = NULL;
+ bits_list_ptr->bits = (unsigned *) malloc (sizeof (unsigned));
+
+ if (bits_list_ptr->bits == NULL)
+ return 0;
+
+ bits_list_ptr->bits[0] = (unsigned)0;
+ bits_list_ptr->size = BITS_BLOCK_SIZE;
+
+ return 1;
+}
+
+
+main()
+{
+ bits_list_type dummy;
+ bits_list_type dummy_1;
+ bits_list_type dummy_2;
+ bits_list_type dummy_3;
+
+ init_bits_list (&dummy);
+printf("init 1\n");
+ init_bits_list (&dummy_1);
+printf("init 2\n");
+ init_bits_list (&dummy_2);
+printf("init 3\n");
+ init_bits_list (&dummy_3);
+printf("init 4\n");
+}
diff --git a/gnu/lib/libregex/test/other.c b/gnu/lib/libregex/test/other.c
new file mode 100644
index 0000000..1023fc6
--- /dev/null
+++ b/gnu/lib/libregex/test/other.c
@@ -0,0 +1,503 @@
+/* other.c: test (not exhaustively) non-POSIX regular expressions. */
+
+#include "test.h"
+
+void
+test_others ()
+{
+ struct re_registers regs;
+
+ printf ("\nStarting non-POSIX tests.\n");
+ t = other_test;
+
+ test_should_match = true;
+
+ /* The big question: does the group participate in the match, or match
+ the empty string? */
+ re_set_syntax (RE_NO_BK_PARENS);
+ test_match ("(a*)*ab", "ab");
+ TEST_REGISTERS ("(a*)*ab", "ab", 0, 2, 0, 0, -1, -1);
+ test_match ("(a*)*", "");
+ TEST_REGISTERS ("(a*)*ab", "ab", 0, 0, 0, 0, -1, -1);
+
+ /* This tests finding the highest and lowest active registers. */
+ test_match ("(a(b)c(d(e)f)g)h(i(j)k(l(m)n)o)\\1\\2\\3\\4\\5\\6\\7\\8",
+ "abcdefghijklmnoabcdefgbdefeijklmnojlmnm");
+
+ /* Test that \< and \> match at the beginning and end of the string. */
+ test_match ("\\<abc\\>", "abc");
+
+ /* May as well test \` and \' while we're at it. */
+ test_match ("\\`abc\\'", "abc");
+
+#if 0
+ /* Test backreferencing and the fastmap -- which doesn't work. */
+ test_fastmap ("(a)*\\1", "a", 0, 0);
+#endif
+
+ /* But at least we shouldn't search improperly. */
+ test_search_return (-1, "(a)\\1", "");
+
+ re_set_syntax (RE_SYNTAX_EMACS);
+
+ MATCH_SELF("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ MATCH_SELF ("a^");
+ MATCH_SELF ("a^b");
+ MATCH_SELF ("$a");
+ MATCH_SELF ("a$b");
+
+ re_set_syntax (RE_BACKSLASH_ESCAPE_IN_LISTS);
+ test_match ("[\\^a]", "a");
+ test_match ("[\\^a]", "^");
+
+ /* These op characters should be ordinary if RE_CONTEXT_INVALID_OPS
+ isn't set. */
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_BRACES | RE_INTERVALS
+ | RE_NO_BK_PARENS);
+ MATCH_SELF ("*");
+ test_match ("a|*", "*");
+ test_match ("(*)", "*");
+
+ MATCH_SELF ("+");
+ test_match ("a|+", "+");
+ test_match ("(+)", "+");
+
+ MATCH_SELF ("?");
+ test_match ("a|?", "?");
+ test_match ("(?)", "?");
+
+ MATCH_SELF ("{1}");
+ test_match ("a|{1}", "a");
+ test_match ("a|{1}", "{1}");
+ test_match ("({1})", "{1}");
+
+ test_match ("\\{", "{");
+
+
+ re_set_syntax (RE_LIMITED_OPS);
+ MATCH_SELF ("|");
+ MATCH_SELF ("a|");
+ MATCH_SELF ("a|");
+ MATCH_SELF ("a||");
+ MATCH_SELF ("a||");
+ MATCH_SELF ("(|)");
+
+ re_set_syntax (RE_SYNTAX_EMACS);
+ TEST_SEARCH ("^a", "b\na", 0, 3);
+ TEST_SEARCH ("b$", "b\na", 0, 3);
+
+#if 0
+ /* Newline is no longer special for anchors (16 Sep 92). --karl */
+ test_match_2 ("a\n^b", "a", "\nb");
+ test_match_2 ("a$\nb", "a\n", "b");
+#endif
+
+ /* Test grouping. */
+ re_set_syntax (RE_NO_BK_PARENS);
+
+ test_match ("()", "");
+ test_fastmap ("()", "", 0, 0);
+ TEST_REGISTERS ("()", "", 0, 0, 0, 0, -1, -1);
+
+ test_match ("((((((((()))))))))", "");
+ test_fastmap ("((((((((()))))))))", "", 0, 0);
+ test_match ("a()b", "ab");
+ TEST_REGISTERS ("a()b", "ab", 0, 2, 1, 1, -1, -1);
+
+ test_match ("(((((((((())))))))))", "");
+ test_fastmap ("(((((((((())))))))))", "", 0, 0);
+
+ test_match ("()*", "");
+ TEST_REGISTERS ("()*", "", 0, 0, 0, 0, -1, -1); /* empty string */
+ test_match ("(())*", "");
+
+ re_set_syntax (RE_CONTEXT_INDEP_OPS);
+ test_match ("*", "");
+
+ re_set_syntax (RE_INTERVALS | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES);
+ test_match ("{1}", ""); /* Should remain an interval. */
+ MATCH_SELF ("{1"); /* Not a valid interval. */
+
+ re_set_syntax (RE_NEWLINE_ALT);
+ test_match ("a\nb", "a");
+ test_match ("a\nb", "b");
+
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS);
+ test_match ("^a", "a");
+ test_match ("(^a)", "a");
+ test_match ("(a|^b)", "b");
+ test_match ("a$", "a");
+ test_match ("(a$)", "a");
+ test_match ("a$|b", "a");
+
+ /* You should be able to have empty alternatives if RE_NO_EMPTY_ALTS
+ isn't set. */
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS);
+
+ test_match ("|", "");
+ test_match ("^|a", "");
+ test_match ("^|a", "a");
+ test_match ("a|", "");
+ test_match ("a|", "a");
+ test_match ("a|$", "");
+ test_match ("a|$", "a");
+ test_match ("a||b", "a");
+ test_match ("a||b", "");
+ test_match ("a||b", "b");
+ test_match ("(|a)", "");
+ test_match ("(|a)", "a");
+ test_match ("(a|)", "");
+ test_match ("(a|)", "a");
+
+ TEST_SEARCH ("a|$", "xa", 0, 2);
+ TEST_SEARCH ("a|$", "x", 0, 1);
+ TEST_SEARCH ("$|b", "x", 0, 1);
+ TEST_SEARCH ("$|b", "xb", 0, 2);
+ TEST_SEARCH ("c(a|$)", "xca", 0, 3);
+ TEST_SEARCH ("c(a|$)", "xc", 0, 2);
+ TEST_SEARCH ("c($|b)", "xcb", 0, 3);
+ TEST_SEARCH ("c($|b)", "xc", 0, 2);
+ TEST_SEARCH ("c($|b$)", "xcb", 0, 3);
+ TEST_SEARCH ("c($|b$)", "xc", 0, 2);
+ TEST_SEARCH ("c(a$|$)", "xca", 0, 3);
+ TEST_SEARCH ("c(a$|$)", "xc", 0, 2);
+ TEST_SEARCH ("(a$|b$)|$", "x", 0, 1);
+ TEST_SEARCH ("(a$|b$)|$", "xa", 0, 2);
+ TEST_SEARCH ("(a$|b$)|$", "xb", 0, 2);
+ TEST_SEARCH ("(a$|$)|c$", "x", 0, 1);
+ TEST_SEARCH ("(a$|$)|c$", "xa", 0, 2);
+ TEST_SEARCH ("(a$|$)|c$", "xc", 0, 2);
+ TEST_SEARCH ("($|b$)|c$", "x", 0, 1);
+ TEST_SEARCH ("($|b$)|c$", "xb", 0, 2);
+ TEST_SEARCH ("($|b$)|c$", "xc", 0, 2);
+ TEST_SEARCH ("c$|(a$|$)", "x", 0, 1);
+ TEST_SEARCH ("c$|(a$|$)", "xa", 0, 2);
+ TEST_SEARCH ("c$|(a$|$)", "xc", 0, 2);
+ TEST_SEARCH ("c$|($|b$)", "x", 0, 1);
+ TEST_SEARCH ("c$|($|b$)", "xb", 0, 2);
+ TEST_SEARCH ("c$|($|b$)", "xc", 0, 2);
+ TEST_SEARCH ("$|(a$|b$)", "x", 0, 1);
+ TEST_SEARCH ("$|(a$|b$)", "xa", 0, 2);
+ TEST_SEARCH ("$|(a$|b$)", "xb", 0, 2);
+ TEST_SEARCH ("c(a$|b$)|$", "x", 0, 1);
+ TEST_SEARCH ("c(a$|b$)|$", "xca", 0, 3);
+ TEST_SEARCH ("c(a$|b$)|$", "xcb", 0, 3);
+ TEST_SEARCH ("c(a$|$)|d$", "xc", 0, 2);
+ TEST_SEARCH ("c(a$|$)|d$", "xca", 0, 3);
+ TEST_SEARCH ("c(a$|$)|d$", "xd", 0, 2);
+ TEST_SEARCH ("c($|b$)|d$", "xc", 0, 2);
+ TEST_SEARCH ("c($|b$)|d$", "xcb", 0, 3);
+ TEST_SEARCH ("c($|b$)|d$", "xd", 0, 2);
+ TEST_SEARCH ("d(c$|e((a$|$)))", "xdc", 0, 3);
+ TEST_SEARCH ("d(c$|e((a$|$)))", "xde", 0, 3);
+ TEST_SEARCH ("d(c$|e((a$|$)))", "xdea", 0, 4);
+ TEST_SEARCH ("d(c$|e(($|b$)))", "xdc", 0, 3);
+ TEST_SEARCH ("d(c$|e(($|b$)))", "xde", 0, 3);
+ TEST_SEARCH ("d(c$|e(($|b$)))", "xdeb", 0, 4);
+ TEST_SEARCH ("d($|e((a$|b$)))", "xd", 0, 2);
+ TEST_SEARCH ("d($|e((a$|b$)))", "xdea", 0, 4);
+ TEST_SEARCH ("d($|e((a$|b$)))", "xdeb", 0, 4);
+ TEST_SEARCH ("a(b$|c$)|$", "x", 0, 1);
+ TEST_SEARCH ("a(b$|c$)|$", "xab", 0, 3);
+ TEST_SEARCH ("a(b$|c$)|$", "xac", 0, 3);
+ TEST_SEARCH ("a(b$|$)|d$", "xa", 0, 2);
+ TEST_SEARCH ("a(b$|$)|d$", "xab", 0, 3);
+ TEST_SEARCH ("a(b$|$)|d$", "xd", 0, 2);
+ TEST_SEARCH ("a($|c$)|d$", "xa", 0, 2);
+ TEST_SEARCH ("a($|c$)|d$", "xac", 0, 3);
+ TEST_SEARCH ("a($|c$)|d$", "xd", 0, 2);
+ TEST_SEARCH ("d$|a(b$|$)", "xd", 0, 2);
+ TEST_SEARCH ("d$|a(b$|$)", "xa", 0, 2);
+ TEST_SEARCH ("d$|a(b$|$)", "xab", 0, 3);
+ TEST_SEARCH ("d$|a($|c$)", "xd", 0, 2);
+ TEST_SEARCH ("d$|a($|c$)", "xa", 0, 2);
+ TEST_SEARCH ("d$|a($|c$)", "xac", 0, 3);
+ TEST_SEARCH ("$|a(b$|c$)", "x", 0, 1);
+ TEST_SEARCH ("$|a(b$|c$)", "xab", 0, 3);
+ TEST_SEARCH ("$|a(b$|c$)", "xac", 0, 3);
+ TEST_SEARCH ("(a)(b$|c$)|d$", "xab", 0, 3);
+ TEST_SEARCH ("(a)(b$|c$)|d$", "xac", 0, 3);
+ TEST_SEARCH ("(a)(b$|c$)|d$", "xd", 0, 2);
+ TEST_SEARCH ("(a)(b$|$)|d$", "xa", 0, 2);
+ TEST_SEARCH ("(a)(b$|$)|d$", "xab", 0, 3);
+ TEST_SEARCH ("(a)(b$|$)|d$", "xd", 0, 2);
+ TEST_SEARCH ("(a)($|c$)|d$", "xa", 0, 2);
+ TEST_SEARCH ("(a)($|c$)|d$", "xac", 0, 3);
+ TEST_SEARCH ("(a)($|c$)|d$", "xd", 0, 2);
+ TEST_SEARCH ("d$|(a)(b$|$)", "xd", 0, 2);
+ TEST_SEARCH ("d$|(a)(b$|$)", "xa", 0, 2);
+ TEST_SEARCH ("d$|(a)(b$|$)", "xab", 0, 3);
+ TEST_SEARCH ("d$|(a)($|c$)", "xd", 0, 2);
+ TEST_SEARCH ("d$|(a)($|c$)", "xa", 0, 2);
+ TEST_SEARCH ("d$|(a)($|c$)", "xac", 0, 3);
+ TEST_SEARCH ("$|(a)(b$|c$)", "x", 0, 1);
+ TEST_SEARCH ("$|(a)(b$|c$)", "xab", 0, 3);
+ TEST_SEARCH ("$|(a)(b$|c$)", "xac", 0, 3);
+ TEST_SEARCH ("d$|(c$|(a$|$))", "x", 0, 1);
+ TEST_SEARCH ("d$|(c$|(a$|$))", "xd", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a$|$))", "xc", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a$|$))", "xa", 0, 2);
+ TEST_SEARCH ("d$|(c$|($|b$))", "x", 0, 1);
+ TEST_SEARCH ("d$|(c$|($|b$))", "xd", 0, 2);
+ TEST_SEARCH ("d$|(c$|($|b$))", "xc", 0, 2);
+ TEST_SEARCH ("d$|(c$|($|b$))", "xb", 0, 2);
+ TEST_SEARCH ("d$|($|(a$|b$))", "x", 0, 1);
+ TEST_SEARCH ("d$|($|(a$|b$))", "xd", 0, 2);
+ TEST_SEARCH ("d$|($|(a$|b$))", "xa", 0, 2);
+ TEST_SEARCH ("d$|($|(a$|b$))", "xb", 0, 2);
+ TEST_SEARCH ("$|(c$|(a$|b$))", "x", 0, 1);
+ TEST_SEARCH ("$|(c$|(a$|b$))", "xc", 0, 2);
+ TEST_SEARCH ("$|(c$|(a$|b$))", "xa", 0, 2);
+ TEST_SEARCH ("$|(c$|(a$|b$))", "xb", 0, 2);
+ TEST_SEARCH ("d$|c(a$|$)", "xd", 0, 2);
+ TEST_SEARCH ("d$|c(a$|$)", "xc", 0, 2);
+ TEST_SEARCH ("d$|c(a$|$)", "xca", 0, 3);
+ TEST_SEARCH ("d$|c($|b$)", "xd", 0, 2);
+ TEST_SEARCH ("d$|c($|b$)", "xc", 0, 2);
+ TEST_SEARCH ("d$|c($|b$)", "xcb", 0, 3);
+ TEST_SEARCH ("$|c(a$|b$)", "x", 0, 1);
+ TEST_SEARCH ("$|c(a$|b$)", "xca", 0, 3);
+ TEST_SEARCH ("$|c(a$|b$)", "xcb", 0, 3);
+ TEST_SEARCH ("e(d$|c((a$|$)))", "xed", 0, 3);
+ TEST_SEARCH ("e(d$|c((a$|$)))", "xec", 0, 3);
+ TEST_SEARCH ("e(d$|c((a$|$)))", "xeca", 0, 3);
+ TEST_SEARCH ("e(d$|c(($|b$)))", "xed", 0, 3);
+ TEST_SEARCH ("e(d$|c(($|b$)))", "xec", 0, 3);
+ TEST_SEARCH ("e(d$|c(($|b$)))", "xecb", 0, 4);
+ TEST_SEARCH ("e($|c((a$|b$)))", "xe", 0, 2);
+ TEST_SEARCH ("e($|c((a$|b$)))", "xeca", 0, 4);
+ TEST_SEARCH ("e($|c((a$|b$)))", "xecb", 0, 4);
+ TEST_SEARCH ("ed$|(c((a$|$)))", "xed", 0, 3);
+ TEST_SEARCH ("ed$|(c((a$|$)))", "xc", 0, 2);
+ TEST_SEARCH ("ed$|(c((a$|$)))", "xca", 0, 3);
+ TEST_SEARCH ("ed$|(c(($|b$)))", "xed", 0, 3);
+ TEST_SEARCH ("ed$|(c(($|b$)))", "xc", 0, 2);
+ TEST_SEARCH ("ed$|(c(($|b$)))", "xcb", 0, 3);
+ TEST_SEARCH ("$|(c((a$|b$)))", "x", 0, 1);
+ TEST_SEARCH ("$|(c((a$|b$)))", "xca", 0, 3);
+ TEST_SEARCH ("$|(c((a$|b$)))", "xcb", 0, 3);
+ TEST_SEARCH ("d$|($|(a|b)$)", "x", 0, 1);
+ TEST_SEARCH ("d$|($|(a|b)$)", "xa", 0, 2);
+ TEST_SEARCH ("d$|($|(a|b)$)", "xb", 0, 2);
+ TEST_SEARCH ("$|(c$|(a|b)$)", "x", 0, 1);
+ TEST_SEARCH ("$|(c$|(a|b)$)", "xc", 0, 2);
+ TEST_SEARCH ("$|(c$|(a|b)$)", "xa", 0, 2);
+ TEST_SEARCH ("$|(c$|(a|b)$)", "xb", 0, 2);
+
+ re_set_syntax (0);
+ test_match ("[^\n]", "a");
+ test_match ("[^a]", "\n");
+
+ TEST_SEARCH ("^a", "b\na", 0, 3);
+ TEST_SEARCH ("b$", "b\na", 0, 3);
+
+ test_case_fold ("[!-`]", "A");
+ test_case_fold ("[!-`]", "a");
+
+ re_set_syntax (RE_CONTEXT_INDEP_OPS | RE_NO_BK_VBAR | RE_NO_BK_PARENS
+ | RE_NO_BK_BRACES | RE_INTERVALS);
+ valid_nonposix_pattern ("()^a");
+ valid_nonposix_pattern ("()\\1^a");
+
+ /* Per Cederqvist (cedar@lysator.liu.se) bug. */
+
+ re_set_syntax (RE_SYNTAX_EMACS);
+
+ /* One `a' before the \n and 638 a's after it. */
+ test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "a\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+
+ /* No a's before the \n and 639 a's after it. */
+ test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+
+ /* One `a' before the \n and 639 a's after it. */
+ test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "a\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+
+ /* No a's before the \n and 640 a's after it. */
+ test_search_return (0, "\\(.*\\)\n\\(\\(.\\|\n\\)*\\)$", "\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS);
+ TEST_SEARCH ("^(^a)", "ab", 0, 2);
+ TEST_SEARCH ("(a$)$", "ba", 0, 2);
+ test_match ("a|$b", "$b");
+
+ /* Mike's curiosity item. */
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS);
+ test_all_registers ("(foo|foobar)(foo|bar)*\\1(foo|bar)*",
+ "foobarfoobar", "",
+ 0, 12, 0, 3, 3, 6, 9, 12, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1);
+
+ /* Another one from Mike. */
+ test_match ("(foo|foobarfoo)(bar)*", "foobarfoo");
+
+ /* And another. */
+ test_match("(foo|foobar)(bar|barfoo)?\\1", "foobarfoobar");
+
+ re_set_syntax (RE_NO_BK_PARENS | RE_INTERVALS | RE_NO_BK_VBAR
+ | RE_NO_BK_BRACES); /* xx get new ones from ext.*/
+ test_match ("((a{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)*", "bb");
+ test_all_registers ("((a{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)*", "", "bb",
+ 0, 2, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1);
+
+ test_match ("((a+?*{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)", "b");
+ test_all_registers ("((a+?*{0,}{0,0}()\\3\\b\\B\\<\\>\\`\\')|b)", "", "b",
+ 0, 1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1);
+
+ /* Valid anchoring. */
+ /* See generic_test.c and extended_test.c for more search
+ tests. xx Not sure all these tests are represented in the
+ search tests. */
+
+ re_set_syntax (RE_NO_BK_PARENS | RE_NO_BK_VBAR);
+ valid_nonposix_pattern
+ ("(((((((((((((((((((((((((((((((((^a)))))))))))))))))))))))))))))))))");
+ valid_nonposix_pattern
+ ("(((((((((((((((((((((((((((((((((a$)))))))))))))))))))))))))))))))))");
+ valid_nonposix_pattern ("\\b\\B\\<\\>\\`\\'^a");
+ valid_nonposix_pattern ("a$\\b\\B\\<\\>\\`\\'");
+ valid_nonposix_pattern ("(^a)");
+ valid_nonposix_pattern ("(a$)");
+ valid_nonposix_pattern ("(^a)b");
+ valid_nonposix_pattern ("b(a$)");
+ valid_nonposix_pattern ("(^a|^b)c");
+ valid_nonposix_pattern ("c(a$|b$)");
+ valid_nonposix_pattern ("(^a|^b)|^c");
+ valid_nonposix_pattern ("(a$|b$)|c$");
+ valid_nonposix_pattern ("^c|(^a|^b)");
+ valid_nonposix_pattern ("c$|(a$|b$)");
+ valid_nonposix_pattern ("(^a|^b)c|^d");
+ valid_nonposix_pattern ("c(a$|b$)|d$");
+ valid_nonposix_pattern ("(((^a|^b))c|^d)e");
+ valid_nonposix_pattern ("(c((a|b))|d)e$");
+ valid_nonposix_pattern ("^d(c|e((a|b)))");
+ valid_nonposix_pattern ("d(c$|e((a$|b$)))");
+ valid_nonposix_pattern ("(((^a|^b))c)|^de");
+ valid_nonposix_pattern ("(((a|b))c$)|de$");
+
+ valid_nonposix_pattern ("((a$)$)$");
+ valid_nonposix_pattern ("^(^(^a))");
+
+ valid_nonposix_pattern ("^de|^(c((a|b)))");
+ valid_nonposix_pattern ("^de|(^c((a|b)))");
+ valid_nonposix_pattern ("de$|(c((a|b)$))");
+ valid_nonposix_pattern ("de$|(c((a|b))$)");
+ valid_nonposix_pattern ("de$|(c((a|b)))$");
+
+ valid_nonposix_pattern ("^a(b|c)|^d");
+ valid_nonposix_pattern ("a(b$|c$)|d$");
+ valid_nonposix_pattern ("^d|^a(b|c)");
+ valid_nonposix_pattern ("d$|a(b$|c$)");
+ valid_nonposix_pattern ("^d|^(b|c)a");
+ valid_nonposix_pattern ("d$|(b|c)a$");
+ valid_nonposix_pattern ("^(a)(b|c)|^d");
+ valid_nonposix_pattern ("(a)(b|c)$|d$");
+ valid_nonposix_pattern ("(^a)(b|c)|^d");
+ valid_nonposix_pattern ("(a)(b$|c$)|d$");
+ valid_nonposix_pattern ("^d|^(b|c)(a)");
+ valid_nonposix_pattern ("d$|(b|c)(a)$");
+ valid_nonposix_pattern ("^d|(^b|^c)(a)");
+ valid_nonposix_pattern ("d$|(b|c)(a$)");
+ valid_nonposix_pattern ("^d|^(a)(b|c)");
+ valid_nonposix_pattern ("^d|(^a)(b|c)");
+ valid_nonposix_pattern ("d$|(a)(b$|c$)");
+ valid_nonposix_pattern ("((^a|^b)|^c)|^d");
+ valid_nonposix_pattern ("d$|(c$|(a$|b$))");
+
+
+ /* Tests shouldn't match. */
+ test_should_match = false;
+
+ /* Test that RE_CONTEXT_INVALID_OPS has precedence over
+ RE_CONTEXT_INDEP_OPS. */
+
+ re_set_syntax (RE_CONTEXT_INDEP_OPS | RE_CONTEXT_INVALID_OPS
+ | RE_NO_BK_VBAR | RE_NO_BK_PARENS
+ | RE_NO_BK_BRACES | RE_INTERVALS);
+ INVALID_PATTERN ("*");
+ INVALID_PATTERN ("^*");
+ INVALID_PATTERN ("a|*");
+ INVALID_PATTERN ("(*)");
+
+ INVALID_PATTERN ("^+");
+ INVALID_PATTERN ("+");
+ INVALID_PATTERN ("a|+");
+ INVALID_PATTERN ("(+)");
+
+ INVALID_PATTERN ("^?");
+ INVALID_PATTERN ("?");
+ INVALID_PATTERN ("a|?");
+ INVALID_PATTERN ("(?)");
+
+ INVALID_PATTERN ("^{1}");
+ INVALID_PATTERN ("{1}");
+ INVALID_PATTERN ("a|{1}");
+ INVALID_PATTERN ("({1})");
+
+#if 0
+ /* No longer have this syntax option -- POSIX says empty alternatives
+ are undefined as of draft 11.2. */
+
+ /* You can't have empty alternatives if RE_NO_EMPTY_ALTS is set. */
+
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS | RE_NO_EMPTY_ALTS);
+
+ INVALID_PATTERN ("|");
+ INVALID_PATTERN ("^|a");
+ INVALID_PATTERN ("a|");
+ INVALID_PATTERN ("a||");
+ INVALID_PATTERN ("a||b");
+ INVALID_PATTERN ("(|a)");
+ INVALID_PATTERN ("(a|)");
+ INVALID_PATTERN ("(a|)");
+
+
+ /* Test above with `\(' and `\)'. */
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_EMPTY_ALTS);
+ INVALID_PATTERN ("\\(|a\\)");
+ INVALID_PATTERN ("\\(a|\\)");
+
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS | RE_NO_EMPTY_ALTS);
+ INVALID_PATTERN ("(|)()$|d$");
+#endif
+
+ /* Test grouping. */
+ test_match ("()", "a");
+
+ /* Test backslashed intervals that are CONTEXTly invalid if have
+ nothing on which to operate. */
+
+ re_set_syntax (RE_INTERVALS | RE_CONTEXT_INVALID_OPS);
+ INVALID_PATTERN ("\\{1\\}");
+
+ re_set_syntax (0);
+ test_match ("z-a", "a");
+
+ re_set_syntax (RE_BK_PLUS_QM);
+ INVALID_PATTERN ("a*\\");
+
+ re_set_syntax (0);
+ INVALID_PATTERN ("a*\\");
+
+ re_set_syntax (RE_BACKSLASH_ESCAPE_IN_LISTS);
+ INVALID_PATTERN ("[\\");
+
+#if 0
+ /* Empty groups are always ok now. (13 Sep 92) */
+ re_set_syntax (RE_NO_BK_VBAR | RE_NO_BK_PARENS | RE_NO_EMPTY_GROUPS);
+ INVALID_PATTERN ("(|)()$|d$");
+#endif
+
+ printf ("\nFinished non-POSIX tests.\n");
+}
+
+
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/test/printchar.c b/gnu/lib/libregex/test/printchar.c
new file mode 100644
index 0000000..1b756f4
--- /dev/null
+++ b/gnu/lib/libregex/test/printchar.c
@@ -0,0 +1,14 @@
+void
+printchar (c)
+ char c;
+{
+ if (c < 040 || c >= 0177)
+ {
+ putchar ('\\');
+ putchar (((c >> 6) & 3) + '0');
+ putchar (((c >> 3) & 7) + '0');
+ putchar ((c & 7) + '0');
+ }
+ else
+ putchar (c);
+}
diff --git a/gnu/lib/libregex/test/psx-basic.c b/gnu/lib/libregex/test/psx-basic.c
new file mode 100644
index 0000000..487c604
--- /dev/null
+++ b/gnu/lib/libregex/test/psx-basic.c
@@ -0,0 +1,253 @@
+/* psx-basic.c: Test POSIX basic regular expressions. */
+
+#include "test.h"
+
+
+void
+test_posix_basic ()
+{
+ /* Intervals can only match up to RE_DUP_MAX occurences of anything. */
+ char dup_max_plus_one[6];
+ sprintf (dup_max_plus_one, "%d", RE_DUP_MAX + 1);
+
+ printf ("\nStarting POSIX basic tests.\n");
+ t = posix_basic_test;
+
+ re_set_syntax (RE_SYNTAX_POSIX_MINIMAL_BASIC);
+
+ test_posix_generic ();
+
+ printf ("\nContinuing POSIX basic tests.\n");
+
+/* Grouping tests that are not the same. */
+
+ test_should_match = false;
+ invalid_pattern (REG_EPAREN, PARENS_TO_OPS ("a)"));
+
+ test_should_match = true;
+ /* Special characters. */
+ MATCH_SELF ("*");
+ test_match ("\\(*\\)", "*");
+ test_match ("\\(^*\\)", "*");
+ test_match ("**", "***");
+ test_match ("***", "****");
+
+ MATCH_SELF ("{"); /* of extended... */
+ MATCH_SELF ("()"); /* also non-Posix. */
+ MATCH_SELF ("a+");
+ MATCH_SELF ("a?");
+ MATCH_SELF ("a|b");
+ MATCH_SELF ("a|"); /* No alternations, */
+ MATCH_SELF ("|a"); /* so OK if empty. */
+ MATCH_SELF ("a||");
+ test_match ("\\(|a\\)", "|a");
+ test_match ("\\(a|\\)", "a|");
+ test_match ("a\\+", "a+");
+ test_match ("a\\?", "a?");
+ test_match ("a\\|b", "a|b");
+ test_match ("^*", "*");
+ test_match ("^+", "+");
+ test_match ("^?", "?");
+ test_match ("^{", "{");
+ /* Valid subexpressions
+ (empty) in basic only. */
+ test_match ("\\(\\)", "");
+
+ test_match ("a\\(\\)", "a");
+ test_match ("\\(\\)b", "b");
+ test_match ("a\\(\\)b", "ab");
+ TEST_REGISTERS ("a\\(\\)b", "ab", 0, 2, 1, 1, -1, -1);
+
+ test_match ("\\(\\)*", "");
+ test_match ("\\(\\(\\)\\)*", "");
+ /* Valid back references. */
+
+ /* N.B.: back references to subexpressions that include a * are
+ undefined in the spec. The tests are in here to see if we handle
+ the situation consistently, but if it fails any of them, it doesn't
+ matter. */
+
+ test_match ("\\(\\)\\1", "");
+ TEST_REGISTERS ("\\(\\)\\1", "", 0, 0, 0, 0, -1, -1);
+
+ test_match ("\\(\\(\\)\\)\\(\\)\\2", "");
+
+ test_match ("\\(a\\)\\1", "aa");
+ TEST_REGISTERS ("\\(a\\)\\1", "aa", 0, 2, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a\\)\\1", "xaax", 1, 3, 1, 2, -1, -1);
+
+ test_match ("\\(\\(a\\)\\)\\1", "aa");
+ test_match ("\\(a\\)\\(b\\)\\2\\1", "abba");
+
+ test_match ("\\(a\\)*\\1", "aa");
+ TEST_REGISTERS ("\\(a\\)*\\1", "aa", 0, 2, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a\\)*\\1", "xaax", 0, 0, -1, -1, -1, -1);
+
+ test_match ("\\(\\(a\\)\\2b\\)*", "aab");
+ TEST_REGISTERS ("\\(\\(a\\)\\2b\\)*", "aab", 0, 3, 0, 3, 0, 1);
+ TEST_REGISTERS ("\\(\\(a\\)\\2b\\)*", "xaabx", 0, 0, -1, -1, -1, -1);
+
+ test_match ("\\(a*\\)*\\1", "");
+ test_match ("\\(a*\\)*\\1", "aa");
+ TEST_REGISTERS ("\\(a*\\)*\\1", "aa", 0, 2, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a*\\)*\\1", "xaax", 0, 0, 0, 0, -1, -1);
+
+ test_match ("\\(a*\\)*\\1", "");
+ test_match ("\\(a*\\)*\\1", "aa");
+ test_match ("\\(\\(a*\\)*\\)*\\1", "aa");
+ test_match ("\\(ab*\\)*\\1", "abab");
+ TEST_REGISTERS ("\\(ab*\\)*\\1", "abab", 0, 4, 0, 2, -1, -1);
+ TEST_REGISTERS ("\\(ab*\\)*\\1", "xababx", 0, 0, -1, -1, -1, -1);
+
+ test_match ("\\(a*\\)ab\\1", "aaba");
+ TEST_REGISTERS ("\\(a*\\)ab\\1", "aaba", 0, 4, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a*\\)ab\\1", "xaabax", 1, 5, 1, 2, -1, -1);
+
+ test_match ("\\(a*\\)*ab\\1", "aaba");
+ TEST_REGISTERS ("\\(a*\\)*ab\\1", "aaba", 0, 4, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a*\\)*ab\\1", "xaabax", 1, 5, 1, 2, -1, -1);
+
+ test_match ("\\(\\(a*\\)b\\)*\\2", "abb");
+ TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "abb", 0, 3, 2, 3, 2, 2);
+ TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "xabbx", 0, 0, -1, -1, -1, -1);
+
+ /* Different from above. */
+ test_match ("\\(\\(a*\\)b*\\)*\\2", "aa");
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aa", 0, 2, 0, 1, 0, 1);
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaax", 0, 0, 0, 0, 0, 0);
+
+ test_match ("\\(\\(a*\\)b*\\)*\\2", "aba");
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aba", 0, 3, 0, 2, 0, 1);
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xabax", 0, 0, 0, 0, 0, 0);
+
+ test_match ("\\(\\(a*\\)b\\)*\\2", "aababa");
+ TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "aababa", 0, 6, 3, 5, 3, 4);
+ TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2", "xaababax", 0, 0, -1, -1, -1, -1);
+
+ test_match ("\\(\\(a*\\)b*\\)*\\2", "aabaa");
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aabaa", 0, 5, 0, 3, 0, 2);
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaabaax", 0, 0, 0, 0, 0, 0);
+
+ test_match ("\\(\\(a*\\)b*\\)*\\2", "aabbaa");
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "aabbaa", 0, 6, 0, 4, 0, 2);
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaabbaax", 0, 0, 0, 0, 0, 0);
+
+ test_match ("\\(\\(a*\\)b*\\)*\\2", "abaabaa");
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "abaabaa", 0, 7, 2, 5, 2, 4);
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2", "xaababaax", 0, 0, 0, 0, 0, 0);
+
+ test_match ("\\(\\(a*\\)b*\\)*a\\2", "aabaaa");
+ TEST_REGISTERS ("\\(\\(a*\\)b*a\\)*\\2", "aabaaa", 0, 6, 0, 3, 0, 2);
+ TEST_REGISTERS ("\\(\\(a*\\)b*a\\)*\\2", "xaabaax", 0, 0, -1, -1, -1, -1);
+
+ test_match ("\\(\\(a*\\)b*\\)*\\2a", "aabaaa");
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2a", "aabaaa", 0, 6, 0, 3, 0, 2);
+ TEST_REGISTERS ("\\(\\(a*\\)b*\\)*\\2a", "xaabaaax", 1, 7, 1, 4, 1, 3);
+
+ test_match ("\\(\\(a*\\)b\\)*\\2\\1", "abaabaaaab");
+ TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2\\1", "abaabaaaab", 0, 10, 2, 5, 2, 4);
+ /* We are matching the empty string here. */
+ TEST_REGISTERS ("\\(\\(a*\\)b\\)*\\2\\1", "xabaabaaaabx", 0, 0, -1, -1, -1, -1);
+
+ test_match ("\\(a*b\\)\\1", "abab");
+ test_match ("\\(a\\)\\1\\1", "aaa");
+ test_match ("\\(a\\(c\\)d\\)\\1\\2", "acdacdc");
+
+ test_match ("\\(a\\)\\1*", "aaa");
+ TEST_REGISTERS ("\\(a\\)\\1*", "aaa", 0, 3, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a\\)\\1*", "xaaax", 1, 4, 1, 2, -1, -1);
+
+ test_match ("\\(a\\)\\{1,3\\}b\\1", "aba");
+ TEST_REGISTERS ("\\(a\\)\\{1,3\\}b\\1", "aba", 0, 3, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a\\)\\{1,3\\}b\\1", "xabax", 1, 4, 1, 2, -1, -1);
+
+ test_match ("\\(\\(a\\)\\2\\)*", "aaaa"); /* rms? */
+ TEST_REGISTERS ("\\(\\(a*b\\)\\2\\)*", "bbabab", 0, 6, 2, 6, 2, 4); /* rms? */
+
+ test_match ("\\(\\(a\\)\\1\\)*", "a1a1");
+
+ test_match ("\\(\\(a\\)\\2\\)\\1", "aaaa");
+
+ test_match ("\\(\\(a*\\)\\2\\)\\1", "aaaa");
+ TEST_REGISTERS ("\\(\\(a*\\)\\2\\)\\1", "aaaa", 0, 4, 0, 2, 0, 1);
+ TEST_REGISTERS ("\\(\\(a*\\)\\2\\)\\1", "xaaaax", 0, 0, 0, 0, 0, 0);
+
+ test_match ("\\{1\\}", "{1}");
+ test_match ("^\\{1\\}", "{1}");
+
+ test_match ("\\(a\\)\\1\\{1,2\\}", "aaa");
+ TEST_REGISTERS ("\\(a\\)\\1\\{1,2\\}", "aaa", 0, 3, 0, 1, -1, -1);
+ TEST_REGISTERS ("\\(a\\)\\1\\{1,2\\}", "xaaax", 1, 4, 1, 2, -1, -1);
+
+
+ /* Per POSIX D11.1 p. 109, leftmost longest match. */
+
+ test_match (PARENS_TO_OPS ("(.*).*\\1"), "abcabc");
+
+
+ /* Per POSIX D11.1, p. 125, leftmost longest match. */
+
+ test_match (PARENS_TO_OPS ("(ac*)c*d[ac]*\\1"), "acdacaaa");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ac*)c*d[ac]*\\1"), "acdacaaa",
+ 0, 8, 0, 1, -1, -1);
+
+ /* Anchors become ordinary, sometimes. */
+ MATCH_SELF ("a^");
+ MATCH_SELF ("$a");
+ MATCH_SELF ("$^");
+ test_fastmap ("$a^", "$", 0, 0);
+ test_match ("$^*", "$^^");
+ test_match ("\\($^\\)", "$^");
+ test_match ("$*", "$$");
+ /* xx -- known bug, solution pending test_match ("^^$", "^"); */
+ test_match ("$\\{0,\\}", "$$");
+ TEST_SEARCH ("^$*", "$$", 0, 2);
+ TEST_SEARCH ("^$\\{0,\\}", "$$", 0, 2);
+ MATCH_SELF ("2^10");
+ MATCH_SELF ("$HOME");
+ MATCH_SELF ("$1.35");
+
+
+ /* Basic regular expressions, continued; these don't match their strings. */
+ test_should_match = false;
+
+ invalid_pattern (REG_EESCAPE, "\\(a\\");
+ /* Invalid back references. */
+ test_match ("\\(a\\)\\1", "ab");
+ test_match ("\\(a\\)\\1\\1", "aab");
+ test_match ("\\(a\\)\\(b\\)\\2\\1", "abab");
+ test_match ("\\(a\\(c\\)d\\)\\1\\2", "acdc");
+ test_match ("\\(a*b\\)\\1", "abaab");
+ test_match ("\\(a\\)\\1*", "aaaaaaaaaab");
+ test_match ("\\(\\(a\\)\\1\\)*", "aaa");
+ invalid_pattern (REG_ESUBREG, "\\1");
+ invalid_pattern (REG_ESUBREG, "\\(a\\)\\2");
+ test_match ("\\(\\(a\\)\\2\\)*", "abaa");
+ test_match ("\\(\\(a\\)\\1\\)*", "a");
+ test_match ("\\(\\(a\\)\\2\\)\\1", "abaa");
+ test_match ("\\(\\(a*\\)\\2\\)\\1", "abaa");
+ /* Invalid intervals. */
+ invalid_pattern (REG_EBRACE, "a\\{");
+
+ invalid_pattern (REG_BADBR, "a\\{-1");
+ invalid_pattern (REG_BADBR, concat ("a\\{", (char *)dup_max_plus_one));
+ invalid_pattern (REG_BADBR, concat (concat ("a\\{", (char *)dup_max_plus_one), ","));
+ invalid_pattern (REG_BADBR, "a\\{1,0");
+
+ invalid_pattern (REG_EBRACE, "a\\{1");
+ invalid_pattern (REG_EBRACE, "a\\{0,");
+ invalid_pattern (REG_EBRACE, "a\\{0,1");
+ invalid_pattern (REG_EBRACE, "a\\{0,1}");
+
+ printf ("\nFinished POSIX basic tests.\n");
+}
+
+
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/test/psx-extend.c b/gnu/lib/libregex/test/psx-extend.c
new file mode 100644
index 0000000..14b8a5e
--- /dev/null
+++ b/gnu/lib/libregex/test/psx-extend.c
@@ -0,0 +1,1244 @@
+/* psx-extend.c: Test POSIX extended regular expressions. */
+
+#include "test.h"
+
+
+void
+test_posix_extended ()
+{
+ /* Intervals can only match up to RE_DUP_MAX occurences of anything. */
+ char dup_max_plus_one[6];
+ sprintf (dup_max_plus_one, "%d", RE_DUP_MAX + 1);
+
+
+ printf ("\nStarting POSIX extended tests.\n");
+ t = posix_extended_test;
+
+ re_set_syntax (RE_SYNTAX_POSIX_MINIMAL_EXTENDED);
+
+ test_posix_generic ();
+
+ printf ("\nContinuing POSIX extended tests.\n");
+
+ /* Grouping tests that differ from basic's. */
+
+ test_should_match = true;
+ MATCH_SELF ("a)");
+
+ /* Valid use of special characters. */
+ test_match ("\\(a", "(a");
+ test_match ("a\\+", "a+");
+ test_match ("a\\?", "a?");
+ test_match ("\\{a", "{a");
+ test_match ("\\|a", "|a");
+ test_match ("a\\|b", "a|b");
+ test_match ("a\\|?", "a");
+ test_match ("a\\|?", "a|");
+ test_match ("a\\|*", "a");
+ test_match ("a\\|*", "a||");
+ test_match ("\\(*\\)", ")");
+ test_match ("\\(*\\)", "(()");
+ test_match ("a\\|+", "a|");
+ test_match ("a\\|+", "a||");
+ test_match ("\\(+\\)", "()");
+ test_match ("\\(+\\)", "(()");
+ test_match ("a\\||b", "a|");
+ test_match ("\\(?\\)", ")");
+ test_match ("\\(?\\)", "()");
+
+ test_match ("a+", "a");
+ test_match ("a+", "aa");
+ test_match ("a?", "");
+ test_match ("a?", "a");
+
+ /* Bracket expressions. */
+ test_match ("[(]", "(");
+ test_match ("[+]", "+");
+ test_match ("[?]", "?");
+ test_match ("[{]", "{");
+ test_match ("[|]", "|");
+ /* Subexpressions. */
+ test_match ("(a+)*", "");
+ test_match ("(a+)*", "aa");
+ test_match ("(a?)*", "");
+ test_match ("(a?)*", "aa");
+ /* (No) back references. */
+ test_match ("(a)\\1", "a1");
+ /* Invalid as intervals,
+ but are valid patterns. */
+ MATCH_SELF ("{");
+ test_match ("^{", "{");
+ test_match ("a|{", "{");
+ test_match ("({)", "{");
+ MATCH_SELF ("a{");
+ MATCH_SELF ("a{}");
+ MATCH_SELF ("a{-1");
+ MATCH_SELF ("a{-1}");
+ MATCH_SELF ("a{0");
+ MATCH_SELF ("a{0,");
+ MATCH_SELF (concat ("a{", dup_max_plus_one));
+ MATCH_SELF (concat (concat ("a{", dup_max_plus_one), ","));
+ MATCH_SELF ("a{1,0");
+ MATCH_SELF ("a{1,0}");
+ MATCH_SELF ("a{0,1");
+ test_match ("[a{0,1}]", "}");
+ test_match ("a{1,3}{-1}", "aaa{-1}");
+ test_match (concat ("a{1,3}{", dup_max_plus_one),
+ concat ("aaa{", dup_max_plus_one));
+ test_match ("a{1,3}{2,1}", "aaa{2,1}");
+ test_match ("a{1,3}{1,2", "aaa{1,2");
+ /* Valid consecutive repetitions. */
+ test_match ("a*+", "a");
+ test_match ("a*?", "a");
+ test_match ("a++", "a");
+ test_match ("a+*", "a");
+ test_match ("a+?", "a");
+ test_match ("a??", "a");
+ test_match ("a?*", "a");
+ test_match ("a?+", "a");
+
+ test_match ("a{2}?", "");
+ test_match ("a{2}?", "aa");
+ test_match ("a{2}+", "aa");
+ test_match ("a{2}{2}", "aaaa");
+
+ test_match ("a{1}?*", "");
+ test_match ("a{1}?*", "aa");
+
+ test_match ("(a?){0,3}b", "aaab");
+ test_fastmap ("(a?){0,3}b", "ab", 0, 0);
+ test_match ("(a+){0,3}b", "b");
+ test_fastmap ("(a+){0,3}b", "ab", 0, 0);
+ test_match ("(a+){0,3}b", "ab");
+ test_fastmap ("(a+){0,3}b", "ab", 0, 0);
+ test_match ("(a+){1,3}b", "aaab");
+ test_match ("(a?){1,3}b", "aaab");
+
+ test_match ("\\\\{1}", "\\"); /* Extended only. */
+
+ test_match ("(a?)?", "a");
+ test_match ("(a?b)?c", "abc");
+ test_match ("(a+)*b", "b");
+ /* Alternatives. */
+ test_match ("a|b", "a");
+ test_match ("a|b", "b");
+ test_fastmap ("a|b", "ab", 0, 0);
+
+ TEST_SEARCH ("a|b", "cb", 0, 2);
+ TEST_SEARCH ("a|b", "cb", 0, 2);
+
+ test_match ("(a|b|c)", "a");
+ test_match ("(a|b|c)", "b");
+ test_match ("(a|b|c)", "c");
+
+ test_match ("(a|b|c)*", "abccba");
+
+ test_match ("(a(b*))|c", "a"); /* xx do registers. */
+ test_match ("(a(b*))|c", "ab");
+ test_match ("(a(b*))|c", "c");
+
+ test_fastmap ("(a+?*|b)", "ab", 0, 0);
+ test_match ("(a+?*|b)", "b");
+ TEST_REGISTERS ("(a+?*|b)", "b", 0, 1, 0, 1, -1, -1);
+
+ test_fastmap ("(a+?*|b)*", "ab", 0, 0);
+ test_match ("(a+?*|b)*", "bb");
+ TEST_REGISTERS ("(a+?*|b)*", "bb", 0, 2, 1, 2, -1, -1);
+
+ test_fastmap ("(a*|b)*", "ab", 0, 0);
+ test_match ("(a*|b)*", "bb");
+ TEST_REGISTERS ("(a*|b)*", "bb", 0, 2, 1, 2, -1, -1);
+
+ test_fastmap ("((a*)|b)*", "ab", 0, 0);
+ test_match ("((a*)|b)*", "bb");
+ TEST_REGISTERS ("((a*)|b)*", "bb", 0, 2, 1, 2, 1, 1);
+
+ test_fastmap ("(a{0,}|b)*", "ab", 0, 0);
+ test_match ("(a{0,}|b)*", "bb");
+ TEST_REGISTERS ("(a{0,}|b)*", "bb", 0, 2, 1, 2, -1, -1);
+
+ test_fastmap ("((a{0,})|b)*", "ab", 0, 0);
+ test_match ("((a{0,})|b)*", "bb");
+ TEST_REGISTERS ("((a{0,})|b)*", "bb", 0, 2, 1, 2, 1, 1);
+
+ /* With c's */
+ test_fastmap ("(a+?*|b)c", "abc", 0, 0);
+ test_match ("(a+?*|b)c", "bc");
+ TEST_REGISTERS ("(a+?*|b)c", "bc", 0, 2, 0, 1, -1, -1);
+
+ test_fastmap ("(a+?*|b)*c", "abc", 0, 0);
+ test_match ("(a+?*|b)*c", "bbc");
+ TEST_REGISTERS ("(a+?*|b)*c", "bbc", 0, 3, 1, 2, -1, -1);
+
+ test_fastmap ("(a*|b)*c", "abc", 0, 0);
+ test_match ("(a*|b)*c", "bbc");
+ TEST_REGISTERS ("(a*|b)*c", "bbc", 0, 3, 1, 2, -1, -1);
+
+ test_fastmap ("((a*)|b)*c", "abc", 0, 0);
+ test_match ("((a*)|b)*c", "bbc");
+ TEST_REGISTERS ("((a*)|b)*c", "bbc", 0, 3, 1, 2, 1, 1);
+
+ test_fastmap ("(a{0,}|b)*c", "abc", 0, 0);
+ test_match ("(a{0,}|b)*c", "bbc");
+ TEST_REGISTERS ("(a{0,}|b)*c", "bbc", 0, 3, 1, 2, -1, -1);
+
+ test_fastmap ("((a{0,})|b)*c", "abc", 0, 0);
+ test_match ("((a{0,})|b)*c", "bbc");
+ TEST_REGISTERS ("((a{0,})|b)*c", "bbc", 0, 3, 1, 2, 1, 1);
+
+
+ test_fastmap ("((a{0,}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a{0,}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a{0,}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a{0,}\\b\\<)|b)*", "ab", 0, 0);
+ test_match ("((a{0,}\\b\\<)|b)*", "b");
+ TEST_REGISTERS ("((a{0,}\\b\\<)|b)*", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,1}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,1}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,1}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,2}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,2}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,2}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+
+ test_fastmap ("((a+?*{0,4095}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,4095}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,4095}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,5119}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,5119}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,5119}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,6143}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,6143}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,6143}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,8191}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,8191}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,8191}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,16383}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,16383}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,16383}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+
+ test_fastmap ("((a+?*{0,}\\b\\<)|b)", "ab", 0, 0);
+ test_match ("((a+?*{0,}\\b\\<)|b)", "b");
+ TEST_REGISTERS ("((a+?*{0,}\\b\\<)|b)", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,}\\b\\<)|b)*", "ab", 0, 0);
+ test_match ("((a+?*{0,}\\b\\<)|b)*", "b");
+ TEST_REGISTERS ("((a+?*{0,}\\b\\<)|b)*", "b",
+ 0, 1, 0, 1, 0, 0);
+
+ test_fastmap ("((a+?*{0,}\\b\\<)|b)*", "ab", 0, 0);
+ test_match ("((a+?*{0,}\\b\\<)|b)*", "bb");
+ TEST_REGISTERS ("((a+?*{0,}\\b\\<)|b)*", "bb",
+ 0, 2, 1, 2, 0, 0);
+
+
+ /* `*' after group. */
+ test_match ("(a*|b*)*c", "c");
+ TEST_REGISTERS ("(a*|b*)*c", "c", 0, 1, 0, 0, -1, -1);
+
+ test_match ("(a*|b*)*c", "ac");
+ TEST_REGISTERS ("(a*|b*)*c", "ac", 0, 2, 0, 1, -1, -1);
+
+ test_match ("(a*|b*)*c", "aac");
+ TEST_REGISTERS ("(a*|b*)*c", "aac", 0, 3, 0, 2, -1, -1);
+
+ test_match ("(a*|b*)*c", "bbc");
+ TEST_REGISTERS ("(a*|b*)*c", "bbc", 0, 3, 0, 2, -1, -1);
+
+ test_match ("(a*|b*)*c", "abc");
+ TEST_REGISTERS ("(a*|b*)*c", "abc", 0, 3, 1, 2, -1, -1);
+
+ /* No `*' after group. */
+ test_match ("(a*|b*)c", "c");
+ TEST_REGISTERS ("(a*|b*)c", "c", 0, 1, 0, 0, -1, -1);
+
+ test_match ("(a*|b*)c", "ac");
+ TEST_REGISTERS ("(a*|b*)c", "ac", 0, 2, 0, 1, -1, -1);
+
+ test_match ("(a*|b*)c", "bc");
+ TEST_REGISTERS ("(a*|b*)c", "bc", 0, 2, 0, 1, -1, -1);
+
+ test_match ("(a*|b*)c", "aac");
+ TEST_REGISTERS ("(a*|b*)c", "aac", 0, 3, 0, 2, -1, -1);
+
+ /* Same as above, but with no `*'s in alternatives.
+
+ test_match ("(a|b)*c", "c"); /* `*' after group. */
+ TEST_REGISTERS ("(a|b)*c", "c", 0, 1, -1, -1, -1, -1);
+
+ test_match ("(a|b)*c", "ac");
+ TEST_REGISTERS ("(a|b)*c", "ac", 0, 2, 0, 1, -1, -1);
+
+ test_match ("(a|b)*c", "bc");
+ TEST_REGISTERS ("(a|b)*c", "bc", 0, 2, 0, 1, -1, -1);
+
+ test_match ("(a|b)*c", "abc");
+ TEST_REGISTERS ("(a|b)*c", "abc", 0, 3, 1, 2, -1, -1);
+
+
+ test_match ("(a*|b*)c", "bbc");
+ TEST_REGISTERS ("(a*|b*)c", "bbc", 0, 3, 0, 2, -1, -1);
+
+ /* Complicated second alternative. */
+
+ test_match ("(a*|(b*)*)*c", "bc");
+ TEST_REGISTERS ("(a*|(b*)*)*c", "bc", 0, 2, 0, 1, 0, 1);
+
+ test_match ("(a*|(b*|c*)*)*d", "bd");
+ TEST_REGISTERS ("(a*|(b*|c*)*)*d", "bd", 0, 2, 0, 1, 0, 1);
+
+ test_match ("(a*|(b*|c*)*)*d", "bbd");
+ TEST_REGISTERS ("(a*|(b*|c*)*)*d", "bbd", 0, 3, 0, 2, 0, 2);
+
+ test_match ("(a*|(b*|c*)*)*d", "cd");
+ TEST_REGISTERS ("(a*|(b*|c*)*)*d", "cd", 0, 2, 0, 1, 0, 1);
+
+ test_match ("(a*|(b*|c*)*)*d", "ccd");
+ TEST_REGISTERS ("(a*|(b*|c*)*)*d", "ccd", 0, 3, 0, 2, 0, 2);
+
+ test_match ("(a*|b*|c*)*d", "aad");
+ TEST_REGISTERS ("(a*|b*|c*)*d", "aad", 0, 3, 0, 2, 0, 2);
+
+ test_match ("(a*|b*|c*)*d", "bbd");
+ TEST_REGISTERS ("(a*|b*|c*)*d", "bbd", 0, 3, 0, 2, 0, 2);
+
+ test_match ("(a*|b*|c*)*d", "ccd");
+ TEST_REGISTERS ("(a*|b*|c*)*d", "ccd", 0, 3, 0, 2, 0, 2);
+
+ /* Valid anchoring. */
+ valid_pattern ("a^");
+ valid_pattern ("a^b");
+ valid_pattern ("$a");
+ valid_pattern ("a$b");
+ valid_pattern ("foo^bar");
+ valid_pattern ("foo$bar");
+ valid_pattern ("(^)");
+ valid_pattern ("($)");
+ valid_pattern ("(^$)");
+
+ /* These are the same (but valid) as those (invalid) in other_test.c. */
+ valid_pattern
+ ("(((((((((((((((((((((((((((((((((a^)))))))))))))))))))))))))))))))))");
+ valid_pattern
+ ("((((((((((((((((((((((((((((((((($a)))))))))))))))))))))))))))))))))");
+ valid_pattern ("\\(^a\\)");
+ valid_pattern ("a\\|^b");
+ valid_pattern ("\\w^a");
+ valid_pattern ("\\W^a");
+ valid_pattern ("(a^)");
+ valid_pattern ("($a)");
+ valid_pattern ("a(^b)");
+ valid_pattern ("a$(b)");
+ valid_pattern ("(a)^b");
+ valid_pattern ("(a)$b");
+ valid_pattern ("(a)(^b)");
+ valid_pattern ("(a$)(b)");
+ valid_pattern ("(a|b)^c");
+ valid_pattern ("(a|b)$c");
+ valid_pattern ("(a$|b)c");
+ valid_pattern ("(a|b$)c");
+ valid_pattern ("a(b|^c)");
+ valid_pattern ("a(^b|c)");
+ valid_pattern ("a$(b|c)");
+ valid_pattern ("(a)(^b|c)");
+ valid_pattern ("(a)(b|^c)");
+ valid_pattern ("(b$|c)(a)");
+ valid_pattern ("(b|c$)(a)");
+ valid_pattern ("(a(^b|c))");
+ valid_pattern ("(a(b|^c))");
+ valid_pattern ("((b$|c)a)");
+ valid_pattern ("((b|c$)a)");
+ valid_pattern ("((^a|^b)^c)");
+ valid_pattern ("(c$(a$|b$))");
+ valid_pattern ("((^a|^b)^c)");
+ valid_pattern ("((a$|b$)c)");
+ valid_pattern ("(c$(a$|b$))");
+ valid_pattern ("((^a|^b)|^c)^d");
+ valid_pattern ("((a$|b$)|c$)d$");
+ valid_pattern ("d$(c$|(a$|b$))");
+ valid_pattern ("((^a|^b)|^c)(^d)");
+ valid_pattern ("((a$|b$)|c$)(d$)");
+ valid_pattern ("(d$)((a$|b$)|c$)");
+ valid_pattern ("((^a|^b)|^c)((^d))");
+ valid_pattern ("((a$|b$)|c$)((d$))");
+ valid_pattern ("((d$))((a$|b$)|c$)");
+ valid_pattern ("(((^a|^b))c|^d)^e");
+ valid_pattern ("(((a$|b$))c|d$)$e$");
+ valid_pattern ("e$(d$|c((a$|b$)))");
+ valid_pattern ("(^a)((^b))");
+ valid_pattern ("(a$)((b$))");
+ valid_pattern ("((^a))(^b)");
+ valid_pattern ("((a$))(b$)");
+ valid_pattern ("((^a))((^b))");
+ valid_pattern ("((a$))((b$))");
+ valid_pattern ("((^a)^b)");
+ valid_pattern ("((a$)b$)");
+ valid_pattern ("(b$(a$))");
+ valid_pattern ("(((^a)b)^c)");
+ valid_pattern ("(((a$)b)c$)");
+ valid_pattern ("(c$(b(a$)))");
+ valid_pattern ("(((^a)b)c)^d");
+ valid_pattern ("(((a$)b)c)d$");
+ valid_pattern ("d$(c(b(a$)))");
+ valid_pattern (".^a");
+ valid_pattern ("a$.");
+ valid_pattern ("[a]^b");
+ valid_pattern ("b$[a]");
+ valid_pattern ("\\(a$\\)");
+ valid_pattern ("a$\\|b");
+ valid_pattern ("(^a|^b)^c");
+ valid_pattern ("c$(a$|b$)");
+ valid_pattern ("(^a|^b)^|^c");
+ valid_pattern ("(a$|b$)$|$c$");
+ valid_pattern ("(a$|$b$)$|c$");
+ valid_pattern ("($a$|b$)$|c$");
+ valid_pattern ("$(a$|b$)$|c$");
+ valid_pattern ("^c|d(^a|^b)");
+ valid_pattern ("(^a|^b)|d^c");
+ valid_pattern ("c$|(a$|b$)d");
+ valid_pattern ("c$d|(a$|b$)");
+ valid_pattern ("c(^a|^b)|^d");
+ valid_pattern ("(a$|b$)c|d$");
+ valid_pattern ("c(((^a|^b))|^d)e");
+ valid_pattern ("(c((^a|^b))|^d)e");
+ valid_pattern ("((c(^a|^b))|^d)e");
+ valid_pattern ("(((^a|^b))|c^d)e");
+ valid_pattern ("(((^a|^b))|^d)^e");
+ valid_pattern ("(c$((a|b))|d)e$");
+ valid_pattern ("(c((a$|b$))|d)e$");
+ valid_pattern ("(c((a|b)$)|d)e$");
+ valid_pattern ("(c((a|b))|d$)e$");
+ valid_pattern ("^d(^c|e((a|b)))");
+ valid_pattern ("^d(c|^e((a|b)))");
+ valid_pattern ("^d(c|e(^(a|b)))");
+ valid_pattern ("^d(c|e((^a|b)))");
+ valid_pattern ("^d(c|e((a|^b)))");
+ valid_pattern ("^d(c|e((a|b^)))");
+ valid_pattern ("^d(c|e((a|b)^))");
+ valid_pattern ("^d(c|e((a|b))^)");
+ valid_pattern ("^d(c|e((a|b)))^");
+ valid_pattern ("d$(c$|e((a$|b$)))");
+ valid_pattern ("d(c$|e$((a$|b$)))");
+ valid_pattern ("(((^a|^b))^c)|^de");
+ valid_pattern ("(((^a|^b))c)|^d^e");
+ valid_pattern ("(((a$|b))c$)|de$");
+ valid_pattern ("(((a|b$))c$)|de$");
+ valid_pattern ("(((a|b))c$)|d$e$");
+ valid_pattern ("^d^e|^(c((a|b)))");
+ valid_pattern ("^de|^(c^((a|b)))");
+ valid_pattern ("^de|^(c(^(a|b)))");
+ valid_pattern ("^de|^(c((^a|b)))");
+ valid_pattern ("^de|^(c((a|^b)))");
+ valid_pattern ("^de|(^c(^(a|b)))");
+ valid_pattern ("^de|(^c((^a|b)))");
+ valid_pattern ("^de|(^c((a|^b)))");
+ valid_pattern ("de$|(c($(a|b)$))");
+ valid_pattern ("de$|(c$((a|b)$))");
+ valid_pattern ("de$|($c((a|b)$))");
+ valid_pattern ("de$|$(c((a|b)$))");
+ valid_pattern ("de$|(c($(a|b))$)");
+ valid_pattern ("de$|(c$((a|b))$)");
+ valid_pattern ("de$|$(c((a|b))$)");
+ valid_pattern ("de$|(c($(a|b)))$");
+ valid_pattern ("de$|(c$((a|b)))$");
+ valid_pattern ("de$|($c((a|b)))$");
+ valid_pattern ("de$|$(c((a|b)))$");
+ valid_pattern ("^a(^b|c)|^d");
+ valid_pattern ("^a(b|^c)|^d");
+ valid_pattern ("^a(b|c^)|^d");
+ valid_pattern ("^a(b|c)^|^d");
+ valid_pattern ("a$(b$|c$)|d$");
+ valid_pattern ("^d|^a(^b|c)");
+ valid_pattern ("^d|^a(b|^c)");
+ valid_pattern ("d$|a$(b$|c$)");
+ valid_pattern ("^d|^(b|c)^a");
+ valid_pattern ("d$|(b|c$)a$");
+ valid_pattern ("d$|(b$|c)a$");
+ valid_pattern ("^(a)^(b|c)|^d");
+ valid_pattern ("^(a)(^b|c)|^d");
+ valid_pattern ("^(a)(b|^c)|^d");
+ valid_pattern ("(a)$(b|c)$|d$");
+ valid_pattern ("(a$)(b|c)$|d$");
+ valid_pattern ("(^a)(^b|c)|^d");
+ valid_pattern ("(^a)(b|^c)|^d");
+ valid_pattern ("(a)$(b$|c$)|d$");
+ valid_pattern ("(a$)(b$|c$)|d$");
+ valid_pattern ("^d|^(b|c)^(a)");
+ valid_pattern ("^d|^(b|c)(^a)");
+ valid_pattern ("d$|(b|c$)(a)$");
+ valid_pattern ("d$|(b$|c)(a)$");
+ valid_pattern ("^d|(^b|^c)^(a)");
+ valid_pattern ("^d|(^b|^c)(^a)");
+ valid_pattern ("d$|(b|c)$(a$)");
+ valid_pattern ("d$|(b|c$)(a$)");
+ valid_pattern ("d$|(b$|c)(a$)");
+ valid_pattern ("^d|^(a)^(b|c)");
+ valid_pattern ("^d|^(a)(^b|c)");
+ valid_pattern ("^d|^(a)(b|^c)");
+ valid_pattern ("^d|(^a)^(b|c)");
+ valid_pattern ("^d|(^a)(^b|c)");
+ valid_pattern ("^d|(^a)(b|^c)");
+ valid_pattern ("d$|(a)$(b$|c$)");
+ valid_pattern ("d$|(a$)(b$|c$)");
+ valid_pattern ("((e^a|^b)|^c)|^d");
+ valid_pattern ("((^a|e^b)|^c)|^d");
+ valid_pattern ("((^a|^b)|e^c)|^d");
+ valid_pattern ("((^a|^b)|^c)|e^d");
+ valid_pattern ("d$e|(c$|(a$|b$))");
+ valid_pattern ("d$|(c$e|(a$|b$))");
+ valid_pattern ("d$|(c$|(a$e|b$))");
+ valid_pattern ("d$|(c$|(a$|b$e))");
+ valid_pattern ("d$|(c$|(a$|b$)e)");
+ valid_pattern ("d$|(c$|(a$|b$))e");
+ valid_pattern ("(a|b)^|c");
+ valid_pattern ("(a|b)|c^");
+ valid_pattern ("$(a|b)|c");
+ valid_pattern ("(a|b)|$c");
+ valid_pattern ("(a^|^b)|^c");
+ valid_pattern ("(^a|b^)|^c");
+ valid_pattern ("(^a|^b)|c^");
+ valid_pattern ("($a|b$)|c$");
+ valid_pattern ("(a$|$b)|c$");
+ valid_pattern ("(a$|b$)|$c");
+ valid_pattern ("c^|(^a|^b)");
+ valid_pattern ("^c|(a^|^b)");
+ valid_pattern ("^c|(^a|b^)");
+ valid_pattern ("$c|(a$|b$)");
+ valid_pattern ("c$|($a|b$)");
+ valid_pattern ("c$|(a$|$b)");
+ valid_pattern ("c^|^(a|b)");
+ valid_pattern ("^c|(a|b)^");
+ valid_pattern ("$c|(a|b)$");
+ valid_pattern ("c$|$(a|b)");
+ valid_pattern ("(a^|^b)c|^d");
+ valid_pattern ("(^a|b^)c|^d");
+ valid_pattern ("(^a|^b)c|d^");
+ valid_pattern ("(^a|^b)^c|^d");
+ valid_pattern ("(a|b)c$|$d");
+ valid_pattern ("(a|b)$c$|d$");
+ valid_pattern ("(a|b)$c$|d$");
+ valid_pattern ("(a|b$)c$|d$");
+ valid_pattern ("(a$|b)c$|d$");
+ valid_pattern ("($a|b)c$|d$");
+ valid_pattern ("$(a|b)c$|d$");
+ valid_pattern ("^d|^c^(a|b)");
+ valid_pattern ("^d|^c(^a|b)");
+ valid_pattern ("^d|^c(a|^b)");
+ valid_pattern ("^d|^c(a|b^)");
+ valid_pattern ("^d|^c(a|b)^");
+ valid_pattern ("$d|c(a$|b$)");
+ valid_pattern ("d$|c($a$|b$)");
+ valid_pattern ("d$|c$(a$|b$)");
+ valid_pattern ("d$|$c(a$|b$)");
+
+ valid_pattern ("(((a^|^b))c|^d)e");
+ valid_pattern ("(((^a|b^))c|^d)e");
+ valid_pattern ("(((^a|^b))^c|^d)e");
+ valid_pattern ("((^(a|b))c|d^)e");
+ valid_pattern ("(^((a|b))c|^d)^e");
+ valid_pattern ("(^((a|b)^)c|^d)e");
+ valid_pattern ("(^((a^|b))c|^d)e");
+ valid_pattern ("(^((a|b^))c|^d)e");
+ valid_pattern ("(^((a|b)^)c|^d)e");
+ valid_pattern ("(^((a|b))^c|^d)e");
+ valid_pattern ("(^((a|b))c^|^d)e");
+ valid_pattern ("(^((a|b))c|^d^)e");
+ valid_pattern ("(^((a|b))c|^d)^e");
+ valid_pattern ("(((a|b))c|d)$e$");
+ valid_pattern ("(((a|b))c|d$)e$");
+ valid_pattern ("(((a|b))c|$d)e$");
+ valid_pattern ("(((a|b))c$|d)e$");
+ valid_pattern ("(((a|b))$c|d)e$");
+ valid_pattern ("(((a|b)$)c|d)e$");
+ valid_pattern ("(((a|b$))c|d)e$");
+ valid_pattern ("(((a$|b))c|d)e$");
+ valid_pattern ("((($a|b))c|d)e$");
+ valid_pattern ("(($(a|b))c|d)e$");
+ valid_pattern ("($((a|b))c|d)e$");
+ valid_pattern ("$(((a|b))c|d)e$");
+ valid_pattern ("(^((a|b)^)c|^d)e");
+ valid_pattern ("(^((a|b))^c|^d)e");
+ valid_pattern ("(^((a|b))c|^d^)e");
+ valid_pattern ("(^((a|b))c|^d)^e");
+
+ valid_pattern ("^e(^d|c((a|b)))");
+ valid_pattern ("^e(d|^c((a|b)))");
+ valid_pattern ("^e(d|c^((a|b)))");
+ valid_pattern ("^e(d|c(^(a|b)))");
+ valid_pattern ("^e(d|c((^a|b)))");
+ valid_pattern ("^e(d|c((a|^b)))");
+ valid_pattern ("^e(d|c((a|b^)))");
+ valid_pattern ("^e(d|c((a|b)^))");
+ valid_pattern ("^e(d|c((a|b))^)");
+ valid_pattern ("^e(d|c((a|b)))^");
+ valid_pattern ("e$(d$|c((a$|b$)))");
+ valid_pattern ("e(d$|c$((a$|b$)))");
+ valid_pattern ("e(d$|c($(a$|b$)))");
+ valid_pattern ("e(d$|c(($a$|b$)))");
+ valid_pattern ("e$(d$|c((a|b)$))");
+ valid_pattern ("e($d$|c((a|b)$))");
+ valid_pattern ("e(d$|$c((a|b)$))");
+ valid_pattern ("e(d$|c$((a|b)$))");
+ valid_pattern ("e(d$|c($(a|b)$))");
+ valid_pattern ("e(d$|c(($a|b)$))");
+ valid_pattern ("e(d$|c((a|$b)$))");
+ valid_pattern ("e(d$|c((a$|$b$)))");
+
+ valid_pattern ("e$(d$|c((a|b))$)");
+ valid_pattern ("e($d$|c((a|b))$)");
+ valid_pattern ("e(d$|$c((a|b))$)");
+ valid_pattern ("e(d$|c$((a|b))$)");
+ valid_pattern ("e(d$|c($(a|b))$)");
+ valid_pattern ("e(d$|c(($a|b))$)");
+ valid_pattern ("e(d$|c((a|$b))$)");
+ valid_pattern ("e$(d$|c((a|b)))$");
+ valid_pattern ("e($d$|c((a|b)))$");
+ valid_pattern ("e(d$|$c((a|b)))$");
+ valid_pattern ("e(d$|c$((a|b)))$");
+ valid_pattern ("e(d$|c($(a|b)))$");
+ valid_pattern ("e(d$|c(($a|b)))$");
+ valid_pattern ("e(d$|c((a|$b)))$");
+ valid_pattern ("(((^a|^b)^)c)|^de");
+ valid_pattern ("(((^a|^b))^c)|^de");
+ valid_pattern ("(((^a|^b))c)^|^de");
+ valid_pattern ("$(((a|b))c$)|de$");
+ valid_pattern ("($((a|b))c$)|de$");
+ valid_pattern ("(($(a|b))c$)|de$");
+ valid_pattern ("((($a|b))c$)|de$");
+ valid_pattern ("(((a|$b))c$)|de$");
+ valid_pattern ("(((a|b)$)c$)|de$");
+ valid_pattern ("(((a|b))$c$)|de$");
+ valid_pattern ("$(((a|b))c)$|de$");
+ valid_pattern ("($((a|b))c)$|de$");
+ valid_pattern ("(($(a|b))c)$|de$");
+ valid_pattern ("((($a|b))c)$|de$");
+ valid_pattern ("(((a|$b))c)$|de$");
+ valid_pattern ("(((a|b)$)c)$|de$");
+ valid_pattern ("(((a|b))$c)$|de$");
+ valid_pattern ("^ed|^(c((a|b)))^");
+ valid_pattern ("^ed|^(c((a|b))^)");
+ valid_pattern ("^ed|^(c((a|b)^))");
+ valid_pattern ("^ed|^(c((a|b^)))");
+ valid_pattern ("^ed|^(c((a^|b)))");
+ valid_pattern ("^ed|^(c((^a|b)))");
+ valid_pattern ("^ed|^(c(^(a|b)))");
+ valid_pattern ("^ed|^(c^((a|b)))");
+ valid_pattern ("^ed|(^c((a|b)))^");
+ valid_pattern ("^ed|(^c((a|b))^)");
+ valid_pattern ("^ed|(^c((a|b)^))");
+ valid_pattern ("^ed|(^c((a|b^)))");
+ valid_pattern ("^ed|(^c((a|^b)))");
+ valid_pattern ("^ed|(^c((a^|b)))");
+ valid_pattern ("^ed|(^c((^a|b)))");
+ valid_pattern ("^ed|(^c(^(a|b)))");
+ valid_pattern ("^ed|(^c(^(a|b)))");
+ valid_pattern ("^ed|(^c^((a|b)))");
+ valid_pattern ("ed$|$(c((a|b)))$");
+ valid_pattern ("ed$|($c((a|b)))$");
+ valid_pattern ("ed$|(c$((a|b)))$");
+ valid_pattern ("ed$|(c($(a|b)))$");
+ valid_pattern ("ed$|(c(($a|b)))$");
+ valid_pattern ("ed$|(c((a|$b)))$");
+ valid_pattern ("ed$|$(c((a|b))$)");
+ valid_pattern ("ed$|($c((a|b))$)");
+ valid_pattern ("ed$|(c$((a|b))$)");
+ valid_pattern ("ed$|(c($(a|b))$)");
+ valid_pattern ("ed$|(c(($a|b))$)");
+ valid_pattern ("ed$|(c((a|$b))$)");
+ valid_pattern ("ed$|$(c((a|b)$))");
+ valid_pattern ("ed$|($c((a|b)$))");
+ valid_pattern ("ed$|(c$((a|b)$))");
+ valid_pattern ("ed$|(c($(a|b)$))");
+ valid_pattern ("ed$|(c(($a|b)$))");
+ valid_pattern ("ed$|(c((a|$b)$))");
+ valid_pattern ("ed$|$(c((a|b)$))");
+ valid_pattern ("ed$|($c((a|b)$))");
+ valid_pattern ("ed$|(c$((a|b)$))");
+ valid_pattern ("ed$|(c($(a|b)$))");
+ valid_pattern ("ed$|(c(($a|b)$))");
+ valid_pattern ("ed$|(c((a|$b)$))");
+ valid_pattern ("ed$|$(c((a|b)$))");
+ valid_pattern ("ed$|($c((a|b)$))");
+ valid_pattern ("ed$|(c$((a|b)$))");
+ valid_pattern ("ed$|(c($(a|b)$))");
+ valid_pattern ("ed$|(c(($a|b)$))");
+ valid_pattern ("ed$|(c((a|$b)$))");
+ valid_pattern ("ed$|$(c((a|b)$))");
+ valid_pattern ("ed$|($c((a|b)$))");
+ valid_pattern ("ed$|(c$((a|b)$))");
+ valid_pattern ("ed$|(c($(a|b)$))");
+ valid_pattern ("ed$|(c(($a|b)$))");
+ valid_pattern ("ed$|(c((a|$b)$))");
+ valid_pattern ("ed$|$(c((a|b)$))");
+ valid_pattern ("ed$|($c((a|b)$))");
+ valid_pattern ("ed$|(c$((a|b)$))");
+ valid_pattern ("ed$|(c($(a|b)$))");
+ valid_pattern ("ed$|(c(($a|b)$))");
+ valid_pattern ("ed$|(c((a|$b)$))");
+ valid_pattern ("ed$|$(c((a$|b$)))");
+ valid_pattern ("ed$|($c((a$|b$)))");
+ valid_pattern ("ed$|(c$((a$|b$)))");
+ valid_pattern ("ed$|(c($(a$|b$)))");
+ valid_pattern ("ed$|(c(($a$|b$)))");
+ valid_pattern ("ed$|(c((a$|$b$)))");
+ valid_pattern ("^a(b|c)^|^d");
+ valid_pattern ("^a(b|c^)|^d");
+ valid_pattern ("^a(b|^c)|^d");
+ valid_pattern ("^a(b^|c)|^d");
+ valid_pattern ("^a(^b|c)|^d");
+ valid_pattern ("^a^(b|c)|^d");
+ valid_pattern ("$a(b$|c$)|d$");
+ valid_pattern ("a$(b$|c$)|d$");
+ valid_pattern ("a($b$|c$)|d$");
+ valid_pattern ("a(b$|$c$)|d$");
+ valid_pattern ("a(b$|c$)|$d$");
+ valid_pattern ("^(a^)(b|c)|^d");
+ valid_pattern ("^(a)^(b|c)|^d");
+ valid_pattern ("^(a)(^b|c)|^d");
+ valid_pattern ("^(a)(b^|c)|^d");
+ valid_pattern ("^(a)(b|^c)|^d");
+ valid_pattern ("^(a)(b|c^)|^d");
+ valid_pattern ("^(a)(b|c)^|^d");
+ valid_pattern ("(^a^)(b|c)|^d");
+ valid_pattern ("(^a)^(b|c)|^d");
+ valid_pattern ("(^a)(^b|c)|^d");
+ valid_pattern ("(^a)(b^|c)|^d");
+ valid_pattern ("(^a)(b|^c)|^d");
+ valid_pattern ("(^a)(b|c^)|^d");
+ valid_pattern ("(^a)(b|c)^|^d");
+
+ valid_pattern ("(a)(b$|c$)d$");
+ valid_pattern ("(a)(b|$c)$|d$");
+ valid_pattern ("(a)($b|c)$|d$");
+ valid_pattern ("(a)$(b|c)$|d$");
+ valid_pattern ("(a$)(b|c)$|d$");
+ valid_pattern ("($a)(b|c)$|d$");
+ valid_pattern ("$(a)(b|c)$|d$");
+ valid_pattern ("(b|c)($a)$|d$");
+ valid_pattern ("(b|c)$(a)$|d$");
+ valid_pattern ("(b|c$)(a)$|d$");
+ valid_pattern ("(b|$c)(a)$|d$");
+ valid_pattern ("(b$|c)(a)$|d$");
+ valid_pattern ("($b|c)(a)$|d$");
+ valid_pattern ("$(b|c)(a)$|d$");
+ valid_pattern ("(b|c)($a$)|d$");
+ valid_pattern ("(b|c)$(a$)|d$");
+ valid_pattern ("(b|c$)(a$)|d$");
+ valid_pattern ("(b|$c)(a$)|d$");
+ valid_pattern ("(b$|c)(a$)|d$");
+ valid_pattern ("($b|c)(a$)|d$");
+ valid_pattern ("$(b|c)(a$)|d$");
+ valid_pattern ("(a)$(b$|c$)|d$");
+ valid_pattern ("(a$)(b$|c$)|d$");
+ valid_pattern ("($a)(b$|c$)|d$");
+ valid_pattern ("$(a)(b$|c$)|d$");
+ valid_pattern ("^d|^(b^|c)(a)");
+ valid_pattern ("^d|^(b|c^)(a)");
+ valid_pattern ("^d|^(b|c)^(a)");
+ valid_pattern ("^d|^(b|c)(^a)");
+ valid_pattern ("^d|^(b|c)(a^)");
+ valid_pattern ("^d|^(b|c)(a)^");
+ valid_pattern ("^d|(^b|^c^)(a)");
+ valid_pattern ("^d|(^b|^c)^(a)");
+ valid_pattern ("^d|(^b|^c)(^a)");
+ valid_pattern ("^d|(^b|^c)(a^)");
+ valid_pattern ("^d|(^b|^c)(a)^");
+ valid_pattern ("d$|(b|c)($a$)");
+ valid_pattern ("d$|(b|c)$(a$)");
+ valid_pattern ("d$|(b|c$)(a$)");
+ valid_pattern ("d$|(b$|c)(a$)");
+ valid_pattern ("d$|($b|c)(a$)");
+ valid_pattern ("d$|$(b|c)(a$)");
+ valid_pattern ("d$|(b|c)($a)$");
+ valid_pattern ("d$|(b|c)$(a)$");
+ valid_pattern ("d$|(b|c$)(a)$");
+ valid_pattern ("d$|(b$|c)(a)$");
+ valid_pattern ("d$|($b|c)(a)$");
+ valid_pattern ("d$|$(b|c)(a)$");
+ valid_pattern ("^d|^(a^)(b|c)");
+ valid_pattern ("^d|^(a)^(b|c)");
+ valid_pattern ("^d|^(a)(^b|c)");
+ valid_pattern ("^d|^(a)(b^|c)");
+ valid_pattern ("^d|^(a)(b|^c)");
+ valid_pattern ("^d|^(a)(b|c^)");
+ valid_pattern ("^d|^(a)(b|c)^");
+ valid_pattern ("^d|(^a^)(b|c)");
+ valid_pattern ("^d|(^a)^(b|c)");
+ valid_pattern ("^d|(^a)(^b|c)");
+ valid_pattern ("^d|(^a)(b^|c)");
+ valid_pattern ("^d|(^a)(b|^c)");
+ valid_pattern ("^d|(^a)(b|c^)");
+ valid_pattern ("^d|(^a)(b|c)^");
+ valid_pattern ("d$|(a)$(b$|c$)");
+ valid_pattern ("d$|(a$)(b$|c$)");
+ valid_pattern ("d$|($a)(b$|c$)");
+ valid_pattern ("d$|$(a)(b$|c$)");
+ valid_pattern ("d$|(a)(b|$c)$");
+ valid_pattern ("d$|(a)($b|c)$");
+ valid_pattern ("d$|(a)$(b|c)$");
+ valid_pattern ("d$|(a$)(b|c)$");
+ valid_pattern ("d$|($a)(b|c)$");
+ valid_pattern ("d$|$(a)(b|c)$");
+ valid_pattern ("((^a|^b)|^c)|^d^");
+ valid_pattern ("((^a|^b)|^c)^|^d");
+ valid_pattern ("((^a|^b)|^c^)|^d");
+ valid_pattern ("((^a|^b)^|^c)|^d");
+ valid_pattern ("((^a|^b^)|^c)|^d");
+ valid_pattern ("((^a^|^b)|^c)|^d");
+ valid_pattern ("((a|b)|c)|$d$");
+ valid_pattern ("((a|b)|$c)|d$");
+ valid_pattern ("((a|$b)|c)|d$");
+ valid_pattern ("(($a|b)|c)|d$");
+ valid_pattern ("($(a|b)|c)|d$");
+ valid_pattern ("$((a|b)|c)|d$");
+ valid_pattern ("^d^|(c|(a|b))");
+ valid_pattern ("^d|(c^|(a|b))");
+ valid_pattern ("^d|(c|(a^|b))");
+ valid_pattern ("^d|(c|(a|b^))");
+ valid_pattern ("^d|(c|(a|b)^)");
+ valid_pattern ("^d|(c|(a|b))^");
+ valid_pattern ("d$|(c$|(a$|$b$))");
+ valid_pattern ("d$|(c$|($a$|b$))");
+ valid_pattern ("d$|($c$|(a$|b$))");
+ valid_pattern ("d$|$(c$|(a$|b$))");
+ valid_pattern ("$d$|(c$|(a$|b$))");
+ valid_pattern ("d$|(c$|(a|$b)$)");
+ valid_pattern ("d$|(c$|($a|b)$)");
+ valid_pattern ("d$|($c$|(a|b)$)");
+ valid_pattern ("d$|$(c$|(a|b)$)");
+ valid_pattern ("$d$|(c$|(a|b)$)");
+ valid_pattern ("d$|(c$|(a|$b))$");
+ valid_pattern ("d$|(c$|($a|b))$");
+ valid_pattern ("d$|($c$|(a|b))$");
+ valid_pattern ("d$|$(c$|(a|b))$");
+ valid_pattern ("$d$|(c$|(a|b))$");
+ valid_pattern ("^c^|(^a|^b)");
+ valid_pattern ("^c|(^a^|^b)");
+ valid_pattern ("^c|(^a|^b^)");
+ valid_pattern ("^c|(^a|^b)^");
+ valid_pattern ("c$|(a$|$b$)");
+ valid_pattern ("c$|($a$|b$)");
+ valid_pattern ("c$|$(a$|b$)");
+ valid_pattern ("$c$|(a$|b$)");
+ valid_pattern ("^d^(c|e((a|b)))");
+ valid_pattern ("^d(^c|e((a|b)))");
+ valid_pattern ("^d(c^|e((a|b)))");
+ valid_pattern ("^d(c|^e((a|b)))");
+ valid_pattern ("^d(c|e^((a|b)))");
+ valid_pattern ("^d(c|e(^(a|b)))");
+ valid_pattern ("^d(c|e((^a|b)))");
+ valid_pattern ("^d(c|e((a|^b)))");
+ valid_pattern ("^d(c|e((a|b^)))");
+ valid_pattern ("^d(c|e((a|b)^))");
+ valid_pattern ("^d(c|e((a|b))^)");
+ valid_pattern ("^d(c|e((a|b)))^");
+ valid_pattern ("d(c$|e($(a$|b$)))");
+ valid_pattern ("d(c$|e$((a$|b$)))");
+ valid_pattern ("d(c$|$e((a$|b$)))");
+ valid_pattern ("d($c$|e((a$|b$)))");
+ valid_pattern ("d$(c$|e((a$|b$)))");
+ valid_pattern ("$d(c$|e((a$|b$)))");
+ valid_pattern ("^d|^a^(b|c)");
+ valid_pattern ("^d|^a(^b|c)");
+ valid_pattern ("^d|^a(b^|c)");
+ valid_pattern ("^d|^a(b|^c)");
+ valid_pattern ("^d|^a(b|c^)");
+ valid_pattern ("^d|^a(b|c)^");
+ valid_pattern ("d$|a($b$|c$)");
+ valid_pattern ("d$|a$(b$|c$)");
+ valid_pattern ("d$|$a(b$|c$)");
+ valid_pattern ("$d$|a(b$|c$)");
+ valid_pattern ("^d|^(b^|c)a");
+ valid_pattern ("^d|^(b|c^)a");
+ valid_pattern ("^d|^(b|c)^a");
+ valid_pattern ("^d|^(b|c)a^");
+ valid_pattern ("d$|(b|c)$a$");
+ valid_pattern ("d$|(b|c$)a$");
+ valid_pattern ("d$|(b|$c)a$");
+ valid_pattern ("d$|(b$|c)a$");
+ valid_pattern ("d$|($b|c)a$");
+ valid_pattern ("d$|$(b|c)a$");
+ valid_pattern ("$d$|(b|c)a$");
+
+ /* xx Do these use all the valid_nonposix_pattern ones in other_test.c? */
+
+ TEST_SEARCH ("(^a|^b)c", "ac", 0, 2);
+ TEST_SEARCH ("(^a|^b)c", "bc", 0, 2);
+ TEST_SEARCH ("c(a$|b$)", "ca", 0, 2);
+ TEST_SEARCH ("c(a$|b$)", "cb", 0, 2);
+ TEST_SEARCH ("^(a|b)|^c", "ad", 0, 2);
+ TEST_SEARCH ("^(a|b)|^c", "bd", 0, 2);
+ TEST_SEARCH ("(a|b)$|c$", "da", 0, 2);
+ TEST_SEARCH ("(a|b)$|c$", "db", 0, 2);
+ TEST_SEARCH ("(a|b)$|c$", "dc", 0, 2);
+ TEST_SEARCH ("(^a|^b)|^c", "ad", 0, 2);
+ TEST_SEARCH ("(^a|^b)|^c", "bd", 0, 2);
+ TEST_SEARCH ("(^a|^b)|^c", "cd", 0, 2);
+ TEST_SEARCH ("(a$|b$)|c$", "da", 0, 2);
+ TEST_SEARCH ("(a$|b$)|c$", "db", 0, 2);
+ TEST_SEARCH ("(a$|b$)|c$", "dc", 0, 2);
+ TEST_SEARCH ("^c|(^a|^b)", "ad", 0, 2);
+ TEST_SEARCH ("^c|(^a|^b)", "bd", 0, 2);
+ TEST_SEARCH ("^c|(^a|^b)", "cd", 0, 2);
+ TEST_SEARCH ("c$|(a$|b$)", "da", 0, 2);
+ TEST_SEARCH ("c$|(a$|b$)", "db", 0, 2);
+ TEST_SEARCH ("c$|(a$|b$)", "dc", 0, 2);
+ TEST_SEARCH ("^c|^(a|b)", "ad", 0, 2);
+ TEST_SEARCH ("^c|^(a|b)", "bd", 0, 2);
+ TEST_SEARCH ("^c|^(a|b)", "cd", 0, 2);
+ TEST_SEARCH ("c$|(a|b)$", "da", 0, 2);
+ TEST_SEARCH ("c$|(a|b)$", "db", 0, 2);
+ TEST_SEARCH ("c$|(a|b)$", "dc", 0, 2);
+ TEST_SEARCH ("(^a|^b)c|^d", "ace", 0, 3);
+ TEST_SEARCH ("(^a|^b)c|^d", "bce", 0, 3);
+ TEST_SEARCH ("(^a|^b)c|^d", "de", 0, 2);
+ TEST_SEARCH ("(a|b)c$|d$", "eac", 0, 3);
+ TEST_SEARCH ("(a|b)c$|d$", "ebc", 0, 3);
+ TEST_SEARCH ("(a|b)c$|d$", "ed", 0, 3);
+ TEST_SEARCH ("^d|^c(a|b)", "cae", 0, 3);
+ TEST_SEARCH ("^d|^c(a|b)", "cbe", 0, 3);
+ TEST_SEARCH ("^d|^c(a|b)", "de", 0, 3);
+ TEST_SEARCH ("d$|c(a$|b$)", "eca", 0, 3);
+ TEST_SEARCH ("d$|c(a$|b$)", "ecb", 0, 3);
+ TEST_SEARCH ("d$|c(a$|b$)", "ed", 0, 3);
+
+ TEST_SEARCH ("(((^a|^b))c|^d)e", "acef", 0, 4);
+ TEST_SEARCH ("(((^a|^b))c|^d)e", "bcef", 0, 4);
+ TEST_SEARCH ("(((^a|^b))c|^d)e", "def", 0, 3);
+
+ TEST_SEARCH ("((^(a|b))c|^d)e", "acef", 0, 4);
+ TEST_SEARCH ("((^(a|b))c|^d)e", "bcef", 0, 4);
+ TEST_SEARCH ("((^(a|b))c|^d)e", "def", 0, 3);
+
+ TEST_SEARCH ("(^((a|b))c|^d)e", "acef", 0, 4);
+ TEST_SEARCH ("(^((a|b))c|^d)e", "bcef", 0, 4);
+ TEST_SEARCH ("(^((a|b))c|^d)e", "def", 0, 3);
+
+ TEST_SEARCH ("(((a|b))c|d)e$", "face", 0, 4);
+ TEST_SEARCH ("(((a|b))c|d)e$", "fbce", 0, 4);
+ TEST_SEARCH ("(((a|b))c|d)e$", "fde", 0, 3);
+
+ TEST_SEARCH ("^e(d|c((a|b)))", "edf", 0, 3);
+ TEST_SEARCH ("^e(d|c((a|b)))", "ecaf", 0, 4);
+ TEST_SEARCH ("^e(d|c((a|b)))", "ecbf", 0, 4);
+
+ TEST_SEARCH ("e(d$|c((a$|b$)))", "fed", 0, 3);
+ TEST_SEARCH ("e(d$|c((a$|b$)))", "feca", 0, 4);
+ TEST_SEARCH ("e(d$|c((a$|b$)))", "fecb", 0, 4);
+
+ TEST_SEARCH ("e(d$|c((a|b)$))", "fed", 0, 3);
+ TEST_SEARCH ("e(d$|c((a|b)$))", "feca", 0, 4);
+ TEST_SEARCH ("e(d$|c((a|b)$))", "fecb", 0, 4);
+
+ TEST_SEARCH ("e(d$|c((a|b))$)", "fed", 0, 3);
+ TEST_SEARCH ("e(d$|c((a|b))$)", "feca", 0, 3);
+ TEST_SEARCH ("e(d$|c((a|b))$)", "fecb", 0, 3);
+
+ TEST_SEARCH ("e(d$|c((a|b)))$", "fed", 0, 3);
+ TEST_SEARCH ("e(d$|c((a|b)))$", "feca", 0, 3);
+ TEST_SEARCH ("e(d$|c((a|b)))$", "fecb", 0, 3);
+
+ TEST_SEARCH ("(((^a|^b))c)|^de", "acf", 0, 3);
+ TEST_SEARCH ("(((^a|^b))c)|^de", "bcf", 0, 3);
+ TEST_SEARCH ("(((^a|^b))c)|^de", "def", 0, 3);
+
+ TEST_SEARCH ("(((a|b))c$)|de$", "fac", 0, 3);
+ TEST_SEARCH ("(((a|b))c$)|de$", "fbc", 0, 3);
+ TEST_SEARCH ("(((a|b))c$)|de$", "fde", 0, 3);
+
+ TEST_SEARCH ("(((a|b))c)$|de$", "fac", 0, 3);
+ TEST_SEARCH ("(((a|b))c)$|de$", "fbc", 0, 3);
+ TEST_SEARCH ("(((a|b))c)$|de$", "fde", 0, 3);
+
+ TEST_SEARCH ("^ed|^(c((a|b)))", "edf", 0, 3);
+ TEST_SEARCH ("^ed|^(c((a|b)))", "caf", 0, 3);
+ TEST_SEARCH ("^ed|^(c((a|b)))", "cbf", 0, 3);
+
+ TEST_SEARCH ("^ed|(^c((a|b)))", "edf", 0, 3);
+ TEST_SEARCH ("^ed|(^c((a|b)))", "caf", 0, 3);
+ TEST_SEARCH ("^ed|(^c((a|b)))", "cbf", 0, 3);
+
+ TEST_SEARCH ("ed$|(c((a|b)))$", "fed", 0, 3);
+ TEST_SEARCH ("ed$|(c((a|b)))$", "fca", 0, 3);
+ TEST_SEARCH ("ed$|(c((a|b)))$", "fcb", 0, 3);
+
+ TEST_SEARCH ("ed$|(c((a|b))$)", "fed", 0, 3);
+ TEST_SEARCH ("ed$|(c((a|b))$)", "fca", 0, 3);
+ TEST_SEARCH ("ed$|(c((a|b))$)", "fcb", 0, 3);
+
+ TEST_SEARCH ("ed$|(c((a|b)$))", "fed", 0, 3);
+ TEST_SEARCH ("ed$|(c((a|b)$))", "fca", 0, 3);
+ TEST_SEARCH ("ed$|(c((a|b)$))", "fcb", 0, 3);
+
+ TEST_SEARCH ("ed$|(c((a$|b$)))", "fed", 0, 3);
+ TEST_SEARCH ("ed$|(c((a$|b$)))", "fca", 0, 3);
+ TEST_SEARCH ("ed$|(c((a$|b$)))", "fcb", 0, 3);
+
+ TEST_SEARCH ("^a(b|c)|^d", "abe", 0, 3);
+ TEST_SEARCH ("^a(b|c)|^d", "ace", 0, 3);
+ TEST_SEARCH ("^a(b|c)|^d", "df", 0, 2);
+
+ TEST_SEARCH ("a(b$|c$)|d$", "fab", 0, 3);
+ TEST_SEARCH ("a(b$|c$)|d$", "fac", 0, 3);
+ TEST_SEARCH ("a(b$|c$)|d$", "fd", 0, 2);
+
+ TEST_SEARCH ("^(a)(b|c)|^d", "abe", 0, 3);
+ TEST_SEARCH ("^(a)(b|c)|^d", "ace", 0, 3);
+ TEST_SEARCH ("^(a)(b|c)|^d", "df", 0, 2);
+
+ TEST_SEARCH ("(^a)(b|c)|^d", "abe", 0, 3);
+ TEST_SEARCH ("(^a)(b|c)|^d", "ace", 0, 3);
+ TEST_SEARCH ("(^a)(b|c)|^d", "df", 0, 2);
+
+ TEST_SEARCH ("(a)(b|c)$|d$", "fab", 0, 3);
+ TEST_SEARCH ("(a)(b|c)$|d$", "fac", 0, 3);
+ TEST_SEARCH ("(a)(b|c)$|d$", "fd", 0, 2);
+
+ TEST_SEARCH ("(b|c)(a)$|d$", "fba", 0, 3);
+ TEST_SEARCH ("(b|c)(a)$|d$", "fca", 0, 3);
+ TEST_SEARCH ("(b|c)(a)$|d$", "fd", 0, 2);
+
+ TEST_SEARCH ("(b|c)(a$)|d$", "fba", 0, 3);
+ TEST_SEARCH ("(b|c)(a$)|d$", "fca", 0, 3);
+ TEST_SEARCH ("(b|c)(a$)|d$", "fd", 0, 2);
+
+ TEST_SEARCH ("(a)(b$|c$)|d$", "fab", 0, 3);
+ TEST_SEARCH ("(a)(b$|c$)|d$", "fac", 0, 3);
+ TEST_SEARCH ("(a)(b$|c$)|d$", "fd", 0, 2);
+
+ TEST_SEARCH ("^d|^(b|c)(a)", "df", 0, 2);
+ TEST_SEARCH ("^d|^(b|c)(a)", "baf", 0, 3);
+ TEST_SEARCH ("^d|^(b|c)(a)", "caf", 0, 3);
+
+ TEST_SEARCH ("^d|(^b|^c)(a)", "df", 0, 2);
+ TEST_SEARCH ("^d|(^b|^c)(a)", "baf", 0, 3);
+ TEST_SEARCH ("^d|(^b|^c)(a)", "caf", 0, 3);
+
+ TEST_SEARCH ("d$|(b|c)(a$)", "fd", 0, 2);
+ TEST_SEARCH ("d$|(b|c)(a$)", "fba", 0, 3);
+ TEST_SEARCH ("d$|(b|c)(a$)", "fca", 0, 3);
+
+ TEST_SEARCH ("d$|(b|c)(a)$", "fd", 0, 2);
+ TEST_SEARCH ("d$|(b|c)(a)$", "fba", 0, 3);
+ TEST_SEARCH ("d$|(b|c)(a)$", "fca", 0, 3);
+
+ TEST_SEARCH ("d$|(b|c)(a$)", "fd", 0, 2);
+ TEST_SEARCH ("d$|(b|c)(a$)", "fba", 0, 3);
+ TEST_SEARCH ("d$|(b|c)(a$)", "fca", 0, 3);
+
+ TEST_SEARCH ("^d|^(a)(b|c)", "df", 0, 2);
+ TEST_SEARCH ("^d|^(a)(b|c)", "abf", 0, 3);
+ TEST_SEARCH ("^d|^(a)(b|c)", "acf", 0, 3);
+
+ TEST_SEARCH ("^d|(^a)(b|c)", "df", 0, 2);
+ TEST_SEARCH ("^d|(^a)(b|c)", "abf", 0, 3);
+ TEST_SEARCH ("^d|(^a)(b|c)", "acf", 0, 3);
+
+ TEST_SEARCH ("d$|(a)(b$|c$)", "fd", 0, 2);
+ TEST_SEARCH ("d$|(a)(b$|c$)", "fab", 0, 3);
+ TEST_SEARCH ("d$|(a)(b$|c$)", "fac", 0, 3);
+
+ TEST_SEARCH ("d$|(a)(b|c)$", "fd", 0, 2);
+ TEST_SEARCH ("d$|(a)(b|c)$", "fab", 0, 3);
+ TEST_SEARCH ("d$|(a)(b|c)$", "fac", 0, 3);
+
+ TEST_SEARCH ("((^a|^b)|^c)|^d", "ae", 0, 2);
+ TEST_SEARCH ("((^a|^b)|^c)|^d", "be", 0, 2);
+ TEST_SEARCH ("((^a|^b)|^c)|^d", "ce", 0, 2);
+ TEST_SEARCH ("((^a|^b)|^c)|^d", "de", 0, 2);
+
+ TEST_SEARCH ("((a|b)|c)|d$", "ed", 0, 2);
+ TEST_SEARCH ("((a|b)|c)|d$", "ea", 0, 2);
+ TEST_SEARCH ("((a|b)|c)|d$", "eb", 0, 2);
+ TEST_SEARCH ("((a|b)|c)|d$", "ec", 0, 2);
+
+ TEST_SEARCH ("^d|(c|(a|b))", "de", 0, 2);
+
+ TEST_SEARCH ("d$|(c$|(a$|b$))", "ed", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a$|b$))", "ec", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a$|b$))", "ea", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a$|b$))", "eb", 0, 2);
+
+ TEST_SEARCH ("d$|(c$|(a|b)$)", "ed", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a|b)$)", "ec", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a|b)$)", "ea", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a|b)$)", "eb", 0, 2);
+
+ TEST_SEARCH ("d$|(c$|(a|b))$", "ed", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a|b))$", "ec", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a|b))$", "ea", 0, 2);
+ TEST_SEARCH ("d$|(c$|(a|b))$", "eb", 0, 2);
+
+ test_match ("a|^b", "b");
+ test_match ("a|b$", "b");
+ test_match ("^b|a", "b");
+ test_match ("b$|a", "b");
+ test_match ("(^a)", "a");
+ test_match ("(a$)", "a");
+ TEST_SEARCH ("c|^ab", "aba", 0, 3);
+ TEST_SEARCH ("c|ba$", "aba", 0, 3);
+ TEST_SEARCH ("^ab|c", "aba", 0, 3);
+ TEST_SEARCH ("ba$|c", "aba", 0, 3);
+ TEST_SEARCH ("(^a)", "ab", 0, 2);
+ TEST_SEARCH ("(a$)", "ba", 0, 2);
+
+ TEST_SEARCH ("(^a$)", "a", 0, 1);
+ TEST_SEARCH ("(^a)", "ab", 0, 2);
+ TEST_SEARCH ("(b$)", "ab", 0, 2);
+
+ /* Backtracking. */
+ /* Per POSIX D11.1 p. 108, leftmost longest match. */
+ test_match ("(wee|week)(knights|night)", "weeknights");
+
+ test_match ("(fooq|foo)qbar", "fooqbar");
+ test_match ("(fooq|foo)(qbarx|bar)", "fooqbarx");
+
+ /* Take first alternative that does the longest match. */
+ test_all_registers ("(fooq|(foo)|(fo))((qbarx)|(oqbarx)|bar)", "fooqbarx",
+ "", 0, 8, 0, 3, 0, 3, -1, -1, 3, 8, 3, 8, -1, -1, -1, -1, -1, -1,
+ -1, -1);
+
+ test_match ("(fooq|foo)*qbar", "fooqbar");
+ test_match ("(fooq|foo)*(qbar)", "fooqbar");
+ test_match ("(fooq|foo)*(qbar)*", "fooqbar");
+
+ test_match ("(fooq|fo|o)*qbar", "fooqbar");
+ test_match ("(fooq|fo|o)*(qbar)", "fooqbar");
+ test_match ("(fooq|fo|o)*(qbar)*", "fooqbar");
+
+ test_match ("(fooq|fo|o)*(qbar|q)*", "fooqbar");
+ test_match ("(fooq|foo)*(qbarx|bar)", "fooqbarx");
+ test_match ("(fooq|foo)*(qbarx|bar)*", "fooqbarx");
+
+ test_match ("(fooq|fo|o)+(qbar|q)+", "fooqbar");
+ test_match ("(fooq|foo)+(qbarx|bar)", "fooqbarx");
+ test_match ("(fooq|foo)+(qbarx|bar)+", "fooqbarx");
+
+ /* Per Mike Haertel. */
+ test_match ("(foo|foobarfoo)(bar)*", "foobarfoo");
+
+ /* Combination. */
+ test_match ("[ab]?c", "ac");
+ test_match ("[ab]*c", "ac");
+ test_match ("[ab]+c", "ac");
+ test_match ("(a|b)?c", "ac");
+ test_match ("(a|b)*c", "ac");
+ test_match ("(a|b)+c", "ac");
+ test_match ("(a*c)?b", "b");
+ test_match ("(a*c)+b", "aacb");
+ /* Registers. */
+ /* Per David A. Willcox. */
+ test_match ("a((b)|(c))d", "acd");
+ test_all_registers ("a((b)|(c))d", "acd", "", 0, 3, 1, 2, -1, -1, 1, 2,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+
+ /* Extended regular expressions, continued; these don't match their strings. */
+ test_should_match = false;
+
+#if 0
+ /* Invalid use of special characters. */
+ /* These are not invalid anymore, since POSIX says the behavior is
+ undefined, and we prefer context-independent to context-invalid. */
+ invalid_pattern (REG_BADRPT, "*");
+ invalid_pattern (REG_BADRPT, "a|*");
+ invalid_pattern (REG_BADRPT, "(*)");
+ invalid_pattern (REG_BADRPT, "^*");
+ invalid_pattern (REG_BADRPT, "+");
+ invalid_pattern (REG_BADRPT, "a|+");
+ invalid_pattern (REG_BADRPT, "(+)");
+ invalid_pattern (REG_BADRPT, "^+");
+
+ invalid_pattern (REG_BADRPT, "?");
+ invalid_pattern (REG_BADRPT, "a|?");
+ invalid_pattern (REG_BADRPT, "(?)");
+ invalid_pattern (REG_BADRPT, "^?");
+
+ invalid_pattern (REG_BADPAT, "|");
+ invalid_pattern (REG_BADPAT, "a|");
+ invalid_pattern (REG_BADPAT, "a||");
+ invalid_pattern (REG_BADPAT, "(|a)");
+ invalid_pattern (REG_BADPAT, "(a|)");
+
+ invalid_pattern (REG_BADPAT, PARENS_TO_OPS ("(|)"));
+
+ invalid_pattern (REG_BADRPT, "{1}");
+ invalid_pattern (REG_BADRPT, "a|{1}");
+ invalid_pattern (REG_BADRPT, "^{1}");
+ invalid_pattern (REG_BADRPT, "({1})");
+
+ invalid_pattern (REG_BADPAT, "|b");
+
+ invalid_pattern (REG_BADRPT, "^{0,}*");
+ invalid_pattern (REG_BADRPT, "$*");
+ invalid_pattern (REG_BADRPT, "${0,}*");
+#endif /* 0 */
+
+ invalid_pattern (REG_EESCAPE, "\\");
+
+ test_match ("a?b", "a");
+
+
+ test_match ("a+", "");
+ test_match ("a+b", "a");
+ test_match ("a?", "b");
+
+#if 0
+ /* We make empty groups valid now, since they are undefined in POSIX.
+ (13 Sep 92) */
+ /* Subexpressions. */
+ invalid_pattern (REG_BADPAT, "()");
+ invalid_pattern (REG_BADPAT, "a()");
+ invalid_pattern (REG_BADPAT, "()b");
+ invalid_pattern (REG_BADPAT, "a()b");
+ invalid_pattern (REG_BADPAT, "()*");
+ invalid_pattern (REG_BADPAT, "(()*");
+#endif
+ /* Invalid intervals. */
+ test_match ("a{2}*", "aaa");
+ test_match ("a{2}?", "aaa");
+ test_match ("a{2}+", "aaa");
+ test_match ("a{2}{2}", "aaa");
+ test_match ("a{1}{1}{2}", "aaa");
+ test_match ("a{1}{1}{2}", "a");
+ /* Invalid alternation. */
+ test_match ("a|b", "c");
+
+ TEST_SEARCH ("c|^ba", "aba", 0, 3);
+ TEST_SEARCH ("c|ab$", "aba", 0, 3);
+ TEST_SEARCH ("^ba|c", "aba", 0, 3);
+ TEST_SEARCH ("ab$|c", "aba", 0, 3);
+ /* Invalid anchoring. */
+ TEST_SEARCH ("(^a)", "ba", 0, 2);
+ TEST_SEARCH ("(b$)", "ba", 0, 2);
+
+ printf ("\nFinished POSIX extended tests.\n");
+}
+
+
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/test/psx-generic.c b/gnu/lib/libregex/test/psx-generic.c
new file mode 100644
index 0000000..8e97f75
--- /dev/null
+++ b/gnu/lib/libregex/test/psx-generic.c
@@ -0,0 +1,336 @@
+/* psx-generic.c: test POSIX re's independent of us using basic or
+ extended syntax. */
+
+#include "test.h"
+
+
+void
+test_posix_generic ()
+{
+ int omit_generic_tests = 0; /* reset in debugger to skip */
+
+ if (omit_generic_tests)
+ return;
+ /* Tests somewhat in the order of P1003.2. */
+
+ /* Both posix basic and extended; should match. */
+
+ printf ("\nStarting generic POSIX tests.\n");
+ test_grouping ();
+ test_intervals ();
+
+ test_should_match = true;
+ /* Ordinary characters. */
+ printf ("\nContinuing generic POSIX tests.\n");
+
+ MATCH_SELF ("");
+ test_fastmap ("", "", 0, 0);
+ test_fastmap_search ("", "", "", 0, 0, 2, 0, 0);
+ TEST_REGISTERS ("", "", 0, 0, -1, -1, -1, -1);
+ TEST_SEARCH ("", "", 0, 0);
+ TEST_SEARCH_2 ("", "", "", 0, 1, 0);
+
+ MATCH_SELF ("abc");
+ test_fastmap ("abc", "a", 0, 0);
+ TEST_REGISTERS ("abc", "abc", 0, 3, -1, -1, -1, -1);
+ TEST_REGISTERS ("abc", "xabcx", 1, 4, -1, -1, -1, -1);
+
+ test_match ("\\a","a");
+ test_match ("\\0", "0");
+
+ TEST_SEARCH ("a", "ab", 0, 2);
+ TEST_SEARCH ("b", "ab", 0, 2);
+ TEST_SEARCH ("a", "ab", 1, -2);
+ TEST_SEARCH_2 ("a", "a", "b", 0, 2, 2);
+ TEST_SEARCH_2 ("b", "a", "b", 0, 2, 2);
+ TEST_SEARCH_2 ("a", "a", "b", 1, -2, 2);
+
+ test_match ("\n", "\n");
+ test_match ("a\n", "a\n");
+ test_match ("\nb", "\nb");
+ test_match ("a\nb", "a\nb");
+
+ TEST_SEARCH ("b", "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 236, -237);
+ /* Valid use of special characters. */
+ test_match ("a*", "aa");
+ test_fastmap ("a*", "a", 0, 0);
+ TEST_REGISTERS ("a*", "aa", 0, 2, -1, -1, -1, -1);
+
+ test_match ("a*b", "aab");
+ test_fastmap ("a*b", "ab", 0, 0);
+
+ test_match ("a*ab", "aab");
+ TEST_REGISTERS ("a*a", "aa", 0, 2, -1, -1, -1, -1);
+ TEST_REGISTERS ("a*a", "xaax", 1, 3, -1, -1, -1, -1);
+
+ test_match ("\\{", "{");
+ test_match ("\\^", "^");
+ test_match ("\\.", ".");
+ test_match ("\\*", "*");
+ test_match ("\\[", "[");
+ test_match ("\\$", "$");
+ test_match ("\\\\", "\\");
+
+ test_match ("ab*", "a");
+ test_match ("ab*", "abb");
+
+ /* Valid consecutive repetitions. */
+ test_match ("a**", "a");
+ /* Valid period. */
+ test_match (".", "a");
+ TEST_REGISTERS (".", "a", 0, 1, -1, -1, -1, -1);
+ test_match (".", "\004");
+ test_match (".", "\n");
+ /* Valid bracket expressions. */
+ test_match ("[ab]", "a");
+ test_match ("[ab]", "b");
+ test_fastmap ("[ab]", "ab", 0, 0);
+ TEST_REGISTERS ("[ab]", "a", 0, 1, -1, -1, -1, -1);
+ TEST_REGISTERS ("[ab]", "xax", 1, 2, -1, -1, -1, -1);
+
+ test_fastmap ("[^ab]", "ab", 1, 1);
+ test_match ("[^ab]", "c");
+ test_match ("[^a]", "\n");
+
+ test_match ("[a]*a", "aa");
+
+ test_match ("[[]", "[");
+ test_match ("[]]", "]");
+ test_match ("[.]", ".");
+ test_match ("[*]", "*");
+ test_match ("[\\]", "\\");
+ test_match ("[\\(]", "(");
+ test_match ("[\\)]", ")");
+ test_match ("[^]]", "a");
+ test_match ("[a^]", "^");
+ test_match ("[a$]", "$");
+ test_match ("[]a]", "]");
+ test_match ("[a][]]", "a]");
+ test_match ("[\n]", "\n");
+ test_match ("[^a]", "\n");
+ test_match ("[a-]", "a");
+
+ TEST_REGISTERS ("\\`[ \t\n]*", " karl (Karl Berry)", 0, 1, -1, -1, -1, -1);
+ TEST_REGISTERS ("[ \t\n]*\\'", " karl (Karl Berry)", 18, 18, -1, -1, -1, -1);
+
+ /* Collating, noncollating,
+ equivalence classes aren't
+ implemented yet. */
+
+
+ /* Character classes. */
+ test_match ("[:alpha:]", "p");
+ test_match ("[[:alpha:]]", "a");
+ test_match ("[[:alpha:]]", "z");
+ test_match ("[[:alpha:]]", "A");
+ test_match ("[[:alpha:]]", "Z");
+ test_match ("[[:upper:]]", "A");
+ test_match ("[[:upper:]]", "Z");
+ test_match ("[[:lower:]]", "a");
+ test_match ("[[:lower:]]", "z");
+
+ test_match ("[[:digit:]]", "0");
+ test_match ("[[:digit:]]", "9");
+ test_fastmap ("[[:digit:]]", "0123456789", 0, 0);
+
+ test_match ("[[:alnum:]]", "0");
+ test_match ("[[:alnum:]]", "9");
+ test_match ("[[:alnum:]]", "a");
+ test_match ("[[:alnum:]]", "z");
+ test_match ("[[:alnum:]]", "A");
+ test_match ("[[:alnum:]]", "Z");
+ test_match ("[[:xdigit:]]", "0");
+ test_match ("[[:xdigit:]]", "9");
+ test_match ("[[:xdigit:]]", "A");
+ test_match ("[[:xdigit:]]", "F");
+ test_match ("[[:xdigit:]]", "a");
+ test_match ("[[:xdigit:]]", "f");
+ test_match ("[[:space:]]", " ");
+ test_match ("[[:print:]]", " ");
+ test_match ("[[:print:]]", "~");
+ test_match ("[[:punct:]]", ",");
+ test_match ("[[:graph:]]", "!");
+ test_match ("[[:graph:]]", "~");
+ test_match ("[[:cntrl:]]", "\177");
+ test_match ("[[:digit:]a]", "a");
+ test_match ("[[:digit:]a]", "2");
+ test_match ("[a[:digit:]]", "a");
+ test_match ("[a[:digit:]]", "2");
+ test_match ("[[:]", "[");
+ test_match ("[:]", ":");
+ test_match ("[[:a]", "[");
+ test_match ("[[:alpha:a]", "[");
+ /* Valid ranges. */
+ test_match ("[a-a]", "a");
+ test_fastmap ("[a-a]", "a", 0, 0);
+ TEST_REGISTERS ("[a-a]", "xax", 1, 2, -1, -1, -1, -1);
+
+ test_match ("[a-z]", "z");
+ test_fastmap ("[a-z]", "abcdefghijklmnopqrstuvwxyz", 0, 0);
+ test_match ("[-a]", "-"); /* First */
+ test_match ("[-a]", "a");
+ test_match ("[a-]", "-"); /* Last */
+ test_match ("[a-]", "a");
+ test_match ("[--@]", "@"); /* First and starting point. */
+
+ test_match ("[%--a]", "%"); /* Ending point. */
+ test_match ("[%--a]", "-"); /* Ditto. */
+
+ test_match ("[a%--]", "%"); /* Both ending point and last. */
+ test_match ("[a%--]", "-");
+ test_match ("[%--a]", "a"); /* Ending point only. */
+ test_match ("[a-c-f]", "e"); /* Piggyback. */
+
+ test_match ("[)-+--/]", "*");
+ test_match ("[)-+--/]", ",");
+ test_match ("[)-+--/]", "/");
+ test_match ("[[:digit:]-]", "-");
+ /* Concatenation ????*/
+ test_match ("[ab][cd]", "ac");
+ test_fastmap ("[ab][cd]", "ab", 0, 0);
+ TEST_REGISTERS ("[ab][cd]", "ad", 0, 2, -1, -1, -1, -1);
+ TEST_REGISTERS ("[ab][cd]", "xadx", 1, 3, -1, -1, -1, -1);
+
+ /* Valid expression anchoring. */
+ test_match ("^a", "a");
+ test_fastmap ("^a", "a", 0, 0);
+ TEST_REGISTERS ("^a", "ax", 0, 1, -1, -1, -1, -1);
+
+ test_match ("^", "");
+ TEST_REGISTERS ("^", "", 0, 0, -1, -1, -1, -1);
+ test_match ("$", "");
+ TEST_REGISTERS ("$", "", 0, 0, -1, -1, -1, -1);
+
+ test_match ("a$", "a");
+ test_fastmap ("a$", "a", 0, 0);
+ TEST_REGISTERS ("a$", "xa", 1, 2, -1, -1, -1, -1);
+
+ test_match ("^ab$", "ab");
+ test_fastmap ("^ab$", "a", 0, 0);
+ TEST_REGISTERS ("^a$", "a", 0, 1, -1, -1, -1, -1);
+
+ test_fastmap ("^$", "", 0, 0);
+ test_match ("^$", "");
+ TEST_REGISTERS ("^$", "", 0, 0, -1, -1, -1, -1);
+
+ TEST_SEARCH (PARENS_TO_OPS ("(^a)"), "ab", 0, 2);
+ TEST_SEARCH (PARENS_TO_OPS ("(a$)"), "ba", 0, 2);
+ TEST_SEARCH (PARENS_TO_OPS ("^(^a)"), "ab", 0, 2);
+ TEST_SEARCH (PARENS_TO_OPS ("(a$)$"), "ba", 0, 2);
+
+ /* Two strings. */
+ test_match_2 ("ab", "a", "b");
+ TEST_REGISTERS_2 ("ab", "a", "b", 0, 2, -1, -1, -1, -1);
+
+ test_match_2 ("a", "", "a");
+ test_match_2 ("a", "a", "");
+ test_match_2 ("ab", "a", "b");
+ /* (start)pos. */
+ TEST_POSITIONED_MATCH ("b", "ab", 1);
+ /* mstop. */
+ TEST_TRUNCATED_MATCH ("a", "ab", 1);
+
+
+ /* Both basic and extended, continued; should not match. */
+
+ test_should_match = false;
+ /* Ordinary characters. */
+ test_match ("abc", "ab");
+
+ TEST_SEARCH ("c", "ab", 0, 2);
+ TEST_SEARCH ("c", "ab", 0, 2);
+ TEST_SEARCH ("c", "ab", 1, -2);
+ TEST_SEARCH ("c", "ab", 0, 10);
+ TEST_SEARCH ("c", "ab", 1, -10);
+ TEST_SEARCH_2 ("c", "a", "b", 0, 2, 2);
+ TEST_SEARCH_2 ("c", "a", "b", 0, 2, 2);
+ TEST_SEARCH_2 ("c", "a", "b", 0, 2, 2);
+ TEST_SEARCH_2 ("c", "a", "b", 1, -2, 2);
+ TEST_SEARCH_2 ("c", "a", "b", 1, -2, 2);
+
+ TEST_SEARCH ("c", "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 236, -237);
+
+ /* Invalid use of special characters. */
+ invalid_pattern (REG_EESCAPE, "\\");
+ invalid_pattern (REG_EESCAPE, "a\\");
+ invalid_pattern (REG_EESCAPE, "a*\\");
+ /* Invalid period. */
+ test_match (".", "");
+ /* Invalid bracket expressions. */
+ test_match ("[ab]", "c");
+ test_match ("[^b]", "b");
+ test_match ("[^]]", "]");
+
+ invalid_pattern (REG_EBRACK, "[");
+ invalid_pattern (REG_EBRACK, "[^");
+ invalid_pattern (REG_EBRACK, "[a");
+ invalid_pattern (REG_EBRACK, "[]");
+ invalid_pattern (REG_EBRACK, "[]a");
+ invalid_pattern (REG_EBRACK, "a[]a");
+
+
+ test_match ("[:alpha:]", "q"); /* Character classes. */
+ test_match ("[[:alpha:]]", "2");
+ test_match ("[[:upper:]]", "a");
+ test_match ("[[:lower:]]", "A");
+ test_match ("[[:digit:]]", "a");
+ test_match ("[[:alnum:]]", ":");
+ test_match ("[[:xdigit:]]", "g");
+ test_match ("[[:space:]]", "a");
+ test_match ("[[:print:]]", "\177");
+ test_match ("[[:punct:]]", "a");
+ test_match ("[[:graph:]]", " ");
+ test_match ("[[:cntrl:]]", "a");
+ invalid_pattern (REG_EBRACK, "[[:");
+ invalid_pattern (REG_EBRACK, "[[:alpha:");
+ invalid_pattern (REG_EBRACK, "[[:alpha:]");
+ invalid_pattern (REG_ECTYPE, "[[::]]");
+ invalid_pattern (REG_ECTYPE, "[[:a:]]");
+ invalid_pattern (REG_ECTYPE, "[[:alpo:]]");
+ invalid_pattern (REG_ECTYPE, "[[:a:]");
+
+ test_match ("[a-z]", "2"); /* Invalid ranges. */
+ test_match ("[^-a]", "-");
+ test_match ("[^a-]", "-");
+ test_match ("[)-+--/]", ".");
+ invalid_pattern (REG_ERANGE, "[z-a]"); /* Empty */
+ invalid_pattern (REG_ERANGE, "[a--]"); /* Empty */
+ invalid_pattern (REG_ERANGE, "[[:digit:]-9]");
+ invalid_pattern (REG_ERANGE, "[a-[:alpha:]]");
+ invalid_pattern (REG_ERANGE, "[a-");
+ invalid_pattern (REG_EBRACK, "[a-z");
+
+ test_match ("[ab][cd]", "ae"); /* Concatenation. */
+ test_match ("b*c", "b"); /* Star. */
+
+ /* Invalid anchoring. */
+ test_match ("^", "a");
+ test_match ("^a", "ba");
+ test_match ("$", "b");
+ test_match ("a$", "ab");
+ test_match ("^$", "a");
+ test_match ("^ab$", "a");
+
+ TEST_SEARCH ("^a", "b\na", 0, 3);
+ TEST_SEARCH ("b$", "b\na", 0, 3);
+
+ test_match_2 ("^a", "\n", "a");
+ test_match_2 ("a$", "a", "\n");
+
+ TEST_SEARCH (PARENS_TO_OPS ("(^a)"), "ba", 0, 2);
+ TEST_SEARCH (PARENS_TO_OPS ("(a$)"), "ab", 0, 2);
+ TEST_SEARCH (PARENS_TO_OPS ("^(^a)"), "ba", 0, 2);
+ TEST_SEARCH (PARENS_TO_OPS ("(a$)$"), "ab", 0, 2);
+
+ printf ("\nFinished generic POSIX tests.\n");
+}
+
+
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/test/psx-group.c b/gnu/lib/libregex/test/psx-group.c
new file mode 100644
index 0000000..08ae8a2
--- /dev/null
+++ b/gnu/lib/libregex/test/psx-group.c
@@ -0,0 +1,440 @@
+/* psx-group.c: test POSIX grouping, both basic and extended. */
+
+#include "test.h"
+
+
+void
+test_grouping ()
+{
+ printf ("\nStarting POSIX grouping tests.\n");
+
+ test_should_match = true;
+
+ test_fastmap (PARENS_TO_OPS ("(a)"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a)"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)"), "a", 0, 1, 0, 1, -1, -1);
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)"), "xax", 1, 2, 1, 2, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a))"), "a");
+ test_fastmap (PARENS_TO_OPS ("((a))"), "a", 0, 0);
+ TEST_REGISTERS (PARENS_TO_OPS ("((a))"), "a", 0, 1, 0, 1, 0, 1);
+ TEST_REGISTERS (PARENS_TO_OPS ("((a))"), "xax", 1, 2, 1, 2, 1, 2);
+
+ test_fastmap (PARENS_TO_OPS ("(a)(b)"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a)(b)"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)(b)"), "ab", 0, 2, 0, 1, 1, 2);
+
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)(b)"), "xabx", 1, 3, 1, 2, 2, 3);
+
+ test_all_registers (PARENS_TO_OPS ("((a)(b))"), "ab", "", 0, 2, 0, 2, 0, 1,
+ 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+
+ /* Test that we simply ignore groups past the 255th. */
+ test_match (PARENS_TO_OPS ("((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((a))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))"), "a");
+
+
+ /* Per POSIX D11.1, p. 125. */
+
+ test_fastmap (PARENS_TO_OPS ("(a)*"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*"), "", 0, 0, -1, -1, -1, -1);
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*"), "aa", 0, 2, 1, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*)"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*)"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)"), "", 0, 0, 0, 0, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*)"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*)"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)"), "a", 0, 1, 0, 1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*)b"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*)b"), "b");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)b"), "b", 0, 1, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*)b"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)b"), "ab", 0, 2, 0, 1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a*)b)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("((a*)b)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "", 0, 0, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a*)b)*"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "ab", 0, 2, 0, 2, 0, 1);
+
+ test_match (PARENS_TO_OPS ("((a*)b)*"), "abb");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "abb", 0, 3, 2, 3, 2, 2);
+
+ test_match (PARENS_TO_OPS ("((a*)b)*"), "aabab");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "aabab", 0, 5, 3, 5, 3, 4);
+
+ test_match (PARENS_TO_OPS ("((a*)b)*"), "abbab");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "abbab", 0, 5, 3, 5, 3, 4);
+
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "xabbabx", 0, 0, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a*)b)*"), "abaabaaaab");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b)*"), "abaabaaab", 0, 9, 5, 9, 5, 8);
+
+ test_fastmap (PARENS_TO_OPS ("(ab)*"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(ab)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab)*"), "", 0, 0, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(ab)*"), "abab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab)*"), "abab", 0, 4, 2, 4, -1, -1);
+
+ /* We match the empty string here. */
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab)*"), "xababx", 0, 0, -1, -1, -1, -1);
+
+ /* Per David A. Willcox. */
+ TEST_REGISTERS (PARENS_TO_OPS ("a(b*)c"), "ac", 0, 2, 1, 1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a)*b"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(a)*b"), "b");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*b"), "b", 0, 1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a)*b"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*b"), "ab", 0, 2, 0, 1, -1, -1);
+
+ test_match_2 (PARENS_TO_OPS ("(a)*b"), "a", "ab");
+ TEST_REGISTERS_2 (PARENS_TO_OPS ("(a)*b"), "a", "ab", 0, 3, 1, 2, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a)*b"), "aab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*b"), "aab", 0, 3, 1, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a)*a"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a)*a"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*a"), "a", 0, 1, -1, -1, -1, -1);
+
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*"), "", 0, 0, 0, 0, 0, 0);
+
+ test_match (PARENS_TO_OPS ("((a*))*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*))*"), "", 0, 0, 0, 0, 0, 0);
+ test_match (PARENS_TO_OPS ("((a*))*"), "aa");
+
+ test_fastmap (PARENS_TO_OPS ("(a*)*b"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*)*b"), "b");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "b", 0, 1, 0, 0, -1, -1);
+
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "xbx", 1, 2, 1, 1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*)*b"), "ab"); /* Per rms. */
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "ab", 0, 2, 0, 1, -1, -1);
+
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "xabx", 1, 3, 1, 2, -1, -1);
+
+ /* Test register restores. */
+ test_match (PARENS_TO_OPS ("(a*)*b"), "aab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b"), "aab", 0, 3, 0, 2, -1, -1);
+
+ TEST_REGISTERS_2 (PARENS_TO_OPS ("(a*)*b"), "a", "ab", 0, 3, 0, 2, -1, -1);
+
+ /* We are matching the empty string, with backtracking. */
+ test_fastmap (PARENS_TO_OPS ("(a*)a"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*)a"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)a"), "a", 0, 1, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*)a"), "aa");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)a"), "aa", 0, 2, 0, 1, -1, -1);
+
+ /* We are matching the empty string, with backtracking. */
+/*fails test_match (PARENS_TO_OPS ("(a*)*a"), "a"); */
+ test_match (PARENS_TO_OPS ("(a*)*a"), "aa");
+ /* Match the empty string. */
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "a", 0, 1, 0, 0, -1, -1);
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "xax", 1, 2, 1, 1, -1, -1);
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "aa", 0, 2, 0, 1, -1, -1);
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*a"), "xaax", 1, 3, 1, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a)*ab"), "a", 0 , 0);
+ test_match (PARENS_TO_OPS ("(a)*ab"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*ab"), "ab", 0, 2, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a)*ab"), "aab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*ab"), "aab", 0, 3, 0, 1, -1, -1);
+
+ TEST_REGISTERS (PARENS_TO_OPS("(a)*ab"), "xaabx", 1, 4, 1, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*)ab"), "a", 0 , 0);
+ test_match (PARENS_TO_OPS ("(a*)ab"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)ab"), "ab", 0, 2, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*)ab"), "aab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)ab"), "aab", 0, 3, 0, 1, -1, -1);
+
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)ab"), "xaabx", 1, 4, 1, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*)*ab"), "a", 0 , 0);
+ test_match (PARENS_TO_OPS ("(a*)*ab"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*ab"), "ab", 0, 2, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*)*ab"), "aab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*ab"), "aab", 0, 3, 0, 1, -1, -1);
+
+ TEST_REGISTERS (PARENS_TO_OPS("(a*)*ab"), "xaabx", 1, 4, 1, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*)*b*c"), "abc", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*)*b*c"), "c");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*b*c"), "c", 0, 1, 0, 0, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a)*(ab)*"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a)*(ab)*"), "ab");
+ /* Register 1 doesn't match at all (vs. matching the empty string)
+ because of backtracking, hence -1's. */
+ TEST_REGISTERS (PARENS_TO_OPS ("(a)*(ab)*"), "ab", 0, 2, -1, -1, 0, 2);
+
+ test_match (PARENS_TO_OPS ("(a*)*(ab)*"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*(ab)*"), "ab", 0, 2, 0, 0, 0, 2);
+
+ test_fastmap (PARENS_TO_OPS ("(a*b)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*b)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*"), "", 0, 0, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b)*"), "b");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*"), "b", 0, 1, 0, 1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b)*"), "baab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*"), "baab", 0, 4, 1, 4, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*b*)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "", 0, 0, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "a", 0, 1, 0, 1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "ba");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "ba", 0, 2, 1, 2, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "ab", 0, 2, 0, 2, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "aa");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "aa", 0, 2, 0, 2, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "bb");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "bb", 0, 2, 0, 2, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "aba");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "aba", 0, 3, 2, 3, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b*)b"), "b");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)b"), "b", 0, 1, 0, 0, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a*)*(b*)*)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("((a*)*(b*)*)*"), "");
+ test_all_registers (PARENS_TO_OPS ("((a*)*(b*)*)*"), "", "", 0, 0, 0, 0,
+ 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a*)*(b*)*)*"), "aba");
+ /* Perhaps register 3 should be 3/3 here? Not sure if standard
+ specifies this. xx*/
+ test_all_registers (PARENS_TO_OPS ("((a*)*(b*)*)*"), "aba", "", 0, 3, 2, 3,
+ 2, 3, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a*)(b*))*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("((a*)(b*))*"), "");
+
+ test_all_registers (PARENS_TO_OPS ("((a*)(b*))*"), "", "", 0, 0, 0, 0,
+ 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), "");
+
+ test_match (PARENS_TO_OPS ("((a*)(b*))*"), "aba");
+ test_all_registers (PARENS_TO_OPS ("((a*)(b*))*"), "aba", "", 0, 3, 2, 3,
+ 2, 3, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a)*(b)*)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("((a)*(b)*)*"), "");
+ test_all_registers (PARENS_TO_OPS ("((a)*(b)*)*"), "", "", 0, 0, 0, 0,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a)*(b)*)*"), "aba");
+
+ test_all_registers (PARENS_TO_OPS ("((a)*(b)*)*"), "aba", "", 0, 3, 2, 3,
+ 2, 3, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(c(a)*(b)*)*"), "c", 0, 0);
+ test_match (PARENS_TO_OPS ("(c(a)*(b)*)*"), "");
+ test_all_registers (PARENS_TO_OPS ("(c(a)*(b)*)*"), "", "", 0, 0, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(c(a)*(b)*)*"), "c");
+ test_all_registers (PARENS_TO_OPS ("(c(a)*(b)*)*"), "c", "", 0, 1, 0, 1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("c((a)*(b)*)*"), "c", 0, 0);
+ test_match (PARENS_TO_OPS ("c((a)*(b)*)*"), "c");
+ test_all_registers (PARENS_TO_OPS ("c((a)*(b)*)*"), "c", "", 0, 1, 1, 1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(((a)*(b)*)*)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(((a)*(b)*)*)*"), "");
+ test_all_registers (PARENS_TO_OPS ("(((a)*(b)*)*)*"), "", "", 0, 0, 0, 0,
+ 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), "");
+ test_fastmap (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), "c", 0, 0);
+
+ test_all_registers (PARENS_TO_OPS ("(c(c(a)*(b)*)*)*"), "", "", 0, 0, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a)*b)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("((a)*b)*"), "");
+
+ test_match (PARENS_TO_OPS ("((a)*b)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "", 0, 0, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a)*b)*"), "abb");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "abb", 0, 3, 2, 3, 0, 1); /*zz*/
+
+ test_match (PARENS_TO_OPS ("((a)*b)*"), "abbab");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "abbab", 0, 5, 3, 5, 3, 4);
+
+ /* We match the empty string here. */
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*"), "xabbabx", 0, 0, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*)*"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*"), "", 0, 0, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*)*"), "aa");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*)*"), "aa", 0, 2, 0, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a*)*)*"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("((a*)*)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)*)*"), "", 0, 0, 0, 0, 0, 0);
+
+ test_match (PARENS_TO_OPS ("((a*)*)*"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)*)*"), "a", 0, 1, 0, 1, 0, 1);
+
+ test_fastmap (PARENS_TO_OPS ("(ab*)*"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("(ab*)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*"), "", 0, 0, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(ab*)*"), "aa");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*"), "aa", 0, 2, 1, 2, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(ab*)*c"), "ac", 0, 0);
+ test_match (PARENS_TO_OPS ("(ab*)*c"), "c");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*c"), "c", 0, 1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(ab*)*c"), "abbac");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*c"), "abbac", 0, 5, 3, 4, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(ab*)*c"), "abac");
+ TEST_REGISTERS (PARENS_TO_OPS ("(ab*)*c"), "abac", 0, 4, 2, 3, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*b)*c"), "abc", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*b)*c"), "c");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "c", 0, 1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b)*c"), "bbc");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "bbc", 0, 3, 1, 2, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b)*c"), "aababc");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "aababc", 0, 6, 3, 5, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(a*b)*c"), "aabaabc");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b)*c"), "aabaabc", 0, 7, 3, 6, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a*)b*)"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("((a*)b*)"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)"), "", 0, 0, 0, 0, 0, 0);
+
+ test_match (PARENS_TO_OPS ("((a*)b*)"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)"), "a", 0, 1, 0, 1, 0, 1);
+
+ test_match (PARENS_TO_OPS ("((a*)b*)"), "b");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)"), "b", 0, 1, 0, 1, 0, 0);
+
+ test_fastmap (PARENS_TO_OPS ("((a)*b*)"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("((a)*b*)"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "", 0, 0, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a)*b*)"), "a");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "a", 0, 1, 0, 1, 0, 1);
+
+ test_match (PARENS_TO_OPS ("((a)*b*)"), "b");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "b", 0, 1, 0, 1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("((a)*b*)"), "ab");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)"), "ab", 0, 2, 0, 2, 0, 1);
+
+ test_fastmap (PARENS_TO_OPS ("((a*)b*)c"), "abc", 0, 0);
+ test_match (PARENS_TO_OPS ("((a*)b*)c"), "c");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a*)b*)c"), "c", 0, 1, 0, 0, 0, 0);
+
+ test_fastmap (PARENS_TO_OPS ("((a)*b*)c"), "abc", 0, 0);
+ test_match (PARENS_TO_OPS ("((a)*b*)c"), "c");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b*)c"), "c", 0, 1, 0, 0, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(a*b*)*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "");
+ TEST_REGISTERS (PARENS_TO_OPS ("(a*b*)*"), "", 0, 0, 0, 0, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(((a*))((b*)))*"), "ab", 0, 0);
+ test_match (PARENS_TO_OPS ("(((a*))((b*)))*"), "");
+ test_all_registers (PARENS_TO_OPS ("(((a*))((b*)))*"), "", "", 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("(c*((a*))d*((b*))e*)*"), "abcde", 0, 0);
+ test_match (PARENS_TO_OPS ("(c*((a*))d*((b*))e*)*"), "");
+ test_all_registers (PARENS_TO_OPS ("(c*((a*))d*((b*))e*)*"), "", "", 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1);
+
+ test_fastmap (PARENS_TO_OPS ("((a)*b)*c"), "abc", 0, 0);
+ test_match (PARENS_TO_OPS ("((a)*b)*c"), "c");
+ TEST_REGISTERS (PARENS_TO_OPS ("((a)*b)*c"), "c", 0, 1, -1, -1, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(ab)*"), "");
+ test_match (PARENS_TO_OPS ("((ab)*)"), "");
+ test_match (PARENS_TO_OPS ("(((ab)*))"), "");
+ test_match (PARENS_TO_OPS ("((((ab)*)))"), "");
+ test_match (PARENS_TO_OPS ("(((((ab)*))))"), "");
+ test_match (PARENS_TO_OPS ("((((((ab)*)))))"), "");
+ test_match (PARENS_TO_OPS ("(((((((ab)*))))))"), "");
+ test_match (PARENS_TO_OPS ("((((((((ab)*)))))))"), "");
+ test_match (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "");
+
+
+ test_fastmap (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "a", 0, 0);
+ test_match (PARENS_TO_OPS ("((((((((((ab)*)))))))))"), "");
+ test_match (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "");
+ test_all_registers (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "", NULL,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1);
+
+ test_match (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "abab");
+ test_all_registers (PARENS_TO_OPS ("(((((((((ab)*))))))))"), "abab", NULL,
+ 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 0, 4, 2, 4);
+
+
+ test_should_match = false;
+
+ invalid_pattern (REG_EPAREN, PARENS_TO_OPS ("(a"));
+
+ test_match (PARENS_TO_OPS ("(a)"), "");
+ test_match (PARENS_TO_OPS ("((a))"), "b");
+ test_match (PARENS_TO_OPS ("(a)(b)"), "ac");
+ test_match (PARENS_TO_OPS ("(ab)*"), "acab");
+ test_match (PARENS_TO_OPS ("(a*)*b"), "c");
+ test_match (PARENS_TO_OPS ("(a*b)*"), "baa");
+ test_match (PARENS_TO_OPS ("(a*b)*"), "baabc");
+ test_match (PARENS_TO_OPS ("(a*b*)*"), "c");
+ test_match (PARENS_TO_OPS ("((a*)*(b*)*)*"), "c");
+ test_match (PARENS_TO_OPS ("(a*)*"), "ab");
+ test_match (PARENS_TO_OPS ("((a*)*)*"), "ab");
+ test_match (PARENS_TO_OPS ("((a*)*)*"), "b");
+ test_match (PARENS_TO_OPS ("(ab*)*"), "abc");
+ test_match (PARENS_TO_OPS ("(ab*)*c"), "abbad");
+ test_match (PARENS_TO_OPS ("(a*c)*b"), "aacaacd");
+ test_match (PARENS_TO_OPS ("(a*)"), "b");
+ test_match (PARENS_TO_OPS ("((a*)b*)"), "c");
+
+ /* Expression anchoring. */
+ TEST_SEARCH (PARENS_TO_OPS ("(^b)"), "ab", 0, 2);
+ TEST_SEARCH (PARENS_TO_OPS ("(a$)"), "ab", 0, 2);
+
+ printf ("\nFinished POSIX grouping tests.\n");
+}
diff --git a/gnu/lib/libregex/test/psx-interf.c b/gnu/lib/libregex/test/psx-interf.c
new file mode 100644
index 0000000..80498fb
--- /dev/null
+++ b/gnu/lib/libregex/test/psx-interf.c
@@ -0,0 +1,624 @@
+/* psx-interf.c: test POSIX interface. */
+
+#include <string.h>
+#include <assert.h>
+
+#include "test.h"
+
+#define ERROR_CODE_LENGTH 20
+#define TEST_ERRBUF_SIZE 15
+
+
+void test_compile ();
+
+
+/* ANSWER should be at least ERROR_CODE_LENGTH long. */
+
+static char *
+get_error_string (error_code, answer)
+ int error_code;
+ char answer[];
+{
+ switch (error_code)
+ {
+ case 0: strcpy (answer, "No error"); break;
+ case REG_NOMATCH: strcpy (answer, "REG_NOMATCH"); break;
+ case REG_BADPAT: strcpy (answer, "REG_BADPAT"); break;
+ case REG_EPAREN: strcpy (answer, "REG_EPAREN"); break;
+ case REG_ESPACE: strcpy (answer, "REG_ESPACE"); break;
+ case REG_ECOLLATE: strcpy (answer, "REG_ECOLLATE"); break;
+ case REG_ECTYPE: strcpy (answer, "REG_ECTYPE"); break;
+ case REG_EESCAPE: strcpy (answer, "REG_EESCAPE"); break;
+ case REG_ESUBREG: strcpy (answer, "REG_ESUBREG"); break;
+ case REG_EBRACK: strcpy (answer, "REG_EBRACK"); break;
+ case REG_EBRACE: strcpy (answer, "REG_EBRACE"); break;
+ case REG_BADBR: strcpy (answer, "REG_BADBR"); break;
+ case REG_ERANGE: strcpy (answer, "REG_ERANGE"); break;
+ case REG_BADRPT: strcpy (answer, "REG_BADRPT"); break;
+ case REG_EEND: strcpy (answer, "REG_EEND"); break;
+ default: strcpy (answer, "Bad error code");
+ }
+ return answer;
+}
+
+
+/* I don't think we actually need to initialize all these things.
+ --karl */
+
+void
+init_pattern_buffer (pattern_buffer_ptr)
+ regex_t *pattern_buffer_ptr;
+{
+ pattern_buffer_ptr->buffer = NULL;
+ pattern_buffer_ptr->allocated = 0;
+ pattern_buffer_ptr->used = 0;
+ pattern_buffer_ptr->fastmap = NULL;
+ pattern_buffer_ptr->fastmap_accurate = 0;
+ pattern_buffer_ptr->translate = NULL;
+ pattern_buffer_ptr->can_be_null = 0;
+ pattern_buffer_ptr->re_nsub = 0;
+ pattern_buffer_ptr->no_sub = 0;
+ pattern_buffer_ptr->not_bol = 0;
+ pattern_buffer_ptr->not_eol = 0;
+}
+
+
+void
+test_compile (valid_pattern, error_code_expected, pattern,
+ pattern_buffer_ptr, cflags)
+ unsigned valid_pattern;
+ int error_code_expected;
+ const char *pattern;
+ regex_t *pattern_buffer_ptr;
+ int cflags;
+{
+ int error_code_returned;
+ boolean error = false;
+ char errbuf[TEST_ERRBUF_SIZE];
+
+ init_pattern_buffer (pattern_buffer_ptr);
+ error_code_returned = regcomp (pattern_buffer_ptr, pattern, cflags);
+
+ if (valid_pattern && error_code_returned)
+ {
+ printf ("\nShould have been a valid pattern but wasn't.\n");
+ regerror (error_code_returned, pattern_buffer_ptr, errbuf,
+ TEST_ERRBUF_SIZE);
+ printf ("%s", errbuf);
+ error = true;
+ }
+
+ if (!valid_pattern && !error_code_returned)
+ {
+ printf ("\n\nInvalid pattern compiled as valid:\n");
+ error = true;
+ }
+
+ if (error_code_returned != error_code_expected)
+ {
+ char expected_error_string[ERROR_CODE_LENGTH];
+ char returned_error_string[ERROR_CODE_LENGTH];
+
+ get_error_string (error_code_expected, expected_error_string),
+ get_error_string (error_code_returned, returned_error_string);
+
+ printf (" Expected error code %s but got `%s'.\n",
+ expected_error_string, returned_error_string);
+
+ error = true;
+ }
+
+ if (error)
+ print_pattern_info (pattern, pattern_buffer_ptr);
+}
+
+
+static void
+test_nsub (sub_count, pattern, cflags)
+ unsigned sub_count;
+ char *pattern;
+ int cflags;
+
+{
+ regex_t pattern_buffer;
+
+ test_compile (1, 0, pattern, &pattern_buffer, cflags);
+
+ if (pattern_buffer.re_nsub != sub_count)
+ {
+ printf ("\nShould have counted %d subexpressions but counted %d \
+instead.\n", sub_count, pattern_buffer.re_nsub);
+ }
+
+ regfree (&pattern_buffer);
+}
+
+
+static void
+test_regcomp ()
+{
+ regex_t pattern_buffer;
+ int cflags = 0;
+
+
+ printf ("\nStarting regcomp tests.\n");
+
+ cflags = 0;
+ test_compile (0, REG_ESUBREG, "\\(a\\)\\2", &pattern_buffer, cflags);
+ test_compile (0, REG_EBRACE, "a\\{", &pattern_buffer, cflags);
+ test_compile (0, REG_BADBR, "a\\{-1\\}", &pattern_buffer, cflags);
+ test_compile (0, REG_EBRACE, "a\\{", &pattern_buffer, cflags);
+ test_compile (0, REG_EBRACE, "a\\{1", &pattern_buffer, cflags);
+
+ cflags = REG_EXTENDED;
+ test_compile (0, REG_ECTYPE, "[[:alpo:]]", &pattern_buffer, cflags);
+ test_compile (0, REG_EESCAPE, "\\", &pattern_buffer, cflags);
+ test_compile (0, REG_EBRACK, "[a", &pattern_buffer, cflags);
+ test_compile (0, REG_EPAREN, "(", &pattern_buffer, cflags);
+ test_compile (0, REG_ERANGE, "[z-a]", &pattern_buffer, cflags);
+
+ test_nsub (1, "(a)", cflags);
+ test_nsub (2, "((a))", cflags);
+ test_nsub (2, "(a)(b)", cflags);
+
+ cflags = REG_EXTENDED | REG_NOSUB;
+ test_nsub (1, "(a)", cflags);
+
+ regfree (&pattern_buffer);
+
+ printf ("\nFinished regcomp tests.\n");
+}
+
+
+static void
+fill_pmatch (pmatch, start0, end0, start1, end1, start2, end2)
+ regmatch_t pmatch[];
+ regoff_t start0, end0, start1, end1, start2, end2;
+{
+ pmatch[0].rm_so = start0;
+ pmatch[0].rm_eo = end0;
+ pmatch[1].rm_so = start1;
+ pmatch[1].rm_eo = end1;
+ pmatch[2].rm_so = start2;
+ pmatch[2].rm_eo = end2;
+}
+
+
+static void
+test_pmatch (pattern, string, nmatch, pmatch, correct_pmatch, cflags)
+ char *pattern;
+ char *string;
+ unsigned nmatch;
+ regmatch_t pmatch[];
+ regmatch_t correct_pmatch[];
+ int cflags;
+{
+ regex_t pattern_buffer;
+ unsigned this_match;
+ int error_code_returned;
+ boolean found_nonmatch = false;
+
+ test_compile (1, 0, pattern, &pattern_buffer, cflags);
+ error_code_returned = regexec (&pattern_buffer, string, nmatch, pmatch, 0);
+
+ if (error_code_returned == REG_NOMATCH)
+ printf ("Matching failed in test_pmatch.\n");
+ else
+ {
+ for (this_match = 0; this_match < nmatch; this_match++)
+ {
+ if (pmatch[this_match].rm_so != correct_pmatch[this_match].rm_so)
+ {
+ if (found_nonmatch == false)
+ printf ("\n");
+
+ printf ("Pmatch start %d wrong: was %d when should have \
+been %d.\n", this_match, pmatch[this_match].rm_so,
+ correct_pmatch[this_match].rm_so);
+ found_nonmatch = true;
+ }
+ if (pmatch[this_match].rm_eo != correct_pmatch[this_match].rm_eo)
+ {
+ if (found_nonmatch == false)
+ printf ("\n");
+
+ printf ("Pmatch end %d wrong: was %d when should have been \
+%d.\n", this_match, pmatch[this_match].rm_eo,
+ correct_pmatch[this_match].rm_eo);
+ found_nonmatch = true;
+ }
+ }
+
+ if (found_nonmatch)
+ {
+ printf (" The number of pmatches requested was: %d.\n", nmatch);
+ printf (" The string to match was: `%s'.\n", string);
+ print_pattern_info (pattern, &pattern_buffer);
+ }
+ } /* error_code_returned == REG_NOMATCH */
+
+ regfree (&pattern_buffer);
+}
+
+
+static void
+test_eflags (must_match_bol, must_match_eol, pattern, string, cflags, eflags)
+ boolean must_match_bol;
+ boolean must_match_eol;
+ char *pattern;
+ char *string;
+ int cflags;
+ int eflags;
+{
+ regex_t pattern_buffer;
+ int error_code_returned;
+ boolean was_error = false;
+
+ test_compile (1, 0, pattern, &pattern_buffer, cflags);
+ error_code_returned = regexec (&pattern_buffer, string, 0, 0, eflags);
+
+ if (error_code_returned == REG_NOMATCH)
+ {
+ /* If wasn't true that both 1) the anchored part of the pattern
+ had to match this string and 2) this string was a proper
+ substring... */
+
+ if (!( (must_match_bol && (eflags & REG_NOTBOL))
+ || (must_match_eol && (eflags & REG_NOTEOL)) ))
+ {
+ printf ("\nEflags test failed: didn't match when should have.\n");
+ was_error = true;
+ }
+ }
+ else /* We got a match. */
+ {
+ /* If wasn't true that either 1) the anchored part of the pattern
+ didn't have to match this string or 2) this string wasn't a
+ proper substring... */
+
+ if ((must_match_bol == (eflags & REG_NOTBOL))
+ || (must_match_eol == (eflags & REG_NOTEOL)))
+ {
+ printf ("\nEflags test failed: matched when shouldn't have.\n");
+ was_error = true;
+ }
+ }
+
+ if (was_error)
+ {
+ printf (" The string to match was: `%s'.\n", string);
+ print_pattern_info (pattern, &pattern_buffer);
+
+ if (eflags & REG_NOTBOL)
+ printf (" The eflag REG_BOL was set.\n");
+ if (eflags & REG_NOTEOL)
+ printf (" The eflag REG_EOL was set.\n");
+ }
+
+ regfree (&pattern_buffer);
+}
+
+
+static void
+test_ignore_case (should_match, pattern, string, cflags)
+ boolean should_match;
+ char *pattern;
+ char *string;
+ int cflags;
+{
+ regex_t pattern_buffer;
+ int error_code_returned;
+
+ test_compile (1, 0, pattern, &pattern_buffer, cflags);
+ error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0);
+
+ if (should_match && error_code_returned == REG_NOMATCH)
+ {
+ printf ("\nIgnore-case test failed:\n");
+ printf (" The string to match was: `%s'.\n", string);
+ print_pattern_info (pattern, &pattern_buffer);
+
+ if (cflags & REG_ICASE)
+ printf (" The cflag REG_ICASE was set.\n");
+ }
+
+ regfree (&pattern_buffer);
+}
+
+
+static void
+test_newline (should_match, pattern, string, cflags)
+ boolean should_match;
+ char *pattern;
+ char *string;
+ int cflags;
+{
+ regex_t pattern_buffer;
+ int error_code_returned;
+
+ test_compile (1, 0, pattern, &pattern_buffer, cflags);
+ error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0);
+
+ if (should_match && error_code_returned == REG_NOMATCH)
+ {
+ printf ("\nNewline test failed:\n");
+ printf (" The string to match was: `%s'.\n", string);
+ print_pattern_info (pattern, &pattern_buffer);
+
+ if (cflags & REG_NEWLINE)
+ printf (" The cflag REG_NEWLINE was set.\n");
+ else
+ printf (" The cflag REG_NEWLINE wasn't set.\n");
+ }
+
+ regfree (&pattern_buffer);
+}
+
+
+static void
+test_posix_match (should_match, pattern, string, cflags)
+ boolean should_match;
+ char *pattern;
+ char *string;
+ int cflags;
+{
+ regex_t pattern_buffer;
+ int error_code_returned;
+ boolean was_error = false;
+
+ test_compile (1, 0, pattern, &pattern_buffer, cflags);
+ error_code_returned = regexec (&pattern_buffer, string, 0, 0, 0);
+
+ if (should_match && error_code_returned == REG_NOMATCH)
+ {
+ printf ("\nShould have matched but didn't:\n");
+ was_error = true;
+ }
+ else if (!should_match && error_code_returned != REG_NOMATCH)
+ {
+ printf ("\nShould not have matched but did:\n");
+ was_error = true;
+ }
+
+ if (was_error)
+ {
+ printf (" The string to match was: `%s'.\n", string);
+ print_pattern_info (pattern, &pattern_buffer);
+ }
+
+ regfree (&pattern_buffer);
+}
+
+
+static void
+test_regexec ()
+{
+ regmatch_t pmatch[3];
+ regmatch_t correct_pmatch[3];
+ int cflags = 0;
+ int eflags = 0;
+
+ printf ("\nStarting regexec tests.\n");
+
+ cflags = REG_NOSUB; /* shouldn't look at any of pmatch. */
+ test_pmatch ("a", "a", 0, pmatch, correct_pmatch, cflags);
+
+ /* Ask for less `pmatch'es than there are pattern subexpressions.
+ (Shouldn't look at pmatch[2]. */
+ cflags = REG_EXTENDED;
+ fill_pmatch (correct_pmatch, 0, 1, 0, 1, 100, 101);
+ test_pmatch ("((a))", "a", 2, pmatch, correct_pmatch, cflags);
+
+ /* Ask for same number of `pmatch'es as there are pattern subexpressions. */
+ cflags = REG_EXTENDED;
+ fill_pmatch(correct_pmatch, 0, 1, 0, 1, -1, -1);
+ test_pmatch ("(a)", "a", 2, pmatch, correct_pmatch, cflags);
+
+ /* Ask for more `pmatch'es than there are pattern subexpressions. */
+ cflags = REG_EXTENDED;
+ fill_pmatch (correct_pmatch, 0, 1, -1, -1, -1, -1);
+ test_pmatch ("a", "a", 2, pmatch, correct_pmatch, cflags);
+
+ eflags = REG_NOTBOL;
+ test_eflags (true, false, "^a", "a", cflags, eflags);
+ test_eflags (true, false, "(^a)", "a", cflags, eflags);
+ test_eflags (true, false, "a|^b", "b", cflags, eflags);
+ test_eflags (true, false, "^b|a", "b", cflags, eflags);
+
+ eflags = REG_NOTEOL;
+ test_eflags (false, true, "a$", "a", cflags, eflags);
+ test_eflags (false, true, "(a$)", "a", cflags, eflags);
+ test_eflags (false, true, "a|b$", "b", cflags, eflags);
+ test_eflags (false, true, "b$|a", "b", cflags, eflags);
+
+ eflags = REG_NOTBOL | REG_NOTEOL;
+ test_eflags (true, true, "^a$", "a", cflags, eflags);
+ test_eflags (true, true, "(^a$)", "a", cflags, eflags);
+ test_eflags (true, true, "a|(^b$)", "b", cflags, eflags);
+ test_eflags (true, true, "(^b$)|a", "b", cflags, eflags);
+
+ cflags = REG_ICASE;
+ test_ignore_case (true, "a", "a", cflags);
+ test_ignore_case (true, "A", "A", cflags);
+ test_ignore_case (true, "A", "a", cflags);
+ test_ignore_case (true, "a", "A", cflags);
+
+ test_ignore_case (true, "@", "@", cflags);
+ test_ignore_case (true, "\\[", "[", cflags);
+ test_ignore_case (true, "`", "`", cflags);
+ test_ignore_case (true, "{", "{", cflags);
+
+ test_ignore_case (true, "[!-`]", "A", cflags);
+ test_ignore_case (true, "[!-`]", "a", cflags);
+
+ cflags = 0;
+ test_ignore_case (false, "a", "a", cflags);
+ test_ignore_case (false, "A", "A", cflags);
+ test_ignore_case (false, "A", "a", cflags);
+ test_ignore_case (false, "a", "A", cflags);
+
+ test_ignore_case (true, "@", "@", cflags);
+ test_ignore_case (true, "\\[", "[", cflags);
+ test_ignore_case (true, "`", "`", cflags);
+ test_ignore_case (true, "{", "{", cflags);
+
+ test_ignore_case (true, "[!-`]", "A", cflags);
+ test_ignore_case (false, "[!-`]", "a", cflags);
+
+
+ /* Test newline stuff. */
+ cflags = REG_EXTENDED | REG_NEWLINE;
+ test_newline (true, "\n", "\n", cflags);
+ test_newline (true, "a\n", "a\n", cflags);
+ test_newline (true, "\nb", "\nb", cflags);
+ test_newline (true, "a\nb", "a\nb", cflags);
+
+ test_newline (false, ".", "\n", cflags);
+ test_newline (false, "[^a]", "\n", cflags);
+
+ test_newline (true, "\n^a", "\na", cflags);
+ test_newline (true, "\n(^a|b)", "\na", cflags);
+ test_newline (true, "a$\n", "a\n", cflags);
+ test_newline (true, "(a$|b)\n", "a\n", cflags);
+ test_newline (true, "(a$|b|c)\n", "a\n", cflags);
+ test_newline (true, "((a$|b|c)$)\n", "a\n", cflags);
+ test_newline (true, "((a$|b|c)$)\n", "b\n", cflags);
+ test_newline (true, "(a$|b)\n|a\n", "a\n", cflags);
+
+ test_newline (true, "^a", "\na", cflags);
+ test_newline (true, "a$", "a\n", cflags);
+
+ /* Now test normal behavior. */
+ cflags = REG_EXTENDED;
+ test_newline (true, "\n", "\n", cflags);
+ test_newline (true, "a\n", "a\n", cflags);
+ test_newline (true, "\nb", "\nb", cflags);
+ test_newline (true, "a\nb", "a\nb", cflags);
+
+ test_newline (true, ".", "\n", cflags);
+ test_newline (true, "[^a]", "\n", cflags);
+
+ test_newline (false, "\n^a", "\na", cflags);
+ test_newline (false, "a$\n", "a\n", cflags);
+
+ test_newline (false, "^a", "\na", cflags);
+ test_newline (false, "a$", "a\n", cflags);
+
+
+ /* Test that matches whole string only. */
+ cflags = 0;
+ test_posix_match (true, "a", "a", cflags);
+
+ /* Tests that match substrings. */
+ test_posix_match (true, "a", "ab", cflags);
+ test_posix_match (true, "b", "ab", cflags);
+
+ /* Test that doesn't match. */
+ test_posix_match (false, "a", "b", cflags);
+
+ printf ("\nFinished regexec tests.\n");
+}
+
+
+static void
+test_error_code_message (error_code, expected_error_message)
+ int error_code;
+ char *expected_error_message;
+{
+ char returned_error_message[TEST_ERRBUF_SIZE];
+ char error_code_string[ERROR_CODE_LENGTH];
+ size_t expected_error_message_length = strlen (expected_error_message) + 1;
+ size_t returned_error_message_length = regerror (error_code, 0,
+ returned_error_message,
+ TEST_ERRBUF_SIZE);
+
+ if (returned_error_message_length != expected_error_message_length)
+ {
+ printf ("\n\n Testing returned error codes, with expected error \
+message `%s':\n", expected_error_message);
+
+ printf ("\n\n and returned error message `%s':\n",
+ returned_error_message);
+ printf (" should have returned a length of %d but returned %d.\n",
+ expected_error_message_length, returned_error_message_length);
+ }
+
+ if (strncmp (expected_error_message, returned_error_message,
+ TEST_ERRBUF_SIZE - 1) != 0)
+ {
+
+ get_error_string (error_code, error_code_string),
+ printf ("\n\n With error code %s (%d), expected error message:\n",
+ error_code_string, error_code);
+
+ printf (" `%s'\n", expected_error_message);
+ printf (" but got:\n");
+ printf (" `%s'\n", returned_error_message);
+ }
+}
+
+
+static void
+test_error_code_allocation (error_code, expected_error_message)
+ int error_code;
+ char *expected_error_message;
+{
+ char *returned_error_message = NULL;
+ char error_code_string[ERROR_CODE_LENGTH];
+ size_t returned_error_message_length = regerror (error_code, 0,
+ returned_error_message,
+ (size_t)0);
+
+ returned_error_message = xmalloc (returned_error_message_length + 1);
+
+ regerror (error_code, 0, returned_error_message,
+ returned_error_message_length);
+
+ if (strcmp (expected_error_message, returned_error_message) != 0)
+ {
+ get_error_string (error_code, error_code_string),
+
+ printf ("\n\n Testing error code allocation,\n");
+ printf ("with error code %s (%d), expected error message:\n",
+ error_code_string, error_code);
+ printf (" `%s'\n", expected_error_message);
+ printf (" but got:\n");
+ printf (" `%s'\n", returned_error_message);
+ }
+}
+
+
+static void
+test_regerror ()
+{
+ test_error_code_message (REG_NOMATCH, "No match");
+ test_error_code_message (REG_BADPAT, "Invalid regular expression");
+ test_error_code_message (REG_ECOLLATE, "Invalid collation character");
+ test_error_code_message (REG_ECTYPE, "Invalid character class name");
+ test_error_code_message (REG_EESCAPE, "Trailing backslash");
+ test_error_code_message (REG_ESUBREG, "Invalid back reference");
+ test_error_code_message (REG_EBRACK, "Unmatched [ or [^");
+ test_error_code_message (REG_EPAREN, "Unmatched ( or \\(");
+ test_error_code_message (REG_EBRACE, "Unmatched \\{");
+ test_error_code_message (REG_BADBR, "Invalid content of \\{\\}");
+ test_error_code_message (REG_ERANGE, "Invalid range end");
+ test_error_code_message (REG_ESPACE, "Memory exhausted");
+ test_error_code_message (REG_BADRPT, "Invalid preceding regular expression");
+ test_error_code_message (REG_EEND, "Premature end of regular expression");
+ test_error_code_message (REG_ESIZE, "Regular expression too big");
+ test_error_code_allocation (REG_ERPAREN, "Unmatched ) or \\)");
+}
+
+
+void
+test_posix_interface ()
+{
+ printf ("\nStarting POSIX interface tests.\n");
+ t = posix_interface_test;
+
+ test_regcomp ();
+ test_regexec ();
+ test_regerror ();
+
+ printf ("\nFinished POSIX interface tests.\n");
+}
diff --git a/gnu/lib/libregex/test/psx-interv.c b/gnu/lib/libregex/test/psx-interv.c
new file mode 100644
index 0000000..fcdf488
--- /dev/null
+++ b/gnu/lib/libregex/test/psx-interv.c
@@ -0,0 +1,140 @@
+/* psx-interv.c: test POSIX intervals, both basic and extended. */
+
+#include "test.h"
+
+void
+test_intervals ()
+{
+ printf ("\nStarting POSIX interval tests.\n");
+
+ test_should_match = true;
+ /* Valid intervals. */
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,2}b)*")), "abaab");
+ test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,2}b)*")), "a", 0, 0);
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,2}b)*")),
+ "abaab", 0, 5, 2, 5, -1, -1);
+
+ test_match (BRACES_TO_OPS ("a{0}"), "");
+ test_fastmap (BRACES_TO_OPS ("a{0}"), "", 0, 0);
+ TEST_REGISTERS (BRACES_TO_OPS ("a{0}"), "", 0, 0, -1, -1, -1, -1);
+ TEST_REGISTERS (BRACES_TO_OPS ("a{0}"), "x", 0, 0, -1, -1, -1, -1);
+
+ test_match (BRACES_TO_OPS ("a{0,}"), "");
+ test_match (BRACES_TO_OPS ("a{0,}"), "a");
+ test_fastmap (BRACES_TO_OPS ("a{0,}"), "a", 0, 0);
+ TEST_REGISTERS (BRACES_TO_OPS ("a{0,}"), "a", 0, 1, -1, -1, -1, -1);
+ TEST_REGISTERS (BRACES_TO_OPS ("a{0,}"), "xax", 0, 0, -1, -1, -1, -1);
+
+ test_match (BRACES_TO_OPS ("a{1}"), "a");
+ test_match (BRACES_TO_OPS ("a{1,}"), "a");
+ test_match (BRACES_TO_OPS ("a{1,}"), "aa");
+ test_match (BRACES_TO_OPS ("a{0,0}"), "");
+ test_match (BRACES_TO_OPS ("a{0,1}"), "");
+ test_match (BRACES_TO_OPS ("a{0,1}"), "a");
+ test_match (BRACES_TO_OPS ("a{1,3}"), "a");
+ test_match (BRACES_TO_OPS ("a{1,3}"), "aa");
+ test_match (BRACES_TO_OPS ("a{1,3}"), "aaa");
+ TEST_REGISTERS (BRACES_TO_OPS ("a{1,3}"), "aaa", 0, 3, -1, -1, -1, -1);
+ TEST_REGISTERS (BRACES_TO_OPS ("a{1,3}"), "xaaax", 1, 4, -1, -1, -1, -1);
+
+ test_match (BRACES_TO_OPS ("a{0,3}b"), "b");
+ test_match (BRACES_TO_OPS ("a{0,3}b"), "aaab");
+ test_fastmap (BRACES_TO_OPS ("a{0,3}b"), "ab", 0, 0);
+ TEST_REGISTERS (BRACES_TO_OPS ("a{0,3}b"), "b", 0, 1, -1, -1, -1, -1);
+ TEST_REGISTERS (BRACES_TO_OPS ("a{0,3}b"), "xbx", 1, 2, -1, -1, -1, -1);
+
+ test_match (BRACES_TO_OPS ("a{1,3}b"), "ab");
+ test_match (BRACES_TO_OPS ("a{1,3}b"), "aaab");
+ test_match (BRACES_TO_OPS ("ab{1,3}c"), "abbbc");
+
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "b");
+ test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "ab", 0, 0);
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "b", 0, 1, -1, -1, -1, -1);
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "ab", 0, 2, 0, 1, -1, -1);
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){0,3}b")), "xabx", 1, 3, 1, 2, -1, -1);
+
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "ab");
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "aaab");
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "aaab", 0, 4, 2, 3, -1, -1);
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "xaaabx", 1, 5, 3, 4, -1, -1);
+
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){0,3}b")), "aaaab");
+ test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){0,3}b")), "ab", 0, 0);
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){0,3}b")), "aaaab", 0, 5, 4, 4, -1, -1);
+
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "b");
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "aaab");
+ test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "ab", 0, 0);
+
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,1}ab")), "aaaab");
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,1}ab")), "aaaab", 0, 5, 0, 3, -1, -1);
+
+ test_match (BRACES_TO_OPS (".{0,3}b"), "b");
+ test_match (BRACES_TO_OPS (".{0,3}b"), "ab");
+
+ test_match (BRACES_TO_OPS ("[a]{0,3}b"), "b");
+ test_match (BRACES_TO_OPS ("[a]{0,3}b"), "aaab");
+ test_fastmap (BRACES_TO_OPS ("[a]{0,3}b"), "ab", 0, 0);
+ test_match (BRACES_TO_OPS ("[^a]{0,3}b"), "bcdb");
+ test_match (BRACES_TO_OPS ("ab{0,3}c"), "abbbc");
+ test_match (BRACES_TO_OPS ("[[:digit:]]{0,3}d"), "123d");
+ test_fastmap (BRACES_TO_OPS ("[[:digit:]]{0,3}d"), "0123456789d", 0, 0);
+
+ test_match (BRACES_TO_OPS ("\\*{0,3}a"), "***a");
+ test_match (BRACES_TO_OPS (".{0,3}b"), "aaab");
+ test_match (BRACES_TO_OPS ("a{0,3}a"), "aaa");
+ /* Backtracking. */
+ test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,})*a")), "a", 0, 0);
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,})*a")), "a");
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a{1,})*a")), "a", 0, 1, -1, -1, -1, -1);
+
+ test_fastmap (BRACES_TO_OPS (PARENS_TO_OPS ("(a{2,})*aa")), "aa", 0, 0);
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a{2,})*aa")), "aa");
+ TEST_REGISTERS (BRACES_TO_OPS (PARENS_TO_OPS ("(a{2,})*aa")), "aa", 0, 2, -1, -1, -1, -1);
+
+ test_match (BRACES_TO_OPS ("a{2}*"), "");
+ test_match (BRACES_TO_OPS ("a{2}*"), "aa");
+
+ test_match (BRACES_TO_OPS ("a{1}*"), "");
+ test_match (BRACES_TO_OPS ("a{1}*"), "a");
+ test_match (BRACES_TO_OPS ("a{1}*"), "aa");
+
+ test_match (BRACES_TO_OPS ("a{1}{1}"), "a");
+
+ test_match (BRACES_TO_OPS ("a{1}{1}{1}"), "a");
+ test_match (BRACES_TO_OPS ("a{1}{1}{2}"), "aa");
+
+ test_match (BRACES_TO_OPS ("a{1}{1}*"), "");
+ test_match (BRACES_TO_OPS ("a{1}{1}*"), "a");
+ test_match (BRACES_TO_OPS ("a{1}{1}*"), "aa");
+ test_match (BRACES_TO_OPS ("a{1}{1}*"), "aaa");
+
+ test_match (BRACES_TO_OPS ("a{1}{2}"), "aa");
+ test_match (BRACES_TO_OPS ("a{2}{1}"), "aa");
+
+
+ test_should_match = false;
+
+ test_match (BRACES_TO_OPS ("a{0}"), "a");
+ test_match (BRACES_TO_OPS ("a{0,}"), "b");
+ test_match (BRACES_TO_OPS ("a{1}"), "");
+ test_match (BRACES_TO_OPS ("a{1}"), "aa");
+ test_match (BRACES_TO_OPS ("a{1,}"), "");
+ test_match (BRACES_TO_OPS ("a{1,}"), "b");
+ test_match (BRACES_TO_OPS ("a{0,0}"), "a");
+ test_match (BRACES_TO_OPS ("a{0,1}"), "aa");
+ test_match (BRACES_TO_OPS ("a{0,1}"), "b");
+ test_match (BRACES_TO_OPS ("a{1,3}"), "");
+ test_match (BRACES_TO_OPS ("a{1,3}"), "aaaa");
+ test_match (BRACES_TO_OPS ("a{1,3}"), "b");
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a){1,3}b")), "aaaab");
+ test_match (BRACES_TO_OPS (PARENS_TO_OPS ("(a*){1,3}b")), "bb");
+ test_match (BRACES_TO_OPS ("[a]{0,3}"), "aaaa");
+ test_match (BRACES_TO_OPS ("[^a]{0,3}b"), "ab");
+ test_match (BRACES_TO_OPS ("ab{0,3}c"), "abababc");
+ test_match (BRACES_TO_OPS ("[:alpha:]{0,3}d"), "123d");
+ test_match (BRACES_TO_OPS ("\\^{1,3}a"), "a");
+ test_match (BRACES_TO_OPS (".{0,3}b"), "aaaab");
+
+ printf ("\nFinished POSIX interval tests.\n");
+}
diff --git a/gnu/lib/libregex/test/regexcpp.sed b/gnu/lib/libregex/test/regexcpp.sed
new file mode 100644
index 0000000..082c136
--- /dev/null
+++ b/gnu/lib/libregex/test/regexcpp.sed
@@ -0,0 +1,8 @@
+/;..*$/s/;/;\
+/g
+/{ .*$/s/{/{\
+/g
+/ \?[^'] /s/?/?\
+/g
+/ : /s/:/:\
+/g
diff --git a/gnu/lib/libregex/test/syntax.skel b/gnu/lib/libregex/test/syntax.skel
new file mode 100644
index 0000000..a3fbf64
--- /dev/null
+++ b/gnu/lib/libregex/test/syntax.skel
@@ -0,0 +1,74 @@
+/* Print which syntax bits are set. */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include "regex.h"
+
+/* It's coincidental that these two are currently the same. */
+#define LONGEST_BIT_NAME "RE_UNMATCHED_RIGHT_PAREN_ORD"
+#define LAST_BIT RE_UNMATCHED_RIGHT_PAREN_ORD
+
+/* Sum of above, when printed. Assigned in main. */
+static unsigned longest;
+
+
+static void
+test_bit (syntax, bit, name)
+ reg_syntax_t syntax;
+ unsigned bit;
+ char *name;
+{
+ char padding[100], test_str[100];
+ int padding_count;
+
+ sprintf (test_str, "%s (%d=0x%x)", name, bit, bit);
+ padding_count = longest - strlen (test_str);
+
+ padding[padding_count] = 0;
+ while (padding_count--)
+ {
+ padding[padding_count] = ' ';
+ }
+
+ printf ("%s%s (%d=0x%x): %c\n",
+ name, padding, bit, bit, syntax & bit ? 'y' : 'n');
+}
+
+
+/* Macro to abbreviate the constant arguments. */
+#define TEST_BIT(bit) test_bit (syntax, bit, #bit)
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ reg_syntax_t syntax;
+ char syntax_str[1000], test_str[100];
+
+ switch (argc)
+ {
+ case 1:
+ printf ("Syntax? ");
+ scanf ("%s", syntax_str);
+ break;
+
+ case 2:
+ strcpy (syntax_str, argv[1]);
+ break;
+
+ default:
+ fprintf (stderr, "Usage: syntax [syntax].\n");
+ exit (1);
+ }
+
+ sscanf (syntax_str, "%i", &syntax);
+
+ /* Figure out the longest name, so we can align the output nicely. */
+ sprintf (test_str, "%s (%d=0x%x)", LONGEST_BIT_NAME, LAST_BIT, LAST_BIT);
+ longest = strlen (test_str);
+
+ /* [[[replace with bit tests]]] */
+
+ return 0;
+}
diff --git a/gnu/lib/libregex/test/test.c b/gnu/lib/libregex/test/test.c
new file mode 100644
index 0000000..74b43b2
--- /dev/null
+++ b/gnu/lib/libregex/test/test.c
@@ -0,0 +1,782 @@
+/* test.c: testing routines for regex.c. */
+
+#include <assert.h>
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+char *malloc ();
+char *realloc ();
+#endif
+
+/* Just to be complete, we make both the system V/ANSI and the BSD
+ versions of the string functions available. */
+#if USG || STDC_HEADERS
+#include <string.h>
+#define index strchr
+#define rindex strrchr
+#define bcmp(s1, s2, len) memcmp ((s1), (s2), (len))
+#define bcopy(from, to, len) memcpy ((to), (from), (len))
+#define bzero(s, len) memset ((s), 0, (len))
+#else
+#include <strings.h>
+#define strchr index
+#define strrchr rindex
+#ifndef NEED_MEMORY_H
+#define memcmp(s1, s2, n) bcmp ((s1), (s2), (n))
+#define memcpy(to, from, len) bcopy ((from), (to), (len))
+#endif
+extern char *strtok ();
+extern char *strstr ();
+#endif /* not USG or STDC_HEADERS */
+
+/* SunOS 4.1 declares memchr in <memory.h>, not <string.h>. I don't
+ understand why. */
+#if NEED_MEMORY_H
+#include <memory.h>
+#endif
+
+#include "test.h"
+
+#define BYTEWIDTH 8
+
+extern void print_partial_compiled_pattern ();
+extern void print_compiled_pattern ();
+extern void print_double_string ();
+
+/* If nonzero, the results of every test are displayed. */
+boolean verbose = false;
+
+/* If nonzero, don't do register testing. */
+boolean omit_register_tests = true;
+
+/* Says whether the current test should match or fail to match. */
+boolean test_should_match;
+
+
+static void
+set_all_registers (start0, end0, start1, end1,
+ start2, end2, start3, end3,
+ start4, end4, start5, end5,
+ start6, end6, start7, end7,
+ start8, end8, start9, end9, regs)
+
+ int start0; int end0; int start1; int end1;
+ int start2; int end2; int start3; int end3;
+ int start4; int end4; int start5; int end5;
+ int start6; int end6; int start7; int end7;
+ int start8; int end8; int start9; int end9;
+ struct re_registers *regs;
+
+ {
+ unsigned r;
+
+ regs->start[0] = start0; regs->end[0] = end0;
+ regs->start[1] = start1; regs->end[1] = end1;
+ regs->start[2] = start2; regs->end[2] = end2;
+ regs->start[3] = start3; regs->end[3] = end3;
+ regs->start[4] = start4; regs->end[4] = end4;
+ regs->start[5] = start5; regs->end[5] = end5;
+ regs->start[6] = start6; regs->end[6] = end6;
+ regs->start[7] = start7; regs->end[7] = end7;
+ regs->start[8] = start8; regs->end[8] = end8;
+ regs->start[9] = start9; regs->end[9] = end9;
+ for (r = 10; r < regs->num_regs; r++)
+ {
+ regs->start[r] = -1;
+ regs->end[r] = -1;
+ }
+ }
+
+
+
+/* Return the concatenation of S1 and S2. This would be a prime place
+ to use varargs. */
+
+char *
+concat (s1, s2)
+ char *s1;
+ char *s2;
+{
+ char *answer = xmalloc (strlen (s1) + strlen (s2) + 1);
+
+ strcpy (answer, s1);
+ strcat (answer, s2);
+
+ return answer;
+}
+
+
+#define OK_TO_SEARCH (nonconst_buf.fastmap_accurate && (str1 || str2))
+
+/* We ignore the `can_be_null' argument. Should just be removed. */
+
+void
+general_test (pattern_should_be_valid, match_whole_string,
+ pat, str1, str2, start, range, end, correct_fastmap,
+ correct_regs, can_be_null)
+ unsigned pattern_should_be_valid;
+ unsigned match_whole_string;
+ const char *pat;
+ char *str1, *str2;
+ int start, range, end;
+ char *correct_fastmap;
+ struct re_registers *correct_regs;
+ int can_be_null;
+{
+ struct re_pattern_buffer nonconst_buf;
+ struct re_pattern_buffer old_buf;
+ struct re_registers regs;
+ const char *r;
+ char fastmap[1 << BYTEWIDTH];
+ unsigned *regs_correct = NULL;
+ unsigned all_regs_correct = 1;
+ boolean fastmap_internal_error = false;
+ unsigned match = 0;
+ unsigned match_1 = 0;
+ unsigned match_2 = 0;
+ unsigned invalid_pattern = 0;
+ boolean internal_error_1 = false;
+ boolean internal_error_2 = false;
+
+
+ nonconst_buf.allocated = 8;
+ nonconst_buf.buffer = xmalloc (nonconst_buf.allocated);
+ nonconst_buf.fastmap = fastmap;
+ nonconst_buf.translate = 0;
+
+ assert (pat != NULL);
+ r = re_compile_pattern (pat, strlen (pat), &nonconst_buf);
+
+ /* Kludge: if we are doing POSIX testing, we really should have
+ called regcomp, not re_compile_pattern. As it happens, the only
+ way in which it matters is that re_compile_pattern sets the
+ newline/anchor field for matching (part of what happens when
+ REG_NEWLINE is given to regcomp). We have to undo that for POSIX
+ matching. */
+ if (t == posix_basic_test || t == posix_extended_test)
+ nonconst_buf.newline_anchor = 0;
+
+ invalid_pattern = r != NULL;
+
+ if (!r)
+ {
+ int r;
+
+ if (!pattern_should_be_valid)
+ printf ("\nShould have been an invalid pattern but wasn't:\n");
+ else
+ {
+ fastmap_internal_error = (re_compile_fastmap (&nonconst_buf) == -2);
+
+ if (correct_fastmap)
+ nonconst_buf.fastmap_accurate =
+ memcmp (nonconst_buf.fastmap, correct_fastmap, 1 << BYTEWIDTH)
+ == 0;
+
+ if (OK_TO_SEARCH)
+ {
+ old_buf = nonconst_buf;
+ old_buf.buffer = (unsigned char *) xmalloc (nonconst_buf.used);
+ memcpy (old_buf.buffer, nonconst_buf.buffer, nonconst_buf.used);
+
+ /* If only one string is null, call re_match or re_search,
+ which is what the user would probably do. */
+ if (str1 == NULL && str2 != NULL
+ || str2 == NULL && str1 != NULL)
+ {
+ char *the_str = str1 == NULL ? str2 : str1;
+
+ match_1
+ = match_whole_string
+ ? (r = re_match (&nonconst_buf, the_str,
+ strlen (the_str), start, &regs))
+ == strlen (the_str)
+ : (r = re_search (&nonconst_buf,
+ the_str, strlen (the_str),
+ start, range, &regs))
+ >= 0;
+
+ if (r == -2)
+ internal_error_1 = true;
+ }
+ else
+ match_1 = 1;
+
+ /* Also call with re_match_2 or re_search_2, as they might
+ do this. (Also can check calling with either string1
+ or string2 or both null.) */
+ if (match_whole_string)
+ {
+ r = re_match_2 (&nonconst_buf,
+ str1, SAFE_STRLEN (str1),
+ str2, SAFE_STRLEN (str2),
+ start, &regs, end);
+ match_2 = r == SAFE_STRLEN (str1) + SAFE_STRLEN (str2);
+ }
+ else
+ {
+ r = re_search_2 (&nonconst_buf,
+ str1, SAFE_STRLEN (str1),
+ str2, SAFE_STRLEN (str2),
+ start, range, &regs, end);
+ match_2 = r >= 0;
+ }
+
+ if (r == -2)
+ internal_error_2 = true;
+
+ match = match_1 & match_2;
+
+ if (correct_regs)
+ {
+ unsigned reg;
+ if (regs_correct != NULL)
+ free (regs_correct);
+
+ regs_correct
+ = (unsigned *) xmalloc (regs.num_regs * sizeof (unsigned));
+
+ for (reg = 0;
+ reg < regs.num_regs && reg < correct_regs->num_regs;
+ reg++)
+ {
+ regs_correct[reg]
+ = (regs.start[reg] == correct_regs->start[reg]
+ && regs.end[reg] == correct_regs->end[reg])
+#ifdef EMPTY_REGS_CONFUSED
+ /* There is confusion in the standard about
+ the registers in some patterns which can
+ match either the empty string or not match.
+ For example, in `((a*))*' against the empty
+ string, the two registers can either match
+ the empty string (be 0/0), or not match
+ (because of the outer *) (be -1/-1). (Or
+ one can do one and one can do the other.) */
+ || (regs.start[reg] == -1 && regs.end[reg] == -1
+ && correct_regs->start[reg]
+ == correct_regs->end[reg])
+#endif
+ ;
+
+ all_regs_correct &= regs_correct[reg];
+ }
+ }
+ } /* OK_TO_SEARCH */
+ }
+ }
+
+ if (fastmap_internal_error)
+ printf ("\n\nInternal error in re_compile_fastmap:");
+
+ if (internal_error_1)
+ {
+ if (!fastmap_internal_error)
+ printf ("\n");
+
+ printf ("\nInternal error in re_match or re_search:");
+ }
+
+ if (internal_error_2)
+ {
+ if (!internal_error_1)
+ printf ("\n");
+
+ printf ("\nInternal error in re_match_2 or re_search_2:");
+ }
+
+ if ((OK_TO_SEARCH && ((match && !test_should_match)
+ || (!match && test_should_match))
+ || (correct_regs && !all_regs_correct))
+ || !nonconst_buf.fastmap_accurate
+ || invalid_pattern
+ || !pattern_should_be_valid
+ || internal_error_1 || internal_error_2
+ || verbose)
+ {
+ if (OK_TO_SEARCH && match && !test_should_match)
+ {
+ printf ("\n\nMatched but shouldn't have:\n");
+ if (match_1)
+ printf ("The single match/search succeeded.\n");
+
+ if (match_2)
+ printf ("The double match/search succeeded.\n");
+ }
+ else if (OK_TO_SEARCH && !match && test_should_match)
+ {
+ printf ("\n\nDidn't match but should have:\n");
+ if (!match_1)
+ printf ("The single match/search failed.\n");
+
+ if (!match_2)
+ printf ("The double match/search failed.\n");
+ }
+ else if (invalid_pattern && pattern_should_be_valid)
+ printf ("\n\nInvalid pattern (%s):\n", r);
+ else if (!nonconst_buf.fastmap_accurate && pattern_should_be_valid)
+ printf ("\n\nIncorrect fastmap:\n");
+ else if (OK_TO_SEARCH && correct_regs && !all_regs_correct)
+ printf ("\n\nNot all registers were correct:\n");
+ else if (verbose)
+ printf ("\n\nTest was OK:\n");
+
+
+ if ((!(invalid_pattern && !pattern_should_be_valid)) || verbose)
+ printf (" Pattern: `%s'.\n", pat);
+
+ if (pattern_should_be_valid || verbose
+ || internal_error_1 || internal_error_2)
+ {
+ printf(" Strings: ");
+ printf ("`%s' and ", str1 == NULL ? "NULL" : str1);
+ printf ("`%s'.\n", str2 == NULL ? "NULL" : str2);
+
+ if ((OK_TO_SEARCH || verbose || internal_error_1 || internal_error_2)
+ && !invalid_pattern)
+ {
+ if (memcmp (old_buf.buffer, nonconst_buf.buffer,
+ nonconst_buf.used) != 0
+ && !invalid_pattern)
+ {
+ printf(" (%s)\n", r ? r : "Valid regular expression");
+ printf ("\n Compiled pattern before matching: ");
+ print_compiled_pattern (&old_buf);
+ printf ("\n Compiled pattern after matching: ");
+ }
+ else
+ printf ("\n Compiled pattern: ");
+
+ print_compiled_pattern (&nonconst_buf);
+ }
+
+ if (correct_fastmap && (!nonconst_buf.fastmap_accurate || verbose))
+ {
+ printf ("\n The fastmap should have been: ");
+ print_fastmap (correct_fastmap);
+
+ printf ("\n Fastmap: ");
+ print_fastmap (fastmap);
+
+ printf ("\n Compiled pattern before matching: ");
+ print_compiled_pattern (&nonconst_buf);
+ }
+
+ if ((!all_regs_correct || verbose) && correct_regs)
+ {
+ unsigned this_reg;
+ printf ("\n Incorrect registers:");
+
+ for (this_reg = 0; this_reg < regs.num_regs; this_reg++)
+ {
+ if (!regs_correct[this_reg])
+ {
+ printf ("\n Register %d's start was %2d. ", this_reg,
+ regs.start[this_reg]);
+ printf ("\tIt should have been %d.\n",
+ correct_regs->start[this_reg]);
+ printf (" Register %d's end was %2d. ", this_reg,
+ regs.end[this_reg]);
+ printf ("\tIt should have been %d.\n",
+ correct_regs->end[this_reg]);
+ }
+ }
+ }
+ }
+ }
+
+ if (nonconst_buf.buffer != NULL)
+ free (nonconst_buf.buffer);
+
+ if (OK_TO_SEARCH)
+ {
+ free (old_buf.buffer);
+
+ if (correct_regs)
+ free (regs_correct);
+
+ }
+
+ nonconst_buf.buffer = old_buf.buffer = NULL;
+ regs_correct = NULL;
+ regs.start = regs.end = NULL;
+
+} /* general_test */
+
+
+void
+test_search_return (match_start_wanted, pattern, string)
+ int match_start_wanted;
+ const char *pattern;
+ char *string;
+{
+ struct re_pattern_buffer buf;
+ char fastmap[1 << BYTEWIDTH];
+ const char *compile_return;
+ int match_start;
+ static num_times_called = 0;
+
+ num_times_called++;
+ buf.allocated = 1;
+ buf.buffer = xmalloc (buf.allocated);
+
+ assert (pattern != NULL);
+ buf.translate = 0;
+ compile_return = re_compile_pattern (pattern, strlen (pattern), &buf);
+
+ if (compile_return)
+ {
+ printf ("\n\nInvalid pattern in test_match_start:\n");
+ printf ("%s\n", compile_return);
+ }
+ else
+ {
+ buf.fastmap = fastmap;
+ match_start = re_search (&buf, string, strlen (string),
+ 0, strlen (string), 0);
+
+ if (match_start != match_start_wanted)
+ printf ("\nWanted search to start at %d but started at %d.\n",
+ match_start, match_start_wanted);
+ }
+ free (buf.buffer);
+ buf.buffer = NULL;
+}
+
+
+#define SET_FASTMAP() \
+ { \
+ unsigned this_char; \
+ \
+ memset (correct_fastmap, invert, (1 << BYTEWIDTH)); \
+ \
+ for (this_char = 0; this_char < strlen (fastmap_string); this_char++)\
+ correct_fastmap[fastmap_string[this_char]] = !invert; \
+ correct_fastmap['\n'] = match_newline; \
+ }
+
+
+void
+test_fastmap (pat, fastmap_string, invert, match_newline)
+ const char *pat;
+ char *fastmap_string;
+ unsigned invert;
+ unsigned match_newline;
+{
+ char correct_fastmap[(1 << BYTEWIDTH)];
+
+ SET_FASTMAP ();
+ general_test (1, 0, pat, NULL, NULL, -1, 0, -1, correct_fastmap, 0, -1);
+}
+
+
+void
+test_fastmap_search (pat, str, fastmap_string, invert, match_newline,
+ can_be_null, start0, end0)
+ const char *pat;
+ char *str;
+ char *fastmap_string;
+ unsigned invert;
+ unsigned match_newline;
+ int can_be_null;
+ int start0;
+ int end0;
+{
+ char correct_fastmap[(1 << BYTEWIDTH)];
+ struct re_registers correct_regs;
+
+ correct_regs.num_regs = RE_NREGS;
+ correct_regs.start = (int *) xmalloc (RE_NREGS * sizeof (int));
+ correct_regs.end = (int *) xmalloc (RE_NREGS * sizeof (int));
+
+ set_all_registers (start0, end0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, &correct_regs);
+ SET_FASTMAP ();
+ general_test (1, 0, pat, str, NULL, 0, SAFE_STRLEN (str), SAFE_STRLEN (str),
+ correct_fastmap, &correct_regs, can_be_null);
+
+ free (correct_regs.start);
+ free (correct_regs.end);
+}
+
+
+
+
+void
+test_all_registers (pat, str1, str2,
+ start0, end0, start1, end1,
+ start2, end2, start3, end3,
+ start4, end4, start5, end5,
+ start6, end6, start7, end7,
+ start8, end8, start9, end9)
+ char *pat; char *str1; char *str2;
+ int start0; int end0; int start1; int end1;
+ int start2; int end2; int start3; int end3;
+ int start4; int end4; int start5; int end5;
+ int start6; int end6; int start7; int end7;
+ int start8; int end8; int start9; int end9;
+{
+ struct re_registers correct_regs;
+
+ if (omit_register_tests) return;
+
+ correct_regs.num_regs = RE_NREGS;
+ correct_regs.start = (int *) xmalloc (RE_NREGS * sizeof (int));
+ correct_regs.end = (int *) xmalloc (RE_NREGS * sizeof (int));
+
+ set_all_registers (start0, end0, start1, end1, start2, end2, start3, end3,
+ start4, end4, start5, end5, start6, end6, start7, end7,
+ start8, end8, start9, end9, &correct_regs);
+
+ general_test (1, 0, pat, str1, str2, 0,
+ SAFE_STRLEN (str1) + SAFE_STRLEN (str2),
+ SAFE_STRLEN (str1) + SAFE_STRLEN (str2),
+ NULL, &correct_regs, -1);
+
+ free (correct_regs.start);
+ free (correct_regs.end);
+}
+
+
+void
+invalid_pattern (error_code_expected, pattern)
+ int error_code_expected;
+ char *pattern;
+{
+ regex_t pattern_buffer;
+ int cflags
+ = re_syntax_options == RE_SYNTAX_POSIX_EXTENDED
+ || re_syntax_options == RE_SYNTAX_POSIX_MINIMAL_EXTENDED
+ ? REG_EXTENDED : 0;
+
+ test_compile (0, error_code_expected, pattern, &pattern_buffer, cflags);
+}
+
+
+void
+valid_pattern (pattern)
+ char *pattern;
+{
+ regex_t pattern_buffer;
+ int cflags
+ = re_syntax_options == RE_SYNTAX_POSIX_EXTENDED
+ || re_syntax_options == RE_SYNTAX_POSIX_MINIMAL_EXTENDED
+ ? REG_EXTENDED : 0;
+
+ test_compile (1, 0, pattern, &pattern_buffer, cflags);
+}
+
+
+char *
+delimiters_to_ops (source, left_delimiter, right_delimiter)
+ char *source;
+ char left_delimiter;
+ char right_delimiter;
+{
+ static char *answer = NULL;
+ char *tmp = NULL;
+ boolean double_size = false;
+ unsigned source_char;
+ unsigned answer_char = 0;
+
+ assert (source != NULL);
+
+ switch (left_delimiter)
+ {
+ case '(': if (!(re_syntax_options & RE_NO_BK_PARENS))
+ double_size = true;
+ break;
+ case '{': if (!(re_syntax_options & RE_NO_BK_BRACES))
+ double_size = true;
+ break;
+ default: printf ("Found strange delimiter %c in delimiter_to_ops.\n",
+ left_delimiter);
+ printf ("The source was `%s'\n", source);
+ exit (0);
+ }
+
+ if (answer == source)
+ {
+ tmp = (char *) xmalloc (strlen (source) + 1);
+ strcpy (tmp, source);
+ source = tmp;
+ }
+
+ if (answer)
+ {
+ free (answer);
+ answer = NULL;
+ }
+
+ answer = (char *) xmalloc ((double_size
+ ? strlen (source) << 1
+ : strlen (source))
+ + 1);
+ if (!double_size)
+ strcpy (answer, source);
+ else
+ {
+ for (source_char = 0; source_char < strlen (source); source_char++)
+ {
+ if (source[source_char] == left_delimiter
+ || source[source_char] == right_delimiter)
+ answer[answer_char++] = '\\';
+
+ answer[answer_char++] = source[source_char];
+ }
+ answer[answer_char] = 0;
+ }
+
+ return answer;
+}
+
+
+void
+print_pattern_info (pattern, pattern_buffer_ptr)
+ const char *pattern;
+ regex_t *pattern_buffer_ptr;
+{
+ printf (" Pattern: `%s'.\n", pattern);
+ printf (" Compiled pattern: ");
+ print_compiled_pattern (pattern_buffer_ptr);
+}
+
+
+void
+valid_nonposix_pattern (pattern)
+ char *pattern;
+{
+ struct re_pattern_buffer nonconst_buf;
+
+ nonconst_buf.allocated = 0;
+ nonconst_buf.buffer = NULL;
+ nonconst_buf.translate = NULL;
+
+ assert (pattern != NULL);
+
+ if (re_compile_pattern (pattern, strlen (pattern), &nonconst_buf))
+ {
+ printf ("Couldn't compile the pattern.\n");
+ print_pattern_info (pattern, &nonconst_buf);
+ }
+}
+
+
+void
+compile_and_print_pattern (pattern)
+ char *pattern;
+{
+ struct re_pattern_buffer nonconst_buf;
+
+ nonconst_buf.allocated = 0;
+ nonconst_buf.buffer = NULL;
+
+ if (re_compile_pattern (pattern, strlen (pattern), &nonconst_buf))
+ printf ("Couldn't compile the pattern.\n");
+
+ print_pattern_info (pattern, &nonconst_buf);
+}
+
+
+void
+test_case_fold (pattern, string)
+ const char *pattern;
+ char* string;
+{
+ struct re_pattern_buffer nonconst_buf;
+ const char *ret;
+
+ init_pattern_buffer (&nonconst_buf);
+ nonconst_buf.translate = upcase;
+
+ assert (pattern != NULL);
+ ret = re_compile_pattern (pattern, strlen (pattern), &nonconst_buf);
+
+ if (ret)
+ {
+ printf ("\nShould have been a valid pattern but wasn't.\n");
+ print_pattern_info (pattern, &nonconst_buf);
+ }
+ else
+ {
+ if (test_should_match
+ && re_match (&nonconst_buf, string, strlen (string), 0, 0)
+ != strlen (string))
+ {
+ printf ("Match failed for case fold.\n");
+ printf (" Pattern: `%s'.\n", pattern);
+ printf (" String: `%s'.\n", string == NULL ? "NULL" : string);
+ }
+ }
+}
+
+
+void
+test_match_n_times (n, pattern, string)
+ unsigned n;
+ char* pattern;
+ char* string;
+{
+ struct re_pattern_buffer buf;
+ const char *r;
+ unsigned match = 0;
+ unsigned this_match;
+
+ buf.allocated = 0;
+ buf.buffer = NULL;
+ buf.translate = 0;
+
+ assert (pattern != NULL);
+
+ r = re_compile_pattern (pattern, strlen (pattern), &buf);
+ if (r)
+ {
+ printf ("Didn't compile.\n");
+ printf (" Pattern: %s.\n", pattern);
+ }
+ else
+ {
+ for (this_match = 1; this_match <= n; this_match++)
+ match = (re_match (&buf, string, strlen (string),
+ 0, 0)
+ == strlen (string));
+
+ if (match && !test_should_match)
+ printf ("\n\nMatched but shouldn't have:\n");
+ else if (!match && test_should_match)
+ printf ("\n\nDidn't match but should have:\n");
+
+ if ((match && !test_should_match) || (!match && test_should_match))
+ {
+ printf(" The string to match was: ");
+ if (string)
+ printf ("`%s' and ", string);
+ else
+ printf ("`'");
+
+ printf (" Pattern: %s.\n", pattern);
+ printf (" Compiled pattern: %s.\n", pattern);
+ print_compiled_pattern (&buf);
+ }
+ }
+}
+
+
+void
+test_match_2 (pat, str1, str2)
+ const char *pat;
+ char *str1;
+ char *str2;
+{
+ general_test (1, 1, pat, str1, str2, 0, 1,
+ SAFE_STRLEN (str1) + SAFE_STRLEN (str2), NULL, 0, -1);
+}
+
+void
+test_match (pat, str)
+ const char *pat;
+ char *str;
+{
+ test_match_2 (pat, str, NULL);
+ test_match_2 (pat, NULL, str);
+}
diff --git a/gnu/lib/libregex/test/test.h b/gnu/lib/libregex/test/test.h
new file mode 100644
index 0000000..e367c93
--- /dev/null
+++ b/gnu/lib/libregex/test/test.h
@@ -0,0 +1,141 @@
+/* test.h: for Regex testing. */
+
+#ifndef TEST_H
+#define TEST_H
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include "regex.h"
+
+
+/* A strlen that works even on a null pointer. */
+#define SAFE_STRLEN(s) (s == NULL ? 0 : strlen (s))
+
+typedef enum { false = 0, true = 1 } boolean;
+
+extern boolean test_should_match;
+extern boolean omit_register_tests;
+extern void *xmalloc ();
+
+/* Defined in upcase.c. */
+extern char upcase[];
+
+typedef enum
+{
+ all_test,
+ other_test,
+ posix_basic_test,
+ posix_extended_test,
+ posix_interface_test,
+ regress_test
+} test_type;
+
+extern test_type t;
+
+
+#if __STDC__
+
+extern char *concat (char *, char *);
+
+extern void general_test (unsigned pattern_should_be_valid,
+ unsigned match_whole_string,
+ const char *pat, char *str1, char *str2,
+ int start, int range, int end,
+ char *correct_fastmap,
+ struct re_registers *correct_regs, int can_be_null);
+
+
+extern void init_pattern_buffer (regex_t *pattern_buffer_ptr);
+
+extern void test_compile (unsigned valid_pattern, int error_code_expected,
+ const char *pattern, regex_t *pattern_buffer_ptr,
+ int cflags);
+
+extern char *delimiter_to_ops (char *source, char left_delimiter,
+ char right_delimiter);
+
+
+extern void test_search_return (int, const char *, char *);
+
+extern void test_berk_search (const char *pattern, char *string);
+
+extern void test_fastmap (const char *pat, char *fastmap_string, unsigned invert,
+ unsigned match_newline);
+
+extern void test_fastmap_search (const char *pat, char *str, char *fastmap_string,
+ unsigned invert, unsigned match_newline,
+ int can_be_null, int start0, int end0);
+
+extern void test_all_registers (char *pat, char *str1, char *str2,
+ int start0, int end0, int start1, int end1,
+ int start2, int end2, int start3, int end3,
+ int start4, int end4, int start5, int end5,
+ int start6, int end6, int start7, int end7,
+ int start8, int end8, int start9, int end9);
+
+extern void print_pattern_info (const char *pattern, regex_t *pattern_buffer_ptr);
+extern void compile_and_print_pattern (char *pattern);
+
+extern void test_case_fold (const char *pattern, char* string);
+
+extern void test_posix_generic ();
+
+extern void test_grouping ();
+
+extern void invalid_pattern (int error_code_expected, char *pattern);
+extern void valid_nonposix_pattern (char *pattern);
+extern void valid_pattern (char *pattern);
+
+extern void test_match_2 (const char *pat, char *str1, char *str2);
+extern void test_match (const char *pat, char *str);
+
+#endif /* __STDC__ */
+
+
+#define TEST_REGISTERS_2(pat, str1, str2, start0, end0, start1, end1, start2, end2)\
+ if (!omit_register_tests) \
+ test_all_registers (pat, str1, str2, start0, end0, start1, end1, \
+ start2, end2, -1, -1, -1, -1, -1, -1, -1, -1,\
+ -1, -1, -1, -1, -1, -1) \
+
+
+#define TEST_REGISTERS(pat, str, start0, end0, start1, end1, start2, end2) \
+ TEST_REGISTERS_2 (pat, str, NULL, start0, end0, start1, end1, start2, end2)\
+
+#define BRACES_TO_OPS(string) ((char *) delimiters_to_ops (string, '{', '}'))
+#define PARENS_TO_OPS(string) ((char *) delimiters_to_ops (string, '(', ')'))
+
+#define INVALID_PATTERN(pat) \
+ general_test (0, 0, pat, NULL, NULL, -1, 0, -1, NULL, 0, -1)
+
+
+#define MATCH_SELF(p) test_match (p, p)
+
+#define TEST_POSITIONED_MATCH(pat, str, start) \
+ general_test (1, 0, pat, str, NULL, start, 1, SAFE_STRLEN (str), \
+ NULL, 0, -1)
+
+#define TEST_TRUNCATED_MATCH(pat, str, end) \
+ general_test (1, 0, pat, str, NULL, 0, 1, end, NULL, 0, -1)
+
+#define TEST_SEARCH_2(pat, str1, str2, start, range, one_past_end) \
+ general_test (1, 0, pat, str1, str2, start, range, one_past_end, \
+ NULL, 0, -1)
+
+#define TEST_SEARCH(pat, str, start, range) \
+ { \
+ TEST_SEARCH_2 (pat, str, NULL, start, range, SAFE_STRLEN (str)); \
+ TEST_SEARCH_2 (pat, NULL, str, start, range, SAFE_STRLEN (str)); \
+ }
+
+#endif /* TEST_H */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/test/tregress.c b/gnu/lib/libregex/test/tregress.c
new file mode 100644
index 0000000..b6aa560
--- /dev/null
+++ b/gnu/lib/libregex/test/tregress.c
@@ -0,0 +1,464 @@
+/* tregress.c: reported bugs. The `t' just makes the filename not have
+ a common prefix with `regex.c', so completion works better. */
+
+#include "test.h"
+
+
+boolean pause_at_error = true;
+
+char *
+itoa (i)
+ int i;
+{
+ char *a = xmalloc (21); /* sign + 19 digits (enough for 64 bits) + null */
+
+ sprintf (a, "%d", i);
+ return a;
+}
+
+
+static void
+simple_fail (routine, pat, buf, str, ret)
+ const char *routine;
+ const char *pat;
+ struct re_pattern_buffer *buf;
+ const char *str;
+ char *ret;
+{
+ fprintf (stderr, "Failed %s (return = %s).\n", routine, ret);
+ if (str && *str) fprintf (stderr, " String = %s\n", str);
+ fprintf (stderr, " Pattern = %s\n", pat);
+ print_compiled_pattern (buf);
+
+ if (pause_at_error)
+ {
+ fprintf (stderr, "RET to continue: ");
+ (void) getchar ();
+ }
+}
+
+
+/* Abbreviate the most common calls. */
+
+static void
+simple_compile (pat, buf)
+ const char *pat;
+ struct re_pattern_buffer *buf;
+{
+ const char *ret = re_compile_pattern (pat, strlen (pat), buf);
+
+ if (ret != NULL) simple_fail ("compile", pat, buf, NULL, ret);
+}
+
+
+static void
+simple_fastmap (pat)
+ const char *pat;
+{
+ struct re_pattern_buffer buf;
+ char fastmap[256];
+ int ret;
+
+ buf.allocated = 0;
+ buf.buffer = buf.translate = NULL;
+ buf.fastmap = fastmap;
+
+ simple_compile (pat, &buf);
+
+ ret = re_compile_fastmap (&buf);
+
+ if (ret != 0) simple_fail ("fastmap compile", pat, &buf, NULL, itoa (ret));
+}
+
+
+#define SIMPLE_MATCH(pat, str) do_match (pat, str, strlen (str))
+#define SIMPLE_NONMATCH(pat, str) do_match (pat, str, -1)
+
+static void
+do_match (pat, str, expected)
+ const char *pat, *str;
+ int expected;
+{
+ int ret;
+ unsigned len;
+ struct re_pattern_buffer buf;
+
+ buf.allocated = 0;
+ buf.buffer = buf.translate = buf.fastmap = NULL;
+
+ simple_compile (pat, &buf);
+
+ len = strlen (str);
+
+ ret = re_match_2 (&buf, NULL, 0, str, len, 0, NULL, len);
+
+ if (ret != expected) simple_fail ("match", pat, &buf, str, itoa (ret));
+}
+
+
+static void
+simple_search (pat, str, correct_startpos)
+ const char *pat, *str;
+ int correct_startpos;
+{
+ int ret;
+ unsigned len;
+ struct re_pattern_buffer buf;
+
+ buf.allocated = 0;
+ buf.buffer = buf.translate = buf.fastmap = NULL;
+
+ simple_compile (pat, &buf);
+
+ len = strlen (str);
+
+ ret = re_search_2 (&buf, NULL, 0, str, len, 0, len, NULL, len);
+
+ if (ret != correct_startpos)
+ simple_fail ("match", pat, &buf, str, itoa (ret));
+}
+
+/* Past bugs people have reported. */
+
+void
+test_regress ()
+{
+ extern char upcase[];
+ struct re_pattern_buffer buf;
+ unsigned len;
+ struct re_registers regs;
+ int ret;
+ char *fastmap = xmalloc (256);
+
+ buf.translate = NULL;
+ buf.fastmap = NULL;
+ buf.allocated = 0;
+ buf.buffer = NULL;
+
+ printf ("\nStarting regression tests.\n");
+ t = regress_test;
+
+ test_should_match = true;
+ re_set_syntax (RE_SYNTAX_EMACS);
+
+ /* enami@sys.ptg.sony.co.jp 10 Nov 92 15:19:02 JST */
+ buf.translate = upcase;
+ SIMPLE_MATCH ("[A-[]", "A");
+ buf.translate = NULL;
+
+ /* meyering@cs.utexas.edu Nov 6 22:34:41 1992 */
+ simple_search ("\\w+", "a", 0);
+
+ /* jimb@occs.cs.oberlin.edu 10 Sep 92 00:42:33 */
+ buf.translate = upcase;
+ SIMPLE_MATCH ("[\001-\377]", "\001");
+ SIMPLE_MATCH ("[\001-\377]", "a");
+ SIMPLE_MATCH ("[\001-\377]", "\377");
+ buf.translate = NULL;
+
+ /* mike@skinner.cs.uoregon.edu 1 Sep 92 01:45:22 */
+ SIMPLE_MATCH ("^^$", "^");
+
+ /* pclink@qld.tne.oz.au Sep 7 22:42:36 1992 */
+ re_set_syntax (RE_INTERVALS);
+ SIMPLE_MATCH ("^a\\{3\\}$", "aaa");
+ SIMPLE_NONMATCH ("^a\\{3\\}$", "aa");
+ re_set_syntax (RE_SYNTAX_EMACS);
+
+ /* pclink@qld.tne.oz.au, 31 Aug 92. (conjecture) */
+ re_set_syntax (RE_INTERVALS);
+ simple_search ("a\\{1,3\\}b", "aaab", 0);
+ simple_search ("a\\{1,3\\}b", "aaaab", 1);
+ re_set_syntax (RE_SYNTAX_EMACS);
+
+ /* trq@dionysos.thphys.ox.ac.uk, 31 Aug 92. (simplified) */
+ simple_fastmap ("^.*\n[ ]*");
+
+ /* wind!greg@plains.NoDak.edu, 25 Aug 92. (simplified) */
+ re_set_syntax (RE_INTERVALS);
+ SIMPLE_MATCH ("[a-zA-Z]*.\\{5\\}", "xN0000");
+ SIMPLE_MATCH ("[a-zA-Z]*.\\{5\\}$", "systemxN0000");
+ SIMPLE_MATCH ("\\([a-zA-Z]*\\).\\{5\\}$", "systemxN0000");
+ re_set_syntax (RE_SYNTAX_EMACS);
+
+ /* jimb, 18 Aug 92. Don't use \000, so `strlen' (in our testing
+ routines) will work. (This still tickles the bug jimb reported.) */
+ SIMPLE_MATCH ("[\001-\377]", "\001");
+ SIMPLE_MATCH ("[\001-\377]", "a");
+ SIMPLE_MATCH ("[\001-\377]", "\377");
+
+ /* jimb, 13 Aug 92. */
+ SIMPLE_MATCH ("[\001-\177]", "\177");
+
+ /* Tests based on bwoelfel's below. */
+ SIMPLE_MATCH ("\\(a\\|ab\\)*", "aab");
+ SIMPLE_MATCH ("\\(a\\|ab\\)+", "aab");
+ SIMPLE_MATCH ("\\(a*\\|ab\\)+", "aab");
+ SIMPLE_MATCH ("\\(a+\\|ab\\)+", "aab");
+ SIMPLE_MATCH ("\\(a?\\|ab\\)+", "aab");
+
+ /* bwoelfel@widget.seas.upenn.edu, 25 Jul 92. */
+ SIMPLE_MATCH ("^\\([ab]+\\|bc\\)+", "abc");
+
+ /* jla, 3 Jul 92. Core dump in re_search_2. */
+ buf.fastmap = fastmap;
+ buf.translate = upcase;
+#define DATEDUMP_PATTERN " *[0-9]*:"
+ if (re_compile_pattern (DATEDUMP_PATTERN, strlen (DATEDUMP_PATTERN), &buf)
+ != NULL)
+ printf ("date dump compile failed.\n");
+ regs.num_regs = 0;
+ regs.start = regs.end = NULL;
+ if (re_search_2 (&buf, NULL, 0, "Thu Jul 2 18:34:18 1992",
+ 24, 3, 21, &regs, 24) != 10)
+ printf ("date dump search failed.\n");
+ buf.fastmap = 0;
+ buf.translate = 0;
+
+
+ /* rms, 4 Jul 1992. Pattern is much slower in Emacs 19. Fastmap
+ should be only a backslash. */
+#define BEGINEND_PATTERN "\\(\\\\begin\\s *{\\)\\|\\(\\\\end\\s *{\\)"
+ test_fastmap (BEGINEND_PATTERN, "\\", false, 0);
+
+
+ /* kaoru@is.s.u-tokyo.ac.jp, 27 Jun 1992. Code for [a-z] (in regex.c)
+ should translate the whole set. */
+ buf.translate = upcase;
+#define CASE_SET_PATTERN "[ -`]"
+ if (re_compile_pattern (CASE_SET_PATTERN, strlen (CASE_SET_PATTERN), &buf)
+ != NULL)
+ printf ("case set compile failed.\n");
+ if (re_match_2 (&buf, "K", 1, "", 0, 0, NULL, 1) != 1)
+ printf ("case set match failed.\n");
+
+#define CASE_SET_PATTERN2 "[`-|]"
+ if (re_compile_pattern (CASE_SET_PATTERN2, strlen (CASE_SET_PATTERN2), &buf)
+ != NULL)
+ printf ("case set2 compile failed.\n");
+ if (re_match_2 (&buf, "K", 1, "", 0, 0, NULL, 1) != 1)
+ printf ("case set2 match failed.\n");
+
+ buf.translate = NULL;
+
+
+ /* jimb, 27 Jun 92. Problems with gaps in the string. */
+#define GAP_PATTERN "x.*y.*z"
+ if (re_compile_pattern (GAP_PATTERN, strlen (GAP_PATTERN), &buf) != NULL)
+ printf ("gap didn't compile.\n");
+ if (re_match_2 (&buf, "x-", 2, "y-z-", 4, 0, NULL, 6) != 5)
+ printf ("gap match failed.\n");
+
+
+ /* jimb, 19 Jun 92. Since `beginning of word' matches at the
+ beginning of the string, then searching ought to find it there.
+ If `re_compile_fastmap' is not called, then it works ok. */
+ buf.fastmap = fastmap;
+#define BOW_BEG_PATTERN "\\<"
+ if (re_compile_pattern (BOW_BEG_PATTERN, strlen (BOW_BEG_PATTERN), &buf)
+ != NULL)
+ printf ("begword-begstring didn't compile.\n");
+ if (re_search (&buf, "foo", 3, 0, 3, NULL) != 0)
+ printf ("begword-begstring search failed.\n");
+
+ /* Same bug report, different null-matching pattern. */
+#define EMPTY_ANCHOR_PATTERN "^$"
+ if (re_compile_pattern (EMPTY_ANCHOR_PATTERN, strlen (EMPTY_ANCHOR_PATTERN),
+ &buf) != NULL)
+ printf ("empty anchor didn't compile.\n");
+ if (re_search (&buf, "foo\n\nbar", 8, 0, 8, NULL) != 4)
+ printf ("empty anchor search failed.\n");
+
+ /* jimb@occs.cs.oberlin.edu, 21 Apr 92. After we first allocate
+ registers for a particular re_pattern_buffer, we might have to
+ reallocate more registers on subsequent calls -- and we should be
+ reusing the same memory. */
+#define ALLOC_REG_PATTERN "\\(abc\\)"
+ free (buf.fastmap);
+ buf.fastmap = 0;
+ if (re_compile_pattern (ALLOC_REG_PATTERN, strlen (ALLOC_REG_PATTERN), &buf)
+ != NULL)
+ printf ("register allocation didn't compile.\n");
+ if (re_match (&buf, "abc", 3, 0, &regs) != 3)
+ printf ("register allocation didn't match.\n");
+ if (regs.start[1] != 0 || regs.end[1] != 3)
+ printf ("register allocation reg #1 wrong.\n");
+
+ {
+ int *old_regstart = regs.start;
+ int *old_regend = regs.end;
+
+ if (re_match (&buf, "abc", 3, 0, &regs) != 3)
+ printf ("register reallocation didn't match.\n");
+ if (regs.start[1] != 0 || regs.end[1] != 3
+ || old_regstart[1] != 0 || old_regend[1] != 3
+ || regs.start != old_regstart || regs.end != old_regend)
+ printf ("register reallocation registers wrong.\n");
+ }
+
+ /* jskudlarek@std.MENTORG.COM, 21 Apr 92 (string-match). */
+#define JSKUD_PATTERN "[^/]+\\(/[^/.]+\\)?/[0-9]+$"
+ if (re_compile_pattern (JSKUD_PATTERN, strlen (JSKUD_PATTERN), &buf) != NULL)
+ printf ("jskud test didn't compile.\n");
+ if (re_search (&buf, "a/1", 3, 0, 3, &regs) != 0)
+ printf ("jskud test didn't match.\n");
+ if (regs.start[1] != -1 || regs.end[1] != -1)
+ printf ("jskud test, reg #1 wrong.\n");
+
+ /* jla's bug (with string-match), 5 Feb 92. */
+ TEST_SEARCH ("\\`[ \t\n]*", "jla@challenger (Joseph Arceneaux)", 0, 100);
+
+ /* jwz@lucid.com, 8 March 1992 (re-search-forward). (His is the
+ second.) These are not supposed to match. */
+#if 0
+ /* This one fails quickly, because we can change the maybe_pop_jump
+ from the + to a pop_failure_pop, because of the c's. */
+ TEST_SEARCH ("^\\(To\\|CC\\):\\([^c]*\\)+co",
+"To: hbs%titanic@lucid.com (Harlan Sexton)\n\
+Cc: eb@thalidomide, jlm@thalidomide\n\
+Subject: Re: so is this really as horrible an idea as it seems to me?\n\
+In-Reply-To: Harlan Sexton's message of Sun 8-Mar-92 11:00:06 PST <9203081900.AA24794@titanic.lucid>\n\
+References: <9203080736.AA05869@thalidomide.lucid>\n\
+ <9203081900.AA24794@titanic.lucid>", 0, 5000);
+
+ /* This one takes a long, long time to complete, because we have to
+ keep the failure points around because we might backtrack. */
+ TEST_SEARCH ("^\\(To\\|CC\\):\\(.*\n.*\\)+co",
+ /* "X-Windows: The joke that kills.\n\
+FCC: /u/jwz/VM/inbox\n\
+From: Jamie Zawinski <jwz@lucid.com>\n\ */
+"To: hbs%titanic@lucid.com (Harlan Sexton)\n\
+Cc: eb@thalidomide, jlm@thalidomide\n\
+Subject: Re: so is this really as horrible an idea as it seems to me?\n\
+In-Reply-To: Harlan Sexton's message of Sun 8-Mar-92 11:00:06 PST <9203081900.AA24794@titanic.lucid>\n\
+References: <9203080736.AA05869@thalidomide.lucid>\n\
+ <9203081900.AA24794@titanic.lucid>", 0, 5000);
+#endif /* 0 [failed searches] */
+
+
+ /* macrakis' bugs. */
+ buf.translate = upcase; /* message of 24 Jan 91 */
+ if (re_compile_pattern ("[!-`]", 5, &buf) != NULL)
+ printf ("Range test didn't compile.\n");
+ if (re_match (&buf, "A", 1, 0, NULL) != 1)
+ printf ("Range test #1 didn't match.\n");
+ if (re_match (&buf, "a", 1, 0, NULL) != 1)
+ printf ("Range test #2 didn't match.\n");
+
+ buf.translate = 0;
+#define FAO_PATTERN "\\(f\\(.\\)o\\)+"
+ if (re_compile_pattern (FAO_PATTERN, strlen (FAO_PATTERN), &buf) != NULL)
+ printf ("faofdx test didn't compile.\n");
+ if (re_search (&buf, "faofdx", 6, 0, 6, &regs) != 0)
+ printf ("faofdx test didn't match.\n");
+ if (regs.start[1] != 0 || regs.end[1] != 3)
+ printf ("faofdx test, reg #1 wrong.\n");
+ if (regs.start[2] != 1 || regs.end[2] != 2)
+ printf ("faofdx test, reg #2 wrong.\n");
+
+ TEST_REGISTERS ("\\(a\\)*a", "aaa", 0, 3, 1, 2, -1, -1);
+ test_fastmap ("^\\([^ \n]+:\n\\)+\\([^ \n]+:\\)", " \n", 1, 0);
+
+ /* 40 lines, 48 a's in each line. */
+ test_match ("^\\([^ \n]+:\n\\)+\\([^ \n]+:\\)",
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n\
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:");
+
+ /* 640 a's followed by one b, twice. */
+ test_match ("\\(.*\\)\\1", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab");
+
+ /* 640 a's followed by two b's, twice. */
+ test_match ("\\(.*\\)\\1", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb");
+
+
+ /* Dave G. bug: Reference to a subexpression which didn't match.
+ Should fail. */
+ re_set_syntax (RE_NO_BK_PARENS | RE_NO_BK_VBAR);
+ test_match ("(ooooooooooone())-annnnnnnnnnnd-(twooooooooooo\\2)",
+ "ooooooooooone-annnnnnnnnnnd-twooooooooooo");
+ test_match ("(o|t)", "o");
+ test_match ("(o()|t)", "o");
+ test_match ("(o|t)", "o");
+ test_match ("(ooooooooooooooo|tttttttttttttttt())", "ooooooooooooooo");
+ test_match ("(o|t())", "o");
+ test_match ("(o()|t())", "o");
+ test_match ("(ooooooooooooooooooooooooone()|twooooooooooooooooooooooooo())", "ooooooooooooooooooooooooone");
+ test_match ("(o()|t())-a-(t\\2|f\\3)", "o-a-t");
+ test_match ("(o()|t())-a-(t\\2|f\\3)", "t-a-f");
+
+ test_should_match = 0;
+ test_match ("(foo(bar)|second)\\2", "second");
+ test_match ("(o()|t())-a-(t\\2|f\\3)", "t-a-t");
+ test_match ("(o()|t())-a-(t\\2|f\\3)", "o-a-f");
+
+ re_set_syntax (RE_SYNTAX_EMACS);
+ test_match ("\\(foo\\(bar\\)\\|second\\)\\2", "secondbar");
+ test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)",
+ "one-and-four");
+ test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)",
+ "two-and-three");
+
+ test_should_match = 1;
+ re_set_syntax (RE_SYNTAX_EMACS);
+ test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)",
+ "one-and-three");
+ test_match ("\\(one\\(\\)\\|two\\(\\)\\)-and-\\(three\\2\\|four\\3\\)",
+ "two-and-four");
+
+ TEST_REGISTERS (":\\(.*\\)", ":/", 0, 2, 1, 2, -1, -1);
+
+ /* Bug with `upcase' translation table, from Nico Josuttis
+ <nico@bredex.de> */
+ test_should_match = 1;
+ test_case_fold ("[a-a]", "a");
+
+ printf ("\nFinished regression tests.\n");
+}
+
+
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/gnu/lib/libregex/test/upcase.c b/gnu/lib/libregex/test/upcase.c
new file mode 100644
index 0000000..a3c0fbc
--- /dev/null
+++ b/gnu/lib/libregex/test/upcase.c
@@ -0,0 +1,39 @@
+/* Indexed by a character, gives the upper case equivalent of the
+ character. */
+
+char upcase[0400] =
+ { 000, 001, 002, 003, 004, 005, 006, 007,
+ 010, 011, 012, 013, 014, 015, 016, 017,
+ 020, 021, 022, 023, 024, 025, 026, 027,
+ 030, 031, 032, 033, 034, 035, 036, 037,
+ 040, 041, 042, 043, 044, 045, 046, 047,
+ 050, 051, 052, 053, 054, 055, 056, 057,
+ 060, 061, 062, 063, 064, 065, 066, 067,
+ 070, 071, 072, 073, 074, 075, 076, 077,
+ 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+ };
+
+
diff --git a/gnu/lib/libregex/test/xmalloc.c b/gnu/lib/libregex/test/xmalloc.c
new file mode 100644
index 0000000..aa1c6c4
--- /dev/null
+++ b/gnu/lib/libregex/test/xmalloc.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+extern char *malloc ();
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+void *
+xmalloc (size)
+ unsigned size;
+{
+ char *new_mem = malloc (size);
+
+ if (new_mem == NULL)
+ {
+ fprintf (stderr, "xmalloc: request for %u bytes failed.\n", size);
+ abort ();
+ }
+
+ return new_mem;
+}
diff --git a/gnu/lib/libstdc++/Makefile b/gnu/lib/libstdc++/Makefile
new file mode 100644
index 0000000..84d26ad
--- /dev/null
+++ b/gnu/lib/libstdc++/Makefile
@@ -0,0 +1,178 @@
+# $FreeBSD$
+
+GCCDIR= ${.CURDIR}/../../../contrib/gcc
+SRCDIR= ${.CURDIR}/../../../contrib/libstdc++
+SUPDIR= ${SRCDIR}/libsupc++
+
+.PATH: ${SRCDIR}/src ${SRCDIR}/libmath ${SRCDIR}/config/io \
+ ${SRCDIR}/config/locale/generic ${SRCDIR} ${SRCDIR}/std \
+ ${SUPDIR} ${GCCDIR}
+
+#SUBDIR= doc
+
+LIB= stdc++
+SHLIB_MAJOR= 4
+SHLIB_MINOR= 0
+
+CFLAGS+= -DIN_GLIBCPP_V3 -DHAVE_CONFIG_H
+CFLAGS+= -I${.CURDIR} -I${SUPDIR} -I${GCCDIR}
+CXXFLAGS+= -fno-implicit-templates -ffunction-sections -fdata-sections -Wno-deprecated
+#LDFLAGS+= -Wl,-version-info,4:0:0 -Wl,--version-script=${SRCDIR}/src/linker.map
+
+LDADD+= -lm
+DPADD+= ${LIBM}
+
+# libstdc++ sources (libstdc++/src/Makefile.in, do not reorder)
+SRCS+= globals.cc limits.cc basic_file_stdio.cc complex_io.cc ios.cc \
+ strstream-fixed.cc cmath.cc bitset.cc functexcept.cc stdexcept.cc \
+ vterminate.cc c_locale.cc locale.cc localename.cc codecvt.cc \
+ collate_members.cc ctype_members.cc messages_members.cc \
+ monetary_members.cc numeric_members.cc time_members.cc concept-inst.cc \
+ locale-inst.cc misc-inst.cc stl-inst.cc string-inst.cc wstring-inst.cc \
+ valarray-inst.cc ext-inst.cc
+
+# C parts of math
+SRCS+= nan.c signbit.c signbitf.c signbitl.c stubs.c
+
+# Embedded copy of libsupc++
+SRCS+= del_op.cc del_opnt.cc del_opv.cc del_opvnt.cc \
+ eh_alloc.cc eh_aux_runtime.cc eh_catch.cc eh_exception.cc \
+ eh_globals.cc eh_personality.cc eh_terminate.cc eh_throw.cc eh_type.cc \
+ new_handler.cc new_op.cc new_opnt.cc new_opv.cc new_opvnt.cc \
+ pure.cc tinfo.cc tinfo2.cc vec.cc
+
+# from libiberty:
+SRCS+= cp-demangle.c dyn-string.c
+
+strstream-fixed.cc: ${SRCDIR}/src/strstream.cc
+ sed -e 's,^#include <strstream.h>,#include <backward/strstream.h>,g' \
+ < ${SRCDIR}/src/strstream.cc > strstream-fixed.cc
+
+CLEANFILES+= strstream-fixed.cc
+
+INCSGROUPS= BITSHDRS BKWHDRS EXTHDRS BASEHDRS BASEXHDRS STDHDRS \
+ TARGETHDRS THRHDRS
+
+BITSHDRS= basic_ios.h basic_ios.tcc basic_string.h basic_string.tcc \
+ boost_concept_check.h char_traits.h codecvt.h concept_check.h \
+ cpp_type_traits.h fpos.h fstream.tcc functexcept.h \
+ generic_shadow.h gslice.h gslice_array.h indirect_array.h \
+ ios_base.h istream.tcc locale_facets.h locale_facets.tcc \
+ localefwd.h mask_array.h ostream.tcc pthread_allocimpl.h \
+ slice.h slice_array.h sstream.tcc stl_algo.h stl_algobase.h \
+ stl_alloc.h stl_bvector.h stl_construct.h stl_deque.h \
+ stl_function.h stl_heap.h stl_iterator.h \
+ stl_iterator_base_funcs.h stl_iterator_base_types.h \
+ stl_list.h stl_map.h stl_multimap.h stl_multiset.h \
+ stl_numeric.h stl_pair.h stl_pthread_alloc.h stl_queue.h \
+ stl_raw_storage_iter.h stl_relops.h stl_set.h stl_stack.h \
+ stl_tempbuf.h stl_threads.h stl_tree.h stl_uninitialized.h \
+ stl_vector.h stream_iterator.h streambuf.tcc \
+ streambuf_iterator.h stringfwd.h type_traits.h \
+ valarray_array.h valarray_array.tcc valarray_meta.h
+BITSHDRS:= ${BITSHDRS:S;^;${SRCDIR}/include/bits/;}
+BITSHDRSDIR= ${INCLUDEDIR}/g++/bits
+
+BKWHDRS= algo.h algobase.h alloc.h backward_warning.h bvector.h \
+ complex.h defalloc.h deque.h fstream.h function.h \
+ hash_map.h hash_set.h hashtable.h heap.h iomanip.h \
+ iostream.h istream.h iterator.h list.h map.h multimap.h \
+ multiset.h new.h ostream.h pair.h queue.h rope.h set.h \
+ slist.h stack.h stream.h streambuf.h strstream strstream.h \
+ tempbuf.h tree.h vector.h
+BKWHDRS:= ${BKWHDRS:S;^;${SRCDIR}/include/backward/;}
+BKWHDRSDIR= ${INCLUDEDIR}/g++/backward
+
+EXTHDRS= algorithm enc_filebuf.h functional hash_map hash_set \
+ iterator memory numeric rb_tree rope ropeimpl.h slist \
+ stdio_filebuf.h stl_hash_fun.h stl_hashtable.h stl_rope.h
+EXTHDRS:= ${EXTHDRS:S;^;${SRCDIR}/include/ext/;}
+EXTHDRSDIR= ${INCLUDEDIR}/g++/ext
+
+# This is the common subset of files that all three "C" header models use.
+BASEHDRS= std_cassert.h std_cctype.h std_cerrno.h std_cfloat.h \
+ std_ciso646.h std_climits.h std_clocale.h std_cmath.h \
+ std_csetjmp.h std_csignal.h std_cstdarg.h std_cstddef.h \
+ std_cstdio.h std_cstdlib.h std_cstring.h std_ctime.h \
+ std_cwchar.h std_cwctype.h
+.for h in ${BASEHDRS}
+BASEHDRSNAME_$h=${h:R:S;^std_;;}
+.endfor
+BASEHDRS:= ${BASEHDRS:S;^;${SRCDIR}/include/c_std/;}
+BASEHDRSDIR= ${INCLUDEDIR}/g++
+
+# Some of the different "C" header models need extra files.
+BASEXHDRS= ${SRCDIR}/include/c_std/cmath.tcc
+BASEXHDRSDIR= ${INCLUDEDIR}/g++/bits
+
+STDHDRS= std_algorithm.h std_bitset.h std_complex.h std_deque.h \
+ std_fstream.h std_functional.h std_iomanip.h std_ios.h \
+ std_iosfwd.h std_iostream.h std_istream.h std_iterator.h \
+ std_limits.h std_list.h std_locale.h std_map.h std_memory.h \
+ std_numeric.h std_ostream.h std_queue.h std_set.h \
+ std_sstream.h std_stack.h std_stdexcept.h std_streambuf.h \
+ std_string.h std_utility.h std_valarray.h std_vector.h
+.for h in ${STDHDRS}
+STDHDRSNAME_$h=${h:R:S;^std_;;}
+.endfor
+STDHDRS:= ${STDHDRS:S;^;${SRCDIR}/include/std/;}
+STDHDRSDIR= ${INCLUDEDIR}/g++
+
+TARGETHDRS= io/basic_file_stdio.h io/c_io_stdio.h \
+ locale/generic/c_locale.h \
+ locale/generic/codecvt_specializations.h \
+ locale/generic/messages_members.h \
+ os/bsd/freebsd/bits/ctype_base.h \
+ os/bsd/freebsd/bits/ctype_inline.h \
+ os/bsd/freebsd/bits/ctype_noninline.h \
+ os/bsd/freebsd/bits/os_defines.h
+TARGETHDRS:= ${TARGETHDRS:S;^;${SRCDIR}/config/;}
+TARGETHDRS+= ${.CURDIR}/c++config.h
+TARGETHDRSNAME_basic_file_stdio.h= basic_file.h
+TARGETHDRSNAME_c_io_stdio.h= c++io.h
+TARGETHDRSNAME_c_locale.h= c++locale.h
+TARGETHDRSDIR= ${INCLUDEDIR}/g++/bits
+
+MARCHHDRS= atomicity.h cpu_limits.h
+.if ${MACHINE_ARCH} == "sparc64"
+MARCHDIR= ${SRCDIR}/config/cpu/sparc/${MACHINE_ARCH}/bits
+.else
+MARCHDIR= ${SRCDIR}/config/cpu/${MACHINE_ARCH}/bits
+.endif
+.for h in ${MARCHHDRS}
+.if exists(${MARCHDIR}/${h})
+TARGETHDRS+= ${MARCHDIR}/${h}
+.else
+TARGETHDRS+= ${SRCDIR}/config/cpu/generic/bits/${h}
+.endif
+.endfor
+
+THRHDRS= gthr.h gthr-single.h gthr-posix.h gthr-default.h
+THRHDRSDIR= ${INCLUDEDIR}/g++/bits
+
+gthr.h: ${GCCDIR}/gthr.h
+ sed -e '/^#/s/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_][ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*\)/_GLIBCPP_\1/g' \
+ -e 's,^#include "\(.*\)",#include <bits/\1>,g' \
+ < ${GCCDIR}/gthr.h > gthr.h
+
+gthr-single.h: ${GCCDIR}/gthr-single.h
+ sed -e 's/\(UNUSED\)/_GLIBCPP_\1/g' \
+ -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCPP_\1/g' \
+ < ${GCCDIR}/gthr-single.h > gthr-single.h
+
+gthr-posix.h: ${GCCDIR}/gthr-posix.h
+ sed -e 's/\(UNUSED\)/_GLIBCPP_\1/g' \
+ -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCPP_\1/g' \
+ -e 's/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*WEAK\)/_GLIBCPP_\1/g' \
+ < ${GCCDIR}/gthr-posix.h > gthr-posix.h
+
+gthr-default.h: ${GCCDIR}/gthr-posix.h
+ sed -e 's/\(UNUSED\)/_GLIBCPP_\1/g' \
+ -e 's/\(GCC[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*_H\)/_GLIBCPP_\1/g' \
+ -e 's/\([ABCDEFGHIJKLMNOPQRSTUVWXYZ_]*WEAK\)/_GLIBCPP_\1/g' \
+ -e 's,^#include "\(.*\)",#include <bits/\1>,g' \
+ < ${GCCDIR}/gthr-posix.h > gthr-default.h
+
+CLEANFILES+= ${THRHDRS}
+
+.include <bsd.lib.mk>
diff --git a/gnu/lib/libstdc++/c++config.h b/gnu/lib/libstdc++/c++config.h
new file mode 100644
index 0000000..6f0c96c
--- /dev/null
+++ b/gnu/lib/libstdc++/c++config.h
@@ -0,0 +1,1154 @@
+// $FreeBSD$
+
+// Predefined symbols and macros -*- C++ -*-
+
+// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction. Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License. This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+#ifndef _CPP_CPPCONFIG
+#define _CPP_CPPCONFIG 1
+
+// Pick up any OS-specific definitions.
+#include <bits/os_defines.h>
+
+// The current version of the C++ library in compressed ISO date format.
+#define __GLIBCPP__ 20020514
+
+// This is necessary until GCC supports separate template
+// compilation.
+#define _GLIBCPP_NO_TEMPLATE_EXPORT 1
+
+// This is a hack around not having either pre-compiled headers or
+// export compilation. If defined, the io, string, and valarray
+// headers will include all the necessary bits. If not defined, the
+// implementation optimizes the headers for the most commonly-used
+// types. For the io library, this means that larger, out-of-line
+// member functions are only declared, and definitions are not parsed
+// by the compiler, but instead instantiated into the library binary.
+#define _GLIBCPP_FULLY_COMPLIANT_HEADERS 1
+
+// To enable older, ARM-style iostreams and other anachronisms use this.
+//#define _GLIBCPP_DEPRECATED 1
+
+// Use corrected code from the committee library group's issues list.
+#define _GLIBCPP_RESOLVE_LIB_DEFECTS 1
+
+// In those parts of the standard C++ library that use a mutex instead
+// of a spin-lock, we now unconditionally use GCC's gthr.h mutex
+// abstraction layer. All support to directly map to various
+// threading models has been removed. Note: gthr.h may well map to
+// gthr-single.h which is a correct way to express no threads support
+// in gcc. Support for the undocumented _NOTHREADS has been removed.
+
+// Default to the typically high-speed, pool-based allocator (as
+// libstdc++-v2) instead of the malloc-based allocator (libstdc++-v3
+// snapshots). See libstdc++-v3/docs/html/17_intro/howto.html for
+// details on why you don't want to override this setting. Ensure
+// that threads are properly configured on your platform before
+// assigning blame to the STL container-memory allocator. After doing
+// so, please report any possible issues to libstdc++@gcc.gnu.org .
+// Do not blindly #define __USE_MALLOC here or on the command line.
+
+// The remainder of the prewritten config is mostly automatic; all the
+// user hooks are listed above.
+
+// End of prewritten config; the discovered settings follow.
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if you have a working `mmap' system call. */
+#define _GLIBCPP_HAVE_MMAP 1
+
+// Define if GCC supports weak symbols.
+#define _GLIBCPP_SUPPORTS_WEAK __GXX_WEAK__
+
+// Define if gthr-default.h exists (meaning that threading support is enabled).
+#define _GLIBCPP_HAVE_GTHR_DEFAULT 1
+
+// Include I/O support for 'long long' and 'unsigned long long'.
+#define _GLIBCPP_USE_LONG_LONG 1
+
+// Define if C99 features such as lldiv_t, llabs, lldiv should be exposed.
+/* #undef _GLIBCPP_USE_C99 */
+
+// Define if code specialized for wchar_t should be used.
+/* #undef _GLIBCPP_USE_WCHAR_T */
+
+// Define if using setrlimit to limit memory usage during 'make check'.
+/* #undef _GLIBCPP_MEM_LIMITS */
+
+// Define to use concept checking code from the boost libraries.
+/* #undef _GLIBCPP_CONCEPT_CHECKS */
+
+// Define if mbstate_t exists in wchar.h.
+#define _GLIBCPP_HAVE_MBSTATE_T 1
+
+// Define if you have the modff function.
+#define _GLIBCPP_HAVE_MODFF 1
+
+// Define if you have the modfl function.
+/* #undef _GLIBCPP_HAVE_MODFL */
+
+// Define if you have the expf function.
+#define _GLIBCPP_HAVE_EXPF 1
+
+// Define if you have the expl function.
+/* #undef _GLIBCPP_HAVE_EXPL */
+
+// Define if you have the hypotf function.
+#define _GLIBCPP_HAVE_HYPOTF 1
+
+// Define if you have the hypotl function.
+/* #undef _GLIBCPP_HAVE_HYPOTL */
+
+// Define if the compiler/host combination has __builtin_abs
+#define _GLIBCPP_HAVE___BUILTIN_ABS 1
+
+// Define if the compiler/host combination has __builtin_labs
+#define _GLIBCPP_HAVE___BUILTIN_LABS 1
+
+// Define if the compiler/host combination has __builtin_cos
+/* #undef _GLIBCPP_HAVE___BUILTIN_COS */
+
+// Define if the compiler/host combination has __builtin_cosf
+/* #undef _GLIBCPP_HAVE___BUILTIN_COSF */
+
+// Define if the compiler/host combination has __builtin_cosl
+/* #undef _GLIBCPP_HAVE___BUILTIN_COSL */
+
+// Define if the compiler/host combination has __builtin_fabs
+#define _GLIBCPP_HAVE___BUILTIN_FABS 1
+
+// Define if the compiler/host combination has __builtin_fabsf
+#define _GLIBCPP_HAVE___BUILTIN_FABSF 1
+
+// Define if the compiler/host combination has __builtin_fabsl
+#define _GLIBCPP_HAVE___BUILTIN_FABSL 1
+
+// Define if the compiler/host combination has __builtin_sin
+/* #undef _GLIBCPP_HAVE___BUILTIN_SIN */
+
+// Define if the compiler/host combination has __builtin_sinf
+/* #undef _GLIBCPP_HAVE___BUILTIN_SINF */
+
+// Define if the compiler/host combination has __builtin_sinl
+/* #undef _GLIBCPP_HAVE___BUILTIN_SINL */
+
+// Define if the compiler/host combination has __builtin_sqrt
+/* #undef _GLIBCPP_HAVE___BUILTIN_SQRT */
+
+// Define if the compiler/host combination has __builtin_sqrtf
+/* #undef _GLIBCPP_HAVE___BUILTIN_SQRTF */
+
+// Define if the compiler/host combination has __builtin_sqrtl
+/* #undef _GLIBCPP_HAVE___BUILTIN_SQRTL */
+
+// Define if LC_MESSAGES is available in <locale.h>.
+#define _GLIBCPP_HAVE_LC_MESSAGES 1
+
+/* Define if you have the __signbit function. */
+/* #undef _GLIBCPP_HAVE___SIGNBIT */
+
+/* Define if you have the __signbitf function. */
+/* #undef _GLIBCPP_HAVE___SIGNBITF */
+
+/* Define if you have the __signbitl function. */
+/* #undef _GLIBCPP_HAVE___SIGNBITL */
+
+/* Define if you have the _acosf function. */
+/* #undef _GLIBCPP_HAVE__ACOSF */
+
+/* Define if you have the _acosl function. */
+/* #undef _GLIBCPP_HAVE__ACOSL */
+
+/* Define if you have the _asinf function. */
+/* #undef _GLIBCPP_HAVE__ASINF */
+
+/* Define if you have the _asinl function. */
+/* #undef _GLIBCPP_HAVE__ASINL */
+
+/* Define if you have the _atan2f function. */
+/* #undef _GLIBCPP_HAVE__ATAN2F */
+
+/* Define if you have the _atan2l function. */
+/* #undef _GLIBCPP_HAVE__ATAN2L */
+
+/* Define if you have the _atanf function. */
+/* #undef _GLIBCPP_HAVE__ATANF */
+
+/* Define if you have the _atanl function. */
+/* #undef _GLIBCPP_HAVE__ATANL */
+
+/* Define if you have the _ceilf function. */
+/* #undef _GLIBCPP_HAVE__CEILF */
+
+/* Define if you have the _ceill function. */
+/* #undef _GLIBCPP_HAVE__CEILL */
+
+/* Define if you have the _copysign function. */
+/* #undef _GLIBCPP_HAVE__COPYSIGN */
+
+/* Define if you have the _copysignl function. */
+/* #undef _GLIBCPP_HAVE__COPYSIGNL */
+
+/* Define if you have the _cosf function. */
+/* #undef _GLIBCPP_HAVE__COSF */
+
+/* Define if you have the _coshf function. */
+/* #undef _GLIBCPP_HAVE__COSHF */
+
+/* Define if you have the _coshl function. */
+/* #undef _GLIBCPP_HAVE__COSHL */
+
+/* Define if you have the _cosl function. */
+/* #undef _GLIBCPP_HAVE__COSL */
+
+/* Define if you have the _expf function. */
+/* #undef _GLIBCPP_HAVE__EXPF */
+
+/* Define if you have the _expl function. */
+/* #undef _GLIBCPP_HAVE__EXPL */
+
+/* Define if you have the _fabsf function. */
+/* #undef _GLIBCPP_HAVE__FABSF */
+
+/* Define if you have the _fabsl function. */
+/* #undef _GLIBCPP_HAVE__FABSL */
+
+/* Define if you have the _finite function. */
+/* #undef _GLIBCPP_HAVE__FINITE */
+
+/* Define if you have the _finitef function. */
+/* #undef _GLIBCPP_HAVE__FINITEF */
+
+/* Define if you have the _finitel function. */
+/* #undef _GLIBCPP_HAVE__FINITEL */
+
+/* Define if you have the _floorf function. */
+/* #undef _GLIBCPP_HAVE__FLOORF */
+
+/* Define if you have the _floorl function. */
+/* #undef _GLIBCPP_HAVE__FLOORL */
+
+/* Define if you have the _fmodf function. */
+/* #undef _GLIBCPP_HAVE__FMODF */
+
+/* Define if you have the _fmodl function. */
+/* #undef _GLIBCPP_HAVE__FMODL */
+
+/* Define if you have the _fpclass function. */
+/* #undef _GLIBCPP_HAVE__FPCLASS */
+
+/* Define if you have the _frexpf function. */
+/* #undef _GLIBCPP_HAVE__FREXPF */
+
+/* Define if you have the _frexpl function. */
+/* #undef _GLIBCPP_HAVE__FREXPL */
+
+/* Define if you have the _hypot function. */
+/* #undef _GLIBCPP_HAVE__HYPOT */
+
+/* Define if you have the _hypotf function. */
+/* #undef _GLIBCPP_HAVE__HYPOTF */
+
+/* Define if you have the _hypotl function. */
+/* #undef _GLIBCPP_HAVE__HYPOTL */
+
+/* Define if you have the _isinf function. */
+/* #undef _GLIBCPP_HAVE__ISINF */
+
+/* Define if you have the _isinff function. */
+/* #undef _GLIBCPP_HAVE__ISINFF */
+
+/* Define if you have the _isinfl function. */
+/* #undef _GLIBCPP_HAVE__ISINFL */
+
+/* Define if you have the _isnan function. */
+/* #undef _GLIBCPP_HAVE__ISNAN */
+
+/* Define if you have the _isnanf function. */
+/* #undef _GLIBCPP_HAVE__ISNANF */
+
+/* Define if you have the _isnanl function. */
+/* #undef _GLIBCPP_HAVE__ISNANL */
+
+/* Define if you have the _ldexpf function. */
+/* #undef _GLIBCPP_HAVE__LDEXPF */
+
+/* Define if you have the _ldexpl function. */
+/* #undef _GLIBCPP_HAVE__LDEXPL */
+
+/* Define if you have the _log10f function. */
+/* #undef _GLIBCPP_HAVE__LOG10F */
+
+/* Define if you have the _log10l function. */
+/* #undef _GLIBCPP_HAVE__LOG10L */
+
+/* Define if you have the _logf function. */
+/* #undef _GLIBCPP_HAVE__LOGF */
+
+/* Define if you have the _logl function. */
+/* #undef _GLIBCPP_HAVE__LOGL */
+
+/* Define if you have the _modff function. */
+/* #undef _GLIBCPP_HAVE__MODFF */
+
+/* Define if you have the _modfl function. */
+/* #undef _GLIBCPP_HAVE__MODFL */
+
+/* Define if you have the _powf function. */
+/* #undef _GLIBCPP_HAVE__POWF */
+
+/* Define if you have the _powl function. */
+/* #undef _GLIBCPP_HAVE__POWL */
+
+/* Define if you have the _qfpclass function. */
+/* #undef _GLIBCPP_HAVE__QFPCLASS */
+
+/* Define if you have the _sincos function. */
+/* #undef _GLIBCPP_HAVE__SINCOS */
+
+/* Define if you have the _sincosf function. */
+/* #undef _GLIBCPP_HAVE__SINCOSF */
+
+/* Define if you have the _sincosl function. */
+/* #undef _GLIBCPP_HAVE__SINCOSL */
+
+/* Define if you have the _sinf function. */
+/* #undef _GLIBCPP_HAVE__SINF */
+
+/* Define if you have the _sinhf function. */
+/* #undef _GLIBCPP_HAVE__SINHF */
+
+/* Define if you have the _sinhl function. */
+/* #undef _GLIBCPP_HAVE__SINHL */
+
+/* Define if you have the _sinl function. */
+/* #undef _GLIBCPP_HAVE__SINL */
+
+/* Define if you have the _sqrtf function. */
+/* #undef _GLIBCPP_HAVE__SQRTF */
+
+/* Define if you have the _sqrtl function. */
+/* #undef _GLIBCPP_HAVE__SQRTL */
+
+/* Define if you have the _tanf function. */
+/* #undef _GLIBCPP_HAVE__TANF */
+
+/* Define if you have the _tanhf function. */
+/* #undef _GLIBCPP_HAVE__TANHF */
+
+/* Define if you have the _tanhl function. */
+/* #undef _GLIBCPP_HAVE__TANHL */
+
+/* Define if you have the _tanl function. */
+/* #undef _GLIBCPP_HAVE__TANL */
+
+/* Define if you have the acosf function. */
+#define _GLIBCPP_HAVE_ACOSF 1
+
+/* Define if you have the acosl function. */
+/* #undef _GLIBCPP_HAVE_ACOSL */
+
+/* Define if you have the asinf function. */
+#define _GLIBCPP_HAVE_ASINF 1
+
+/* Define if you have the asinl function. */
+/* #undef _GLIBCPP_HAVE_ASINL */
+
+/* Define if you have the atan2f function. */
+#define _GLIBCPP_HAVE_ATAN2F 1
+
+/* Define if you have the atan2l function. */
+/* #undef _GLIBCPP_HAVE_ATAN2L */
+
+/* Define if you have the atanf function. */
+#define _GLIBCPP_HAVE_ATANF 1
+
+/* Define if you have the atanl function. */
+/* #undef _GLIBCPP_HAVE_ATANL */
+
+/* Define if you have the btowc function. */
+/* #undef _GLIBCPP_HAVE_BTOWC */
+
+/* Define if you have the ceilf function. */
+#define _GLIBCPP_HAVE_CEILF 1
+
+/* Define if you have the ceill function. */
+/* #undef _GLIBCPP_HAVE_CEILL */
+
+/* Define if you have the copysign function. */
+#define _GLIBCPP_HAVE_COPYSIGN 1
+
+/* Define if you have the copysignf function. */
+#define _GLIBCPP_HAVE_COPYSIGNF 1
+
+/* Define if you have the copysignl function. */
+/* #undef _GLIBCPP_HAVE_COPYSIGNL */
+
+/* Define if you have the cosf function. */
+#define _GLIBCPP_HAVE_COSF 1
+
+/* Define if you have the coshf function. */
+#define _GLIBCPP_HAVE_COSHF 1
+
+/* Define if you have the coshl function. */
+/* #undef _GLIBCPP_HAVE_COSHL */
+
+/* Define if you have the cosl function. */
+/* #undef _GLIBCPP_HAVE_COSL */
+
+/* Define if you have the drand48 function. */
+#define _GLIBCPP_HAVE_DRAND48 1
+
+/* Define if you have the expf function. */
+#define _GLIBCPP_HAVE_EXPF 1
+
+/* Define if you have the expl function. */
+/* #undef _GLIBCPP_HAVE_EXPL */
+
+/* Define if you have the fabsf function. */
+#define _GLIBCPP_HAVE_FABSF 1
+
+/* Define if you have the fabsl function. */
+/* #undef _GLIBCPP_HAVE_FABSL */
+
+/* Define if you have the fgetwc function. */
+/* #undef _GLIBCPP_HAVE_FGETWC */
+
+/* Define if you have the fgetws function. */
+/* #undef _GLIBCPP_HAVE_FGETWS */
+
+/* Define if you have the finite function. */
+#define _GLIBCPP_HAVE_FINITE 1
+
+/* Define if you have the finitef function. */
+#define _GLIBCPP_HAVE_FINITEF 1
+
+/* Define if you have the finitel function. */
+/* #undef _GLIBCPP_HAVE_FINITEL */
+
+/* Define if you have the floorf function. */
+#define _GLIBCPP_HAVE_FLOORF 1
+
+/* Define if you have the floorl function. */
+/* #undef _GLIBCPP_HAVE_FLOORL */
+
+/* Define if you have the fmodf function. */
+#define _GLIBCPP_HAVE_FMODF 1
+
+/* Define if you have the fmodl function. */
+/* #undef _GLIBCPP_HAVE_FMODL */
+
+/* Define if you have the fpclass function. */
+/* #undef _GLIBCPP_HAVE_FPCLASS */
+
+/* Define if you have the fputwc function. */
+/* #undef _GLIBCPP_HAVE_FPUTWC */
+
+/* Define if you have the fputws function. */
+/* #undef _GLIBCPP_HAVE_FPUTWS */
+
+/* Define if you have the frexpf function. */
+#define _GLIBCPP_HAVE_FREXPF 1
+
+/* Define if you have the frexpl function. */
+/* #undef _GLIBCPP_HAVE_FREXPL */
+
+/* Define if you have the fwide function. */
+/* #undef _GLIBCPP_HAVE_FWIDE */
+
+/* Define if you have the fwprintf function. */
+/* #undef _GLIBCPP_HAVE_FWPRINTF */
+
+/* Define if you have the fwscanf function. */
+/* #undef _GLIBCPP_HAVE_FWSCANF */
+
+/* Define if you have the getpagesize function. */
+#define _GLIBCPP_HAVE_GETPAGESIZE 1
+
+/* Define if you have the getwc function. */
+/* #undef _GLIBCPP_HAVE_GETWC */
+
+/* Define if you have the getwchar function. */
+/* #undef _GLIBCPP_HAVE_GETWCHAR */
+
+/* Define if you have the hypot function. */
+#define _GLIBCPP_HAVE_HYPOT 1
+
+/* Define if you have the hypotf function. */
+#define _GLIBCPP_HAVE_HYPOTF 1
+
+/* Define if you have the hypotl function. */
+/* #undef _GLIBCPP_HAVE_HYPOTL */
+
+/* Define if you have the iconv function. */
+/* #undef _GLIBCPP_HAVE_ICONV */
+
+/* Define if you have the iconv_close function. */
+/* #undef _GLIBCPP_HAVE_ICONV_CLOSE */
+
+/* Define if you have the iconv_open function. */
+/* #undef _GLIBCPP_HAVE_ICONV_OPEN */
+
+/* Define if you have the isinf function. */
+#define _GLIBCPP_HAVE_ISINF 1
+
+/* Define if you have the isinff function. */
+/* #undef _GLIBCPP_HAVE_ISINFF */
+
+/* Define if you have the isinfl function. */
+/* #undef _GLIBCPP_HAVE_ISINFL */
+
+/* Define if you have the isnan function. */
+#define _GLIBCPP_HAVE_ISNAN 1
+
+/* Define if you have the isnanf function. */
+#define _GLIBCPP_HAVE_ISNANF 1
+
+/* Define if you have the isnanl function. */
+/* #undef _GLIBCPP_HAVE_ISNANL */
+
+/* Define if you have the ldexpf function. */
+#define _GLIBCPP_HAVE_LDEXPF 1
+
+/* Define if you have the ldexpl function. */
+/* #undef _GLIBCPP_HAVE_LDEXPL */
+
+/* Define if you have the log10f function. */
+#define _GLIBCPP_HAVE_LOG10F 1
+
+/* Define if you have the log10l function. */
+/* #undef _GLIBCPP_HAVE_LOG10L */
+
+/* Define if you have the logf function. */
+#define _GLIBCPP_HAVE_LOGF 1
+
+/* Define if you have the logl function. */
+/* #undef _GLIBCPP_HAVE_LOGL */
+
+/* Define if you have the mbrlen function. */
+/* #undef _GLIBCPP_HAVE_MBRLEN */
+
+/* Define if you have the mbrtowc function. */
+/* #undef _GLIBCPP_HAVE_MBRTOWC */
+
+/* Define if you have the mbsinit function. */
+/* #undef _GLIBCPP_HAVE_MBSINIT */
+
+/* Define if you have the mbsrtowcs function. */
+/* #undef _GLIBCPP_HAVE_MBSRTOWCS */
+
+/* Define if you have the modff function. */
+#define _GLIBCPP_HAVE_MODFF 1
+
+/* Define if you have the modfl function. */
+/* #undef _GLIBCPP_HAVE_MODFL */
+
+/* Define if you have the nan function. */
+/* #undef _GLIBCPP_HAVE_NAN */
+
+/* Define if you have the nl_langinfo function. */
+#define _GLIBCPP_HAVE_NL_LANGINFO 1
+
+/* Define if you have the powf function. */
+#define _GLIBCPP_HAVE_POWF 1
+
+/* Define if you have the powl function. */
+/* #undef _GLIBCPP_HAVE_POWL */
+
+/* Define if you have the putwc function. */
+/* #undef _GLIBCPP_HAVE_PUTWC */
+
+/* Define if you have the putwchar function. */
+/* #undef _GLIBCPP_HAVE_PUTWCHAR */
+
+/* Define if you have the qfpclass function. */
+/* #undef _GLIBCPP_HAVE_QFPCLASS */
+
+/* Define if you have the setenv function. */
+#define _GLIBCPP_HAVE_SETENV 1
+
+/* Define if you have the sincos function. */
+/* #undef _GLIBCPP_HAVE_SINCOS */
+
+/* Define if you have the sincosf function. */
+/* #undef _GLIBCPP_HAVE_SINCOSF */
+
+/* Define if you have the sincosl function. */
+/* #undef _GLIBCPP_HAVE_SINCOSL */
+
+/* Define if you have the sinf function. */
+#define _GLIBCPP_HAVE_SINF 1
+
+/* Define if you have the sinhf function. */
+#define _GLIBCPP_HAVE_SINHF 1
+
+/* Define if you have the sinhl function. */
+/* #undef _GLIBCPP_HAVE_SINHL */
+
+/* Define if you have the sinl function. */
+/* #undef _GLIBCPP_HAVE_SINL */
+
+/* Define if you have the sqrtf function. */
+#define _GLIBCPP_HAVE_SQRTF 1
+
+/* Define if you have the sqrtl function. */
+/* #undef _GLIBCPP_HAVE_SQRTL */
+
+/* Define if you have the strtof function. */
+/* #undef _GLIBCPP_HAVE_STRTOF */
+
+/* Define if you have the strtold function. */
+/* #undef _GLIBCPP_HAVE_STRTOLD */
+
+/* Define if you have the swprintf function. */
+/* #undef _GLIBCPP_HAVE_SWPRINTF */
+
+/* Define if you have the swscanf function. */
+/* #undef _GLIBCPP_HAVE_SWSCANF */
+
+/* Define if you have the tanf function. */
+#define _GLIBCPP_HAVE_TANF 1
+
+/* Define if you have the tanhf function. */
+#define _GLIBCPP_HAVE_TANHF 1
+
+/* Define if you have the tanhl function. */
+/* #undef _GLIBCPP_HAVE_TANHL */
+
+/* Define if you have the tanl function. */
+/* #undef _GLIBCPP_HAVE_TANL */
+
+/* Define if you have the ungetwc function. */
+/* #undef _GLIBCPP_HAVE_UNGETWC */
+
+/* Define if you have the vfwprintf function. */
+/* #undef _GLIBCPP_HAVE_VFWPRINTF */
+
+/* Define if you have the vfwscanf function. */
+/* #undef _GLIBCPP_HAVE_VFWSCANF */
+
+/* Define if you have the vswprintf function. */
+/* #undef _GLIBCPP_HAVE_VSWPRINTF */
+
+/* Define if you have the vswscanf function. */
+/* #undef _GLIBCPP_HAVE_VSWSCANF */
+
+/* Define if you have the vwprintf function. */
+/* #undef _GLIBCPP_HAVE_VWPRINTF */
+
+/* Define if you have the vwscanf function. */
+/* #undef _GLIBCPP_HAVE_VWSCANF */
+
+/* Define if you have the wcrtomb function. */
+/* #undef _GLIBCPP_HAVE_WCRTOMB */
+
+/* Define if you have the wcscat function. */
+#define _GLIBCPP_HAVE_WCSCAT 1
+
+/* Define if you have the wcschr function. */
+#define _GLIBCPP_HAVE_WCSCHR 1
+
+/* Define if you have the wcscmp function. */
+#define _GLIBCPP_HAVE_WCSCMP 1
+
+/* Define if you have the wcscoll function. */
+/* #undef _GLIBCPP_HAVE_WCSCOLL */
+
+/* Define if you have the wcscpy function. */
+#define _GLIBCPP_HAVE_WCSCPY 1
+
+/* Define if you have the wcscspn function. */
+#define _GLIBCPP_HAVE_WCSCSPN 1
+
+/* Define if you have the wcsftime function. */
+/* #undef _GLIBCPP_HAVE_WCSFTIME */
+
+/* Define if you have the wcslen function. */
+#define _GLIBCPP_HAVE_WCSLEN 1
+
+/* Define if you have the wcsncat function. */
+#define _GLIBCPP_HAVE_WCSNCAT 1
+
+/* Define if you have the wcsncmp function. */
+#define _GLIBCPP_HAVE_WCSNCMP 1
+
+/* Define if you have the wcsncpy function. */
+#define _GLIBCPP_HAVE_WCSNCPY 1
+
+/* Define if you have the wcspbrk function. */
+#define _GLIBCPP_HAVE_WCSPBRK 1
+
+/* Define if you have the wcsrchr function. */
+#define _GLIBCPP_HAVE_WCSRCHR 1
+
+/* Define if you have the wcsrtombs function. */
+/* #undef _GLIBCPP_HAVE_WCSRTOMBS */
+
+/* Define if you have the wcsspn function. */
+#define _GLIBCPP_HAVE_WCSSPN 1
+
+/* Define if you have the wcsstr function. */
+#define _GLIBCPP_HAVE_WCSSTR 1
+
+/* Define if you have the wcstod function. */
+/* #undef _GLIBCPP_HAVE_WCSTOD */
+
+/* Define if you have the wcstof function. */
+/* #undef _GLIBCPP_HAVE_WCSTOF */
+
+/* Define if you have the wcstok function. */
+/* #undef _GLIBCPP_HAVE_WCSTOK */
+
+/* Define if you have the wcstol function. */
+/* #undef _GLIBCPP_HAVE_WCSTOL */
+
+/* Define if you have the wcstoul function. */
+/* #undef _GLIBCPP_HAVE_WCSTOUL */
+
+/* Define if you have the wcsxfrm function. */
+/* #undef _GLIBCPP_HAVE_WCSXFRM */
+
+/* Define if you have the wctob function. */
+/* #undef _GLIBCPP_HAVE_WCTOB */
+
+/* Define if you have the wmemchr function. */
+#define _GLIBCPP_HAVE_WMEMCHR 1
+
+/* Define if you have the wmemcmp function. */
+#define _GLIBCPP_HAVE_WMEMCMP 1
+
+/* Define if you have the wmemcpy function. */
+#define _GLIBCPP_HAVE_WMEMCPY 1
+
+/* Define if you have the wmemmove function. */
+#define _GLIBCPP_HAVE_WMEMMOVE 1
+
+/* Define if you have the wmemset function. */
+#define _GLIBCPP_HAVE_WMEMSET 1
+
+/* Define if you have the wprintf function. */
+/* #undef _GLIBCPP_HAVE_WPRINTF */
+
+/* Define if you have the wscanf function. */
+/* #undef _GLIBCPP_HAVE_WSCANF */
+
+/* Define if you have the <endian.h> header file. */
+/* #undef _GLIBCPP_HAVE_ENDIAN_H */
+
+/* Define if you have the <float.h> header file. */
+#define _GLIBCPP_HAVE_FLOAT_H 1
+
+/* Define if you have the <fp.h> header file. */
+/* #undef _GLIBCPP_HAVE_FP_H */
+
+/* Define if you have the <gconv.h> header file. */
+/* #undef _GLIBCPP_HAVE_GCONV_H */
+
+/* Define if you have the <ieeefp.h> header file. */
+#define _GLIBCPP_HAVE_IEEEFP_H 1
+
+/* Define if you have the <inttypes.h> header file. */
+#define _GLIBCPP_HAVE_INTTYPES_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define _GLIBCPP_HAVE_LOCALE_H 1
+
+/* Define if you have the <machine/endian.h> header file. */
+#define _GLIBCPP_HAVE_MACHINE_ENDIAN_H 1
+
+/* Define if you have the <machine/param.h> header file. */
+#define _GLIBCPP_HAVE_MACHINE_PARAM_H 1
+
+/* Define if you have the <nan.h> header file. */
+/* #undef _GLIBCPP_HAVE_NAN_H */
+
+/* Define if you have the <stdlib.h> header file. */
+/* #undef _GLIBCPP_HAVE_STDLIB_H */
+
+/* Define if you have the <sys/isa_defs.h> header file. */
+/* #undef _GLIBCPP_HAVE_SYS_ISA_DEFS_H */
+
+/* Define if you have the <sys/machine.h> header file. */
+/* #undef _GLIBCPP_HAVE_SYS_MACHINE_H */
+
+/* Define if you have the <sys/resource.h> header file. */
+#define _GLIBCPP_HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+/* #undef _GLIBCPP_HAVE_SYS_STAT_H */
+
+/* Define if you have the <sys/types.h> header file. */
+/* #undef _GLIBCPP_HAVE_SYS_TYPES_H */
+
+/* Define if you have the <unistd.h> header file. */
+#define _GLIBCPP_HAVE_UNISTD_H 1
+
+/* Define if you have the <wchar.h> header file. */
+#define _GLIBCPP_HAVE_WCHAR_H 1
+
+/* Define if you have the <wctype.h> header file. */
+#define _GLIBCPP_HAVE_WCTYPE_H 1
+
+/* Define if you have the m library (-lm). */
+#define _GLIBCPP_HAVE_LIBM 1
+
+/* Name of package */
+#define _GLIBCPP_PACKAGE "libstdc++"
+
+/* Version number of package */
+#define _GLIBCPP_VERSION "3.1.0"
+
+/* Define if the compiler is configured for setjmp/longjmp exceptions. */
+/* #undef _GLIBCPP_SJLJ_EXCEPTIONS */
+
+/* Define if sigsetjmp is available. */
+#define _GLIBCPP_HAVE_SIGSETJMP 1
+
+/* Only used in build directory testsuite_hooks.h. */
+#define _GLIBCPP_HAVE_MEMLIMIT_DATA 0
+
+/* Only used in build directory testsuite_hooks.h. */
+#define _GLIBCPP_HAVE_MEMLIMIT_RSS 0
+
+/* Only used in build directory testsuite_hooks.h. */
+#define _GLIBCPP_HAVE_MEMLIMIT_VMEM 0
+
+/* Only used in build directory testsuite_hooks.h. */
+#define _GLIBCPP_HAVE_MEMLIMIT_AS 0
+
+//
+// Systems that have certain non-standard functions prefixed with an
+// underscore, we'll handle those here. Must come after config.h.in.
+//
+#if defined (_GLIBCPP_HAVE__ISNAN) && ! defined (_GLIBCPP_HAVE_ISNAN)
+# define _GLIBCPP_HAVE_ISNAN 1
+# define isnan _isnan
+#endif
+
+#if defined (_GLIBCPP_HAVE__ISNANF) && ! defined (_GLIBCPP_HAVE_ISNANF)
+# define _GLIBCPP_HAVE_ISNANF 1
+# define isnanf _isnanf
+#endif
+
+#if defined (_GLIBCPP_HAVE__ISNANL) && ! defined (_GLIBCPP_HAVE_ISNANL)
+# define _GLIBCPP_HAVE_ISNANL 1
+# define isnanl _isnanl
+#endif
+
+#if defined (_GLIBCPP_HAVE__ISINF) && ! defined (_GLIBCPP_HAVE_ISINF)
+# define _GLIBCPP_HAVE_ISINF 1
+# define isinf _isinf
+#endif
+
+#if defined (_GLIBCPP_HAVE__ISINFF) && ! defined (_GLIBCPP_HAVE_ISINFF)
+# define _GLIBCPP_HAVE_ISINFF 1
+# define isinff _isinff
+#endif
+
+#if defined (_GLIBCPP_HAVE__ISINFL) && ! defined (_GLIBCPP_HAVE_ISINFL)
+# define _GLIBCPP_HAVE_ISINFL 1
+# define isinfl _isinfl
+#endif
+
+#if defined (_GLIBCPP_HAVE__COPYSIGN) && ! defined (_GLIBCPP_HAVE_COPYSIGN)
+# define _GLIBCPP_HAVE_COPYSIGN 1
+# define copysign _copysign
+#endif
+
+#if defined (_GLIBCPP_HAVE__COPYSIGNL) && ! defined (_GLIBCPP_HAVE_COPYSIGNL)
+# define _GLIBCPP_HAVE_COPYSIGNL 1
+# define copysignl _copysignl
+#endif
+
+#if defined (_GLIBCPP_HAVE__COSF) && ! defined (_GLIBCPP_HAVE_COSF)
+# define _GLIBCPP_HAVE_COSF 1
+# define cosf _cosf
+#endif
+
+#if defined (_GLIBCPP_HAVE__ACOSF) && ! defined (_GLIBCPP_HAVE_ACOSF)
+# define _GLIBCPP_HAVE_ACOSF 1
+# define acosf _acosf
+#endif
+
+#if defined (_GLIBCPP_HAVE__ACOSL) && ! defined (_GLIBCPP_HAVE_ACOSL)
+# define _GLIBCPP_HAVE_ACOSL 1
+# define acosl _acosl
+#endif
+
+#if defined (_GLIBCPP_HAVE__ASINF) && ! defined (_GLIBCPP_HAVE_ASINF)
+# define _GLIBCPP_HAVE_ASINF 1
+# define asinf _asinf
+#endif
+
+#if defined (_GLIBCPP_HAVE__ASINL) && ! defined (_GLIBCPP_HAVE_ASINL)
+# define _GLIBCPP_HAVE_ASINL 1
+# define asinl _asinl
+#endif
+
+#if defined (_GLIBCPP_HAVE__ATANF) && ! defined (_GLIBCPP_HAVE_ATANF)
+# define _GLIBCPP_HAVE_ATANF 1
+# define atanf _atanf
+#endif
+
+#if defined (_GLIBCPP_HAVE__ATANL) && ! defined (_GLIBCPP_HAVE_ATANL)
+# define _GLIBCPP_HAVE_ATANL 1
+# define atanl _atanl
+#endif
+
+#if defined (_GLIBCPP_HAVE__CEILF) && ! defined (_GLIBCPP_HAVE_CEILF)
+# define _GLIBCPP_HAVE_CEILF 1
+# define aceil _ceilf
+#endif
+
+#if defined (_GLIBCPP_HAVE__CEILL) && ! defined (_GLIBCPP_HAVE_CEILL)
+# define _GLIBCPP_HAVE_CEILL 1
+# define aceil _ceill
+#endif
+
+#if defined (_GLIBCPP_HAVE__COSHF) && ! defined (_GLIBCPP_HAVE_COSHF)
+# define _GLIBCPP_HAVE_COSHF 1
+# define coshf _coshf
+#endif
+
+#if defined (_GLIBCPP_HAVE__COSL) && ! defined (_GLIBCPP_HAVE_COSL)
+# define _GLIBCPP_HAVE_COSL 1
+# define cosl _cosl
+#endif
+
+#if defined (_GLIBCPP_HAVE__LOGF) && ! defined (_GLIBCPP_HAVE_LOGF)
+# define _GLIBCPP_HAVE_LOGF 1
+# define logf _logf
+#endif
+
+#if defined (_GLIBCPP_HAVE__COSHL) && ! defined (_GLIBCPP_HAVE_COSHL)
+# define _GLIBCPP_HAVE_COSHL 1
+# define coshl _coshl
+#endif
+
+#if defined (_GLIBCPP_HAVE__EXPF) && ! defined (_GLIBCPP_HAVE_EXPF)
+# define _GLIBCPP_HAVE_EXPF 1
+# define expf _expf
+#endif
+
+#if defined (_GLIBCPP_HAVE__EXPL) && ! defined (_GLIBCPP_HAVE_EXPL)
+# define _GLIBCPP_HAVE_EXPL 1
+# define expl _expl
+#endif
+
+#if defined (_GLIBCPP_HAVE__FABSF) && ! defined (_GLIBCPP_HAVE_FABSF)
+# define _GLIBCPP_HAVE_FABSF 1
+# define fabsf _fabsf
+#endif
+
+#if defined (_GLIBCPP_HAVE__FABSL) && ! defined (_GLIBCPP_HAVE_FABSL)
+# define _GLIBCPP_HAVE_FABSL 1
+# define fabsl _fabsl
+#endif
+
+#if defined (_GLIBCPP_HAVE__FLOORF) && ! defined (_GLIBCPP_HAVE_FLOORF)
+# define _GLIBCPP_HAVE_FLOORF 1
+# define floorf _floorf
+#endif
+
+#if defined (_GLIBCPP_HAVE__FLOORL) && ! defined (_GLIBCPP_HAVE_FLOORL)
+# define _GLIBCPP_HAVE_FLOORL 1
+# define floorl _floorl
+#endif
+
+#if defined (_GLIBCPP_HAVE__FMODF) && ! defined (_GLIBCPP_HAVE_FMODF)
+# define _GLIBCPP_HAVE_FMODF 1
+# define fmodf _fmodf
+#endif
+
+#if defined (_GLIBCPP_HAVE__FMODL) && ! defined (_GLIBCPP_HAVE_FMODL)
+# define _GLIBCPP_HAVE_FMODL 1
+# define fmodl _fmodl
+#endif
+
+#if defined (_GLIBCPP_HAVE__FREXPF) && ! defined (_GLIBCPP_HAVE_FREXPF)
+# define _GLIBCPP_HAVE_FREXPF 1
+# define frexpf _frexpf
+#endif
+
+#if defined (_GLIBCPP_HAVE__FREXPL) && ! defined (_GLIBCPP_HAVE_FREXPL)
+# define _GLIBCPP_HAVE_FREXPL 1
+# define frexpl _frexpl
+#endif
+
+#if defined (_GLIBCPP_HAVE__LDEXPF) && ! defined (_GLIBCPP_HAVE_LDEXPF)
+# define _GLIBCPP_HAVE_LDEXPF 1
+# define ldexpf _ldexpf
+#endif
+
+#if defined (_GLIBCPP_HAVE__LDEXPL) && ! defined (_GLIBCPP_HAVE_LDEXPL)
+# define _GLIBCPP_HAVE_LDEXPL 1
+# define ldexpl _ldexpl
+#endif
+
+#if defined (_GLIBCPP_HAVE__LOG10F) && ! defined (_GLIBCPP_HAVE_LOG10F)
+# define _GLIBCPP_HAVE_LOG10F 1
+# define log10f _log10f
+#endif
+
+#if defined (_GLIBCPP_HAVE__LOGL) && ! defined (_GLIBCPP_HAVE_LOGL)
+# define _GLIBCPP_HAVE_LOGL 1
+# define logl _logl
+#endif
+
+#if defined (_GLIBCPP_HAVE__POWF) && ! defined (_GLIBCPP_HAVE_POWF)
+# define _GLIBCPP_HAVE_POWF 1
+# define powf _powf
+#endif
+
+#if defined (_GLIBCPP_HAVE__LOG10L) && ! defined (_GLIBCPP_HAVE_LOG10L)
+# define _GLIBCPP_HAVE_LOG10L 1
+# define log10l _log10l
+#endif
+
+#if defined (_GLIBCPP_HAVE__MODF) && ! defined (_GLIBCPP_HAVE_MODF)
+# define _GLIBCPP_HAVE_MODF 1
+# define modf _modf
+#endif
+
+#if defined (_GLIBCPP_HAVE__MODL) && ! defined (_GLIBCPP_HAVE_MODL)
+# define _GLIBCPP_HAVE_MODL 1
+# define modl _modl
+#endif
+
+#if defined (_GLIBCPP_HAVE__SINF) && ! defined (_GLIBCPP_HAVE_SINF)
+# define _GLIBCPP_HAVE_SINF 1
+# define sinf _sinf
+#endif
+
+#if defined (_GLIBCPP_HAVE__POWL) && ! defined (_GLIBCPP_HAVE_POWL)
+# define _GLIBCPP_HAVE_POWL 1
+# define powl _powl
+#endif
+
+#if defined (_GLIBCPP_HAVE__SINHF) && ! defined (_GLIBCPP_HAVE_SINHF)
+# define _GLIBCPP_HAVE_SINHF 1
+# define sinhf _sinhf
+#endif
+
+#if defined (_GLIBCPP_HAVE__SINL) && ! defined (_GLIBCPP_HAVE_SINL)
+# define _GLIBCPP_HAVE_SINL 1
+# define sinl _sinl
+#endif
+
+#if defined (_GLIBCPP_HAVE__SQRTF) && ! defined (_GLIBCPP_HAVE_SQRTF)
+# define _GLIBCPP_HAVE_SQRTF 1
+# define sqrtf _sqrtf
+#endif
+
+#if defined (_GLIBCPP_HAVE__SINHL) && ! defined (_GLIBCPP_HAVE_SINHL)
+# define _GLIBCPP_HAVE_SINHL 1
+# define sinhl _sinhl
+#endif
+
+#if defined (_GLIBCPP_HAVE__TANF) && ! defined (_GLIBCPP_HAVE_TANF)
+# define _GLIBCPP_HAVE_TANF 1
+# define tanf _tanf
+#endif
+
+#if defined (_GLIBCPP_HAVE__SQRTL) && ! defined (_GLIBCPP_HAVE_SQRTL)
+# define _GLIBCPP_HAVE_SQRTL 1
+# define sqrtl _sqrtl
+#endif
+
+#if defined (_GLIBCPP_HAVE__TANHF) && ! defined (_GLIBCPP_HAVE_TANHF)
+# define _GLIBCPP_HAVE_TANHF 1
+# define tanhf _tanhf
+#endif
+
+#if defined (_GLIBCPP_HAVE__TANL) && ! defined (_GLIBCPP_HAVE_TANL)
+# define _GLIBCPP_HAVE_TANF 1
+# define tanf _tanf
+#endif
+
+#if defined (_GLIBCPP_HAVE__STRTOF) && ! defined (_GLIBCPP_HAVE_STRTOF)
+# define _GLIBCPP_HAVE_STRTOF 1
+# define strtof _strtof
+#endif
+
+#if defined (_GLIBCPP_HAVE__TANHL) && ! defined (_GLIBCPP_HAVE_TANHL)
+# define _GLIBCPP_HAVE_TANHL 1
+# define tanhl _tanhl
+#endif
+
+#if defined (_GLIBCPP_HAVE__STRTOLD) && ! defined (_GLIBCPP_HAVE_STRTOLD)
+# define _GLIBCPP_HAVE_STRTOLD 1
+# define strtold _strtold
+#endif
+
+#if defined (_GLIBCPP_HAVE__SINCOS) && ! defined (_GLIBCPP_HAVE_SINCOS)
+# define _GLIBCPP_HAVE_SINCOS 1
+# define sincos _sincos
+#endif
+
+#if defined (_GLIBCPP_HAVE__SINCOSF) && ! defined (_GLIBCPP_HAVE_SINCOSF)
+# define _GLIBCPP_HAVE_SINCOSF 1
+# define sincosf _sincosf
+#endif
+
+#if defined (_GLIBCPP_HAVE__SINCOSL) && ! defined (_GLIBCPP_HAVE_SINCOSL)
+# define _GLIBCPP_HAVE_SINCOSL 1
+# define sincosl _sincosl
+#endif
+
+#if defined (_GLIBCPP_HAVE__FINITE) && ! defined (_GLIBCPP_HAVE_FINITE)
+# define _GLIBCPP_HAVE_FINITE 1
+# define finite _finite
+#endif
+
+#if defined (_GLIBCPP_HAVE__FINITEF) && ! defined (_GLIBCPP_HAVE_FINITEF)
+# define _GLIBCPP_HAVE_FINITEF 1
+# define finitef _finitef
+#endif
+
+#if defined (_GLIBCPP_HAVE__FINITEL) && ! defined (_GLIBCPP_HAVE_FINITEL)
+# define _GLIBCPP_HAVE_FINITEL 1
+# define finitel _finitel
+#endif
+
+#if defined (_GLIBCPP_HAVE__QFINITE) && ! defined (_GLIBCPP_HAVE_QFINITE)
+# define _GLIBCPP_HAVE_QFINITE 1
+# define qfinite _qfinite
+#endif
+
+#if defined (_GLIBCPP_HAVE__FPCLASS) && ! defined (_GLIBCPP_HAVE_FPCLASS)
+# define _GLIBCPP_HAVE_FPCLASS 1
+# define fpclass _fpclass
+#endif
+
+#if defined (_GLIBCPP_HAVE__QFPCLASS) && ! defined (_GLIBCPP_HAVE_QFPCLASS)
+# define _GLIBCPP_HAVE_QFPCLASS 1
+# define qfpclass _qfpclass
+#endif
+
+#endif // _CPP_CPPCONFIG_
diff --git a/gnu/lib/libstdc++/config.h b/gnu/lib/libstdc++/config.h
new file mode 100644
index 0000000..645d0ac
--- /dev/null
+++ b/gnu/lib/libstdc++/config.h
@@ -0,0 +1,1076 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+// Define if GCC supports weak symbols.
+#define _GLIBCPP_SUPPORTS_WEAK __GXX_WEAK__
+
+// Define if gthr-default.h exists (meaning that threading support is enabled).
+#define HAVE_GTHR_DEFAULT 1
+
+// Include I/O support for 'long long' and 'unsigned long long'.
+#define _GLIBCPP_USE_LONG_LONG 1
+
+// Define if C99 features such as lldiv_t, llabs, lldiv should be exposed.
+/* #undef _GLIBCPP_USE_C99 */
+
+// Define if code specialized for wchar_t should be used.
+/* #undef _GLIBCPP_USE_WCHAR_T */
+
+// Define if using setrlimit to limit memory usage during 'make check'.
+/* #undef _GLIBCPP_MEM_LIMITS */
+
+// Define to use concept checking code from the boost libraries.
+/* #undef _GLIBCPP_CONCEPT_CHECKS */
+
+// Define if mbstate_t exists in wchar.h.
+#define HAVE_MBSTATE_T 1
+
+// Define if you have the modff function.
+#define HAVE_MODFF 1
+
+// Define if you have the modfl function.
+/* #undef HAVE_MODFL */
+
+// Define if you have the expf function.
+#define HAVE_EXPF 1
+
+// Define if you have the expl function.
+/* #undef HAVE_EXPL */
+
+// Define if you have the hypotf function.
+#define HAVE_HYPOTF 1
+
+// Define if you have the hypotl function.
+/* #undef HAVE_HYPOTL */
+
+// Define if the compiler/host combination has __builtin_abs
+#define HAVE___BUILTIN_ABS 1
+
+// Define if the compiler/host combination has __builtin_labs
+#define HAVE___BUILTIN_LABS 1
+
+// Define if the compiler/host combination has __builtin_cos
+/* #undef HAVE___BUILTIN_COS */
+
+// Define if the compiler/host combination has __builtin_cosf
+/* #undef HAVE___BUILTIN_COSF */
+
+// Define if the compiler/host combination has __builtin_cosl
+/* #undef HAVE___BUILTIN_COSL */
+
+// Define if the compiler/host combination has __builtin_fabs
+#define HAVE___BUILTIN_FABS 1
+
+// Define if the compiler/host combination has __builtin_fabsf
+#define HAVE___BUILTIN_FABSF 1
+
+// Define if the compiler/host combination has __builtin_fabsl
+#define HAVE___BUILTIN_FABSL 1
+
+// Define if the compiler/host combination has __builtin_sin
+/* #undef HAVE___BUILTIN_SIN */
+
+// Define if the compiler/host combination has __builtin_sinf
+/* #undef HAVE___BUILTIN_SINF */
+
+// Define if the compiler/host combination has __builtin_sinl
+/* #undef HAVE___BUILTIN_SINL */
+
+// Define if the compiler/host combination has __builtin_sqrt
+/* #undef HAVE___BUILTIN_SQRT */
+
+// Define if the compiler/host combination has __builtin_sqrtf
+/* #undef HAVE___BUILTIN_SQRTF */
+
+// Define if the compiler/host combination has __builtin_sqrtl
+/* #undef HAVE___BUILTIN_SQRTL */
+
+// Define if LC_MESSAGES is available in <locale.h>.
+#define HAVE_LC_MESSAGES 1
+
+/* Define if you have the __signbit function. */
+/* #undef HAVE___SIGNBIT */
+
+/* Define if you have the __signbitf function. */
+/* #undef HAVE___SIGNBITF */
+
+/* Define if you have the __signbitl function. */
+/* #undef HAVE___SIGNBITL */
+
+/* Define if you have the _acosf function. */
+/* #undef HAVE__ACOSF */
+
+/* Define if you have the _acosl function. */
+/* #undef HAVE__ACOSL */
+
+/* Define if you have the _asinf function. */
+/* #undef HAVE__ASINF */
+
+/* Define if you have the _asinl function. */
+/* #undef HAVE__ASINL */
+
+/* Define if you have the _atan2f function. */
+/* #undef HAVE__ATAN2F */
+
+/* Define if you have the _atan2l function. */
+/* #undef HAVE__ATAN2L */
+
+/* Define if you have the _atanf function. */
+/* #undef HAVE__ATANF */
+
+/* Define if you have the _atanl function. */
+/* #undef HAVE__ATANL */
+
+/* Define if you have the _ceilf function. */
+/* #undef HAVE__CEILF */
+
+/* Define if you have the _ceill function. */
+/* #undef HAVE__CEILL */
+
+/* Define if you have the _copysign function. */
+/* #undef HAVE__COPYSIGN */
+
+/* Define if you have the _copysignl function. */
+/* #undef HAVE__COPYSIGNL */
+
+/* Define if you have the _cosf function. */
+/* #undef HAVE__COSF */
+
+/* Define if you have the _coshf function. */
+/* #undef HAVE__COSHF */
+
+/* Define if you have the _coshl function. */
+/* #undef HAVE__COSHL */
+
+/* Define if you have the _cosl function. */
+/* #undef HAVE__COSL */
+
+/* Define if you have the _expf function. */
+/* #undef HAVE__EXPF */
+
+/* Define if you have the _expl function. */
+/* #undef HAVE__EXPL */
+
+/* Define if you have the _fabsf function. */
+/* #undef HAVE__FABSF */
+
+/* Define if you have the _fabsl function. */
+/* #undef HAVE__FABSL */
+
+/* Define if you have the _finite function. */
+/* #undef HAVE__FINITE */
+
+/* Define if you have the _finitef function. */
+/* #undef HAVE__FINITEF */
+
+/* Define if you have the _finitel function. */
+/* #undef HAVE__FINITEL */
+
+/* Define if you have the _floorf function. */
+/* #undef HAVE__FLOORF */
+
+/* Define if you have the _floorl function. */
+/* #undef HAVE__FLOORL */
+
+/* Define if you have the _fmodf function. */
+/* #undef HAVE__FMODF */
+
+/* Define if you have the _fmodl function. */
+/* #undef HAVE__FMODL */
+
+/* Define if you have the _fpclass function. */
+/* #undef HAVE__FPCLASS */
+
+/* Define if you have the _frexpf function. */
+/* #undef HAVE__FREXPF */
+
+/* Define if you have the _frexpl function. */
+/* #undef HAVE__FREXPL */
+
+/* Define if you have the _hypot function. */
+/* #undef HAVE__HYPOT */
+
+/* Define if you have the _hypotf function. */
+/* #undef HAVE__HYPOTF */
+
+/* Define if you have the _hypotl function. */
+/* #undef HAVE__HYPOTL */
+
+/* Define if you have the _isinf function. */
+/* #undef HAVE__ISINF */
+
+/* Define if you have the _isinff function. */
+/* #undef HAVE__ISINFF */
+
+/* Define if you have the _isinfl function. */
+/* #undef HAVE__ISINFL */
+
+/* Define if you have the _isnan function. */
+/* #undef HAVE__ISNAN */
+
+/* Define if you have the _isnanf function. */
+/* #undef HAVE__ISNANF */
+
+/* Define if you have the _isnanl function. */
+/* #undef HAVE__ISNANL */
+
+/* Define if you have the _ldexpf function. */
+/* #undef HAVE__LDEXPF */
+
+/* Define if you have the _ldexpl function. */
+/* #undef HAVE__LDEXPL */
+
+/* Define if you have the _log10f function. */
+/* #undef HAVE__LOG10F */
+
+/* Define if you have the _log10l function. */
+/* #undef HAVE__LOG10L */
+
+/* Define if you have the _logf function. */
+/* #undef HAVE__LOGF */
+
+/* Define if you have the _logl function. */
+/* #undef HAVE__LOGL */
+
+/* Define if you have the _modff function. */
+/* #undef HAVE__MODFF */
+
+/* Define if you have the _modfl function. */
+/* #undef HAVE__MODFL */
+
+/* Define if you have the _powf function. */
+/* #undef HAVE__POWF */
+
+/* Define if you have the _powl function. */
+/* #undef HAVE__POWL */
+
+/* Define if you have the _qfpclass function. */
+/* #undef HAVE__QFPCLASS */
+
+/* Define if you have the _sincos function. */
+/* #undef HAVE__SINCOS */
+
+/* Define if you have the _sincosf function. */
+/* #undef HAVE__SINCOSF */
+
+/* Define if you have the _sincosl function. */
+/* #undef HAVE__SINCOSL */
+
+/* Define if you have the _sinf function. */
+/* #undef HAVE__SINF */
+
+/* Define if you have the _sinhf function. */
+/* #undef HAVE__SINHF */
+
+/* Define if you have the _sinhl function. */
+/* #undef HAVE__SINHL */
+
+/* Define if you have the _sinl function. */
+/* #undef HAVE__SINL */
+
+/* Define if you have the _sqrtf function. */
+/* #undef HAVE__SQRTF */
+
+/* Define if you have the _sqrtl function. */
+/* #undef HAVE__SQRTL */
+
+/* Define if you have the _tanf function. */
+/* #undef HAVE__TANF */
+
+/* Define if you have the _tanhf function. */
+/* #undef HAVE__TANHF */
+
+/* Define if you have the _tanhl function. */
+/* #undef HAVE__TANHL */
+
+/* Define if you have the _tanl function. */
+/* #undef HAVE__TANL */
+
+/* Define if you have the acosf function. */
+#define HAVE_ACOSF 1
+
+/* Define if you have the acosl function. */
+/* #undef HAVE_ACOSL */
+
+/* Define if you have the asinf function. */
+#define HAVE_ASINF 1
+
+/* Define if you have the asinl function. */
+/* #undef HAVE_ASINL */
+
+/* Define if you have the atan2f function. */
+#define HAVE_ATAN2F 1
+
+/* Define if you have the atan2l function. */
+/* #undef HAVE_ATAN2L */
+
+/* Define if you have the atanf function. */
+#define HAVE_ATANF 1
+
+/* Define if you have the atanl function. */
+/* #undef HAVE_ATANL */
+
+/* Define if you have the btowc function. */
+/* #undef HAVE_BTOWC */
+
+/* Define if you have the ceilf function. */
+#define HAVE_CEILF 1
+
+/* Define if you have the ceill function. */
+/* #undef HAVE_CEILL */
+
+/* Define if you have the copysign function. */
+#define HAVE_COPYSIGN 1
+
+/* Define if you have the copysignf function. */
+#define HAVE_COPYSIGNF 1
+
+/* Define if you have the copysignl function. */
+/* #undef HAVE_COPYSIGNL */
+
+/* Define if you have the cosf function. */
+#define HAVE_COSF 1
+
+/* Define if you have the coshf function. */
+#define HAVE_COSHF 1
+
+/* Define if you have the coshl function. */
+/* #undef HAVE_COSHL */
+
+/* Define if you have the cosl function. */
+/* #undef HAVE_COSL */
+
+/* Define if you have the drand48 function. */
+#define HAVE_DRAND48 1
+
+/* Define if you have the expf function. */
+#define HAVE_EXPF 1
+
+/* Define if you have the expl function. */
+/* #undef HAVE_EXPL */
+
+/* Define if you have the fabsf function. */
+#define HAVE_FABSF 1
+
+/* Define if you have the fabsl function. */
+/* #undef HAVE_FABSL */
+
+/* Define if you have the fgetwc function. */
+/* #undef HAVE_FGETWC */
+
+/* Define if you have the fgetws function. */
+/* #undef HAVE_FGETWS */
+
+/* Define if you have the finite function. */
+#define HAVE_FINITE 1
+
+/* Define if you have the finitef function. */
+#define HAVE_FINITEF 1
+
+/* Define if you have the finitel function. */
+/* #undef HAVE_FINITEL */
+
+/* Define if you have the floorf function. */
+#define HAVE_FLOORF 1
+
+/* Define if you have the floorl function. */
+/* #undef HAVE_FLOORL */
+
+/* Define if you have the fmodf function. */
+#define HAVE_FMODF 1
+
+/* Define if you have the fmodl function. */
+/* #undef HAVE_FMODL */
+
+/* Define if you have the fpclass function. */
+/* #undef HAVE_FPCLASS */
+
+/* Define if you have the fputwc function. */
+/* #undef HAVE_FPUTWC */
+
+/* Define if you have the fputws function. */
+/* #undef HAVE_FPUTWS */
+
+/* Define if you have the frexpf function. */
+#define HAVE_FREXPF 1
+
+/* Define if you have the frexpl function. */
+/* #undef HAVE_FREXPL */
+
+/* Define if you have the fwide function. */
+/* #undef HAVE_FWIDE */
+
+/* Define if you have the fwprintf function. */
+/* #undef HAVE_FWPRINTF */
+
+/* Define if you have the fwscanf function. */
+/* #undef HAVE_FWSCANF */
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getwc function. */
+/* #undef HAVE_GETWC */
+
+/* Define if you have the getwchar function. */
+/* #undef HAVE_GETWCHAR */
+
+/* Define if you have the hypot function. */
+#define HAVE_HYPOT 1
+
+/* Define if you have the hypotf function. */
+#define HAVE_HYPOTF 1
+
+/* Define if you have the hypotl function. */
+/* #undef HAVE_HYPOTL */
+
+/* Define if you have the iconv function. */
+/* #undef HAVE_ICONV */
+
+/* Define if you have the iconv_close function. */
+/* #undef HAVE_ICONV_CLOSE */
+
+/* Define if you have the iconv_open function. */
+/* #undef HAVE_ICONV_OPEN */
+
+/* Define if you have the isinf function. */
+#define HAVE_ISINF 1
+
+/* Define if you have the isinff function. */
+/* #undef HAVE_ISINFF */
+
+/* Define if you have the isinfl function. */
+/* #undef HAVE_ISINFL */
+
+/* Define if you have the isnan function. */
+#define HAVE_ISNAN 1
+
+/* Define if you have the isnanf function. */
+#define HAVE_ISNANF 1
+
+/* Define if you have the isnanl function. */
+/* #undef HAVE_ISNANL */
+
+/* Define if you have the ldexpf function. */
+#define HAVE_LDEXPF 1
+
+/* Define if you have the ldexpl function. */
+/* #undef HAVE_LDEXPL */
+
+/* Define if you have the log10f function. */
+#define HAVE_LOG10F 1
+
+/* Define if you have the log10l function. */
+/* #undef HAVE_LOG10L */
+
+/* Define if you have the logf function. */
+#define HAVE_LOGF 1
+
+/* Define if you have the logl function. */
+/* #undef HAVE_LOGL */
+
+/* Define if you have the mbrlen function. */
+/* #undef HAVE_MBRLEN */
+
+/* Define if you have the mbrtowc function. */
+/* #undef HAVE_MBRTOWC */
+
+/* Define if you have the mbsinit function. */
+/* #undef HAVE_MBSINIT */
+
+/* Define if you have the mbsrtowcs function. */
+/* #undef HAVE_MBSRTOWCS */
+
+/* Define if you have the modff function. */
+#define HAVE_MODFF 1
+
+/* Define if you have the modfl function. */
+/* #undef HAVE_MODFL */
+
+/* Define if you have the nan function. */
+/* #undef HAVE_NAN */
+
+/* Define if you have the nl_langinfo function. */
+#define HAVE_NL_LANGINFO 1
+
+/* Define if you have the powf function. */
+#define HAVE_POWF 1
+
+/* Define if you have the powl function. */
+/* #undef HAVE_POWL */
+
+/* Define if you have the putwc function. */
+/* #undef HAVE_PUTWC */
+
+/* Define if you have the putwchar function. */
+/* #undef HAVE_PUTWCHAR */
+
+/* Define if you have the qfpclass function. */
+/* #undef HAVE_QFPCLASS */
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the sincos function. */
+/* #undef HAVE_SINCOS */
+
+/* Define if you have the sincosf function. */
+/* #undef HAVE_SINCOSF */
+
+/* Define if you have the sincosl function. */
+/* #undef HAVE_SINCOSL */
+
+/* Define if you have the sinf function. */
+#define HAVE_SINF 1
+
+/* Define if you have the sinhf function. */
+#define HAVE_SINHF 1
+
+/* Define if you have the sinhl function. */
+/* #undef HAVE_SINHL */
+
+/* Define if you have the sinl function. */
+/* #undef HAVE_SINL */
+
+/* Define if you have the sqrtf function. */
+#define HAVE_SQRTF 1
+
+/* Define if you have the sqrtl function. */
+/* #undef HAVE_SQRTL */
+
+/* Define if you have the strtof function. */
+/* #undef HAVE_STRTOF */
+
+/* Define if you have the strtold function. */
+/* #undef HAVE_STRTOLD */
+
+/* Define if you have the swprintf function. */
+/* #undef HAVE_SWPRINTF */
+
+/* Define if you have the swscanf function. */
+/* #undef HAVE_SWSCANF */
+
+/* Define if you have the tanf function. */
+#define HAVE_TANF 1
+
+/* Define if you have the tanhf function. */
+#define HAVE_TANHF 1
+
+/* Define if you have the tanhl function. */
+/* #undef HAVE_TANHL */
+
+/* Define if you have the tanl function. */
+/* #undef HAVE_TANL */
+
+/* Define if you have the ungetwc function. */
+/* #undef HAVE_UNGETWC */
+
+/* Define if you have the vfwprintf function. */
+/* #undef HAVE_VFWPRINTF */
+
+/* Define if you have the vfwscanf function. */
+/* #undef HAVE_VFWSCANF */
+
+/* Define if you have the vswprintf function. */
+/* #undef HAVE_VSWPRINTF */
+
+/* Define if you have the vswscanf function. */
+/* #undef HAVE_VSWSCANF */
+
+/* Define if you have the vwprintf function. */
+/* #undef HAVE_VWPRINTF */
+
+/* Define if you have the vwscanf function. */
+/* #undef HAVE_VWSCANF */
+
+/* Define if you have the wcrtomb function. */
+/* #undef HAVE_WCRTOMB */
+
+/* Define if you have the wcscat function. */
+#define HAVE_WCSCAT 1
+
+/* Define if you have the wcschr function. */
+#define HAVE_WCSCHR 1
+
+/* Define if you have the wcscmp function. */
+#define HAVE_WCSCMP 1
+
+/* Define if you have the wcscoll function. */
+/* #undef HAVE_WCSCOLL */
+
+/* Define if you have the wcscpy function. */
+#define HAVE_WCSCPY 1
+
+/* Define if you have the wcscspn function. */
+#define HAVE_WCSCSPN 1
+
+/* Define if you have the wcsftime function. */
+/* #undef HAVE_WCSFTIME */
+
+/* Define if you have the wcslen function. */
+#define HAVE_WCSLEN 1
+
+/* Define if you have the wcsncat function. */
+#define HAVE_WCSNCAT 1
+
+/* Define if you have the wcsncmp function. */
+#define HAVE_WCSNCMP 1
+
+/* Define if you have the wcsncpy function. */
+#define HAVE_WCSNCPY 1
+
+/* Define if you have the wcspbrk function. */
+#define HAVE_WCSPBRK 1
+
+/* Define if you have the wcsrchr function. */
+#define HAVE_WCSRCHR 1
+
+/* Define if you have the wcsrtombs function. */
+/* #undef HAVE_WCSRTOMBS */
+
+/* Define if you have the wcsspn function. */
+#define HAVE_WCSSPN 1
+
+/* Define if you have the wcsstr function. */
+#define HAVE_WCSSTR 1
+
+/* Define if you have the wcstod function. */
+/* #undef HAVE_WCSTOD */
+
+/* Define if you have the wcstof function. */
+/* #undef HAVE_WCSTOF */
+
+/* Define if you have the wcstok function. */
+/* #undef HAVE_WCSTOK */
+
+/* Define if you have the wcstol function. */
+/* #undef HAVE_WCSTOL */
+
+/* Define if you have the wcstoul function. */
+/* #undef HAVE_WCSTOUL */
+
+/* Define if you have the wcsxfrm function. */
+/* #undef HAVE_WCSXFRM */
+
+/* Define if you have the wctob function. */
+/* #undef HAVE_WCTOB */
+
+/* Define if you have the wmemchr function. */
+#define HAVE_WMEMCHR 1
+
+/* Define if you have the wmemcmp function. */
+#define HAVE_WMEMCMP 1
+
+/* Define if you have the wmemcpy function. */
+#define HAVE_WMEMCPY 1
+
+/* Define if you have the wmemmove function. */
+#define HAVE_WMEMMOVE 1
+
+/* Define if you have the wmemset function. */
+#define HAVE_WMEMSET 1
+
+/* Define if you have the wprintf function. */
+/* #undef HAVE_WPRINTF */
+
+/* Define if you have the wscanf function. */
+/* #undef HAVE_WSCANF */
+
+/* Define if you have the <endian.h> header file. */
+/* #undef HAVE_ENDIAN_H */
+
+/* Define if you have the <float.h> header file. */
+#define HAVE_FLOAT_H 1
+
+/* Define if you have the <fp.h> header file. */
+/* #undef HAVE_FP_H */
+
+/* Define if you have the <gconv.h> header file. */
+/* #undef HAVE_GCONV_H */
+
+/* Define if you have the <ieeefp.h> header file. */
+#define HAVE_IEEEFP_H 1
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <machine/endian.h> header file. */
+#define HAVE_MACHINE_ENDIAN_H 1
+
+/* Define if you have the <machine/param.h> header file. */
+#define HAVE_MACHINE_PARAM_H 1
+
+/* Define if you have the <nan.h> header file. */
+/* #undef HAVE_NAN_H */
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <sys/isa_defs.h> header file. */
+/* #undef HAVE_SYS_ISA_DEFS_H */
+
+/* Define if you have the <sys/machine.h> header file. */
+/* #undef HAVE_SYS_MACHINE_H */
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define if you have the m library (-lm). */
+#define HAVE_LIBM 1
+
+/* Name of package */
+#define PACKAGE "libstdc++"
+
+/* Version number of package */
+#define VERSION "3.1.0"
+
+/* Define if the compiler is configured for setjmp/longjmp exceptions. */
+/* #undef _GLIBCPP_SJLJ_EXCEPTIONS */
+
+/* Define if sigsetjmp is available. */
+#define HAVE_SIGSETJMP 1
+
+/* Only used in build directory testsuite_hooks.h. */
+#define HAVE_MEMLIMIT_DATA 0
+
+/* Only used in build directory testsuite_hooks.h. */
+#define HAVE_MEMLIMIT_RSS 0
+
+/* Only used in build directory testsuite_hooks.h. */
+#define HAVE_MEMLIMIT_VMEM 0
+
+/* Only used in build directory testsuite_hooks.h. */
+#define HAVE_MEMLIMIT_AS 0
+
+//
+// Systems that have certain non-standard functions prefixed with an
+// underscore, we'll handle those here. Must come after config.h.in.
+//
+#if defined (HAVE__ISNAN) && ! defined (HAVE_ISNAN)
+# define HAVE_ISNAN 1
+# define isnan _isnan
+#endif
+
+#if defined (HAVE__ISNANF) && ! defined (HAVE_ISNANF)
+# define HAVE_ISNANF 1
+# define isnanf _isnanf
+#endif
+
+#if defined (HAVE__ISNANL) && ! defined (HAVE_ISNANL)
+# define HAVE_ISNANL 1
+# define isnanl _isnanl
+#endif
+
+#if defined (HAVE__ISINF) && ! defined (HAVE_ISINF)
+# define HAVE_ISINF 1
+# define isinf _isinf
+#endif
+
+#if defined (HAVE__ISINFF) && ! defined (HAVE_ISINFF)
+# define HAVE_ISINFF 1
+# define isinff _isinff
+#endif
+
+#if defined (HAVE__ISINFL) && ! defined (HAVE_ISINFL)
+# define HAVE_ISINFL 1
+# define isinfl _isinfl
+#endif
+
+#if defined (HAVE__COPYSIGN) && ! defined (HAVE_COPYSIGN)
+# define HAVE_COPYSIGN 1
+# define copysign _copysign
+#endif
+
+#if defined (HAVE__COPYSIGNL) && ! defined (HAVE_COPYSIGNL)
+# define HAVE_COPYSIGNL 1
+# define copysignl _copysignl
+#endif
+
+#if defined (HAVE__COSF) && ! defined (HAVE_COSF)
+# define HAVE_COSF 1
+# define cosf _cosf
+#endif
+
+#if defined (HAVE__ACOSF) && ! defined (HAVE_ACOSF)
+# define HAVE_ACOSF 1
+# define acosf _acosf
+#endif
+
+#if defined (HAVE__ACOSL) && ! defined (HAVE_ACOSL)
+# define HAVE_ACOSL 1
+# define acosl _acosl
+#endif
+
+#if defined (HAVE__ASINF) && ! defined (HAVE_ASINF)
+# define HAVE_ASINF 1
+# define asinf _asinf
+#endif
+
+#if defined (HAVE__ASINL) && ! defined (HAVE_ASINL)
+# define HAVE_ASINL 1
+# define asinl _asinl
+#endif
+
+#if defined (HAVE__ATANF) && ! defined (HAVE_ATANF)
+# define HAVE_ATANF 1
+# define atanf _atanf
+#endif
+
+#if defined (HAVE__ATANL) && ! defined (HAVE_ATANL)
+# define HAVE_ATANL 1
+# define atanl _atanl
+#endif
+
+#if defined (HAVE__CEILF) && ! defined (HAVE_CEILF)
+# define HAVE_CEILF 1
+# define aceil _ceilf
+#endif
+
+#if defined (HAVE__CEILL) && ! defined (HAVE_CEILL)
+# define HAVE_CEILL 1
+# define aceil _ceill
+#endif
+
+#if defined (HAVE__COSHF) && ! defined (HAVE_COSHF)
+# define HAVE_COSHF 1
+# define coshf _coshf
+#endif
+
+#if defined (HAVE__COSL) && ! defined (HAVE_COSL)
+# define HAVE_COSL 1
+# define cosl _cosl
+#endif
+
+#if defined (HAVE__LOGF) && ! defined (HAVE_LOGF)
+# define HAVE_LOGF 1
+# define logf _logf
+#endif
+
+#if defined (HAVE__COSHL) && ! defined (HAVE_COSHL)
+# define HAVE_COSHL 1
+# define coshl _coshl
+#endif
+
+#if defined (HAVE__EXPF) && ! defined (HAVE_EXPF)
+# define HAVE_EXPF 1
+# define expf _expf
+#endif
+
+#if defined (HAVE__EXPL) && ! defined (HAVE_EXPL)
+# define HAVE_EXPL 1
+# define expl _expl
+#endif
+
+#if defined (HAVE__FABSF) && ! defined (HAVE_FABSF)
+# define HAVE_FABSF 1
+# define fabsf _fabsf
+#endif
+
+#if defined (HAVE__FABSL) && ! defined (HAVE_FABSL)
+# define HAVE_FABSL 1
+# define fabsl _fabsl
+#endif
+
+#if defined (HAVE__FLOORF) && ! defined (HAVE_FLOORF)
+# define HAVE_FLOORF 1
+# define floorf _floorf
+#endif
+
+#if defined (HAVE__FLOORL) && ! defined (HAVE_FLOORL)
+# define HAVE_FLOORL 1
+# define floorl _floorl
+#endif
+
+#if defined (HAVE__FMODF) && ! defined (HAVE_FMODF)
+# define HAVE_FMODF 1
+# define fmodf _fmodf
+#endif
+
+#if defined (HAVE__FMODL) && ! defined (HAVE_FMODL)
+# define HAVE_FMODL 1
+# define fmodl _fmodl
+#endif
+
+#if defined (HAVE__FREXPF) && ! defined (HAVE_FREXPF)
+# define HAVE_FREXPF 1
+# define frexpf _frexpf
+#endif
+
+#if defined (HAVE__FREXPL) && ! defined (HAVE_FREXPL)
+# define HAVE_FREXPL 1
+# define frexpl _frexpl
+#endif
+
+#if defined (HAVE__LDEXPF) && ! defined (HAVE_LDEXPF)
+# define HAVE_LDEXPF 1
+# define ldexpf _ldexpf
+#endif
+
+#if defined (HAVE__LDEXPL) && ! defined (HAVE_LDEXPL)
+# define HAVE_LDEXPL 1
+# define ldexpl _ldexpl
+#endif
+
+#if defined (HAVE__LOG10F) && ! defined (HAVE_LOG10F)
+# define HAVE_LOG10F 1
+# define log10f _log10f
+#endif
+
+#if defined (HAVE__LOGL) && ! defined (HAVE_LOGL)
+# define HAVE_LOGL 1
+# define logl _logl
+#endif
+
+#if defined (HAVE__POWF) && ! defined (HAVE_POWF)
+# define HAVE_POWF 1
+# define powf _powf
+#endif
+
+#if defined (HAVE__LOG10L) && ! defined (HAVE_LOG10L)
+# define HAVE_LOG10L 1
+# define log10l _log10l
+#endif
+
+#if defined (HAVE__MODF) && ! defined (HAVE_MODF)
+# define HAVE_MODF 1
+# define modf _modf
+#endif
+
+#if defined (HAVE__MODL) && ! defined (HAVE_MODL)
+# define HAVE_MODL 1
+# define modl _modl
+#endif
+
+#if defined (HAVE__SINF) && ! defined (HAVE_SINF)
+# define HAVE_SINF 1
+# define sinf _sinf
+#endif
+
+#if defined (HAVE__POWL) && ! defined (HAVE_POWL)
+# define HAVE_POWL 1
+# define powl _powl
+#endif
+
+#if defined (HAVE__SINHF) && ! defined (HAVE_SINHF)
+# define HAVE_SINHF 1
+# define sinhf _sinhf
+#endif
+
+#if defined (HAVE__SINL) && ! defined (HAVE_SINL)
+# define HAVE_SINL 1
+# define sinl _sinl
+#endif
+
+#if defined (HAVE__SQRTF) && ! defined (HAVE_SQRTF)
+# define HAVE_SQRTF 1
+# define sqrtf _sqrtf
+#endif
+
+#if defined (HAVE__SINHL) && ! defined (HAVE_SINHL)
+# define HAVE_SINHL 1
+# define sinhl _sinhl
+#endif
+
+#if defined (HAVE__TANF) && ! defined (HAVE_TANF)
+# define HAVE_TANF 1
+# define tanf _tanf
+#endif
+
+#if defined (HAVE__SQRTL) && ! defined (HAVE_SQRTL)
+# define HAVE_SQRTL 1
+# define sqrtl _sqrtl
+#endif
+
+#if defined (HAVE__TANHF) && ! defined (HAVE_TANHF)
+# define HAVE_TANHF 1
+# define tanhf _tanhf
+#endif
+
+#if defined (HAVE__TANL) && ! defined (HAVE_TANL)
+# define HAVE_TANF 1
+# define tanf _tanf
+#endif
+
+#if defined (HAVE__STRTOF) && ! defined (HAVE_STRTOF)
+# define HAVE_STRTOF 1
+# define strtof _strtof
+#endif
+
+#if defined (HAVE__TANHL) && ! defined (HAVE_TANHL)
+# define HAVE_TANHL 1
+# define tanhl _tanhl
+#endif
+
+#if defined (HAVE__STRTOLD) && ! defined (HAVE_STRTOLD)
+# define HAVE_STRTOLD 1
+# define strtold _strtold
+#endif
+
+#if defined (HAVE__SINCOS) && ! defined (HAVE_SINCOS)
+# define HAVE_SINCOS 1
+# define sincos _sincos
+#endif
+
+#if defined (HAVE__SINCOSF) && ! defined (HAVE_SINCOSF)
+# define HAVE_SINCOSF 1
+# define sincosf _sincosf
+#endif
+
+#if defined (HAVE__SINCOSL) && ! defined (HAVE_SINCOSL)
+# define HAVE_SINCOSL 1
+# define sincosl _sincosl
+#endif
+
+#if defined (HAVE__FINITE) && ! defined (HAVE_FINITE)
+# define HAVE_FINITE 1
+# define finite _finite
+#endif
+
+#if defined (HAVE__FINITEF) && ! defined (HAVE_FINITEF)
+# define HAVE_FINITEF 1
+# define finitef _finitef
+#endif
+
+#if defined (HAVE__FINITEL) && ! defined (HAVE_FINITEL)
+# define HAVE_FINITEL 1
+# define finitel _finitel
+#endif
+
+#if defined (HAVE__QFINITE) && ! defined (HAVE_QFINITE)
+# define HAVE_QFINITE 1
+# define qfinite _qfinite
+#endif
+
+#if defined (HAVE__FPCLASS) && ! defined (HAVE_FPCLASS)
+# define HAVE_FPCLASS 1
+# define fpclass _fpclass
+#endif
+
+#if defined (HAVE__QFPCLASS) && ! defined (HAVE_QFPCLASS)
+# define HAVE_QFPCLASS 1
+# define qfpclass _qfpclass
+#endif
+
diff --git a/gnu/lib/libstdc++/doc/Makefile b/gnu/lib/libstdc++/doc/Makefile
new file mode 100644
index 0000000..b028519
--- /dev/null
+++ b/gnu/lib/libstdc++/doc/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+SRCDIR= ${.CURDIR}/../../../../contrib/libstdc++
+
+.PATH: ${SRCDIR}/../libio
+
+INFO = iostream
+
+INFOENTRY_iostream= "* iostream: (iostream). The GNU C++ I/O library."
+
+MAKEINFOFLAGS+= -I ${SRCDIR}/../libio
+
+.include <bsd.info.mk>
diff --git a/gnu/lib/libsupc++/Makefile b/gnu/lib/libsupc++/Makefile
new file mode 100644
index 0000000..681b1d8
--- /dev/null
+++ b/gnu/lib/libsupc++/Makefile
@@ -0,0 +1,27 @@
+# $FreeBSD$
+
+GCCDIR= ${.CURDIR}/../../../contrib/gcc
+SRCDIR= ${.CURDIR}/../../../contrib/libstdc++/libsupc++
+
+.PATH: ${SRCDIR} ${GCCDIR}
+
+# Static only.
+LIB= supc++
+SRCS= del_op.cc del_opnt.cc del_opv.cc del_opvnt.cc \
+ eh_alloc.cc eh_aux_runtime.cc eh_catch.cc eh_exception.cc \
+ eh_globals.cc eh_personality.cc eh_terminate.cc eh_throw.cc eh_type.cc \
+ new_handler.cc new_op.cc new_opnt.cc new_opv.cc new_opvnt.cc \
+ pure.cc tinfo.cc tinfo2.cc vec.cc
+
+# from libiberty:
+SRCS+= cp-demangle.c dyn-string.c
+
+CFLAGS+= -DIN_GLIBCPP_V3 -DHAVE_CONFIG_H
+CFLAGS+= -I${SRCDIR} -I${GCCDIR} -I${.CURDIR}/../libstdc++
+CXXFLAGS+= -fno-implicit-templates -ffunction-sections -fdata-sections
+
+HDRS= exception new typeinfo cxxabi.h exception_defines.h
+INCS= ${HDRS:S;^;${SRCDIR}/;}
+INCSDIR=${INCLUDEDIR}/g++
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/Makefile b/gnu/usr.bin/Makefile
new file mode 100644
index 0000000..162586f
--- /dev/null
+++ b/gnu/usr.bin/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+SUBDIR= bc binutils cc cpio dc dialog diff diff3 \
+ gperf grep groff gzip man patch rcs sdiff send-pr sort tar texinfo
+
+.if !defined(NO_CVS)
+SUBDIR+=cvs
+.endif
+
+.if defined(WANT_AOUT)
+.if ${MACHINE_ARCH} == "i386"
+SUBDIR+=as ld
+.endif
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/Makefile.inc b/gnu/usr.bin/Makefile.inc
new file mode 100644
index 0000000..5d2cffd
--- /dev/null
+++ b/gnu/usr.bin/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+BINDIR?= /usr/bin
diff --git a/gnu/usr.bin/as/CONTRIBUTORS b/gnu/usr.bin/as/CONTRIBUTORS
new file mode 100644
index 0000000..cfcc7bc
--- /dev/null
+++ b/gnu/usr.bin/as/CONTRIBUTORS
@@ -0,0 +1,11 @@
+(This file under construction).
+
+If you've contributed to gas and your name isn't listed here, it is
+not meant as a slight. I just don't know about it. Email me,
+rich@cygnus.com and I'll correct the situation.
+
+Dean Elsnor wrote the original gas for vax.
+
+Jay Fenalson maintained gas for a while.
+
+K. Richard Pixley currently maintains gas.
diff --git a/gnu/usr.bin/as/COPYING b/gnu/usr.bin/as/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/gnu/usr.bin/as/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/as/ChangeLog b/gnu/usr.bin/as/ChangeLog
new file mode 100644
index 0000000..db77234
--- /dev/null
+++ b/gnu/usr.bin/as/ChangeLog
@@ -0,0 +1,429 @@
+Sun Mar 1 17:02:06 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * README: updated to 1.92.3, included mail announcement.
+
+Sat Feb 29 00:53:16 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * tc-sparc.c (md_apply_fix): relocation overflow checks.
+
+ * atof-generic.c (atof_generic): recognize 99e999 as infinity for
+ older, broken, compilers.
+
+ * version.c: bump to 1.92.3, drop "Cygnus".
+
+ * input-scrub.c (as_where): use myname (which comes from argv[0])
+ as part of all error messages.
+
+ * mess-dose renaming:
+ flonum-copy.c -> flo-copy.c
+ flonum-const.c -> flo-const.c
+ config/a.out.gnu.h -> config/aout.h
+ config/coff.gnu.h -> config/coff.h
+
+ * Makefile.in, obj-aout.h, obj-coff.h: reflect file renaming.
+
+ * output-file.c (output_file_create): add "b" to the fopen to
+ humor mess-dos.
+
+ * configure.in: tahoe needs atof-tahoe.
+
+ * config/tc-tahoe.[hc], config/atof-tahoe.c, opcode/tahoe.h: new
+ files. This is kinda blind cause I don't have anything to run
+ through it or compare against.
+
+ * read.c (read_a_source_file), expr.c (operand): fix a very old
+ bug in label reading exposed by m88k. Also, m88k can't have a
+ pseudo "set".
+
+ * config/m88k.[hc]: freshen copyrights, version 2 gpl, update to
+ current gas.
+
+ * config/m88k-opcode.h moved to opcode/m88k.h
+
+ * read.c: NO_DOT_PSEUDOS from hacks unfinished work.
+
+ * opcode/m68k.h: Sun's JFcc aliases appear to be variable length.
+ Make them so.
+
+ * opcode/a29k.h: remove rcsid.
+
+ * config/te-sun3.h: remove semicolon typo.
+
+ * config/obj-vms.c: another patch from eric youngdale.
+
+ * write.c: white space only.
+
+ * config/tc-i960.c: change from intel for header flags.
+
+ * config/te-sequent.h, config/obj-aout.h: first cut at building
+ sequent headers.
+
+ * config/tc-ns32k.c: patches from Jyrki Kuoppala <jkp@cs.hut.fi>.
+
+ * struct-symbol.h: removed redundant decl of N_TYPE_seg.
+
+ * config/tc-sparc.c (sparc_ip), opcode/sparc.h: changes from chris
+ torek to correct a problem with "neg". some white space.
+
+ * confic/tc-m68k.c: a fix pulled from hack's unfinished work and
+ my mail archives. Try again to get pcrel working. Fix stupid
+ botch on cpu_type comparison.
+
+ * config/tc-sparc.c: .empty pseudo-op from
+ gordoni@cs.adelaide.edu.au.
+
+ * opcode/sparc.h: some new aliases from chris torek.
+
+ * opcode/i386.h: some new aliases and opcodes. also patches from
+ Steve Bleazard <steve@robobar.co.uk>.
+
+ * config/te-hpux.h: new file.
+
+ * configure.in: when targetting hpux, use te-hpux.h.
+
+ * config/obj-aout.c (obj-pre-write-hook), config/obj-bout.[ch]
+ (obj-pre-write-hook), config/obj-coff.[ch] (obj-pre-write-hook),
+ config/obj-generic.h, config/obj-vms.h, write.c
+ (write_object_file): move magic number fiddling out of write.c
+ and into obj-pre-write-hook.
+
+ * config/tc-i860.c: gcc -Wall cleanup.
+
+Fri Feb 28 00:30:36 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * configure.in: if target is sun3, use te-sun3.h.
+
+ * config/tc-m68k.h, config/te-sun3.h: moved #define of
+ default_magic_number_for_object_file from former to latter.
+
+ * config/te-sun3.h: removed sun_asm_syntax and te_sun3, they
+ aren't used.
+
+ * all: white space changes.
+ " -> " becomes "->"
+ "foo [" becomes "foo["
+ "a . b" becomes "a.b"
+ "\(if\|for\|while\|switch\)(" become "\\1("
+ "\\([^\n]\\)[ \t]*\\([=!+-*/<>]\\)=[ \t]*" become "\\1 \\2= "
+
+ * read.c, write.c, config/tc-i386.c: white space and comments
+ only.
+
+ * config/obj-vms.c: convert PUT_LONG and PUT_SHORT to squirt byte
+ swapped numbers.
+
+ * as.c, flonum-const.c, hex-value.c, input-file.c, version.c,
+ config/obj-aout.h, config/obj-vms.c: VMS -> HO_VMS.
+
+ * config/ho-vms.h: added HO_VMS.
+
+Thu Feb 27 18:25:11 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * config/ChangeLog: removed. entries merged into this file.
+
+ * config/ho-vms.h: new file. Move the VMS stuff out of ho-vax.h
+ into ho-vms.h.
+
+ * configure.in: use ho-i386v4 for i386-sysvr4.
+
+ * config/ho-i386v4: new file.
+
+Tue Feb 25 19:54:04 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * config/obj-vms.c (VMS_write_object_file): Add work-around
+ for g++ compiler bug involving external vtables.
+
+Mon Feb 24 22:19:10 1992 (Eric Youngdale at youngdale@v6550c.nrl.navy.mil)
+
+ * README-vms: Describe how to get a VMS obj file to a vms machine
+ via NFS.
+
+ * configure.in: For i386-sysv*, use gas_host=i386.
+
+ * Makefile.in: Remove continuation line markers when the next line
+ is blank.
+
+ * read.c (line_comment_chars): Make external.
+
+ * input-file.c: Remove redundant include of <assert.h>.
+
+ * config/ho-vax.h [VMS]: Include <ctype.h> and <perror.h>.
+
+ * config/obj-vms.h: Remove said includes. Add RELOC_32 to
+ reloc_type to prevent compilation error.
+
+ * config/obj-vms.c: Change bcopy to memcpy throughout.
+ (VMS_local_stab_Parse): Fix typo.
+ (VMS_local_stab_Parse, VMS_RSYM_Parse, Define_Local_Symbols,
+ Define_Routine, VMS_write_object_file): Allow 'f' for functions
+ as well as 'F'.
+
+Mon Feb 24 03:48:04 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * README: updated to reflect current testing status.
+
+ * README.rich, NOTES, NOTES.config: updated slightly, marked as
+ "under construction".
+
+ * CONTRIBUTORS: new file.
+
+ * README-vms: options to configure are now -options=, not
+ +options=.
+
+ * version.c: bumped version to 1.92.2.
+
+Mon Feb 24 03:27:00 1992 Eric Youngdale (youngdale at v6550c.nrl.navy.mil)
+
+ * config.sub: Added vms as a target system. (So people do not
+ have to try to figure out that "vax-dec-vms" would work).
+
+ * configure.in: Added vms as a target os, and object file format.
+ (Useless on a vms system, but this is for people who want to
+ cross assemble).
+
+ * config-gas.com: New file. Script for VMS systems to set up the
+ configuration to build gas for VMS, and create config.status.
+
+ * make-gas.com: Redone to work with the bfd-gas scheme.
+
+ * as.c: Add const modifier to version_string.
+
+ * atof-vax.c: Remove redundant include of flonum.h. (This is also
+ included via as.h).
+
+ * expr.c: Add "const" modifier to hex_value.
+
+ * read.c: Add "const" modifier to line_comment_chars, and
+ line_separator_chars. Make use of the -1 switch for backward
+ compatibility with gcc 1.nn.
+ (s_ignore): remove redundant declaration of is_end_of_line.
+
+ * symbols.c: Finish conversion to S_* macros in the VMS only
+ parts of the program. Add "const" modifier to
+ md_[long,short]_jump_size. Remove declaration of const_flag
+ (which will be declared in obj-vms.h).
+
+ * write.c: Add "const" modifier to md_[long,short]_jump_size.
+ Fix arguments to VMS_write_object_file.
+
+ * obj-vms.h: New file (sort of). Mostly canibalized from other
+ files, using:
+
+ - objrecdef.h: Removed structure definition that we do not use,
+ and removed dollar signs from identifiers, since Unix System 5
+ does not like them.
+
+ - obj-aout.h: Took S_*, some H_* macros, and a number of
+ symbol definitions.
+
+ - a.out.hp.h: Took nlist structure. We do not really use this
+ per se, but it is easiest to let gas think that we do. When we
+ write the object file, we just pick out the parts that we need.
+
+ - stab.h: Just included it, since on non VMS and non a.out systems
+ we have no guarantee of having it. (Define N_* symbols).
+
+ *obj-vms.c: Renamed from vms.c. Did the following:
+
+ - Reworked to use the S_* macros.
+
+ - Add "const" modifier to version_string.
+
+ - Added global[ref,def,value] support
+
+ - (VMS_Store_PIC_Symbol_Reference):fix a bug with static constants.
+
+ - Remove a few redunant includes - all are now included through as.h.
+
+ - (obj_crawl_symbol_chain): Clean up (a lot), and remove non-VMS
+ code. Add definition for obj_read_begin_hook.
+
+ - Borrow the stab[s,d,n] routines from obj-aout.c.
+
+ - Borrow the seg_N_TYPE and N_TYPE_seg arrays from aout.c
+
+ - Use <fab.h>,<rab.h> and <xab.h> instead of <vms/fabdef.h>
+ <vms/rabdef.h> and <vms/xabdef.h>, for more consistent results.
+ (Some peoples <vms/*.h> files are different than others).
+
+ - Merged vms-dbg.c into obj-vms.c. Modified to use
+ the S_* macros. Added code to remove the psect hack from
+ variable names before writing them to the debugger records.
+
+
+
+ The following patches make cross assembly possible.
+
+ * as.c, read.c, symbols.c, write.c: Change "ifdef VMS" to
+ "ifdef OBJ_VMS".
+
+ * vms.c:
+
+ - Wrap the #include of some VMS system dependent headers
+ with "ifdef VMS".
+
+ - (get_VMS_time_on_unix): Add new routine. Generates current
+ time in VMS format to be written into object file.
+
+ - (Write_VMS_MHD_Records): Use get_VMS_time_on_unix if we are not
+ running on a VMS system.
+
+ - (Flush_VMS_Object_Record_Buffer): Add code to write correct
+ record format when running on a non-VMS system.
+
+ - (Create_VMS_Object_File): Use different mode if running under
+ unix.
+
+ - (VMS_TBT_Source_File): If we are not running on a VMS system,
+ write a source file record for the debugger that looks reasonable.
+
+Mon Feb 24 02:06:00 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: remove $(srcdir)/../include from INCLUDES. It
+ isn't needed.
+
+ * README: updated with current state.
+
+ * read.c (stringer): read arbitrary expressions between the commas
+ and treat them as ".byte" values. At least some i860 assembler
+ does this so now we do too. Also white space throughout.
+
+ * expr.c, expr.h, frags.c, symbols.c, write.c: white space only.
+
+Mon Feb 24 01:45:40 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * config/te-sequent.h, config/tc-ns32k.h, config/tc-ns32k.c:
+ SEQUENT_COMPATIBILITY -> TE_SEQUENT.
+
+ * config/obj-aout.c: if OLD_GAS and i386, then screw up the magic
+ number.
+
+ * config/obj-bout.c: do not include aout/stab_gnu.h if NO_LISTING.
+
+ * config/obj-bout.h: added enum reloc_type.
+
+ * config/tc-i386.c: on OLD_GAS, .align is power of two, rather
+ than bytes.
+
+ * config/tc-i386.h: on OLD_GAS, the filler byte should be zero
+ rather than NOOP.
+
+ * config/tc-i860.c: relocs are 12bytes on this target. Also white
+ space.
+
+ * config/tc-m68kmote.c: removed. Not ready yet.
+
+ * config/a.out.gnu.h, config/tc-a29k.c, config/tc-m68k.c,
+ config/tc-ns32k.c: white space only.
+
+ * config/tc-a29k.h, config/tc-i860.h, config/tc-i960.h,
+ config/tc-m68k.h, config/tc-ns32k.h, config/tc-sparc.h,
+ config/tc-vax.h: NO_LISTING
+
+ * config/tc-m68k.h, config/tc-i860.h, config/tc-vax.h:
+ REVERSE_SORT_RELOCS if OLD_GAS.
+
+ * config/mt-m68k: removed. not needed.
+
+Fri Feb 21 06:22:15 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * config/obj-aout.c: do not include stab.gnu.h if NO_LISTING.
+
+ * config/tc-i860.c, config/a.out.gnu.h: move i860 relocs to a proper place.
+
+ * config/a.out.h: removed.
+
+Fri Feb 21 06:21:07 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: put header files before C source for TAGS; remove
+ references to non-existent syscalls.h.
+
+ * read.c, write.c subsegs.c: back out the .bss changes.
+
+Fri Feb 21 02:17:22 1992 Minh Tran-Le (TRANLE@INTELLICORP.COM)
+
+ * config/tc-i386.c: config/tc-i386.c: added handling of the
+ following opcodes: i/o opcodes - inb, inw, outb and outw.
+ string manipulation with att syntax - scmp, slod, smov, ssca,
+ ssto.
+
+Fri Feb 21 01:53:50 1992 Minh Tran-Le (TRANLE@INTELLICORP.COM)
+
+ * config/obj-coff.c: (for aix386) Moved the symbols .text, .data
+ and .bss to just after .file .
+
+ In obj_crawl_symbol_chain() where it tries to put the external
+ symbols apart, with the condition:
+ (!S_IS_DEFINED(symbolP) &&
+ !S_IS_DEBUG(symbolP) &&
+ !SF_GET_STATICS(symbolP))
+ it was moving too many symbols out. So I switch it back to the
+ condition:
+ (S_GET_STORAGE_CLASS(symbolP) == C_EXT && !SF_GET_FUNCTION(symbolP))
+
+ In obj_emit_relocations() added the conditional on KEEP_RELOC_INFO
+ so that we don't use the F_RELFLG which make the linker complain
+ that somebody has stripped the relocation info.
+
+ Also, the AIX ld program require that the relocation table
+ is sorted by r_vaddr like the standard ATT assembler does.
+
+ [he also changed the sizeof(struct ...)'s into the coff
+ style FOOSZ macros. I'm not sure this is right, but I can't
+ remember why. xoxorich.]
+
+Fri Feb 21 01:08:48 1992 Minh Tran-Le (TRANLE@INTELLICORP.COM)
+
+ * symbols.c (local_label_name): symbols now start with ^A.
+
+ * read.c, subsegs.c, write.c obj-coff.c: added handling of
+ `.bss` pseudo op for unitialized data. The new gcc (1.37.9x)
+ generate these sections. .align: will use NOP_OPCODE or 0
+ for padding. This is just for being nice to the
+ disassembler.
+
+ * expr.c (operand): changed to generate local label "\001L0"
+ starting with a ^A so that it is recognized as a local label.
+
+ * as.c (perform_an_assembly_pass): zero bss_fix_root, too.
+
+Fri Feb 21 01:08:48 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in, doc: use the doc. Build it, install
+ it, clean it, etc.
+
+Tue Feb 18 02:21:25 1992 K. Richard Pixley (rich at cygnus.com)
+
+ * read.c: white space and comments only.
+
+ * configure.in: use the new atof-ns32.c for ns32k.
+
+ * write.c: comment change only.
+
+Tue Feb 18 02:11:10 1992 K. Richard Pixley (rich at cygnus.com)
+
+ * config/tc-m88k.[hc]: pulled in from hack's unfinished work. These
+ aren't yet integrated.
+
+ * config/tc-i860.[hc]: blew off the dust. Something must still be
+ done about conflicting relocation types.
+
+ * config/tc-ns32k.c: Replaced previous tc_aout_fix_to_chars stub
+ with the real thing.
+
+ * config/tc-i960.c, tc-sparc.c: white space and comments only.
+
+ * config/tc-a29k.h: delete duplicate macro definition.
+
+ * new file config/atof-ns32k.c copied from hack's last unreleased
+ gas.
+
+Mon Feb 17 07:51:06 1992 K. Richard Pixley (rich at cygnus.com)
+
+ * config/tc-ns32k.c: actually make tc_aout_fix_to_chars work
+ rather than abort.
+
+ * nearly everything. flush ChangeLog, package as gas-1.92.1.
+ ChangeLog's prior to this are sketchy at best. I have logs.
+ They just aren't ChangeLogs.
+
diff --git a/gnu/usr.bin/as/Makefile b/gnu/usr.bin/as/Makefile
new file mode 100644
index 0000000..a678242
--- /dev/null
+++ b/gnu/usr.bin/as/Makefile
@@ -0,0 +1,69 @@
+# from: @(#)Makefile 6.1 (Berkeley) 3/3/91
+# $FreeBSD$
+
+.include "config/Makefile.$(MACHINE_ARCH)"
+
+.if !defined (gas_hosttype)
+gas_hosttype=$(MACHINE_ARCH)
+.endif
+.if !defined (gas_target)
+gas_target=$(MACHINE_ARCH)
+.endif
+.if !defined (gas_objformat)
+gas_objformat=aout
+.endif
+
+ADDINCLUDE=-I${.OBJDIR}
+
+PROG= as
+BINDIR= /usr/libexec/aout
+MAN= as.1aout
+SRCS+= app.c as.c atof-generic.c bignum-copy.c \
+ cond.c expr.c flo-const.c flo-copy.c flonum-mult.c \
+ frags.c hash.c hex-value.c input-file.c input-scrub.c \
+ listing.c messages.c obstack.c output-file.c read.c subsegs.c \
+ symbols.c version.c write.c xmalloc.c xrealloc.c \
+ obj-$(gas_objformat).c ${CONF_HEADERS}
+CFLAGS+= -I$(.CURDIR) ${ADDINCLUDE} -I$(.CURDIR)/config \
+ -DOLD_GAS -DSIGTY=void -Derror=as_fatal \
+ -DSUB_SEGMENT_ALIGN=4 -DFREEBSD_AOUT
+
+CONF_HEADERS= targ-cpu.h obj-format.h host.h targ-env.h
+
+.PATH: $(.CURDIR)/config
+
+targ-cpu.h: Makefile config/Makefile.$(MACHINE_ARCH) $(.CURDIR)/config/tc-$(gas_target).h
+ @cmp -s $(.CURDIR)/config/tc-$(gas_target).h targ-cpu.h || \
+ ( ${ECHO} "updating ${.TARGET}..." ; /bin/rm -f targ-cpu.h ; \
+ cp $(.CURDIR)/config/tc-$(gas_target).h targ-cpu.h )
+
+obj-format.h: Makefile config/Makefile.$(MACHINE_ARCH) $(.CURDIR)/config/obj-$(gas_objformat).h
+ @cmp -s $(.CURDIR)/config/obj-$(gas_objformat).h obj-format.h || \
+ ( ${ECHO} "updating ${.TARGET}..." ; /bin/rm -f obj-format.h ; \
+ cp $(.CURDIR)/config/obj-$(gas_objformat).h obj-format.h )
+
+.if exists ($(.CURDIR)/config/ho-$(gas_hosttype).h)
+config_hostfile= $(.CURDIR)/config/ho-$(gas_hosttype).h
+.else
+config_hostfile= $(.CURDIR)/config/ho-generic.h
+.endif
+
+host.h: Makefile config/Makefile.$(MACHINE_ARCH) $(config_hostfile)
+ @cmp -s $(config_hostfile) host.h || \
+ ( ${ECHO} "updating ${.TARGET}..." ; /bin/rm -f host.h ; \
+ cp $(config_hostfile) host.h )
+
+.if exists ($(.CURDIR)/config/te-$(MACHINE_ARCH).h)
+config_targenvfile= $(.CURDIR)/config/te-$(MACHINE_ARCH).h
+.else
+config_targenvfile= $(.CURDIR)/config/te-generic.h
+.endif
+
+targ-env.h: Makefile config/Makefile.$(MACHINE_ARCH) $(config_targenvfile)
+ @cmp -s $(config_targenvfile) targ-env.h || \
+ ( ${ECHO} "updating ${.TARGET}..." ; /bin/rm -f targ-env.h ; \
+ cp $(config_targenvfile) targ-env.h )
+
+CLEANFILES+= ${CONF_HEADERS}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/as/Makefile.in b/gnu/usr.bin/as/Makefile.in
new file mode 100644
index 0000000..6b3d993
--- /dev/null
+++ b/gnu/usr.bin/as/Makefile.in
@@ -0,0 +1,411 @@
+# $FreeBSD$
+
+# Makefile for GNU Assembler
+# Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+#This file is part of GNU GAS.
+
+#GNU GAS is free software; you can redistribute it and/or modify
+#it under the terms of the GNU General Public License as published by
+#the Free Software Foundation; either version 2, or (at your option)
+#any later version.
+
+#GNU GAS is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with GNU GAS; see the file COPYING. If not, write to
+#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# The targets for external use include:
+# all, doc, proto, install, uninstall, includes, TAGS,
+# clean, cleanconfig, realclean, stage1, stage2, stage3, stage4.
+
+# Variables that exist for you to override.
+# See below for how to change them for certain systems.
+
+srcdir = .
+
+prefix = /usr/local
+
+bindir = $(prefix)/bin
+datadir = $(prefix)/lib
+libdir = $(prefix)/lib
+mandir = $(datadir)/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 = $(datadir)/info
+includedir = $(prefix)/include
+docdir = $(datadir)/doc
+
+SHELL = /bin/sh
+
+INSTALL = install -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+
+AR = ar
+AR_FLAGS = qv
+BISON = bison
+MAKEINFO = makeinfo
+RANLIB = ranlib
+MINUS_G = -g
+
+# Lists of files for various purposes.
+
+REAL_SOURCES = \
+ $(srcdir)/app.c \
+ $(srcdir)/as.c \
+ $(srcdir)/atof-generic.c \
+ $(srcdir)/bignum-copy.c \
+ $(srcdir)/cond.c \
+ $(srcdir)/expr.c \
+ $(srcdir)/flo-const.c \
+ $(srcdir)/flo-copy.c \
+ $(srcdir)/flonum-mult.c \
+ $(srcdir)/frags.c \
+ $(srcdir)/hash.c \
+ $(srcdir)/hex-value.c \
+ $(srcdir)/input-file.c \
+ $(srcdir)/input-scrub.c \
+ $(srcdir)/messages.c \
+ $(srcdir)/obstack.c \
+ $(srcdir)/output-file.c \
+ $(srcdir)/read.c \
+ $(srcdir)/strerror.c \
+ $(srcdir)/strstr.c \
+ $(srcdir)/subsegs.c \
+ $(srcdir)/symbols.c \
+ $(srcdir)/version.c \
+ $(srcdir)/write.c \
+ $(srcdir)/listing.c \
+ $(srcdir)/xmalloc.c \
+ $(srcdir)/xrealloc.c
+
+# in an expedient order
+LINKED_SOURCES = \
+ targ-cpu.c \
+ obj-format.c \
+ atof-targ.c
+
+SOURCES = $(LINKED_SOURCES) $(REAL_SOURCES)
+
+REAL_HEADERS = \
+ $(srcdir)/as.h \
+ $(srcdir)/bignum.h \
+ $(srcdir)/expr.h \
+ $(srcdir)/flonum.h \
+ $(srcdir)/frags.h \
+ $(srcdir)/hash.h \
+ $(srcdir)/input-file.h \
+ $(srcdir)/listing.h \
+ $(srcdir)/tc.h \
+ $(srcdir)/obj.h \
+ $(srcdir)/obstack.h \
+ $(srcdir)/read.h \
+ $(srcdir)/struc-symbol.h \
+ $(srcdir)/subsegs.h \
+ $(srcdir)/symbols.h \
+ $(srcdir)/write.h
+
+LINKED_HEADERS = \
+ a.out.gnu.h \
+ a.out.h \
+ host.h \
+ targ-env.h \
+ targ-cpu.h \
+ obj-format.h \
+ atof-targ.h
+
+HEADERS = $(LINKED_HEADERS) $(REAL_HEADERS)
+
+OBJS = \
+ targ-cpu.o \
+ obj-format.o \
+ atof-targ.o \
+ app.o \
+ as.o \
+ atof-generic.o \
+ bignum-copy.o \
+ cond.o \
+ expr.o \
+ flo-const.o \
+ flo-copy.o \
+ flonum-mult.o \
+ frags.o \
+ hash.o \
+ hex-value.o \
+ input-file.o \
+ input-scrub.o \
+ messages.o \
+ obstack.o \
+ output-file.o \
+ read.o \
+ strerror.o \
+ strstr.o \
+ subsegs.o \
+ symbols.o \
+ version.o \
+ write.o \
+ listing.o \
+ xmalloc.o \
+ xrealloc.o
+
+#### host, target, and site specific Makefile frags come in here.
+
+all: as.new
+ (cd doc ; $(MAKE) all)
+
+info:
+ (cd doc ; $(MAKE) info)
+
+install-info:
+ (cd doc ; $(MAKE) install-info)
+
+clean-info:
+ (cd doc ; $(MAKE) clean-info)
+
+# Now figure out from those variables how to compile and link.
+
+# This is the variable actually used when we compile.
+ALL_CFLAGS = $(MINUS_G) $(INTERNAL_CFLAGS) $(CFLAGS) $(HDEFINES) $(TDEFINES) -DPIC -DOLD_GAS
+
+# How to link with both our special library facilities
+# and the system's installed libraries.
+
+LIBS = $(HLIBS)
+
+# Specify the directories to be searched for header files.
+# Both . and srcdir are used, in that order,
+# so that tm.h and config.h will be found in the compilation
+# subdirectory rather than in the source directory.
+INCLUDES = -I. -I$(srcdir) -I$(srcdir)/config # -I$(srcdir)/../include
+SUBDIR_INCLUDES = -I.. -I$(srcdir) -I$(srcdir)/config
+
+# Always use -I$(srcdir)/config when compiling.
+.c.o:
+ $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $<
+
+# This tells GNU make version 3 not to export all the variables
+# defined in this file into the environment.
+.NOEXPORT:
+
+# Files to be copied away after each stage in building.
+STAGESTUFF = *.o as.new
+
+as.new: $(OBJS) $(LIBDEPS)
+ -mv -f as.new as.old
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o as.new $(OBJS) $(LIBS)
+
+config.status:
+ @echo You must configure gas. Look at the INSTALL file for details.
+ @false
+
+# Compiling object files from source files.
+
+app.o : app.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+as.o : as.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+atof-generic.o : atof-generic.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+bignum-copy.o : bignum-copy.c as.h host.h \
+ targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+cond.o : cond.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+
+debug.o : debug.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+expr.o : expr.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+
+flo-const.o : flo-const.c flonum.h bignum.h
+flo-copy.o : flo-copy.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+flonum-mult.o : flonum-mult.c flonum.h bignum.h
+frags.o : frags.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+hash.o : hash.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+hex-value.o : hex-value.c
+input-file.o : input-file.c as.h host.h \
+ targ-env.h obj-format.h targ-cpu.h \
+ struc-symbol.h write.h flonum.h bignum.h expr.h \
+ frags.h hash.h read.h symbols.h tc.h obj.h input-file.h
+input-scrub.o : input-scrub.c /usr/include/errno.h /usr/include/sys/errno.h \
+ as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ input-file.h
+listing.o : listing.c as.h host.h targ-env.h flonum.h bignum.h \
+ listing.h obj-format.h targ-cpu.h struc-symbol.h write.h expr.h \
+ frags.h hash.h read.h symbols.h tc.h obj.h input-file.h
+messages.o : messages.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+obstack.o : obstack.c
+output-file.o : output-file.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ output-file.h
+read.o : read.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+
+strstr.o : strstr.c
+subsegs.o : subsegs.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+symbols.o : symbols.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+version.o : version.c
+write.o : write.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h output-file.h
+xmalloc.o : xmalloc.c
+xrealloc.o : xrealloc.c
+atof-targ.o : atof-targ.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+ symbols.h tc.h obj.h
+obj-format.o : obj-format.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+ symbols.h tc.h obj.h
+targ-cpu.o : targ-cpu.c targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+ symbols.h tc.h obj.h $(TARG_CPU_DEPENDENTS)
+
+# Remake the info files.
+
+doc: $(srcdir)/as.info
+
+$(srcdir)/as.info: $(srcdir)/doc/as.texinfo
+ (cd doc; make as.info; mv -f as.info $srcdir)
+
+clean:
+ (cd doc ; $(MAKE) clean)
+ -rm -f $(STAGESTUFF) core
+
+# Like clean but also delete the links made to configure gas.
+distclean: clean
+ -rm -f config.status Makefile host.h targ-env.h targ-cpu.h \
+ targ-cpu.c obj-format.h obj-format.c atof-targ.c \
+ gas.aux gas.cps gas.fns gas.info gas.kys gas.pgs \
+ gas.tps gas.vrs TAGS gas.info* gas.?? gas.??s gas.log \
+ gas.toc gas.*aux *.dvi
+
+# Entry points `install', `includes' and `uninstall'.
+
+# Copy the files into directories where they will be run.
+install:
+ if [ "$(host_alias)" = "$(target_alias)" ] ; then \
+ $(INSTALL_PROGRAM) as.new $(bindir)/as ; \
+ else \
+ $(INSTALL_PROGRAM) as.new $(bindir)/as-$(target_alias) ; \
+ fi
+
+# Create the installation directory.
+install-dir:
+ -mkdir $(libdir)
+ -mkdir $(libdir)/gcc
+ -mkdir $(libdir)/gcc/$(target)
+ -mkdir $(libdir)/gcc/$(target)/$(version)
+
+# Cancel installation by deleting the installed files.
+uninstall:
+ -rm -rf $(libsubdir)
+ -rm -rf $(bindir)/as
+ -rm -rf $(mandir)/gas.$(manext)
+
+
+# These exist for maintenance purposes.
+
+tags TAGS: force
+ etags $(REAL_HEADERS) $(REAL_SOURCES) $(srcdir)/config/*.[hc] $(srcdir)/README $(srcdir)/Makefile.in
+
+bootstrap: as.new force
+ $(MAKE) stage1
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new
+ $(MAKE) stage2
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new
+ $(MAKE) comparison against=stage2
+
+bootstrap2: force
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new
+ $(MAKE) stage2
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new
+ $(MAKE) comparison against=stage2
+
+bootstrap3: force
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= as.new
+ $(MAKE) comparison against=stage2
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1: force
+ -mkdir stage1
+ -mv -f $(STAGESTUFF) stage1
+ if [ -f stage1/as.new -a ! -f stage1/as ] ; then (cd stage1 ; ln -s as.new as) ; fi
+
+stage2: force
+ -mkdir stage2
+ -mv -f $(STAGESTUFF) stage2
+ if [ -f stage2/as.new -a ! -f stage2/as ] ; then (cd stage2 ; ln -s as.new as) ; fi
+
+stage3: force
+ -mkdir stage3
+ -mv -f $(STAGESTUFF) stage3
+ if [ -f stage3/as.new -a ! -f stage3/as ] ; then (cd stage3 ; ln -s as.new as) ; fi
+
+against=stage2
+
+comparison: force
+ for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i ; done
+
+de-stage1: force
+ - (cd stage1 ; rm -f as ; mv -f * ..)
+ - rmdir stage1
+
+de-stage2: force
+ - (cd stage2 ; rm -f as ; mv -f * ..)
+ - rmdir stage2
+
+de-stage3: force
+ - (cd stage3 ; rm -f as ; mv -f * ..)
+ - rmdir stage3
+
+#In GNU Make, ignore whether `stage*' exists.
+.PHONY: stage1 stage2 stage3 stage4 clean realclean TAGS bootstrap
+
+force:
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
+
diff --git a/gnu/usr.bin/as/NOTES b/gnu/usr.bin/as/NOTES
new file mode 100644
index 0000000..9f18fac
--- /dev/null
+++ b/gnu/usr.bin/as/NOTES
@@ -0,0 +1,16 @@
+to do:
+
+remove DONTDEF
+remove the ifdef's from fx_callj tests?
+what are callj tests?
+space tighten sparc alignment.
+fix number_to_chars, & family to have no side effects.
+md_ => tp_
+multiple segments.
+share b.out with a.out.
+
+regress:
+
++-inf
+
+stack:
diff --git a/gnu/usr.bin/as/NOTES.config b/gnu/usr.bin/as/NOTES.config
new file mode 100644
index 0000000..a511519
--- /dev/null
+++ b/gnu/usr.bin/as/NOTES.config
@@ -0,0 +1,52 @@
+(This file under construction).
+
+
+ The GAS Configuration Plan
+
+Theory:
+
+The goal of the new configuration scheme is to bury all object format,
+target processor, and host machine dependancies in object, target, and
+host specific files. That is, to move as many #ifdef's as possible
+out of the gas common code.
+
+Here's how it works. There is a .h and a .c file for each object file
+format, a .h and a .c file for each target processor, and a .h for
+each host. configure creates {sym}links in the current directory to
+the appropriate files in the config directory.
+
+Implementation:
+
+host.h is a {sym}link to .../config/ho-yourhost.h. It is intended to
+be used to hide host compiler, system header file, and system library
+differences between host machines. If your host needs actual c source
+files, then either: these are generally useful functions, in which
+case you should probably build a local library outside of the gas
+source tree, or someone, perhaps me, is confused about what is needed
+by different hosts.
+
+obj-format.h is a {sym}link to .../config/obj-something.h. It is
+intended to hide object file format differences from the bulk of gas,
+and from most of the cpu backend.
+
+All gas .c files include as.h.
+
+as.h #define's "gas", includes host.h, defines a number of gas
+specific structures and types, and then includes tp.h, obj.h, and
+target-environment.h.
+
+te-something.h defines a target environment specific preprocessor
+flag, eg, TE_SUN, and then includes obj-format.h.
+
+obj-format.h defines an object format specific preprocessor flag, eg,
+OBJ_AOUT, OBJ_BOUT, OBJ_COFF, includes "target-processor.h", and then
+defines the object specific macros, functions, types, and structures.
+
+target-processor.h
+
+target-processor.
+
+Porting:
+
+There appear to be four major types of ports; new hosts, new target
+processors, new object file formats, and new target environments.
diff --git a/gnu/usr.bin/as/README b/gnu/usr.bin/as/README
new file mode 100644
index 0000000..73b7605
--- /dev/null
+++ b/gnu/usr.bin/as/README
@@ -0,0 +1,212 @@
+This is a pre-alpha version of the GNU assembler, version 1.92.3.
+
+(this is a copy of the mail announcement. Real README follows below.)
+
+This session I merged the m88k support. It configures, builds, and
+assembles things, including some gcc2 output. I have no way of
+knowing if the output is right.
+
+I've merged the tahoe support. It configures and builds. I couldn't
+build the cygnus version of gcc2 for this machine, so I have no idea
+whether gas is assembling anything at all for it.
+
+I've walked through my bug and patch archives. Gas now makes a
+tolerable guess at a.out headers for hpux and sequent, although I have
+no way to know if these are right yet.
+
+Ming tran-le's changes for 386aix will probably drop out soon. He
+needs multiple segments and I don't plan to get that in before the
+real release.
+
+Eric youngdale's help with vms has been invaluable. According to him,
+this gas is doing vms. I didn't quite get a cross to vms working and
+don't plan to spend any more time on it.
+
+The gas manual is included in the distribution, configuration, and
+Makefiles. It should build, be printable, and readable through info.
+
+I have not yet verified that this gas has all of the unreleased
+changes that hack made after the last gas release. At this point I
+plan to ignore these until those bugs are re-reported in an alpha or
+full release I don't think it's worth my time.
+
+I have not yet verified any hosts other than sun4, although I have
+three-staged sun3 native.
+
+I have not updated the configuration doc.
+
+I do not plan to bring in any new backends for the upcoming release
+unless someone hands them to me on a platter as eric did for vms. I
+merged the m88k and tahoe ports because they were simple for me at
+this point, but would have been difficult for someone else. I may yet
+do this for the ncube support as well.
+
+I've looked at the osf stuff and discarded it for this release. I'm
+not sure I like what they've done for macho object format and without
+macho headers, I can't even build their version.
+
+I've looked at the utah stuff and discarded it for this release.
+They, too, have made some sweeping changes to support their object
+format that I'm not sure were necessary. In any case, merging this
+would be too much work for me right now.
+
+I've looked at the tron port. It's remarkably clean and it's a.out
+format. I don't plan to merge this for the full release for two
+reasons. First, it's so clean, they will be able to add their stuff
+on top and build a seperate distribution without much trouble.
+Second, I'm get responses from them, and hope that they will be able
+to do the merge.
+
+
+To do before alpha:
+
+* merge patches and address bugs as they arrive.
+
+* kill a remaining bug. The following input:
+
+ .text
+a .word 3
+b .word 4
+c .half b-a
+
+kills most risc ports. I believe that this represents a failing of
+the internal representation of relocs (aka fixS's). The fix is
+relatively straightforward and I intend to make it.
+
+* add autoconf style configuration for hosts (not targets).
+
+* test via three-staging (preferably with gcc2) on all a.out based
+ machines to which I have access.
+
+* update/clean out README's and build a brief porting guide.
+
+There is still a copyright issue on the coff back end, so it may need
+to be pulled for the full release. If this gets resolved, I hope to
+see coff run personally on at least one native machine before full
+release.
+
+
+Real README:
+
+This is a pre-alpha version of the GNU assembler, version 1.92.3.
+
+A number of things have changed and the wonderful world of gas looks
+very different. There's still a lot of irrelevant garbage lying
+around that will be cleaned up soon. The gas manual now builds and
+installs, but internal documentation is still scarce, as are logs of
+the changes made since the last gas release. My apologies, and I'll
+try to get something useful
+
+At this point I believe gas to be ansi only code for most target
+cpu's. That is, there should be relatively few, if any host system
+dependencies. Most of my recent effort has been spent testing and
+dusting off ports for which Cygnus hasn't had recent need.
+
+Hosting has recently been tested on only:
+
+ sun4
+ sun3
+
+I believe that gas can currently be targetted for:
+
+ sun4
+ sun3
+
+and "ports" for other cpu's and object file formats from the following
+set are probably trivial at this point:
+
+ a.out
+
+ a29k
+ i386
+ i860
+ i960
+ m68k
+ m88k
+ ns32k
+ tahoe
+ sparc
+ vax
+
+I have tested most of these in "generic" a.out configurations so I
+feel pretty confident in them. If anything else works, it's an
+accident.
+
+Some ports now generate object files that are somewhat differently
+shaped, but should be more correct. Specifically:
+
+* Most a.out ports now sort the relocation table in numerically
+ ascending order. In previous versions of gas, the relocation table
+ was sorted in descending order. To get the previous functionality,
+ compile with -DREVERSE_SORT_RELOCS.
+
+* ns32k: The last gas I have from hack simply looks broken for ns32k.
+ I think this one works, but don't have an assembler that I trust
+ against which to compare.
+
+* i386: now uses ".align x" to mean x bytes rather than 2^x bytes. It
+ also pads with the noop instruction rather than zeroes.
+
+In all cases, compiling with -DOLD_GAS will produce an assembler that
+should produce object files that are bitwise identical to the previous
+version of gas.
+
+
+
+ NEW FEATURES!
+
+
+This isn't a complete catalog. I've forgotten what all has been done.
+
+* support for i960, a29k, m88k, and tahoe.
+
+* support for 68030 and 68040, including the ability to limit the
+ instructions that gas will accept. ie, you can assemble for EXACTLY
+ 68000 and no more.
+
+* object file formats have been broken out into separate backends.
+
+* a new "backend" has been created to represent the target
+ environment. That is, gas now mimics various other assemblers
+ rather than creating it's own requirements. A side effect of this
+ is that this version of gas may not behave the same way as previous
+ versions.
+
+* ansi. gas is now strictly ansi code so host ports should be
+ trivial.
+
+
+
+ REPORTING BUGS IN GAS
+
+
+Bugs in THIS RELEASE of gas should be reported directly to
+rich@cygnus.com. NOT to bug-gnu-utils@prep.ai.mit.edu.
+
+If you report a bug in GAS, please remember to include:
+
+A description of exactly what went wrong.
+
+How GAS was configured,
+
+The Operating System GAS was running under.
+
+The options given to GAS.
+
+The actual input file that caused the problem.
+
+It is silly to report a bug in GAS without including an input file for
+GAS. Don't ask us to generate the file just because you made it from
+files you think we have access to.
+
+1. You might be mistaken.
+2. It might take us a lot of time to install things to regenerate that file.
+3. We might get a different file from the one you got, and might not see any
+bug.
+
+To save us these delays and uncertainties, always send the input file
+for the program that failed.
+
+If the input file is very large, and you are on the internet, you may
+want to make it avaliable for anonymous FTP instead of mailing it. If you
+do, include instructions for FTP'ing it in your bug report.
diff --git a/gnu/usr.bin/as/README-vms b/gnu/usr.bin/as/README-vms
new file mode 100644
index 0000000..796c603
--- /dev/null
+++ b/gnu/usr.bin/as/README-vms
@@ -0,0 +1,248 @@
+ This document explains a couple of things that are specific to VMS.
+There are currently two "chapters", the first deals with cross-assembly
+issues, and the second deals with the VMS debugger and GNU-CC.
+
+
+***********************************************************************
+****************** Notes for Cross Assembly with VMS ******************
+***********************************************************************
+
+ If you wish to build gas on a non-VMS system to cross-assemble,
+you should use:
+
+configure ${hosttype} -target=vms
+
+and then follow the usual procedure. The object files generated on
+Unix will be correct from a binary point of view, but the real trick is
+getting them to the VMS machine. The format of the object file is
+a variable-length record, but each record contains binary data. gas
+writes the records in the same format that VMS would expect,
+namely a two-byte count followed by that number of bytes.
+
+ If you try to copy the file to a VMS system using ftp, the ftp
+protocol will screw up the file by looking for nulls (record terminator for
+unix) and it will insert it's own record terminators at that point. This
+will obviously corrupt the file.
+
+ If you try to transfer the file with ftp in binary mode, the
+file itself will not be corrupt, but VMS will think that the file contains
+fixed-length records of 512 bytes. You can use the public-domain FILE
+utility to change this with a command like:
+
+$FILE foo.o/type=variable
+
+If you do not have this utility available, the following program can be
+used to perform this task:
+
+ #include <fab.h>
+
+ #define RME$C_SETRFM 1
+
+ struct FAB * fab;
+
+ main(int argc, char * argv[]){
+ int i, status;
+ fab = (struct FAB*) malloc(sizeof(struct FAB));
+ *fab = cc$rms_fab; /* initialize FAB*/
+ fab->fab$b_fac = FAB$M_PUT;
+ fab->fab$l_fop |= FAB$M_ESC;
+ fab->fab$l_ctx = RME$C_SETRFM;
+ fab->fab$w_ifi = 0;
+ for(i=1;i<argc;i++){
+ printf("Setting %s to variable length records.\n",argv[i]);
+ fab->fab$l_fna = argv[i];
+ fab->fab$b_fns = strlen(argv[i]);
+ status = sys$open(fab,0,0);
+ if((status & 7) != 1) lib$signal(status);
+ fab->fab$b_rfm = FAB$C_VAR;
+ status = sys$modify(fab,0,0);
+ if((status & 7) != 1) lib$signal(status);
+ status = sys$close(fab,0,0);
+ if((status & 7) != 1) lib$signal(status);
+ };
+ }
+
+ If you have NFS running on the VMS system, what you need to do
+depends upon which NFS software you are running on the VMS system. There
+are a number of different TCP/IP packages for VMS available, and only very
+limited testing has been performed. In the tests that has been done so
+far, the contents of the file will always be correct when transferring the
+file via NFS, but the record attributes may or may not be correct.
+
+ One proprietary TCP/IP/NFS package for VMS is known to
+automatically fix the record attributes of the object file if you NFS mount
+a unix disk from the VMS system, and if the file has a ".obj" extension on
+the unix system. Other TCP/IP packages might do this for you as well, but
+they have not been checked.
+
+No matter what method you use to get the file to the VMS system, it is
+always a good idea to check to make sure that it is the correct type by
+doing a "$dir/full" on the object file. The desired record attributes will
+be "None". Undesirable record attributes will be "Stream-LF" or anything
+else.
+
+Once you get the files on the VMS system, you can check their integrity
+with the "$anal/obj" command. (Naturally at some point you should rename
+the .o files to .obj). As far as the debugger is concerned, the records
+will be correct, but the debugger will not be able to find the source files,
+since it only has the file name, and not the full directory specification.
+You must give the debugger some help by telling it which directories to
+search for the individual files - once you have done this you should be
+able to proceed normally.
+
+ It is a good idea to use names for your files which will be valid
+under VMS, since otherwise you will have no way of getting the debugger to
+find the source file when deugging.
+
+The reason for this is that the object file normally contins specific
+information that the debugger can use to positively identify a file, and if
+you are assembling on a unix system this information simply does not exist
+in a meaningful way. You must help the debugger by using the "SET FILE="
+command to tell the debugger where to look for source files. The debugger
+records will be correct, except that the debugger will not be initially
+able to find the source files. You can use the "SET FILE" command to tell
+the debugger where to look for the source files.
+
+I have only tested this with a SVr4 i486 machine, and everything seems to
+work OK, with the limited testing that I have done. Other machines may
+or may not work. You should read the chapters on cross-compilers in the gcc
+manual before fooling with this. Since gas does not need to do any floating
+point arithmetic, the floating point constants that are generated here should
+be correct - the only concern is with constant folding in the main compiler.
+The range and precision of floats and doubles are similar on the 486 (with
+a builtin 80387) and the VAX, although there is a factor of 2 to 4
+difference in the range. The double, as implemented on the 486, is quite
+similar to the G_FLOAT on the VAX.
+
+***********************************************************************
+****************** Notes for using GNU CC with the VMS debugger********
+***********************************************************************
+
+
+ 1) You should be aware that GNU-C, as with any other decent compiler,
+will do things when optimization is turned on that you may not expect.
+Sometimes intermediate results are not written to variables, if they are only
+used in one place, and sometimes variables that are not used at all will not be
+written to the symbol table. Also, parameters to inline functions are often
+inaccessible. You can see the assembly code equivalent by using KP7 in the
+debugger, and from this you can tell if in fact a variable should have the
+value that you expect. You can find out if a variable lives withing a register
+by doing a 'show symbol/addr'.
+
+ 2) Overly complex data types, such as:
+
+int (*(*(*(*(*(* sarr6)[1])[1])[2])[3])[4])[5];
+
+will not be debugged properly, since the debugging record overflows an internal
+debugger buffer. gcc-as will convert these to *void as far as the debugger
+symbol table is concerned, which will avoid any problems, and the assembler
+will give you a message informing you that this has happened.
+
+ 3) You must, of course, compile and link with /debug. If you link
+without debug, you still get traceback table in the executable, but there is no
+symbol table for variables.
+
+ 4) Included in the patches to VMS.C are fixes to two bugs that are
+unrelated to the changes that I have made. One of these made it impossible to
+debug small programs sometimes, and the other caused the debugger to become
+confused about which routine it was in, and give this incorrect info in
+tracebacks.
+
+ 5) If you are using the GNU-C++ compiler, you should modify the
+compiler driver file GNU_CC:[000000]GCC.COM (or GXX.COM). If you have a
+seperate GXX.COM, then you need to change one line in GXX.COM to:
+$ if f$locate("D",p2) .ne. P2_Length then Debug = " ""-G0"""
+ Notice zero---> ^
+If you are using a GCC.COM that does both C and C++, add the following lines to
+GCC.COM:
+
+$!
+$! Use old style debugging records for VMS
+$!
+$ if (Debug.nes."" ).and. Plus then Debug = " ""-G0"""
+
+after the variables Plus and Debug are set. The reason for this, is that C++
+compiler by default generates debugging records that are more complex,
+with many new syntactical elements that allow for the new features of the
+language. The -G0 switch tells the C++ compiler to use the old style debugging
+records. Until the debugger understands C++ there is not any point to try and
+use the expanded syntax.
+
+ 6) When you have nested scopes, i.e.:
+main(){
+ int i;
+ {int i;
+ {int i;
+};};}
+and you say "EXAM i" the debugger needs to figure out which variable you
+actually want to reference. I have arranged things to define a block to the
+debugger when you use brackets to enter a new scope, so in the example above,
+the variables would be described as:
+TEST\main\i
+TEST\main\$0\i
+TEST\main\$0\$0\i
+At each level, the block name is a number with a dollar sign prefix, the
+numbers start with 0 and count upward. When you say EXAM i, the debugger looks
+at the current PC, and decides which block it is currently in. It works from
+the innermost level outward until it finds a block that has the variable "i"
+defined. You can always specify the scope explicitly.
+
+ 7) With C++, there can be a lot of inline functions, and it would be
+rather restrictive to force the user to debug the program by converting all of
+the inline functions to normal functions. What I have done is to essentially
+"add" (with the debugger) source lines from the include files that contain the
+inline functions. Thus when you step into an inline function it appears as if
+you have called the function, and you can examine variables and so forth.
+There are several *very* important differences, however. First of all, since
+there is no function call involved, you cannot step over the inline function
+call - you always step into it. Secondly, since the same source lines are used
+in many locations, there is a seperate copy of the source for *each* usage.
+Without this, breakpoints do not work, since we must have a 1-to-1 mapping
+between source lines and PC.
+ Since you cannot step over inline function calls, it can be a real pain
+if you are not really interested in what is going on for that function call.
+What I have done is to use the "-D" switch for the assembler to toggle the
+following behavior. With the "-D" switch, all inline functions are included in
+the object file, and you can debug everything. Without the "-D" switch
+(default case with VMS implementation), inline functions are included *only* if
+they did not come from system header files (i.e. from GNU_CC_INCLUDE: or
+GNU_GXX_INCLUDE:). Thus, without the switch the user only debugs his/her own
+inline functions, and not the system ones. (This is especially useful if you do
+a lot of stream I/O in C++). This probably will not provide enough granularity
+for many users, but for now this is still somewhat experimental, and I would
+like to reflect upon it and get some feedback before I go any further.
+Possible solutions include an interactive prompting, a logical name, or a new
+command line option in gcc.c (which is then passed through somehow to the guts
+of the assembler).
+ The inline functions from header files appear after the source code
+for the source file. This has the advantage that the source file itself is
+numbered with the same line numbers that you get with an editor. In addition,
+the entire header file is not included, since the assembler makes a list of
+the min and max source lines that are used, and only includes those lines from
+the first to the last actually used. (It is easy to change it to include the
+whole file).
+
+ 8) When you are debugging C++ objects, the object "this" is refered to
+as "$this". Actually, the compiler writes it as ".this", but the period is
+not good for the debugger, so I have a routine to convert it to a $. (It
+actually converts all periods to $, but only for variables, since this was
+intended to allow us to access "this".
+
+ 9) If you use the asm("...") keyword for global symbols, you will not
+be able to see that symbol with the debugger. The reason is that there are two
+records for the symbol stored in the data structures of the assembler. One
+contains the info such as psect number and offset, and the other one contains
+the information having to do with the data type of the variable. In order to
+debug as symbol, you need to be able to coorelate these records, and the only
+way to do this is by name. The record with the storage attributes will take
+the name used in the asm directive, and the record that specifies the data type
+has the actual variable name, and thus when you use the asm directive to change
+a variable name, the symbol becomes invisible.
+
+ 10) Older versions of the compiler ( GNU-C 1.37.92 and earlier) place
+global constants in the text psect. This is unfortunate, since to the linker
+this appears to be an entry point. I sent a patch to the compiler to RMS,
+which will generate a .const section for these variables, and patched the
+assembler to put these variables into a psect just like that for normal
+variables, except that they are marked NOWRT. static constants are still
+placed in the text psect, since there is no need for any external access.
diff --git a/gnu/usr.bin/as/README.coff b/gnu/usr.bin/as/README.coff
new file mode 100644
index 0000000..46c61cd
--- /dev/null
+++ b/gnu/usr.bin/as/README.coff
@@ -0,0 +1,79 @@
+The coff patches intend to do the following :
+
+ . Generate coff files very compatible with vanilla linker.
+ . Understands coff debug directives.
+
+Here are the guidelines of the work I have done :
+
+ . Encapsulate format dependent code in macros where it is possible.
+ . Where not possible differenciate with #ifdef
+ . try not to change the calling conventions of the existing functions.
+ I made one exception : symbol_new. I would be pleased to hear about
+ a better solution. (symbols.c)
+ . Extend the use of N_TYPE_seg seg_N_TYPE tables so that segments can
+ be manipulated without using their format dependent name. (subsegs.c)
+ . Write a function to parse the .def debug directives
+ . Write two small peaces of code to handle the .ln directive.
+ . In write.c try to move all the cross compilation specifics (md_..) to
+ format dependent files.
+ . Encapsulate the data structures using generic types, macros calls.
+ . Added too much code to resolve the complexity of the symbol table
+ generated. Most of the code deals with debug stuff.
+ . Create another makefile, shorter, cleaner.
+ . Create a config.gas shell script to mimic the gcc,gdb... configuration
+ mechanism. This reduce the complexity of the makefile.
+ . Isolate the format dependent code in two files
+ coff.c coff.h
+ aout.c aout.h
+ elf.c elf.h [ Not yet ;-]
+ . added a little stack management routine for coff in file stack.c
+ . isolate os specific flags in m- files
+
+If further development is planed on it is should solve the following problems :
+
+ . Encapsulate DESC & OTHER tests in a macro call. I'm not aware
+ of their exact semantics.
+ . Clean up the seg_N_TYPE N_TYPE_seg naming scheme
+ . Try to remove as much reference to segment dependent names as possible
+ . Find a cleaner solution for symbol_new.
+ . Report the modifications on vax, ns32k, sparc machine dependent files.
+ To acheive this goal, search for \<N_, sy_, symbol_new and symbolS.
+ . Allow an arbitrary number of segments (spare sections .ctor .dtor .bletch)
+ . Find a way to extend the debug information without breaking sdb
+ compatibility. Mainly intended for G++.
+ . should it do something to generate shared libraries objects ?
+
+I have tested this code on the following processor/os. gcc-1.37.1 was
+ used for all the tests.
+
+386 SCO unix ODT
+ gcc-1.37.1, gas, emacs-18.55
+
+386 Esix rev C
+ gas-1.37/write.s
+
+386 Ix 2.02
+ gas, all the X11R4 mit clients
+
+386 CTIX 3.2
+ xsol (X11R4 solitary game), gas
+
+68030 unisoft 1.3
+ the kernel (V.3.2) + tcp/ip extensions
+ bash-1.05, bison-1.11, compress-4.0, cproto, shar-3.49, diff-1.14,
+ dist-18.55, flex-2.3, gas-1.37, gcc-1.37.1, gdb-3.6, grep-1.5,
+ kermit, make-3.58, makedep, patch, printf, makeinfo, g++-1.37.1,
+ tar-1.08, texi2roff, uuencode, uutraf-1.2, libg++-1.37.2, groff-0.5
+
+68020 sunos 3.5 (no, not coff, just to be sure that I didn't
+ introduce errors)
+ gcc-1.37.1, gas, emacs-18.55, gdb-3.6, bison-1.11, diff-1.14,
+ make-3.58, tar-1.08
+
+68030 sunos 4.0.3 (idem)
+ gas
+
+I would be glad to hear about new experiences
+
+ Loic (loic@adesign.uucp or loic@afp.uucp)
+
diff --git a/gnu/usr.bin/as/README.pic b/gnu/usr.bin/as/README.pic
new file mode 100644
index 0000000..adde6fe
--- /dev/null
+++ b/gnu/usr.bin/as/README.pic
@@ -0,0 +1,25 @@
+A few short notes on PIC support.
+
+. References to the symbol "_GLOBAL_OFFSET_TABLE_" are special. These always
+ PC relative to the start of the current instruction. Also, they occur
+ in "complex" expressions in function prologs, eg.
+
+ move _GLOBAL_OFFSET_TABLE_ + (. - L1 ), %some_register
+
+ The expression parser can't handle these generically, so the expression
+ above is recognised as a special case.
+
+. Some archs have special PIC assembler syntax to reference static and global
+ data. This is handled in targ-cpu.c.
+
+. Correct relocation_info must be output (eg. fields r_jmptable and r_baserel).
+
+. Internal labels must be output in the symbol table if they are referred to
+ by PIC instructions. The linker must allocate a GOT slot for them.
+
+. The former meaning of the -k switch ("WORKING_DOT" stuff), has been nuked
+ in favour of enabling PIC code recognition.
+
+
+-pk
+
diff --git a/gnu/usr.bin/as/README.rich b/gnu/usr.bin/as/README.rich
new file mode 100644
index 0000000..5a2ecc4
--- /dev/null
+++ b/gnu/usr.bin/as/README.rich
@@ -0,0 +1,144 @@
+(This file is under construction.)
+
+
+ The Code Pedigree of This Directory
+
+
+This directory contains a big merge of several development lines of
+gas as well as a few bug fixes and some configuration that I've added
+in order to retain my own sanity.
+
+A little history.
+
+The only common baseline of all versions was gas-1.31.
+
+From 1.31, Intel branched off and added:
+
+ support for the Intel 80960 (i960) processor.
+ support for b.out object files.
+ some bug fixes.
+ sloppy mac MPW support
+ Intel gnu/960 makefiles and version numbering.
+
+Many of the bug fixes found their way into the main development line
+prior to 1.36. ALL intel changes were ifdef'd I80960. This was good
+as it isolated the changes, but bad in that it connected the b.out
+support to the i960 support, and bad in that the bug fixes were only
+active in the i960+b.out executables of gas, (although most of these
+were nicely marked with comments indicating that they were probably
+general bug fixes.)
+
+To pick up the main FSF development line again, along the way to 1.36,
+several new processors were added, many bugs fixed, and the world was
+a somewhat better place in general.
+
+From gas-1.36, Loic at Axis Design (france!) encapsulated object
+format specific actions, added coff versions of those encapsulations,
+and a config.gas style configuration and Makefile. This was a big
+change and a lot of work.
+
+Then along came the FIRST FSF release of gas-1.37. I say this because
+there have been at least two releases of gas-1.37. Only two of them
+do we care about for this story, so let's call them gas-1.37.1 and
+gas-1.37.2.
+
+Here starts the confusion. Firstly, gas-1.37.1 did not compile.
+
+In the meantime, John Gilmore at Cygnus Support had been hacking
+gas-1.37.1. He got it to compile. He added support for the AMD 29000
+processor. AND he started encapsulating some of the a.out specific
+pieces of code mostly into functions. AND he rebuilt the relocation
+info to be generic. AND he restructured somewhat so that for a single
+host, cross assemblers could be built for all targets in the same
+directory. Useful work but a considerable nuisance because the a29k
+changes were not partitioned from the encapsulation changes, the
+encapsulation changes were incomplete, and the encapsulation required
+functions where alternate structuring might have used macros. Let's
+call this version gas-1.37.1+a29k.
+
+By the time gas-1.37.2 was "released", (remember that it TOO was
+labelled by FSF as gas-1.37), it compiled, but it also added i860
+support and ansi style const declarations.
+
+At this point, Loic rolled his changes into gas-1.37.2.
+
+What I've done.
+
+I collected all the stray versions of gas that sounded relevant to my
+goals of cross assembly and alternate object file formats and the FSF
+releases from which the stray versions had branched.
+
+I rolled the Intel i960 changes from 1.31 into versions that I call
+1.34+i960, 1.36+i960, and then 1.37.1+i960.
+
+Then I merged 1.37.1+i960 with 1.37.1+a29k to produce what I call
+1.37.1+i960+a29k or 1.37.3.
+
+From 1.37.3, I pulled in Loic's stuff. This wasn't easy as Loic's
+stuff hit all the same points as John's encapsulations. Loic's goal
+was to split the a.out from coff dependancies for native assembly on
+coff, while John's was to split for multiple cross assembly from a
+single host.
+
+Loic's config arranged files much like emacs into m-*, etc. I've
+rearranged these somewhat.
+
+Theory:
+
+The goal of the new configuration scheme is to bury all object format,
+target processor, and host machine dependancies in object, target, and
+host specific files. That is, to move all #ifdef's out of the gas
+common code.
+
+Here's how it works. There is a .h and a .c file for each object file
+format, a .h and a .c file for each target processor, and a .h for
+each host. config.gas creates {sym}links in the current directory to
+the appropriate files in the config directory. config.gas also serves
+as a list of triplets {host, target, object-format} that have been
+tested at one time or another. I also recommend that config.gas be
+used to document triplet specific notes as to purpose of the triplet,
+etc.
+
+Implementation:
+
+host.h is a {sym}link to .../config/xm-yourhost.h. It is intended to
+be used to hide host compiler, system header file, and system library
+differences between host machines. If your host needs actual c source
+files, then either: these are generally useful functions, in which
+case you should probably build a local library outside of the gas
+source tree, or someone, perhaps me, is confused about what is needed
+by different hosts.
+
+obj-format.h is a {sym}link to .../config/obj-something.h. It is intended
+
+All gas .c files include as.h.
+
+as.h #define's "gas", includes host.h, defines a number of gas
+specific structures and types, and then includes tp.h, obj.h, and
+target-environment.h.
+
+target-environment.h defines a target environment specific
+preprocessor flag, eg, TE_SUN, and then includes obj-format.h.
+
+obj-format.h defines an object format specific preprocessor flag, eg,
+OBJ_AOUT, OBJ_BOUT, OBJ_COFF, includes "target-processor.h", and then
+defines the object specific macros, functions, types, and structures.
+
+target-processor.h
+
+target-processor.
+
+Porting:
+
+There appear to be four major types of ports; new hosts, new target
+processors, new object file formats, and new target environments.
+
+
+-----
+
+reloc now stored internally as generic. (symbols too?) (segment types
+vs. names?)
+
+I don't mean to overlook anyone here. There have also been several
+other development lines here that I looked at and elected to bypass.
+Specifically, xxx's stabs in coff stuff was particularly tempting.
diff --git a/gnu/usr.bin/as/VERSION b/gnu/usr.bin/as/VERSION
new file mode 100644
index 0000000..a3f79bb
--- /dev/null
+++ b/gnu/usr.bin/as/VERSION
@@ -0,0 +1 @@
+1.92.3
diff --git a/gnu/usr.bin/as/app.c b/gnu/usr.bin/as/app.c
new file mode 100644
index 0000000..130fb1e
--- /dev/null
+++ b/gnu/usr.bin/as/app.c
@@ -0,0 +1,746 @@
+/* This is the Assembler Pre-Processor
+ Copyright (C) 1987, 1990, 1991, 1992, 1994 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Modified by Allen Wirfs-Brock, Instantiations Inc 2/90 */
+/* App, the assembler pre-processor. This pre-processor strips out excess
+ spaces, turns single-quoted characters into a decimal constant, and turns
+ # <number> <filename> <garbage> into a .line <number>\n.file <filename>
+ pair. This needs better error-handling. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <stdio.h>
+#include "as.h" /* For BAD_CASE() only */
+
+#if (__STDC__ != 1)
+#ifndef const
+#define const /* empty */
+#endif
+#endif
+
+static char lex[256];
+static const char symbol_chars[] =
+"$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+#define LEX_IS_SYMBOL_COMPONENT 1
+#define LEX_IS_WHITESPACE 2
+#define LEX_IS_LINE_SEPARATOR 3
+#define LEX_IS_COMMENT_START 4
+#define LEX_IS_LINE_COMMENT_START 5
+#define LEX_IS_TWOCHAR_COMMENT_1ST 6
+#define LEX_IS_TWOCHAR_COMMENT_2ND 7
+#define LEX_IS_STRINGQUOTE 8
+#define LEX_IS_COLON 9
+#define LEX_IS_NEWLINE 10
+#define LEX_IS_ONECHAR_QUOTE 11
+#define IS_SYMBOL_COMPONENT(c) (lex[c] == LEX_IS_SYMBOL_COMPONENT)
+#define IS_WHITESPACE(c) (lex[c] == LEX_IS_WHITESPACE)
+#define IS_LINE_SEPARATOR(c) (lex[c] == LEX_IS_LINE_SEPARATOR)
+#define IS_COMMENT(c) (lex[c] == LEX_IS_COMMENT_START)
+#define IS_LINE_COMMENT(c) (lex[c] == LEX_IS_LINE_COMMENT_START)
+#define IS_NEWLINE(c) (lex[c] == LEX_IS_NEWLINE)
+
+static int process_escape PARAMS ((int));
+
+/* FIXME-soon: The entire lexer/parser thingy should be
+ built statically at compile time rather than dynamically
+ each and every time the assembler is run. xoxorich. */
+
+void
+do_scrub_begin ()
+{
+ const char *p;
+
+ lex[' '] = LEX_IS_WHITESPACE;
+ lex['\t'] = LEX_IS_WHITESPACE;
+ lex['\n'] = LEX_IS_NEWLINE;
+ lex[';'] = LEX_IS_LINE_SEPARATOR;
+ lex['"'] = LEX_IS_STRINGQUOTE;
+#ifndef TC_HPPA
+ lex['\''] = LEX_IS_ONECHAR_QUOTE;
+#endif
+ lex[':'] = LEX_IS_COLON;
+
+
+
+#ifdef SINGLE_QUOTE_STRINGS
+ lex['\''] = LEX_IS_STRINGQUOTE;
+#endif
+
+ /* Note that these override the previous defaults, e.g. if ';' is a
+ comment char, then it isn't a line separator. */
+ for (p = symbol_chars; *p; ++p)
+ {
+ lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
+ } /* declare symbol characters */
+
+ for (p = comment_chars; *p; p++)
+ {
+ lex[(unsigned char) *p] = LEX_IS_COMMENT_START;
+ } /* declare comment chars */
+
+ for (p = line_comment_chars; *p; p++)
+ {
+ lex[(unsigned char) *p] = LEX_IS_LINE_COMMENT_START;
+ } /* declare line comment chars */
+
+ for (p = line_separator_chars; *p; p++)
+ {
+ lex[(unsigned char) *p] = LEX_IS_LINE_SEPARATOR;
+ } /* declare line separators */
+
+ /* Only allow slash-star comments if slash is not in use */
+ if (lex['/'] == 0)
+ {
+ lex['/'] = LEX_IS_TWOCHAR_COMMENT_1ST;
+ }
+ /* FIXME-soon. This is a bad hack but otherwise, we can't do
+ c-style comments when '/' is a line comment char. xoxorich. */
+ if (lex['*'] == 0)
+ {
+ lex['*'] = LEX_IS_TWOCHAR_COMMENT_2ND;
+ }
+} /* do_scrub_begin() */
+
+FILE *scrub_file;
+
+int
+scrub_from_file ()
+{
+ return getc (scrub_file);
+}
+
+void
+scrub_to_file (ch)
+ int ch;
+{
+ ungetc (ch, scrub_file);
+} /* scrub_to_file() */
+
+char *scrub_string;
+char *scrub_last_string;
+
+int
+scrub_from_string ()
+{
+ return scrub_string == scrub_last_string ? EOF : *scrub_string++;
+} /* scrub_from_string() */
+
+void
+scrub_to_string (ch)
+ int ch;
+{
+ *--scrub_string = ch;
+} /* scrub_to_string() */
+
+/* Saved state of the scrubber */
+static int state;
+static int old_state;
+static char *out_string;
+static char out_buf[20];
+static int add_newlines = 0;
+
+/* Data structure for saving the state of app across #include's. Note that
+ app is called asynchronously to the parsing of the .include's, so our
+ state at the time .include is interpreted is completely unrelated.
+ That's why we have to save it all. */
+
+struct app_save
+ {
+ int state;
+ int old_state;
+ char *out_string;
+ char out_buf[sizeof (out_buf)];
+ int add_newlines;
+ char *scrub_string;
+ char *scrub_last_string;
+ FILE *scrub_file;
+ };
+
+char *
+app_push ()
+{
+ register struct app_save *saved;
+
+ saved = (struct app_save *) xmalloc (sizeof (*saved));
+ saved->state = state;
+ saved->old_state = old_state;
+ saved->out_string = out_string;
+ memcpy (saved->out_buf, out_buf, sizeof (out_buf));
+ saved->add_newlines = add_newlines;
+ saved->scrub_string = scrub_string;
+ saved->scrub_last_string = scrub_last_string;
+ saved->scrub_file = scrub_file;
+
+ /* do_scrub_begin() is not useful, just wastes time. */
+ return (char *) saved;
+}
+
+void
+app_pop (arg)
+ char *arg;
+{
+ register struct app_save *saved = (struct app_save *) arg;
+
+ /* There is no do_scrub_end (). */
+ state = saved->state;
+ old_state = saved->old_state;
+ out_string = saved->out_string;
+ memcpy (out_buf, saved->out_buf, sizeof (out_buf));
+ add_newlines = saved->add_newlines;
+ scrub_string = saved->scrub_string;
+ scrub_last_string = saved->scrub_last_string;
+ scrub_file = saved->scrub_file;
+
+ free (arg);
+} /* app_pop() */
+
+/* @@ This assumes that \n &c are the same on host and target. This is not
+ necessarily true. */
+static int
+process_escape (ch)
+ int ch;
+{
+ switch (ch)
+ {
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case '\'':
+ return '\'';
+ case '"':
+ return '\"';
+ default:
+ return ch;
+ }
+}
+int
+do_scrub_next_char (get, unget)
+ int (*get) ();
+ void (*unget) ();
+{
+ /*State 0: beginning of normal line
+ 1: After first whitespace on line (flush more white)
+ 2: After first non-white (opcode) on line (keep 1white)
+ 3: after second white on line (into operands) (flush white)
+ 4: after putting out a .line, put out digits
+ 5: parsing a string, then go to old-state
+ 6: putting out \ escape in a "d string.
+ 7: After putting out a .appfile, put out string.
+ 8: After putting out a .appfile string, flush until newline.
+ 9: After seeing symbol char in state 3 (keep 1white after symchar)
+ 10: After seeing whitespace in state 9 (keep white before symchar)
+ 11: After seeing a symbol character in state 0 (eg a label definition)
+ -1: output string in out_string and go to the state in old_state
+ -2: flush text until a '*' '/' is seen, then go to state old_state
+ */
+
+ /* I added states 9 and 10 because the MIPS ECOFF assembler uses
+ constructs like ``.loc 1 20''. This was turning into ``.loc
+ 120''. States 9 and 10 ensure that a space is never dropped in
+ between characters which could appear in a identifier. Ian
+ Taylor, ian@cygnus.com.
+
+ I added state 11 so that something like "Lfoo add %r25,%r26,%r27" works
+ correctly on the PA (and any other target where colons are optional).
+ Jeff Law, law@cs.utah.edu. */
+
+ register int ch, ch2 = 0;
+ int not_cpp_line = 0;
+
+ switch (state)
+ {
+ case -1:
+ ch = *out_string++;
+ if (*out_string == 0)
+ {
+ state = old_state;
+ old_state = 3;
+ }
+ return ch;
+
+ case -2:
+ for (;;)
+ {
+ do
+ {
+ ch = (*get) ();
+ }
+ while (ch != EOF && ch != '\n' && ch != '*');
+ if (ch == '\n' || ch == EOF)
+ return ch;
+
+ /* At this point, ch must be a '*' */
+ while ((ch = (*get) ()) == '*')
+ {
+ ;
+ }
+ if (ch == EOF || ch == '/')
+ break;
+ (*unget) (ch);
+ }
+ state = old_state;
+ return ' ';
+
+ case 4:
+ ch = (*get) ();
+ if (ch == EOF || (ch >= '0' && ch <= '9'))
+ return ch;
+ else
+ {
+ while (ch != EOF && IS_WHITESPACE (ch))
+ ch = (*get) ();
+ if (ch == '"')
+ {
+ (*unget) (ch);
+ out_string = "\n\t.appfile ";
+ old_state = 7;
+ state = -1;
+ return *out_string++;
+ }
+ else
+ {
+ while (ch != EOF && ch != '\n')
+ ch = (*get) ();
+ state = 0;
+ return ch;
+ }
+ }
+
+ case 5:
+ ch = (*get) ();
+ if (lex[ch] == LEX_IS_STRINGQUOTE)
+ {
+ state = old_state;
+ return ch;
+ }
+#ifndef NO_STRING_ESCAPES
+ else if (ch == '\\')
+ {
+ state = 6;
+ return ch;
+ }
+#endif
+ else if (ch == EOF)
+ {
+ as_warn ("End of file in string: inserted '\"'");
+ state = old_state;
+ (*unget) ('\n');
+ return '"';
+ }
+ else
+ {
+ return ch;
+ }
+
+ case 6:
+ state = 5;
+ ch = (*get) ();
+ switch (ch)
+ {
+ /* Handle strings broken across lines, by turning '\n' into
+ '\\' and 'n'. */
+ case '\n':
+ (*unget) ('n');
+ add_newlines++;
+ return '\\';
+
+ case '"':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+#ifdef BACKSLASH_V
+ case 'v':
+#endif /* BACKSLASH_V */
+ case 'x':
+ case 'X':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ break;
+#if defined(IGNORE_NONSTANDARD_ESCAPES) | defined(ONLY_STANDARD_ESCAPES)
+ default:
+ as_warn ("Unknown escape '\\%c' in string: Ignored", ch);
+ break;
+#else /* ONLY_STANDARD_ESCAPES */
+ default:
+ /* Accept \x as x for any x */
+ break;
+#endif /* ONLY_STANDARD_ESCAPES */
+
+ case EOF:
+ as_warn ("End of file in string: '\"' inserted");
+ return '"';
+ }
+ return ch;
+
+ case 7:
+ ch = (*get) ();
+ state = 5;
+ old_state = 8;
+ return ch;
+
+ case 8:
+ do
+ ch = (*get) ();
+ while (ch != '\n');
+ state = 0;
+ return ch;
+ }
+
+ /* OK, we are somewhere in states 0 through 4 or 9 through 11 */
+
+ /* flushchar: */
+ ch = (*get) ();
+recycle:
+ if (ch == EOF)
+ {
+ if (state != 0)
+ as_warn ("End of file not at end of a line: Newline inserted.");
+ return ch;
+ }
+
+ switch (lex[ch])
+ {
+ case LEX_IS_WHITESPACE:
+ do
+ /* Preserve a single whitespace character at the beginning of
+ a line. */
+ if (state == 0)
+ {
+ state = 1;
+ return ch;
+ }
+ else
+ ch = (*get) ();
+ while (ch != EOF && IS_WHITESPACE (ch));
+ if (ch == EOF)
+ return ch;
+
+ if (IS_COMMENT (ch)
+ || (state == 0 && IS_LINE_COMMENT (ch))
+ || ch == '/'
+ || IS_LINE_SEPARATOR (ch))
+ {
+ /* cpp never outputs a leading space before the #, so try to
+ avoid being confused. */
+ not_cpp_line = 1;
+ goto recycle;
+ }
+#ifdef MRI
+ (*unget) (ch); /* Put back */
+ return ' '; /* Always return one space at start of line */
+#endif
+
+ /* If we're in state 2 or 11, we've seen a non-white character
+ followed by whitespace. If the next character is ':', this
+ is whitespace after a label name which we *must* ignore. */
+ if ((state == 2 || state == 11) && lex[ch] == LEX_IS_COLON)
+ {
+ state = 1;
+ return ch;
+ }
+
+ switch (state)
+ {
+ case 0:
+ state++;
+ goto recycle; /* Punted leading sp */
+ case 1:
+ /* We can arrive here if we leave a leading whitespace character
+ at the beginning of a line. */
+ goto recycle;
+ case 2:
+ state = 3;
+ (*unget) (ch);
+ return ' '; /* Sp after opco */
+ case 3:
+ goto recycle; /* Sp in operands */
+ case 9:
+ case 10:
+ state = 10; /* Sp after symbol char */
+ goto recycle;
+ case 11:
+ state = 1;
+ (*unget) (ch);
+ return ' '; /* Sp after label definition. */
+ default:
+ BAD_CASE (state);
+ }
+ break;
+
+ case LEX_IS_TWOCHAR_COMMENT_1ST:
+ ch2 = (*get) ();
+ if (ch2 != EOF && lex[ch2] == LEX_IS_TWOCHAR_COMMENT_2ND)
+ {
+ for (;;)
+ {
+ do
+ {
+ ch2 = (*get) ();
+ if (ch2 != EOF && IS_NEWLINE (ch2))
+ add_newlines++;
+ }
+ while (ch2 != EOF &&
+ (lex[ch2] != LEX_IS_TWOCHAR_COMMENT_2ND));
+
+ while (ch2 != EOF &&
+ (lex[ch2] == LEX_IS_TWOCHAR_COMMENT_2ND))
+ {
+ ch2 = (*get) ();
+ }
+
+ if (ch2 == EOF
+ || lex[ch2] == LEX_IS_TWOCHAR_COMMENT_1ST)
+ break;
+ (*unget) (ch);
+ }
+ if (ch2 == EOF)
+ as_warn ("End of file in multiline comment");
+
+ ch = ' ';
+ goto recycle;
+ }
+ else
+ {
+ if (ch2 != EOF)
+ (*unget) (ch2);
+ if (state == 9 || state == 10)
+ state = 3;
+ return ch;
+ }
+ break;
+
+ case LEX_IS_STRINGQUOTE:
+ if (state == 9 || state == 10)
+ old_state = 3;
+ else
+ old_state = state;
+ state = 5;
+ return ch;
+#ifndef MRI
+#ifndef IEEE_STYLE
+ case LEX_IS_ONECHAR_QUOTE:
+ ch = (*get) ();
+ if (ch == EOF)
+ {
+ as_warn ("End-of-file after a one-character quote; \\000 inserted");
+ ch = 0;
+ }
+ if (ch == '\\')
+ {
+ ch = (*get) ();
+ ch = process_escape (ch);
+ }
+ sprintf (out_buf, "%d", (int) (unsigned char) ch);
+
+
+ /* None of these 'x constants for us. We want 'x'. */
+ if ((ch = (*get) ()) != '\'')
+ {
+#ifdef REQUIRE_CHAR_CLOSE_QUOTE
+ as_warn ("Missing close quote: (assumed)");
+#else
+ (*unget) (ch);
+#endif
+ }
+ if (strlen (out_buf) == 1)
+ {
+ return out_buf[0];
+ }
+ if (state == 9 || state == 10)
+ old_state = 3;
+ else
+ old_state = state;
+ state = -1;
+ out_string = out_buf;
+ return *out_string++;
+#endif
+#endif
+ case LEX_IS_COLON:
+ if (state == 9 || state == 10)
+ state = 3;
+ else if (state != 3)
+ state = 1;
+ return ch;
+
+ case LEX_IS_NEWLINE:
+ /* Roll out a bunch of newlines from inside comments, etc. */
+ if (add_newlines)
+ {
+ --add_newlines;
+ (*unget) (ch);
+ }
+ /* fall thru into... */
+
+ case LEX_IS_LINE_SEPARATOR:
+ state = 0;
+ return ch;
+
+ case LEX_IS_LINE_COMMENT_START:
+ if (state == 0) /* Only comment at start of line. */
+ {
+ /* FIXME-someday: The two character comment stuff was badly
+ thought out. On i386, we want '/' as line comment start
+ AND we want C style comments. hence this hack. The
+ whole lexical process should be reworked. xoxorich. */
+ if (ch == '/')
+ {
+ ch2 = (*get) ();
+ if (ch2 == '*')
+ {
+ state = -2;
+ return (do_scrub_next_char (get, unget));
+ }
+ else
+ {
+ (*unget) (ch2);
+ }
+ } /* bad hack */
+
+ if (ch != '#')
+ not_cpp_line = 1;
+
+ do
+ ch = (*get) ();
+ while (ch != EOF && IS_WHITESPACE (ch));
+ if (ch == EOF)
+ {
+ as_warn ("EOF in comment: Newline inserted");
+ return '\n';
+ }
+ if (ch < '0' || ch > '9' || not_cpp_line)
+ {
+ /* Non-numerics: Eat whole comment line */
+ while (ch != EOF && !IS_NEWLINE (ch))
+ ch = (*get) ();
+ if (ch == EOF)
+ as_warn ("EOF in Comment: Newline inserted");
+ state = 0;
+ return '\n';
+ }
+ /* Numerics begin comment. Perhaps CPP `# 123 "filename"' */
+ (*unget) (ch);
+ old_state = 4;
+ state = -1;
+ out_string = "\t.appline ";
+ return *out_string++;
+ }
+
+ /* We have a line comment character which is not at the start of
+ a line. If this is also a normal comment character, fall
+ through. Otherwise treat it as a default character. */
+ if (strchr (comment_chars, ch) == NULL)
+ goto de_fault;
+ /* Fall through. */
+ case LEX_IS_COMMENT_START:
+ do
+ ch = (*get) ();
+ while (ch != EOF && !IS_NEWLINE (ch));
+ if (ch == EOF)
+ as_warn ("EOF in comment: Newline inserted");
+ state = 0;
+ return '\n';
+
+ case LEX_IS_SYMBOL_COMPONENT:
+ if (state == 10)
+ {
+ /* This is a symbol character following another symbol
+ character, with whitespace in between. We skipped the
+ whitespace earlier, so output it now. */
+ (*unget) (ch);
+ state = 3;
+ return ' ';
+ }
+ if (state == 3)
+ state = 9;
+ /* Fall through. */
+ default:
+ de_fault:
+ /* Some relatively `normal' character. */
+ if (state == 0)
+ {
+ state = 11; /* Now seeing label definition */
+ return ch;
+ }
+ else if (state == 1)
+ {
+ state = 2; /* Ditto */
+ return ch;
+ }
+ else if (state == 9)
+ {
+ if (lex[ch] != LEX_IS_SYMBOL_COMPONENT)
+ state = 3;
+ return ch;
+ }
+ else if (state == 10)
+ {
+ state = 3;
+ return ch;
+ }
+ else
+ {
+ return ch; /* Opcode or operands already */
+ }
+ }
+ return -1;
+}
+
+#ifdef TEST
+
+const char comment_chars[] = "|";
+const char line_comment_chars[] = "#";
+
+main ()
+{
+ int ch;
+
+ app_begin ();
+ while ((ch = do_scrub_next_char (stdin)) != EOF)
+ putc (ch, stdout);
+}
+
+as_warn (str)
+ char *str;
+{
+ fputs (str, stderr);
+ putc ('\n', stderr);
+}
+
+#endif
+
+/* end of app.c */
diff --git a/gnu/usr.bin/as/as.1 b/gnu/usr.bin/as/as.1
new file mode 100644
index 0000000..c7e792f8
--- /dev/null
+++ b/gnu/usr.bin/as/as.1
@@ -0,0 +1,283 @@
+.\" Copyright (c) 1991, 1992 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.\" $FreeBSD$
+.TH as 1 "21 January 1992" "cygnus support" "GNU Development Tools"
+
+.SH NAME
+as \- the portable GNU assembler.
+
+.SH SYNOPSIS
+.na
+.B as
+.RB "[\|" \-a "\||\|" \-al "\||\|" -as\c
+\&\|]
+.RB "[\|" \-D "\|]"
+.RB "[\|" \-f "\|]"
+.RB "[\|" \-I
+.I path\c
+\&\|]
+.RB "[\|" \-k "\|]"
+.RB "[\|" \-K "\|]"
+.RB "[\|" \-L "\|]"
+.RB "[\|" \-o
+.I objfile\c
+\&\|]
+.RB "[\|" \-R "\|]"
+.RB "[\|" \-v "\|]"
+.RB "[\|" \-w "\|]"
+.RB "[\|" \-\^\- "\ |\ " \c
+.I files\c
+\&\|.\|.\|.\|]
+
+.I i960-only options:
+.br
+.RB "[\|" \-ACA "\||\|" \-ACA_A "\||\|" \-ACB\c
+.RB "\||\|" \-ACC "\||\|" \-AKA "\||\|" \-AKB\c
+.RB "\||\|" \-AKC "\||\|" \-AMC "\|]"
+.RB "[\|" \-b "\|]"
+.RB "[\|" \-norelax "\|]"
+
+.I m680x0-only options:
+.br
+.RB "[\|" \-l "\|]"
+.RB "[\|" \-mc68000 "\||\|" \-mc68010 "\||\|" \-mc68020 "\|]"
+.ad b
+
+.SH DESCRIPTION
+GNU \c
+.B as\c
+\& is really a family of assemblers.
+If you use (or have used) the GNU assembler on one architecture, you
+should find a fairly similar environment when you use it on another
+architecture. Each version has much in common with the others,
+including object file formats, most assembler directives (often called
+\c
+.I pseudo-ops)\c
+\& and assembler syntax.
+
+For information on the syntax and pseudo-ops used by GNU \c
+.B as\c
+\&, see `\|\c
+.B as\c
+\|' entry in \c
+.B info \c
+(or the manual \c
+.I
+.I
+Using as: The GNU Assembler\c
+\&).
+
+\c
+.B as\c
+\& is primarily intended to assemble the output of the GNU C
+compiler \c
+.B gcc\c
+\& for use by the linker \c
+.B ld\c
+\&. Nevertheless,
+we've tried to make \c
+.B as\c
+\& assemble correctly everything that the native
+assembler would.
+This doesn't mean \c
+.B as\c
+\& always uses the same syntax as another
+assembler for the same architecture; for example, we know of several
+incompatible versions of 680x0 assembly language syntax.
+
+Each time you run \c
+.B as\c
+\& it assembles exactly one source
+program. The source program is made up of one or more files.
+(The standard input is also a file.)
+
+If \c
+.B as\c
+\& is given no file names it attempts to read one input file
+from the \c
+.B as\c
+\& standard input, which is normally your terminal. You
+may have to type \c
+.B ctl-D\c
+\& to tell \c
+.B as\c
+\& there is no more program
+to assemble. Use `\|\c
+.B \-\^\-\c
+\|' if you need to explicitly name the standard input file
+in your command line.
+
+.B as\c
+\& may write warnings and error messages to the standard error
+file (usually your terminal). This should not happen when \c
+.B as\c
+\& is
+run automatically by a compiler. Warnings report an assumption made so
+that \c
+.B as\c
+\& could keep assembling a flawed program; errors report a
+grave problem that stops the assembly.
+
+.SH OPTIONS
+.TP
+.BR \-a \||\| \-al \||\| \-as
+Turn on assembly listings; `\|\c
+.B \-al\c
+\&\|', listing only, `\|\c
+.B \-as\c
+\&\|', symbols
+only, `\|\c
+.B \-a\c
+\&\|', everything.
+.TP
+.B \-D
+This option is accepted only for script compatibility with calls to
+other assemblers; it has no effect on \c
+.B as\c
+\&.
+.TP
+.B \-f
+``fast''--skip preprocessing (assume source is compiler output).
+.TP
+.BI "\-I\ " path
+Add
+.I path
+to the search list for
+.B .include
+directives.
+.TP
+.B \-k
+Handle position independent code, generated by gcc -fpic.
+.TP
+.B \-K
+Handle position independent code, generated by gcc -fPIC.
+This is normally the same as -k.
+.TP
+.B \-L
+Keep (in symbol table) local symbols, starting with `\|\c
+.B L\c
+\|'
+.TP
+.BI "\-o\ " objfile
+Name the object-file output from \c
+.B as
+.TP
+.B \-R
+Fold data section into text section
+.TP
+.B \-v
+Announce \c
+.B as\c
+\& version
+.TP
+.B \-W
+Suppress warning messages
+.TP
+.IR "\-\^\-" "\ |\ " "files\|.\|.\|."
+Source files to assemble, or standard input (\c
+.BR "\-\^\-" ")"
+.TP
+.BI \-A var
+.I
+(When configured for Intel 960.)
+Specify which variant of the 960 architecture is the target.
+.TP
+.B \-b
+.I
+(When configured for Intel 960.)
+Add code to collect statistics about branches taken.
+.TP
+.B \-norelax
+.I
+(When configured for Intel 960.)
+Do not alter compare-and-branch instructions for long displacements;
+error if necessary.
+.TP
+.B \-l
+.I
+(When configured for Motorola 68000).
+.br
+Shorten references to undefined symbols, to one word instead of two.
+.TP
+.BR "\-mc68000" "\||\|" "\-mc68010" "\||\|" "\-mc68020"
+.I
+(When configured for Motorola 68000).
+.br
+Specify what processor in the 68000 family is the target (default 68020)
+
+.PP
+Options may be in any order, and may be
+before, after, or between file names. The order of file names is
+significant.
+
+`\|\c
+.B \-\^\-\c
+\|' (two hyphens) by itself names the standard input file
+explicitly, as one of the files for \c
+.B as\c
+\& to assemble.
+
+Except for `\|\c
+.B \-\^\-\c
+\|' any command line argument that begins with a
+hyphen (`\|\c
+.B \-\c
+\|') is an option. Each option changes the behavior of
+\c
+.B as\c
+\&. No option changes the way another option works. An
+option is a `\|\c
+.B \-\c
+\|' followed by one or more letters; the case of
+the letter is important. All options are optional.
+
+The `\|\c
+.B \-o\c
+\|' option expects exactly one file name to follow. The file
+name may either immediately follow the option's letter (compatible
+with older assemblers) or it may be the next command argument (GNU
+standard).
+
+These two command lines are equivalent:
+.br
+.B
+as\ \ \-o\ \ my\-object\-file.o\ \ mumble.s
+.br
+.B
+as\ \ \-omy\-object\-file.o\ \ mumble.s
+
+.SH "SEE ALSO"
+.RB "`\|" as "\|'"
+entry in
+.B
+info\c
+\&;
+.I
+Using as: The GNU Assembler\c
+\&;
+.BR gcc "(" 1 "),"
+.BR ld "(" 1 ")."
+
+.SH HISTORY
+A
+.I as
+command appeared in
+Version 1 AT&T UNIX.
+
+.SH COPYING
+Copyright (c) 1991, 1992 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/gnu/usr.bin/as/as.1aout b/gnu/usr.bin/as/as.1aout
new file mode 100644
index 0000000..c7e792f8
--- /dev/null
+++ b/gnu/usr.bin/as/as.1aout
@@ -0,0 +1,283 @@
+.\" Copyright (c) 1991, 1992 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.\" $FreeBSD$
+.TH as 1 "21 January 1992" "cygnus support" "GNU Development Tools"
+
+.SH NAME
+as \- the portable GNU assembler.
+
+.SH SYNOPSIS
+.na
+.B as
+.RB "[\|" \-a "\||\|" \-al "\||\|" -as\c
+\&\|]
+.RB "[\|" \-D "\|]"
+.RB "[\|" \-f "\|]"
+.RB "[\|" \-I
+.I path\c
+\&\|]
+.RB "[\|" \-k "\|]"
+.RB "[\|" \-K "\|]"
+.RB "[\|" \-L "\|]"
+.RB "[\|" \-o
+.I objfile\c
+\&\|]
+.RB "[\|" \-R "\|]"
+.RB "[\|" \-v "\|]"
+.RB "[\|" \-w "\|]"
+.RB "[\|" \-\^\- "\ |\ " \c
+.I files\c
+\&\|.\|.\|.\|]
+
+.I i960-only options:
+.br
+.RB "[\|" \-ACA "\||\|" \-ACA_A "\||\|" \-ACB\c
+.RB "\||\|" \-ACC "\||\|" \-AKA "\||\|" \-AKB\c
+.RB "\||\|" \-AKC "\||\|" \-AMC "\|]"
+.RB "[\|" \-b "\|]"
+.RB "[\|" \-norelax "\|]"
+
+.I m680x0-only options:
+.br
+.RB "[\|" \-l "\|]"
+.RB "[\|" \-mc68000 "\||\|" \-mc68010 "\||\|" \-mc68020 "\|]"
+.ad b
+
+.SH DESCRIPTION
+GNU \c
+.B as\c
+\& is really a family of assemblers.
+If you use (or have used) the GNU assembler on one architecture, you
+should find a fairly similar environment when you use it on another
+architecture. Each version has much in common with the others,
+including object file formats, most assembler directives (often called
+\c
+.I pseudo-ops)\c
+\& and assembler syntax.
+
+For information on the syntax and pseudo-ops used by GNU \c
+.B as\c
+\&, see `\|\c
+.B as\c
+\|' entry in \c
+.B info \c
+(or the manual \c
+.I
+.I
+Using as: The GNU Assembler\c
+\&).
+
+\c
+.B as\c
+\& is primarily intended to assemble the output of the GNU C
+compiler \c
+.B gcc\c
+\& for use by the linker \c
+.B ld\c
+\&. Nevertheless,
+we've tried to make \c
+.B as\c
+\& assemble correctly everything that the native
+assembler would.
+This doesn't mean \c
+.B as\c
+\& always uses the same syntax as another
+assembler for the same architecture; for example, we know of several
+incompatible versions of 680x0 assembly language syntax.
+
+Each time you run \c
+.B as\c
+\& it assembles exactly one source
+program. The source program is made up of one or more files.
+(The standard input is also a file.)
+
+If \c
+.B as\c
+\& is given no file names it attempts to read one input file
+from the \c
+.B as\c
+\& standard input, which is normally your terminal. You
+may have to type \c
+.B ctl-D\c
+\& to tell \c
+.B as\c
+\& there is no more program
+to assemble. Use `\|\c
+.B \-\^\-\c
+\|' if you need to explicitly name the standard input file
+in your command line.
+
+.B as\c
+\& may write warnings and error messages to the standard error
+file (usually your terminal). This should not happen when \c
+.B as\c
+\& is
+run automatically by a compiler. Warnings report an assumption made so
+that \c
+.B as\c
+\& could keep assembling a flawed program; errors report a
+grave problem that stops the assembly.
+
+.SH OPTIONS
+.TP
+.BR \-a \||\| \-al \||\| \-as
+Turn on assembly listings; `\|\c
+.B \-al\c
+\&\|', listing only, `\|\c
+.B \-as\c
+\&\|', symbols
+only, `\|\c
+.B \-a\c
+\&\|', everything.
+.TP
+.B \-D
+This option is accepted only for script compatibility with calls to
+other assemblers; it has no effect on \c
+.B as\c
+\&.
+.TP
+.B \-f
+``fast''--skip preprocessing (assume source is compiler output).
+.TP
+.BI "\-I\ " path
+Add
+.I path
+to the search list for
+.B .include
+directives.
+.TP
+.B \-k
+Handle position independent code, generated by gcc -fpic.
+.TP
+.B \-K
+Handle position independent code, generated by gcc -fPIC.
+This is normally the same as -k.
+.TP
+.B \-L
+Keep (in symbol table) local symbols, starting with `\|\c
+.B L\c
+\|'
+.TP
+.BI "\-o\ " objfile
+Name the object-file output from \c
+.B as
+.TP
+.B \-R
+Fold data section into text section
+.TP
+.B \-v
+Announce \c
+.B as\c
+\& version
+.TP
+.B \-W
+Suppress warning messages
+.TP
+.IR "\-\^\-" "\ |\ " "files\|.\|.\|."
+Source files to assemble, or standard input (\c
+.BR "\-\^\-" ")"
+.TP
+.BI \-A var
+.I
+(When configured for Intel 960.)
+Specify which variant of the 960 architecture is the target.
+.TP
+.B \-b
+.I
+(When configured for Intel 960.)
+Add code to collect statistics about branches taken.
+.TP
+.B \-norelax
+.I
+(When configured for Intel 960.)
+Do not alter compare-and-branch instructions for long displacements;
+error if necessary.
+.TP
+.B \-l
+.I
+(When configured for Motorola 68000).
+.br
+Shorten references to undefined symbols, to one word instead of two.
+.TP
+.BR "\-mc68000" "\||\|" "\-mc68010" "\||\|" "\-mc68020"
+.I
+(When configured for Motorola 68000).
+.br
+Specify what processor in the 68000 family is the target (default 68020)
+
+.PP
+Options may be in any order, and may be
+before, after, or between file names. The order of file names is
+significant.
+
+`\|\c
+.B \-\^\-\c
+\|' (two hyphens) by itself names the standard input file
+explicitly, as one of the files for \c
+.B as\c
+\& to assemble.
+
+Except for `\|\c
+.B \-\^\-\c
+\|' any command line argument that begins with a
+hyphen (`\|\c
+.B \-\c
+\|') is an option. Each option changes the behavior of
+\c
+.B as\c
+\&. No option changes the way another option works. An
+option is a `\|\c
+.B \-\c
+\|' followed by one or more letters; the case of
+the letter is important. All options are optional.
+
+The `\|\c
+.B \-o\c
+\|' option expects exactly one file name to follow. The file
+name may either immediately follow the option's letter (compatible
+with older assemblers) or it may be the next command argument (GNU
+standard).
+
+These two command lines are equivalent:
+.br
+.B
+as\ \ \-o\ \ my\-object\-file.o\ \ mumble.s
+.br
+.B
+as\ \ \-omy\-object\-file.o\ \ mumble.s
+
+.SH "SEE ALSO"
+.RB "`\|" as "\|'"
+entry in
+.B
+info\c
+\&;
+.I
+Using as: The GNU Assembler\c
+\&;
+.BR gcc "(" 1 "),"
+.BR ld "(" 1 ")."
+
+.SH HISTORY
+A
+.I as
+command appeared in
+Version 1 AT&T UNIX.
+
+.SH COPYING
+Copyright (c) 1991, 1992 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/gnu/usr.bin/as/as.c b/gnu/usr.bin/as/as.c
new file mode 100644
index 0000000..5233f33
--- /dev/null
+++ b/gnu/usr.bin/as/as.c
@@ -0,0 +1,428 @@
+/* as.c - GAS main program.
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Main program for AS; a 32-bit assembler of GNU.
+ * Understands command arguments.
+ * Has a few routines that don't fit in other modules because they
+ * are shared.
+ *
+ *
+ * bugs
+ *
+ * : initialisers
+ * Since no-one else says they will support them in future: I
+ * don't support them now.
+ *
+ */
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _POSIX_SOURCE
+#include <sys/types.h> /* For pid_t in signal.h */
+#endif
+#include <signal.h>
+
+#define COMMON
+
+#include "as.h"
+#include "subsegs.h"
+#if __STDC__ == 1
+
+/* This prototype for got_sig() is ansi. If you want
+ anything else, then your compiler is lying to you when
+ it says that it is __STDC__. If you want to change it,
+ #ifdef protect it from those of us with real ansi
+ compilers. */
+
+#define SIGTY void
+
+static void got_sig(int sig);
+static char *stralloc(char *str);
+static void perform_an_assembly_pass(int argc, char **argv);
+
+#else /* __STDC__ */
+
+#ifndef SIGTY
+#define SIGTY int
+#endif
+
+static SIGTY got_sig();
+static char *stralloc(); /* Make a (safe) copy of a string. */
+static void perform_an_assembly_pass();
+
+#endif /* not __STDC__ */
+
+#ifdef DONTDEF
+static char * gdb_symbol_file_name;
+long gdb_begin();
+#endif
+
+int listing; /* true if a listing is wanted */
+
+char *myname; /* argv[0] */
+extern const char version_string[];
+
+int main(argc,argv)
+int argc;
+char **argv;
+{
+ int work_argc; /* variable copy of argc */
+ char **work_argv; /* variable copy of argv */
+ char *arg; /* an arg to program */
+ char a; /* an arg flag (after -) */
+ static const int sig[] = { SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
+
+ for (a=0;sig[a] != 0;a++)
+ if (signal(sig[a], SIG_IGN) != SIG_IGN)
+ signal(sig[a], got_sig);
+
+ myname=argv[0];
+ memset(flagseen, '\0', sizeof(flagseen)); /* aint seen nothing yet */
+#ifndef OBJ_DEFAULT_OUTPUT_FILE_NAME
+#define OBJ_DEFAULT_OUTPUT_FILE_NAME "a.out"
+#endif /* OBJ_DEFAULT_OUTPUT_FILE_NAME */
+ out_file_name = OBJ_DEFAULT_OUTPUT_FILE_NAME;
+
+ symbol_begin(); /* symbols.c */
+ subsegs_begin(); /* subsegs.c */
+ read_begin(); /* read.c */
+ md_begin(); /* MACHINE.c */
+ input_scrub_begin(); /* input_scrub.c */
+#ifdef DONTDEF
+ gdb_symbol_file_name = 0;
+#endif
+ /*
+ * Parse arguments, but we are only interested in flags.
+ * When we find a flag, we process it then make it's argv[] NULL.
+ * This helps any future argv[] scanners avoid what we processed.
+ * Since it is easy to do here we interpret the special arg "-"
+ * to mean "use stdin" and we set that argv[] pointing to "".
+ * After we have munged argv[], the only things left are source file
+ * name(s) and ""(s) denoting stdin. These file names are used
+ * (perhaps more than once) later.
+ */
+ /* FIXME-SOMEDAY this should use getopt. */
+ work_argc = argc-1; /* don't count argv[0] */
+ work_argv = argv+1; /* skip argv[0] */
+ for (;work_argc--;work_argv++) {
+ arg = * work_argv; /* work_argv points to this argument */
+
+ if (*arg != '-') /* Filename. We need it later. */
+ continue; /* Keep scanning args looking for flags. */
+ if (arg[1] == '-' && arg[2] == 0) {
+ /* "--" as an argument means read STDIN */
+ /* on this scan, we don't want to think about filenames */
+ * work_argv = ""; /* Code that means 'use stdin'. */
+ continue;
+ }
+ /* This better be a switch. */
+ arg ++; /*->letter. */
+
+ while ((a = * arg) != '\0') {/* scan all the 1-char flags */
+ arg ++; /* arg->after letter. */
+ a &= 0x7F; /* ascii only please */
+ /* if (flagseen[a])
+ as_tsktsk("%s: Flag option - %c has already been seen.", myname, a); */
+ flagseen[a] = 1;
+ switch (a) {
+
+ case 'a':
+ {
+ int loop =1;
+
+ while (loop) {
+ switch (*arg)
+ {
+ case 'l':
+ listing |= LISTING_LISTING;
+ arg++;
+ break;
+ case 's':
+ listing |= LISTING_SYMBOLS;
+ arg++;
+ break;
+ case 'h':
+ listing |= LISTING_HLL;
+ arg++;
+ break;
+
+ case 'n':
+ listing |= LISTING_NOFORM;
+ arg++;
+ break;
+ case 'd':
+ listing |= LISTING_NODEBUG;
+ arg++;
+ break;
+ default:
+ if (!listing)
+ listing= LISTING_DEFAULT;
+ loop = 0;
+ break;
+ }
+ }
+ }
+
+ break;
+
+
+ case 'f':
+ break; /* -f means fast - no need for "app" preprocessor. */
+
+ case 'D':
+ /* DEBUG is implemented: it debugs different */
+ /* things to other people's assemblers. */
+ break;
+
+#ifdef DONTDEF
+ case 'G': /* GNU AS switch: include gdbsyms. */
+ if (*arg) /* Rest of argument is file-name. */
+ gdb_symbol_file_name = stralloc (arg);
+ else if (work_argc) { /* Next argument is file-name. */
+ work_argc --;
+ * work_argv = NULL; /* Not a source file-name. */
+ gdb_symbol_file_name = * ++ work_argv;
+ } else
+ as_warn("%s: I expected a filename after -G", myname);
+ arg = ""; /* Finished with this arg. */
+ break;
+#endif
+
+ case 'I': { /* Include file directory */
+
+ char *temp = NULL;
+ if (*arg)
+ temp = stralloc (arg);
+ else if (work_argc) {
+ * work_argv = NULL;
+ work_argc--;
+ temp = * ++ work_argv;
+ } else
+ as_warn("%s: I expected a filename after -I", myname);
+ add_include_dir (temp);
+ arg = ""; /* Finished with this arg. */
+ break;
+ }
+
+ case 'L': /* -L means keep L* symbols */
+ break;
+
+ case 'o':
+ if (*arg) /* Rest of argument is object file-name. */
+ out_file_name = stralloc (arg);
+ else if (work_argc) { /* Want next arg for a file-name. */
+ * work_argv = NULL; /* This is not a file-name. */
+ work_argc--;
+ out_file_name = * ++ work_argv;
+ } else
+ as_warn("%s: I expected a filename after -o. \"%s\" assumed.", myname, out_file_name);
+ arg = ""; /* Finished with this arg. */
+ break;
+
+ case 'R':
+ /* -R means put data into text segment */
+ break;
+
+ case 'v':
+#ifdef OBJ_VMS
+ {
+ extern char *compiler_version_string;
+ compiler_version_string = arg;
+ }
+#else /* not OBJ_VMS */
+ fprintf(stderr,version_string);
+ if (*arg && strcmp(arg,"ersion"))
+ as_warn("Unknown -v option ignored");
+#endif /* not OBJ_VMS */
+ while (*arg) arg++; /* Skip the rest */
+ break;
+
+ case 'W':
+ /* -W means don't warn about things */
+ case 'X':
+ /* -X means treat warnings as errors */
+ case 'Z':
+ /* -Z means attempt to generate object file even after errors. */
+ break;
+
+ default:
+ --arg;
+ if (md_parse_option(&arg,&work_argc,&work_argv) == 0)
+ as_warn("%s: I don't understand '%c' flag.", myname, a);
+ if (arg && *arg)
+ arg++;
+ break;
+ }
+ }
+ /*
+ * We have just processed a "-..." arg, which was not a
+ * file-name. Smash it so the
+ * things that look for filenames won't ever see it.
+ *
+ * Whatever work_argv points to, it has already been used
+ * as part of a flag, so DON'T re-use it as a filename.
+ */
+ *work_argv = NULL; /* NULL means 'not a file-name' */
+ }
+#ifdef PIC
+ if (flagseen['K'] || flagseen['k'])
+ picmode = 1;
+#endif
+#ifdef DONTDEF
+ if (gdb_begin(gdb_symbol_file_name) == 0)
+ flagseen['G'] = 0; /* Don't do any gdbsym stuff. */
+#endif
+ /* Here with flags set up in flagseen[]. */
+
+ perform_an_assembly_pass(argc,argv); /* Assemble it. */
+#ifdef TC_I960
+ brtab_emit();
+#endif
+ if (seen_at_least_1_file()
+ && !((had_warnings() && flagseen['Z'])
+ || had_errors() > 0)) {
+ write_object_file(); /* relax() addresses then emit object file */
+ } /* we also check in write_object_file() just before emit. */
+
+ input_scrub_end();
+ md_end(); /* MACHINE.c */
+
+#ifndef NO_LISTING
+ listing_print("");
+#endif
+
+#ifndef HO_VMS
+ return((had_warnings() && flagseen['Z'])
+ || had_errors() > 0); /* WIN */
+#else /* HO_VMS */
+ return(!((had_warnings() && flagseen['Z'])
+ || had_errors() > 0)); /* WIN */
+#endif /* HO_VMS */
+
+} /* main() */
+
+
+/* perform_an_assembly_pass()
+ *
+ * Here to attempt 1 pass over each input file.
+ * We scan argv[*] looking for filenames or exactly "" which is
+ * shorthand for stdin. Any argv that is NULL is not a file-name.
+ * We set need_pass_2 TRUE if, after this, we still have unresolved
+ * expressions of the form (unknown value)+-(unknown value).
+ *
+ * Note the un*x semantics: there is only 1 logical input file, but it
+ * may be a catenation of many 'physical' input files.
+ */
+static void perform_an_assembly_pass(argc, argv)
+int argc;
+char **argv;
+{
+ int saw_a_file = 0;
+ need_pass_2 = 0;
+
+#ifdef MANY_SEGMENTS
+ unsigned int i;
+
+ for (i= SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ segment_info[i].fix_root = 0;
+ }
+ /* Create the three fixed ones */
+ subseg_new (SEG_E0, 0);
+ subseg_new (SEG_E1, 0);
+ subseg_new (SEG_E2, 0);
+ strcpy(segment_info[SEG_E0].scnhdr.s_name,".text");
+ strcpy(segment_info[SEG_E1].scnhdr.s_name,".data");
+ strcpy(segment_info[SEG_E2].scnhdr.s_name,".bss");
+
+ subseg_new (SEG_E0, 0);
+#else /* not MANY_SEGMENTS */
+ text_fix_root = NULL;
+ data_fix_root = NULL;
+ bss_fix_root = NULL;
+
+ subseg_new (SEG_TEXT, 0);
+#endif /* not MANY_SEGMENTS */
+
+ argv++; /* skip argv[0] */
+ argc--; /* skip argv[0] */
+ while (argc--) {
+ if (*argv) { /* Is it a file-name argument? */
+ saw_a_file++;
+ /* argv->"" if stdin desired, else->filename */
+ read_a_source_file(*argv);
+ }
+ argv++; /* completed that argv */
+ }
+ if (!saw_a_file)
+ read_a_source_file("");
+} /* perform_an_assembly_pass() */
+
+/*
+ * stralloc()
+ *
+ * Allocate memory for a new copy of a string. Copy the string.
+ * Return the address of the new string. Die if there is any error.
+ */
+
+static char *
+ stralloc (str)
+char * str;
+{
+ register char * retval;
+ register long len;
+
+ len = strlen (str) + 1;
+ retval = xmalloc (len);
+ (void) strcpy(retval, str);
+ return(retval);
+}
+
+#ifdef comment
+static void lose() {
+ as_fatal("%s: 2nd pass not implemented - get your code from random(3)", myname);
+ return;
+} /* lose() */
+#endif /* comment */
+
+static SIGTY
+ got_sig(sig)
+int sig;
+{
+ static here_before = 0;
+
+ as_bad("Interrupted by signal %d", sig);
+ if (here_before++)
+ exit(1);
+ return((SIGTY) 0);
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of as.c */
diff --git a/gnu/usr.bin/as/as.h b/gnu/usr.bin/as/as.h
new file mode 100644
index 0000000..4a6893b
--- /dev/null
+++ b/gnu/usr.bin/as/as.h
@@ -0,0 +1,426 @@
+/* as.h - global header file
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+#define GAS 1
+/* #include <ansidecl.h> */
+#include "host.h"
+#include "flonum.h"
+
+#if __STDC__ != 1
+#define volatile /**/
+#ifndef const
+#define const /**/
+#endif /* const */
+#endif /* __STDC__ */
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#define register
+#endif /* __GNUC__ */
+
+#ifndef __LINE__
+#define __LINE__ "unknown"
+#endif /* __LINE__ */
+
+#ifndef __FILE__
+#define __FILE__ "unknown"
+#endif /* __FILE__ */
+
+#ifndef PARAMS
+#if __STDC__ != 1
+#define PARAMS(x) ()
+#else
+#define PARAMS(x) x
+#endif
+#endif /*PARAMS */
+
+/*
+ * I think this stuff is largely out of date. xoxorich.
+ *
+ * CAPITALISED names are #defined.
+ * "lowercaseH" is #defined if "lowercase.h" has been #include-d.
+ * "lowercaseT" is a typedef of "lowercase" objects.
+ * "lowercaseP" is type "pointer to object of type 'lowercase'".
+ * "lowercaseS" is typedef struct ... lowercaseS.
+ *
+ * #define DEBUG to enable all the "know" assertion tests.
+ * #define SUSPECT when debugging.
+ * #define COMMON as "extern" for all modules except one, where you #define
+ * COMMON as "".
+ * If TEST is #defined, then we are testing a module: #define COMMON as "".
+ */
+
+/* These #defines are for parameters of entire assembler. */
+
+/* #define SUSPECT JF remove for speed testing */
+/* These #includes are for type definitions etc. */
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free xfree
+
+#define xfree free
+
+#define BAD_CASE(value) \
+{ \
+ as_fatal("Case value %d unexpected at line %d of file \"%s\"\n", \
+ value, __LINE__, __FILE__); \
+ }
+
+
+/* These are assembler-wide concepts */
+
+
+#ifndef COMMON
+#ifdef TEST
+#define COMMON /* declare our COMMONs storage here. */
+#else
+#define COMMON extern /* our commons live elswhere */
+#endif
+#endif
+/* COMMON now defined */
+#define DEBUG /* temporary */
+
+#ifdef DEBUG
+#undef NDEBUG
+#ifndef know
+#define know(p) assert(p) /* Verify our assumptions! */
+#endif /* not yet defined */
+#else
+#define know(p) /* know() checks are no-op.ed */
+#endif
+
+/* input_scrub.c */
+
+/*
+ * Supplies sanitised buffers to read.c.
+ * Also understands printing line-number part of error messages.
+ */
+
+
+/* subsegs.c Sub-segments. Also, segment(=expression type)s.*/
+
+/*
+ * This table describes the use of segments as EXPRESSION types.
+ *
+ * X_seg X_add_symbol X_subtract_symbol X_add_number
+ * SEG_ABSENT no (legal) expression
+ * SEG_PASS1 no (defined) "
+ * SEG_BIG * > 32 bits const.
+ * SEG_ABSOLUTE 0
+ * SEG_DATA * 0
+ * SEG_TEXT * 0
+ * SEG_BSS * 0
+ * SEG_UNKNOWN * 0
+ * SEG_DIFFERENCE 0 * 0
+ * SEG_REGISTER *
+ *
+ * The blank fields MUST be 0, and are nugatory.
+ * The '0' fields MAY be 0. The '*' fields MAY NOT be 0.
+ *
+ * SEG_BIG: X_add_number is < 0 if the result is in
+ * generic_floating_point_number. The value is -'c' where c is the
+ * character that introduced the constant. e.g. "0f6.9" will have -'f'
+ * as a X_add_number value.
+ * X_add_number > 0 is a count of how many littlenums it took to
+ * represent a bignum.
+ * SEG_DIFFERENCE:
+ * If segments of both symbols are known, they are the same segment.
+ * X_add_symbol != X_sub_symbol (then we just cancel them, => SEG_ABSOLUTE).
+ */
+
+
+#ifdef MANY_SEGMENTS
+#define N_SEGMENTS 10
+#define SEG_NORMAL(x) ((x) >= SEG_E0 && (x) <= SEG_E9)
+#define SEG_LIST SEG_E0,SEG_E1,SEG_E2,SEG_E3,SEG_E4,SEG_E5,SEG_E6,SEG_E7,SEG_E8,SEG_E9
+#define SEG_DATA SEG_E1
+#define SEG_TEXT SEG_E0
+#define SEG_BSS SEG_E2
+#else
+#define N_SEGMENTS 3
+#define SEG_NORMAL(x) ((x) == SEG_TEXT || (x) == SEG_DATA || (x) == SEG_BSS)
+#define SEG_LIST SEG_TEXT,SEG_DATA,SEG_BSS
+#endif
+
+typedef enum _segT {
+ SEG_ABSOLUTE = 0,
+ SEG_LIST,
+ SEG_UNKNOWN,
+ SEG_ABSENT, /* Mythical Segment (absent): NO expression seen. */
+ SEG_PASS1, /* Mythical Segment: Need another pass. */
+ SEG_GOOF, /* Only happens if AS has a logic error. */
+ /* Invented so we don't crash printing */
+ /* error message involving weird segment. */
+ SEG_BIG, /* Bigger than 32 bits constant. */
+ SEG_DIFFERENCE, /* Mythical Segment: absolute difference. */
+ SEG_DEBUG, /* Debug segment */
+ SEG_NTV, /* Transfert vector preload segment */
+ SEG_PTV, /* Transfert vector postload segment */
+ SEG_REGISTER, /* Mythical: a register-valued expression */
+} segT;
+
+#define SEG_MAXIMUM_ORDINAL (SEG_REGISTER)
+
+typedef int subsegT;
+
+COMMON subsegT now_subseg, prev_subseg;
+/* What subseg we are accreting now? */
+
+
+COMMON segT now_seg, prev_seg;
+/* Segment our instructions emit to. */
+/* Only OK values are SEG_TEXT or SEG_DATA. */
+
+
+extern char *const seg_name[];
+extern int section_alignment[];
+
+
+/* relax() */
+
+typedef enum _relax_state {
+ rs_fill, /* Variable chars to be repeated fr_offset times. Fr_symbol
+ unused. Used with fr_offset == 0 for a constant length
+ frag. */
+
+ rs_align, /* Align: Fr_offset: power of 2. 1 variable char: fill
+ character. */
+
+ rs_org, /* Org: Fr_offset, fr_symbol: address. 1 variable char: fill
+ character. */
+
+ rs_machine_dependent,
+
+#ifndef WORKING_DOT_WORD
+ rs_broken_word, /* JF: gunpoint */
+#endif
+} relax_stateT;
+
+/* typedef unsigned char relax_substateT; */
+/* JF this is more likely to leave the end of a struct frag on an align
+ boundry. Be very careful with this. */
+typedef unsigned long relax_substateT;
+
+typedef unsigned long relax_addressT;/* Enough bits for address. */
+/* Still an integer type. */
+
+
+/* frags.c */
+
+/*
+ * A code fragment (frag) is some known number of chars, followed by some
+ * unknown number of chars. Typically the unknown number of chars is an
+ * instruction address whose size is yet unknown. We always know the greatest
+ * possible size the unknown number of chars may become, and reserve that
+ * much room at the end of the frag.
+ * Once created, frags do not change address during assembly.
+ * We chain the frags in (a) forward-linked list(s). The object-file address
+ * of the 1st char of a frag is generally not known until after relax().
+ * Many things at assembly time describe an address by {object-file-address
+ * of a particular frag}+offset.
+
+ BUG: it may be smarter to have a single pointer off to various different
+ notes for different frag kinds. See how code pans
+ */
+struct frag /* a code fragment */
+{
+ unsigned long fr_address; /* Object file address. */
+ struct frag *fr_next; /* Chain forward; ascending address order. */
+ /* Rooted in frch_root. */
+
+ long fr_fix; /* (Fixed) number of chars we know we have. */
+ /* May be 0. */
+ long fr_var; /* (Variable) number of chars after above. */
+ /* May be 0. */
+ struct symbol *fr_symbol; /* For variable-length tail. */
+ long fr_offset; /* For variable-length tail. */
+ char *fr_opcode; /*->opcode low addr byte,for relax()ation*/
+ relax_stateT fr_type; /* What state is my tail in? */
+ relax_substateT fr_subtype;
+ /* These are needed only on the NS32K machines */
+ char fr_pcrel_adjust;
+ char fr_bsr;
+#ifndef NO_LISTING
+ struct list_info_struct *line;
+#endif
+ char fr_literal[1]; /* Chars begin here. */
+ /* One day we will compile fr_literal[0]. */
+};
+#define SIZEOF_STRUCT_FRAG \
+((int)zero_address_frag.fr_literal-(int)&zero_address_frag)
+/* We want to say fr_literal[0] above. */
+
+typedef struct frag fragS;
+
+COMMON fragS *frag_now; /* -> current frag we are building. */
+/* This frag is incomplete. */
+/* It is, however, included in frchain_now. */
+/* Frag_now->fr_fix is bogus. Use: */
+/* Virtual frag_now->fr_fix == obstack_next_free(&frags)-frag_now->fr_literal.*/
+
+COMMON fragS zero_address_frag; /* For foreign-segment symbol fixups. */
+COMMON fragS bss_address_frag; /* For local common (N_BSS segment) fixups. */
+
+/* main program "as.c" (command arguments etc) */
+
+COMMON char
+ flagseen[128]; /* ['x'] TRUE if "-x" seen. */
+
+COMMON char *
+ out_file_name; /* name of emitted object file */
+
+COMMON int need_pass_2; /* TRUE if we need a second pass. */
+
+COMMON int picmode; /* TRUE if "-k" or "-K" seen. */
+
+typedef struct {
+ char * poc_name; /* assembler mnemonic, lower case, no '.' */
+ void (*poc_handler)(); /* Do the work */
+ int poc_val; /* Value to pass to handler */
+} pseudo_typeS;
+
+#if (__STDC__ == 1) & !defined(NO_STDARG)
+
+int had_errors(void);
+int had_warnings(void);
+void as_bad(const char *Format, ...);
+void as_fatal(const char *Format, ...);
+void as_tsktsk(const char *Format, ...);
+void as_warn(const char *Format, ...);
+
+#else
+
+int had_errors();
+int had_warnings();
+void as_bad();
+void as_fatal();
+void as_tsktsk();
+void as_warn();
+
+#endif /* __STDC__ & !NO_STDARG */
+
+#if __STDC__ == 1
+
+char *app_push(void);
+char *atof_ieee(char *str, int what_kind, LITTLENUM_TYPE *words);
+char *input_scrub_include_file(char *filename, char *position);
+char *input_scrub_new_file(char *filename);
+char *input_scrub_next_buffer(char **bufp);
+char *strstr(const char *s, const char *wanted);
+char *xmalloc(int size);
+char *xrealloc(char *ptr, long n);
+int do_scrub_next_char(int (*get)(), void (*unget)());
+int gen_to_words(LITTLENUM_TYPE *words, int precision, long exponent_bits);
+int had_err(void);
+int had_errors(void);
+int had_warnings(void);
+int ignore_input(void);
+int scrub_from_file(void);
+int scrub_from_file(void);
+int scrub_from_string(void);
+int seen_at_least_1_file(void);
+void app_pop(char *arg);
+void as_howmuch(FILE *stream);
+void as_perror(const char *gripe, const char *filename);
+void as_where(char **, unsigned int *);
+void bump_line_counters(void);
+void do_scrub_begin(void);
+void input_scrub_begin(void);
+void input_scrub_close(void);
+void input_scrub_end(void);
+void int_to_gen(long x);
+void new_logical_line(char *fname, int line_number);
+void scrub_to_file(int ch);
+void scrub_to_string(int ch);
+void subseg_change(segT seg, int subseg);
+void subseg_new(segT seg, subsegT subseg);
+void subsegs_begin(void);
+
+#else /* not __STDC__ */
+
+char *app_push();
+char *atof_ieee();
+char *input_scrub_include_file();
+char *input_scrub_new_file();
+char *input_scrub_next_buffer();
+char *strstr();
+char *xmalloc();
+char *xrealloc();
+int do_scrub_next_char();
+int gen_to_words();
+int had_err();
+int had_errors();
+int had_warnings();
+int ignore_input();
+int scrub_from_file();
+int scrub_from_file();
+int scrub_from_string();
+int seen_at_least_1_file();
+void app_pop();
+void as_howmuch();
+void as_perror();
+void as_where();
+void bump_line_counters();
+void do_scrub_begin();
+void input_scrub_begin();
+void input_scrub_close();
+void input_scrub_end();
+void int_to_gen();
+void new_logical_line();
+void scrub_to_file();
+void scrub_to_string();
+void subseg_change();
+void subseg_new();
+void subsegs_begin();
+
+#endif /* not __STDC__ */
+
+/* this one starts the chain of target dependant headers */
+#include "targ-env.h"
+
+/* these define types needed by the interfaces */
+#include "struc-symbol.h"
+#include "write.h"
+#include "expr.h"
+#include "frags.h"
+#include "hash.h"
+#include "read.h"
+#include "symbols.h"
+
+#include "tc.h"
+#include "obj.h"
+
+#include "listing.h"
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of as.h */
diff --git a/gnu/usr.bin/as/atof-generic.c b/gnu/usr.bin/as/atof-generic.c
new file mode 100644
index 0000000..f01fdb2
--- /dev/null
+++ b/gnu/usr.bin/as/atof-generic.c
@@ -0,0 +1,526 @@
+/* atof_generic.c - turn a string of digits into a Flonum
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <ctype.h>
+#include <string.h>
+
+#include "as.h"
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else
+#ifdef sparc
+#include <alloca.h>
+#endif
+#endif
+
+/* #define FALSE (0) */
+/* #define TRUE (1) */
+
+/***********************************************************************\
+ * *
+ * Given a string of decimal digits , with optional decimal *
+ * mark and optional decimal exponent (place value) of the *
+ * lowest_order decimal digit: produce a floating point *
+ * number. The number is 'generic' floating point: our *
+ * caller will encode it for a specific machine architecture. *
+ * *
+ * Assumptions *
+ * uses base (radix) 2 *
+ * this machine uses 2's complement binary integers *
+ * target flonums use " " " " *
+ * target flonums exponents fit in a long *
+ * *
+ \***********************************************************************/
+
+/*
+
+ Syntax:
+
+ <flonum> ::= <optional-sign> <decimal-number> <optional-exponent>
+ <optional-sign> ::= '+' | '-' | {empty}
+ <decimal-number> ::= <integer>
+ | <integer> <radix-character>
+ | <integer> <radix-character> <integer>
+ | <radix-character> <integer>
+
+ <optional-exponent> ::= {empty}
+ | <exponent-character> <optional-sign> <integer>
+
+ <integer> ::= <digit> | <digit> <integer>
+ <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+ <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"}
+ <radix-character> ::= {one character from "string_of_decimal_marks"}
+
+ */
+
+int /* 0 if OK */
+ atof_generic (
+ address_of_string_pointer, /* return pointer to just
+ AFTER number we read. */
+ string_of_decimal_marks, /* At most one per number. */
+ string_of_decimal_exponent_marks,
+ address_of_generic_floating_point_number)
+char **address_of_string_pointer;
+const char *string_of_decimal_marks;
+const char *string_of_decimal_exponent_marks;
+FLONUM_TYPE *address_of_generic_floating_point_number;
+{
+ int return_value; /* 0 means OK. */
+ char * first_digit;
+ /* char *last_digit; JF unused */
+ int number_of_digits_before_decimal;
+ int number_of_digits_after_decimal;
+ long decimal_exponent;
+ int number_of_digits_available;
+ char digits_sign_char;
+
+ /*
+ * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
+ * It would be simpler to modify the string, but we don't; just to be nice
+ * to caller.
+ * We need to know how many digits we have, so we can allocate space for
+ * the digits' value.
+ */
+
+ char *p;
+ char c;
+ int seen_significant_digit;
+
+ first_digit = *address_of_string_pointer;
+ c = *first_digit;
+
+ if (c == '-' || c == '+') {
+ digits_sign_char = c;
+ first_digit++;
+ } else
+ digits_sign_char = '+';
+
+ if ((first_digit[0] == 'n' || first_digit[0] == 'N')
+ && (first_digit[1] == 'a' || first_digit[1] == 'A')
+ && (first_digit[2] == 'n' || first_digit[2] == 'N')) {
+ address_of_generic_floating_point_number->sign = 0;
+ address_of_generic_floating_point_number->exponent = 0;
+ address_of_generic_floating_point_number->leader =
+ address_of_generic_floating_point_number->low;
+ *address_of_string_pointer = first_digit + 3;
+ return(0);
+ }
+
+ /* 99e999 is a "special" token to some older, broken compilers. */
+ if ((first_digit[0] == 'i' || first_digit[0] == 'I')
+ && (first_digit[1] == 'n' || first_digit[1] == 'N')
+ && (first_digit[2] == 'f' || first_digit[2] == 'F')) {
+ address_of_generic_floating_point_number->sign =
+ digits_sign_char == '+' ? 'P' : 'N';
+ address_of_generic_floating_point_number->exponent = 0;
+ address_of_generic_floating_point_number->leader =
+ address_of_generic_floating_point_number->low;
+
+ if ((first_digit[3] == 'i' || first_digit[3] == 'I')
+ && (first_digit[4] == 'n' || first_digit[4] == 'N')
+ && (first_digit[5] == 'i' || first_digit[5] == 'I')
+ && (first_digit[6] == 't' || first_digit[6] == 'T')
+ && (first_digit[7] == 'y' || first_digit[7] == 'Y')) {
+ *address_of_string_pointer = first_digit + 8;
+ } else {
+ *address_of_string_pointer = first_digit + 3;
+ }
+ return(0);
+ }
+
+ if (strncmp(first_digit, "99e999", 6) == 0) {
+ address_of_generic_floating_point_number->sign =
+ digits_sign_char == '+' ? 'P' : 'N';
+ address_of_generic_floating_point_number->exponent = 0;
+ address_of_generic_floating_point_number->leader =
+ address_of_generic_floating_point_number->low;
+ *address_of_string_pointer = first_digit + 6;
+ return(0);
+ }
+
+ number_of_digits_before_decimal = 0;
+ number_of_digits_after_decimal = 0;
+ decimal_exponent = 0;
+ seen_significant_digit = 0;
+ for (p = first_digit; (((c = * p) != '\0')
+ && (!c || ! strchr(string_of_decimal_marks, c))
+ && (!c || !strchr(string_of_decimal_exponent_marks, c)));
+ p++) {
+ if (isdigit(c)) {
+ if (seen_significant_digit || c > '0') {
+ ++number_of_digits_before_decimal;
+ seen_significant_digit = 1;
+ } else {
+ first_digit++;
+ }
+ } else {
+ break; /* p -> char after pre-decimal digits. */
+ }
+ } /* For each digit before decimal mark. */
+
+#ifndef OLD_FLOAT_READS
+ /* Ignore trailing 0's after the decimal point. The original code here
+ * (ifdef'd out) does not do this, and numbers like
+ * 4.29496729600000000000e+09 (2**31)
+ * come out inexact for some reason related to length of the digit
+ * string.
+ */
+ if (c && strchr(string_of_decimal_marks, c)) {
+ int zeros = 0; /* Length of current string of zeros */
+
+ for (p++; (c = *p) && isdigit(c); p++) {
+ if (c == '0') {
+ zeros++;
+ } else {
+ number_of_digits_after_decimal += 1 + zeros;
+ zeros = 0;
+ }
+ }
+ }
+#else
+ if (c && strchr(string_of_decimal_marks, c)) {
+ for (p++; (((c = *p) != '\0')
+ && (!c || !strchr(string_of_decimal_exponent_marks, c)));
+ p++) {
+ if (isdigit(c)) {
+ number_of_digits_after_decimal++; /* This may be retracted below. */
+ if (/* seen_significant_digit || */ c > '0') {
+ seen_significant_digit = TRUE;
+ }
+ } else {
+ if (!seen_significant_digit) {
+ number_of_digits_after_decimal = 0;
+ }
+ break;
+ }
+ } /* For each digit after decimal mark. */
+ }
+
+ while (number_of_digits_after_decimal && first_digit[number_of_digits_before_decimal
+ + number_of_digits_after_decimal] == '0')
+ --number_of_digits_after_decimal;
+ /* last_digit = p; JF unused */
+#endif
+
+ if (c && strchr(string_of_decimal_exponent_marks, c) ) {
+ char digits_exponent_sign_char;
+
+ c = *++p;
+ if (c && strchr ("+-",c)) {
+ digits_exponent_sign_char = c;
+ c = *++p;
+ } else {
+ digits_exponent_sign_char = '+';
+ }
+
+ for ( ; (c); c = *++p) {
+ if (isdigit(c)) {
+ decimal_exponent = decimal_exponent * 10 + c - '0';
+ /*
+ * BUG! If we overflow here, we lose!
+ */
+ } else {
+ break;
+ }
+ }
+
+ if (digits_exponent_sign_char == '-') {
+ decimal_exponent = -decimal_exponent;
+ }
+ }
+
+ *address_of_string_pointer = p;
+
+
+
+ number_of_digits_available =
+ number_of_digits_before_decimal + number_of_digits_after_decimal;
+ return_value = 0;
+ if (number_of_digits_available == 0) {
+ address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */
+ address_of_generic_floating_point_number->leader
+ = -1 + address_of_generic_floating_point_number->low;
+ address_of_generic_floating_point_number->sign = digits_sign_char;
+ /* We have just concocted (+/-)0.0E0 */
+
+ } else {
+ int count; /* Number of useful digits left to scan. */
+
+ LITTLENUM_TYPE *digits_binary_low;
+ int precision;
+ int maximum_useful_digits;
+ int number_of_digits_to_use;
+ int more_than_enough_bits_for_digits;
+ int more_than_enough_littlenums_for_digits;
+ int size_of_digits_in_littlenums;
+ int size_of_digits_in_chars;
+ FLONUM_TYPE power_of_10_flonum;
+ FLONUM_TYPE digits_flonum;
+
+ precision = (address_of_generic_floating_point_number->high
+ - address_of_generic_floating_point_number->low
+ + 1); /* Number of destination littlenums. */
+
+ /* Includes guard bits (two littlenums worth) */
+ maximum_useful_digits = (((double) (precision - 2))
+ * ((double) (LITTLENUM_NUMBER_OF_BITS))
+ / (LOG_TO_BASE_2_OF_10))
+ + 2; /* 2 :: guard digits. */
+
+ if (number_of_digits_available > maximum_useful_digits) {
+ number_of_digits_to_use = maximum_useful_digits;
+ } else {
+ number_of_digits_to_use = number_of_digits_available;
+ }
+
+ decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use;
+
+ more_than_enough_bits_for_digits
+ = ((((double)number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);
+
+ more_than_enough_littlenums_for_digits
+ = (more_than_enough_bits_for_digits
+ / LITTLENUM_NUMBER_OF_BITS)
+ + 2;
+
+ /*
+ * Compute (digits) part. In "12.34E56" this is the "1234" part.
+ * Arithmetic is exact here. If no digits are supplied then
+ * this part is a 0 valued binary integer.
+ * Allocate room to build up the binary number as littlenums.
+ * We want this memory to disappear when we leave this function.
+ * Assume no alignment problems => (room for n objects) ==
+ * n * (room for 1 object).
+ */
+
+ size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
+ size_of_digits_in_chars = size_of_digits_in_littlenums
+ * sizeof(LITTLENUM_TYPE);
+
+ digits_binary_low = (LITTLENUM_TYPE *)
+ alloca(size_of_digits_in_chars);
+
+ memset((char *)digits_binary_low, '\0', size_of_digits_in_chars);
+
+ /* Digits_binary_low[] is allocated and zeroed. */
+
+ /*
+ * Parse the decimal digits as if * digits_low was in the units position.
+ * Emit a binary number into digits_binary_low[].
+ *
+ * Use a large-precision version of:
+ * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
+ */
+
+ for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) {
+ c = *p;
+ if (isdigit(c)) {
+ /*
+ * Multiply by 10. Assume can never overflow.
+ * Add this digit to digits_binary_low[].
+ */
+
+ long carry;
+ LITTLENUM_TYPE *littlenum_pointer;
+ LITTLENUM_TYPE *littlenum_limit;
+
+ littlenum_limit = digits_binary_low
+ + more_than_enough_littlenums_for_digits
+ - 1;
+
+ carry = c - '0'; /* char -> binary */
+
+ for (littlenum_pointer = digits_binary_low;
+ littlenum_pointer <= littlenum_limit;
+ littlenum_pointer++) {
+ long work;
+
+ work = carry + 10 * (long) (*littlenum_pointer);
+ *littlenum_pointer = work & LITTLENUM_MASK;
+ carry = work >> LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ if (carry != 0) {
+ /*
+ * We have a GROSS internal error.
+ * This should never happen.
+ */
+ as_fatal("failed sanity check."); /* RMS prefers abort() to any message. */
+ }
+ } else {
+ ++ count; /* '.' doesn't alter digits used count. */
+ } /* if valid digit */
+ } /* for each digit */
+
+
+ /*
+ * Digits_binary_low[] properly encodes the value of the digits.
+ * Forget about any high-order littlenums that are 0.
+ */
+ while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0
+ && size_of_digits_in_littlenums >= 2)
+ size_of_digits_in_littlenums--;
+
+ digits_flonum.low = digits_binary_low;
+ digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1;
+ digits_flonum.leader = digits_flonum.high;
+ digits_flonum.exponent = 0;
+ /*
+ * The value of digits_flonum.sign should not be important.
+ * We have already decided the output's sign.
+ * We trust that the sign won't influence the other parts of the number!
+ * So we give it a value for these reasons:
+ * (1) courtesy to humans reading/debugging
+ * these numbers so they don't get excited about strange values
+ * (2) in future there may be more meaning attached to sign,
+ * and what was
+ * harmless noise may become disruptive, ill-conditioned (or worse)
+ * input.
+ */
+ digits_flonum.sign = '+';
+
+ {
+ /*
+ * Compute the mantssa (& exponent) of the power of 10.
+ * If sucessful, then multiply the power of 10 by the digits
+ * giving return_binary_mantissa and return_binary_exponent.
+ */
+
+ LITTLENUM_TYPE *power_binary_low;
+ int decimal_exponent_is_negative;
+ /* This refers to the "-56" in "12.34E-56". */
+ /* FALSE: decimal_exponent is positive (or 0) */
+ /* TRUE: decimal_exponent is negative */
+ FLONUM_TYPE temporary_flonum;
+ LITTLENUM_TYPE *temporary_binary_low;
+ int size_of_power_in_littlenums;
+ int size_of_power_in_chars;
+
+ size_of_power_in_littlenums = precision;
+ /* Precision has a built-in fudge factor so we get a few guard bits. */
+
+ decimal_exponent_is_negative = decimal_exponent < 0;
+ if (decimal_exponent_is_negative) {
+ decimal_exponent = -decimal_exponent;
+ }
+
+ /* From now on: the decimal exponent is > 0. Its sign is seperate. */
+
+ size_of_power_in_chars = size_of_power_in_littlenums
+ * sizeof(LITTLENUM_TYPE) + 2;
+
+ power_binary_low = (LITTLENUM_TYPE *) alloca(size_of_power_in_chars);
+ temporary_binary_low = (LITTLENUM_TYPE *) alloca(size_of_power_in_chars);
+ memset((char *)power_binary_low, '\0', size_of_power_in_chars);
+ * power_binary_low = 1;
+ power_of_10_flonum.exponent = 0;
+ power_of_10_flonum.low = power_binary_low;
+ power_of_10_flonum.leader = power_binary_low;
+ power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;
+ power_of_10_flonum.sign = '+';
+ temporary_flonum.low = temporary_binary_low;
+ temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;
+ /*
+ * (power) == 1.
+ * Space for temporary_flonum allocated.
+ */
+
+ /*
+ * ...
+ *
+ * WHILE more bits
+ * DO find next bit (with place value)
+ * multiply into power mantissa
+ * OD
+ */
+ {
+ int place_number_limit;
+ /* Any 10^(2^n) whose "n" exceeds this */
+ /* value will fall off the end of */
+ /* flonum_XXXX_powers_of_ten[]. */
+ int place_number;
+ const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */
+
+ place_number_limit = table_size_of_flonum_powers_of_ten;
+
+ multiplicand = (decimal_exponent_is_negative
+ ? flonum_negative_powers_of_ten
+ : flonum_positive_powers_of_ten);
+
+ for (place_number = 1; /* Place value of this bit of exponent. */
+ decimal_exponent; /* Quit when no more 1 bits in exponent. */
+ decimal_exponent >>= 1, place_number++) {
+ if (decimal_exponent & 1) {
+ if (place_number > place_number_limit) {
+ /*
+ * The decimal exponent has a magnitude so great that
+ * our tables can't help us fragment it. Although this
+ * routine is in error because it can't imagine a
+ * number that big, signal an error as if it is the
+ * user's fault for presenting such a big number.
+ */
+ return_value = ERROR_EXPONENT_OVERFLOW;
+ /*
+ * quit out of loop gracefully
+ */
+ decimal_exponent = 0;
+ } else {
+#ifdef TRACE
+ printf("before multiply, place_number = %d., power_of_10_flonum:\n",
+ place_number);
+
+ flonum_print(&power_of_10_flonum);
+ (void)putchar('\n');
+#endif
+ flonum_multip(multiplicand + place_number,
+ &power_of_10_flonum, &temporary_flonum);
+ flonum_copy(&temporary_flonum, &power_of_10_flonum);
+ } /* If this bit of decimal_exponent was computable.*/
+ } /* If this bit of decimal_exponent was set. */
+ } /* For each bit of binary representation of exponent */
+#ifdef TRACE
+ printf(" after computing power_of_10_flonum: ");
+ flonum_print(&power_of_10_flonum );
+ (void) putchar('\n');
+#endif
+ }
+
+ }
+
+ /*
+ * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
+ * It may be the number 1, in which case we don't NEED to multiply.
+ *
+ * Multiply (decimal digits) by power_of_10_flonum.
+ */
+
+ flonum_multip(&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);
+ /* Assert sign of the number we made is '+'. */
+ address_of_generic_floating_point_number->sign = digits_sign_char;
+
+ } /* If we had any significant digits. */
+ return(return_value);
+} /* atof_generic () */
+
+/* end of atof_generic.c */
diff --git a/gnu/usr.bin/as/bignum-copy.c b/gnu/usr.bin/as/bignum-copy.c
new file mode 100644
index 0000000..bb5763f
--- /dev/null
+++ b/gnu/usr.bin/as/bignum-copy.c
@@ -0,0 +1,76 @@
+/* bignum_copy.c - copy a bignum
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+
+/*
+ * bignum_copy ()
+ *
+ * Copy a bignum from in to out.
+ * If the output is shorter than the input, copy lower-order littlenums.
+ * Return 0 or the number of significant littlenums dropped.
+ * Assumes littlenum arrays are densely packed: no unused chars between
+ * the littlenums. Uses memcpy() to move littlenums, and wants to
+ * know length (in chars) of the input bignum.
+ */
+
+/* void */
+int
+ bignum_copy(in, in_length, out, out_length)
+register LITTLENUM_TYPE *in;
+register int in_length; /* in sizeof(littlenum)s */
+register LITTLENUM_TYPE *out;
+register int out_length; /* in sizeof(littlenum)s */
+{
+ int significant_littlenums_dropped;
+
+ if (out_length < in_length) {
+ LITTLENUM_TYPE *p; /* -> most significant (non-zero) input
+ littlenum. */
+
+ memcpy((void *) out, (void *) in,
+ out_length << LITTLENUM_SHIFT);
+ for (p = in + in_length - 1; p >= in; --p) {
+ if (* p) break;
+ }
+ significant_littlenums_dropped = p - in - in_length + 1;
+
+ if (significant_littlenums_dropped < 0) {
+ significant_littlenums_dropped = 0;
+ }
+ } else {
+ memcpy((char *) out, (char *) in,
+ in_length << LITTLENUM_SHIFT);
+
+ if (out_length > in_length) {
+ memset((char *) (out + out_length),
+ '\0', (out_length - in_length) << LITTLENUM_SHIFT);
+ }
+
+ significant_littlenums_dropped = 0;
+ }
+
+ return(significant_littlenums_dropped);
+} /* bignum_copy() */
+
+/* end of bignum-copy.c */
diff --git a/gnu/usr.bin/as/bignum.h b/gnu/usr.bin/as/bignum.h
new file mode 100644
index 0000000..34435e2
--- /dev/null
+++ b/gnu/usr.bin/as/bignum.h
@@ -0,0 +1,64 @@
+/* bignum.h-arbitrary precision integers
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+/***********************************************************************\
+ * *
+ * Arbitrary-precision integer arithmetic. *
+ * For speed, we work in groups of bits, even though this *
+ * complicates algorithms. *
+ * Each group of bits is called a 'littlenum'. *
+ * A bunch of littlenums representing a (possibly large) *
+ * integer is called a 'bignum'. *
+ * Bignums are >= 0. *
+ * *
+ \***********************************************************************/
+
+#define LITTLENUM_NUMBER_OF_BITS (16)
+#define LITTLENUM_RADIX (1 << LITTLENUM_NUMBER_OF_BITS)
+#define LITTLENUM_MASK (0xFFFF)
+#define LITTLENUM_SHIFT (1)
+#define CHARS_PER_LITTLENUM (1 << LITTLENUM_SHIFT)
+#ifndef BITS_PER_CHAR
+#define BITS_PER_CHAR (8)
+#endif
+
+typedef unsigned short LITTLENUM_TYPE;
+
+/* JF truncated this to get around a problem with GCC */
+#define LOG_TO_BASE_2_OF_10 (3.3219280948873623478703194294893901758651)
+/* WARNING: I haven't checked that the trailing digits are correct! */
+
+ /* lengths are in sizeof(littlenum)s */
+#if __STDC__ == 1
+
+int bignum_copy(LITTLENUM_TYPE *in, int in_length,
+ LITTLENUM_TYPE *out, int out_length);
+
+#else
+
+int bignum_copy();
+
+#endif /* __STDC__ */
+
+
+/* end of bignum.h */
diff --git a/gnu/usr.bin/as/bit_fix.h b/gnu/usr.bin/as/bit_fix.h
new file mode 100644
index 0000000..5820c29
--- /dev/null
+++ b/gnu/usr.bin/as/bit_fix.h
@@ -0,0 +1,54 @@
+/* write.h
+
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+/* The bit_fix was implemented to support machines that need variables
+ to be inserted in bitfields other than 1, 2 and 4 bytes.
+ Furthermore it gives us a possibillity to mask in bits in the symbol
+ when it's fixed in the objectcode and check the symbols limits.
+
+ The or-mask is used to set the huffman bits in displacements for the
+ ns32k port.
+ The acbi, addqi, movqi, cmpqi instruction requires an assembler that
+ can handle bitfields. Ie handle an expression, evaluate it and insert
+ the result in an some bitfield. ( ex: 5 bits in a short field of a opcode)
+ */
+
+#ifndef __bit_fix_h__
+#define __bit_fix_h__
+
+struct bit_fix {
+ int fx_bit_size; /* Length of bitfield */
+ int fx_bit_offset; /* Bit offset to bitfield */
+ long fx_bit_base; /* Where do we apply the bitfix.
+ If this is zero, default is assumed. */
+ long fx_bit_base_adj; /* Adjustment of base */
+ long fx_bit_max; /* Signextended max for bitfield */
+ long fx_bit_min; /* Signextended min for bitfield */
+ long fx_bit_add; /* Or mask, used for huffman prefix */
+};
+typedef struct bit_fix bit_fixS;
+
+#endif /* __bit_fix_h__ */
+
+ /* end of bit_fix.h */
diff --git a/gnu/usr.bin/as/cond.c b/gnu/usr.bin/as/cond.c
new file mode 100644
index 0000000..9fda86f
--- /dev/null
+++ b/gnu/usr.bin/as/cond.c
@@ -0,0 +1,219 @@
+/* cond.c - conditional assembly pseudo-ops, and .include
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+
+#include "obstack.h"
+
+/* This is allocated to grow and shrink as .ifdef/.endif pairs are scanned. */
+struct obstack cond_obstack;
+
+struct file_line
+{
+ char *file;
+ unsigned int line;
+}; /* file_line */
+
+/* This is what we push and pop. */
+struct conditional_frame
+ {
+ struct file_line if_file_line; /* the source file & line number of the "if" */
+ struct file_line else_file_line; /* the source file & line of the "else" */
+ struct conditional_frame *previous_cframe;
+ int else_seen; /* have we seen an else yet? */
+ int ignoring; /* if we are currently ignoring input. */
+ int dead_tree; /* if a conditional at a higher level is ignoring input. */
+ }; /* conditional_frame */
+
+static void initialize_cframe PARAMS ((struct conditional_frame *cframe));
+
+static struct conditional_frame *current_cframe = NULL;
+
+void
+s_ifdef (arg)
+ int arg;
+{
+ register char *name; /* points to name of symbol */
+ register struct symbol *symbolP; /* Points to symbol */
+ struct conditional_frame cframe;
+
+ SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */
+ name = input_line_pointer;
+
+ if (!is_name_beginner (*name))
+ {
+ as_bad ("invalid identifier for \".ifdef\"");
+ obstack_1grow (&cond_obstack, 0);
+ }
+ else
+ {
+ get_symbol_end ();
+ ++input_line_pointer;
+ symbolP = symbol_find (name);
+
+ initialize_cframe (&cframe);
+ cframe.ignoring = cframe.dead_tree || !((symbolP != 0) ^ arg);
+ current_cframe = (struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe));
+ } /* if a valid identifyer name */
+
+ return;
+} /* s_ifdef() */
+
+void
+s_if (arg)
+ int arg;
+{
+ expressionS operand;
+ struct conditional_frame cframe;
+
+ SKIP_WHITESPACE (); /* Leading whitespace is part of operand. */
+ expression (&operand);
+
+#ifdef notyet
+ if (operand.X_op != O_constant)
+ as_bad ("non-constant expression in \".if\" statement");
+#else
+ if (operand.X_add_symbol != NULL || operand.X_subtract_symbol != NULL) {
+ as_bad("non-constant expression in \".if\" statement");
+ } /* bad condition */
+#endif
+
+ /* If the above error is signaled, this will dispatch
+ using an undefined result. No big deal. */
+ initialize_cframe (&cframe);
+ cframe.ignoring = cframe.dead_tree || !((operand.X_add_number != 0) ^ arg);
+ current_cframe = (struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe));
+ return;
+} /* s_if() */
+
+void
+s_endif (arg)
+ int arg;
+{
+ struct conditional_frame *hold;
+
+ if (current_cframe == NULL)
+ {
+ as_bad ("\".endif\" without \".if\"");
+ }
+ else
+ {
+ hold = current_cframe;
+ current_cframe = current_cframe->previous_cframe;
+ obstack_free (&cond_obstack, hold);
+ } /* if one pop too many */
+
+ return;
+} /* s_endif() */
+
+void
+s_else (arg)
+ int arg;
+{
+ if (current_cframe == NULL)
+ {
+ as_bad (".else without matching .if - ignored");
+
+ }
+ else if (current_cframe->else_seen)
+ {
+ as_bad ("duplicate \"else\" - ignored");
+ as_bad_where (current_cframe->else_file_line.file,
+ current_cframe->else_file_line.line,
+ "here is the previous \"else\"");
+ as_bad_where (current_cframe->if_file_line.file,
+ current_cframe->if_file_line.line,
+ "here is the previous \"if\"");
+ }
+ else
+ {
+ as_where (&current_cframe->else_file_line.file,
+ &current_cframe->else_file_line.line);
+
+ if (!current_cframe->dead_tree)
+ {
+ current_cframe->ignoring = !current_cframe->ignoring;
+ } /* if not a dead tree */
+
+ current_cframe->else_seen = 1;
+ } /* if error else do it */
+
+ return;
+} /* s_else() */
+
+void
+s_ifeqs (arg)
+ int arg;
+{
+ as_bad ("ifeqs not implemented.");
+
+ return;
+} /* s_ifeqs() */
+
+void
+s_end (arg)
+ int arg;
+{
+ return;
+} /* s_end() */
+
+int
+ignore_input ()
+{
+ /* We cannot ignore certain pseudo ops. */
+ if (input_line_pointer[-1] == '.'
+ && ((input_line_pointer[0] == 'i'
+ && (!strncmp (input_line_pointer, "if", 2)
+ || !strncmp (input_line_pointer, "ifdef", 5)
+ || !strncmp (input_line_pointer, "ifndef", 6)))
+ || (input_line_pointer[0] == 'e'
+ && (!strncmp (input_line_pointer, "else", 4)
+ || !strncmp (input_line_pointer, "endif", 5)))))
+ {
+ return 0;
+ }
+
+ return ((current_cframe != NULL) && (current_cframe->ignoring));
+} /* ignore_input() */
+
+static void
+initialize_cframe (cframe)
+ struct conditional_frame *cframe;
+{
+ memset (cframe, 0, sizeof (*cframe));
+ as_where (&cframe->if_file_line.file,
+ &cframe->if_file_line.line);
+ cframe->previous_cframe = current_cframe;
+ cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring;
+
+ return;
+} /* initialize_cframe() */
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * comment-column: 0
+ * End:
+ */
+
+/* end of cond.c */
diff --git a/gnu/usr.bin/as/config-gas.com b/gnu/usr.bin/as/config-gas.com
new file mode 100644
index 0000000..48e2e49
--- /dev/null
+++ b/gnu/usr.bin/as/config-gas.com
@@ -0,0 +1,76 @@
+$!
+$! This file sets things up to build gas on a VMS system to generate object
+$! files for a VMS system. We do not use the configure script, since we
+$! do not have /bin/sh to execute it.
+$!
+$! If you are running this file, then obviously the host is vax-dec-vms.
+$!
+$gas_host="vms"
+$!
+$cpu_type="vax"
+$emulation="generic"
+$obj_format="vms"
+$atof="vax"
+$!
+$! host specific information
+$call link host.h [.config]ho-'gas_host'.h
+$!
+$! Target specific information
+$call link targ-cpu.c [.config]tc-'cpu_type'.c
+$call link targ-cpu.h [.config]tc-'cpu_type'.h
+$call link targ-env.h [.config]te-'emulation'.h
+$!
+$! Code to handle the object file format.
+$call link obj-format.h [.config]obj-'obj_format'.h
+$call link obj-format.c [.config]obj-'obj_format'.c
+$!
+$! Code to handle floating point.
+$call link atof-targ.c [.config]atof-'atof'.c
+$!
+$!
+$! Create the file version.opt, which helps identify the executalbe.
+$!
+$search version.c version_string,"="/match=and/output=t.tmp
+$open ifile$ t.tmp
+$read ifile$ line
+$close ifile$
+$delete/nolog t.tmp;
+$ijk=f$locate("""",line)+1
+$line=f$extract(ijk,f$length(line)-ijk,line)
+$ijk=f$locate("""",line)
+$line=f$extract(0,ijk,line)
+$ijk=f$locate("\n",line)
+$line=f$extract(0,ijk,line)
+$!
+$i=0
+$loop:
+$elm=f$element(i," ",line)
+$if elm.eqs."" then goto no_ident
+$if (elm.les."9").and.(elm.ges."0") then goto write_ident
+$i=i+1
+$goto loop
+$!
+$no_ident:
+$elm="?.??"
+$!
+$!
+$write_ident:
+$open ifile$ version.opt/write
+$write ifile$ "ident="+""""+elm+""""
+$close ifile$
+$!
+$ !
+$ if f$search("config.status") .nes. "" then delete config.status.*
+$ open/write file config.status
+$ write file "Links are now set up for use with a vax running VMS."
+$ close file
+$ type config.status
+$exit
+$!
+$!
+$link:
+$subroutine
+$if f$search(p1).nes."" then delete/nolog 'p1';
+$copy 'p2' 'p1'
+$write sys$output "Linked ''p2' to ''p1'."
+$endsubroutine
diff --git a/gnu/usr.bin/as/config/Makefile.hp300 b/gnu/usr.bin/as/config/Makefile.hp300
new file mode 100644
index 0000000..981e5ca
--- /dev/null
+++ b/gnu/usr.bin/as/config/Makefile.hp300
@@ -0,0 +1,7 @@
+# from: @(#)Makefile.hp300 6.1 (Berkeley) 3/3/91
+# $FreeBSD$
+
+CFLAGS+= -Dm68851
+SRCS+= tc-m68k.c atof-ieee.c
+
+gas_target= m68k
diff --git a/gnu/usr.bin/as/config/Makefile.i386 b/gnu/usr.bin/as/config/Makefile.i386
new file mode 100644
index 0000000..79d30b3
--- /dev/null
+++ b/gnu/usr.bin/as/config/Makefile.i386
@@ -0,0 +1,5 @@
+# from: @(#)Makefile.i386 6.1 (Berkeley) 3/3/91
+# $FreeBSD$
+
+CFLAGS+= -DNON_BROKEN_WORDS -DPIC
+SRCS+= tc-i386.c atof-ieee.c
diff --git a/gnu/usr.bin/as/config/Makefile.pc532 b/gnu/usr.bin/as/config/Makefile.pc532
new file mode 100644
index 0000000..34d6fd3
--- /dev/null
+++ b/gnu/usr.bin/as/config/Makefile.pc532
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SRCS+= tc-ns32k.c atof-ns32k.c
+
+CFLAGS+= -DNS32532 -DNS32381
+
+gas_target= ns32k
diff --git a/gnu/usr.bin/as/config/Makefile.sparc b/gnu/usr.bin/as/config/Makefile.sparc
new file mode 100644
index 0000000..2952077
--- /dev/null
+++ b/gnu/usr.bin/as/config/Makefile.sparc
@@ -0,0 +1,5 @@
+# from: @(#)Makefile.i386 6.1 (Berkeley) 3/3/91
+# $FreeBSD$
+
+CFLAGS+= -DNON_BROKEN_WORDS -DPIC
+SRCS+= tc-sparc.c atof-ieee.c
diff --git a/gnu/usr.bin/as/config/Makefile.vax b/gnu/usr.bin/as/config/Makefile.vax
new file mode 100644
index 0000000..3bdd671
--- /dev/null
+++ b/gnu/usr.bin/as/config/Makefile.vax
@@ -0,0 +1,4 @@
+# from: @(#)Makefile.vax 6.1 (Berkeley) 3/3/91
+# $FreeBSD$
+
+SRCS+= tc-vax.c atof-vax.c
diff --git a/gnu/usr.bin/as/config/aout.h b/gnu/usr.bin/as/config/aout.h
new file mode 100644
index 0000000..9856cb0
--- /dev/null
+++ b/gnu/usr.bin/as/config/aout.h
@@ -0,0 +1,440 @@
+/* This file is aout.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef __A_OUT_GNU_H__
+#define __A_OUT_GNU_H__
+
+enum reloc_type {
+
+#ifdef TC_M88K
+ RELOC_LO16, /* lo16(sym) */
+ RELOC_HI16, /* hi16(sym) */
+ RELOC_PC16, /* bb0, bb1, bcnd */
+ RELOC_PC26, /* br, bsr */
+ RELOC_32, /* jump tables, etc */
+ RELOC_IW16, /* global access through linker regs 28 */
+ NO_RELOC,
+#else /* not TC_M88K */
+#ifdef TC_I860
+
+/* NOTE: three bits max, see struct reloc_info_i860.r_type */
+ NO_RELOC = 0, BRADDR, LOW0, LOW1, LOW2, LOW3, LOW4, SPLIT0, SPLIT1, SPLIT2, RELOC_32,
+
+#else /* not TC_I860 */
+
+ RELOC_8, RELOC_16, RELOC_32, /* simple relocations */
+ RELOC_DISP8, RELOC_DISP16, RELOC_DISP32, /* pc-rel displacement */
+ RELOC_WDISP30, RELOC_WDISP22,
+ RELOC_HI22, RELOC_22,
+ RELOC_13, RELOC_LO10,
+ RELOC_SFA_BASE, RELOC_SFA_OFF13,
+ RELOC_BASE10, RELOC_BASE13, RELOC_BASE22, /* P.I.C. (base-relative) */
+ RELOC_PC10, RELOC_PC22, /* for some sort of pc-rel P.I.C. (?) */
+ RELOC_JMP_TBL, /* P.I.C. jump table */
+ RELOC_SEGOFF16, /* reputedly for shared libraries somehow */
+ RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE,
+#ifndef TC_SPARC
+ RELOC_11,
+ RELOC_WDISP2_14,
+ RELOC_WDISP19,
+ RELOC_HHI22,
+ RELOC_HLO10,
+
+ /* 29K relocation types */
+ RELOC_JUMPTARG, RELOC_CONST, RELOC_CONSTH,
+
+ RELOC_WDISP14, RELOC_WDISP21,
+#endif /* not TC_SPARC */
+ NO_RELOC,
+
+#ifdef TC_I386
+ /* Used internally by gas */
+ RELOC_GOT,
+ RELOC_GOTOFF,
+#endif
+
+#endif /* not TC_I860 */
+#endif /* not TC_M88K */
+};
+
+
+#ifdef TC_I860
+ /* NOTE: two bits max, see reloc_info_i860.r_type */
+enum highlow_type {
+ NO_SPEC = 0, PAIR, HIGH, HIGHADJ,
+};
+#endif /* TC_I860 */
+
+
+#define __GNU_EXEC_MACROS__
+
+#ifndef __STRUCT_EXEC_OVERRIDE__
+
+/* This is the layout on disk of a Unix V7, Berkeley, SunOS, Vax Ultrix
+ "struct exec". Don't assume that on this machine, the "struct exec"
+ will lay out the same sizes or alignments. */
+
+struct exec_bytes {
+ unsigned char a_info[4];
+ unsigned char a_text[4];
+ unsigned char a_data[4];
+ unsigned char a_bss[4];
+ unsigned char a_syms[4];
+ unsigned char a_entry[4];
+ unsigned char a_trsize[4];
+ unsigned char a_drsize[4];
+};
+
+/* How big the "struct exec" is on disk */
+#define EXEC_BYTES_SIZE (8 * 4)
+
+/* This is the layout in memory of a "struct exec" while we process it. */
+
+struct exec
+{
+ unsigned long a_info; /* Use macros N_MAGIC, etc for access */
+ unsigned a_text; /* length of text, in bytes */
+ unsigned a_data; /* length of data, in bytes */
+ unsigned a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned a_syms; /* length of symbol table data in file, in bytes */
+ unsigned a_entry; /* start address */
+ unsigned a_trsize; /* length of relocation info for text, in bytes */
+ unsigned a_drsize; /* length of relocation info for data, in bytes */
+};
+
+#endif /* __STRUCT_EXEC_OVERRIDE__ */
+
+/* these go in the N_MACHTYPE field */
+/* These symbols could be defined by code from Suns...punt 'em */
+#undef M_UNKNOWN
+#undef M_68010
+#undef M_68020
+#undef M_SPARC
+enum machine_type {
+ M_UNKNOWN = 0,
+ M_68010 = 1,
+ M_68020 = 2,
+ M_SPARC = 3,
+ /* skip a bunch so we don't run into any of sun's numbers */
+ M_386 = 100,
+ M_29K = 101,
+ M_RS6000 = 102, /* IBM RS/6000 */
+ /* HP/BSD formats */
+ M_HP200 = 200, /* hp200 (68010) BSD binary */
+ M_HP300 = 300, /* hp300 (68020+68881) BSD binary */
+ M_HPUX23 = 0x020C, /* hp200/300 HPUX binary */
+};
+
+#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#define N_SET_MAGIC(exec, magic) \
+ ((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+
+/* Code indicating object file or impure executable. */
+#define OMAGIC 0407
+/* Code indicating pure executable. */
+#define NMAGIC 0410
+/* Code indicating demand-paged executable. */
+#define ZMAGIC 0413
+
+/* Virtual Address of text segment from the a.out file. For OMAGIC,
+ (almost always "unlinked .o's" these days), should be zero.
+ For linked files, should reflect reality if we know it. */
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(x) (N_MAGIC(x) == OMAGIC? 0 : TEXT_START_ADDR)
+#endif
+
+#ifndef N_BADMAG
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+#endif
+
+/* By default, segment size is constant. But on some machines, it can
+ be a function of the a.out header (e.g. machine type). */
+#ifndef N_SEGSIZE
+#define N_SEGSIZE(x) SEGMENT_SIZE
+#endif
+
+ /* This complexity is for encapsulated COFF support */
+#ifndef _N_HDROFF
+#define _N_HDROFF(x) (N_SEGSIZE(x) - sizeof (struct exec))
+#endif
+
+#ifndef N_TXTOFF
+#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? \
+ _N_HDROFF((x)) + sizeof (struct exec) : \
+ sizeof (struct exec))
+#endif
+
+
+#ifndef N_DATOFF
+#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text )
+#endif
+
+#ifndef N_TRELOFF
+#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data )
+#endif
+
+#ifndef N_DRELOFF
+#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
+#endif
+
+#ifndef N_SYMOFF
+#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize )
+#endif
+
+#ifndef N_STROFF
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+#endif
+
+/* Address of text segment in memory after it is loaded. */
+#ifndef N_TXTADDR
+#define N_TXTADDR(x) 0
+#endif
+
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x) == OMAGIC? (N_TXTADDR(x)+(x).a_text) \
+ : (N_SEGSIZE(x) + ((N_TXTADDR(x)+(x).a_text-1) & ~(N_SEGSIZE(x)-1))))
+#endif
+
+/* Address of bss segment in memory after it is loaded. */
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx;
+ } n_un;
+ unsigned char n_type;
+ char n_other;
+ short n_desc;
+ unsigned long n_value;
+};
+
+#define N_UNDF 0
+#define N_ABS 2
+#define N_TEXT 4
+#define N_DATA 6
+#define N_BSS 8
+#define N_COMM 0x12 /* common (visible in shared lib commons) */
+#define N_FN 0x1F /* File name of a .o file */
+
+/* Note: N_EXT can only usefully be 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
+#define N_TYPE 036
+#define N_STAB 0340
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition. */
+
+#define N_INDR 0xa
+
+/* The following type indicates the size of the symbol it refers to */
+#define N_SIZE 0xc
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ element's value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+/* Warning symbol. The text gives a warning message, the next symbol
+ in the table will be undefined. When the symbol is referenced, the
+ message is printed. */
+
+#define N_WARNING 0x1e
+
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+/* The following enum and struct were borrowed from SunOS's
+ /usr/include/sun4/a.out.h and extended to handle
+ other machines. It is currently used on SPARC and AMD 29000.
+
+ reloc_ext_bytes is how it looks on disk. reloc_info_extended is
+ how we might process it on a native host. */
+
+struct reloc_ext_bytes {
+ unsigned char r_address[4];
+ unsigned char r_index[3];
+ unsigned char r_bits[1];
+ unsigned char r_addend[4];
+};
+
+struct reloc_info_i860
+{
+ unsigned long r_address;
+ /*
+ * Using bit fields here is a bad idea because the order is not portable. :-(
+ */
+ unsigned int r_symbolnum: 24;
+ unsigned int r_pcrel : 1;
+ unsigned int r_extern : 1;
+ /* combining the two field simplifies the argument passing in "new_fix()" */
+ /* and is compatible with the existing Sparc #ifdef's */
+ /* r_type: highlow_type - bits 5,4; reloc_type - bits 3-0 */
+ unsigned int r_type : 6;
+ long r_addend;
+};
+
+
+#define RELOC_EXT_BITS_EXTERN_BIG 0x80
+#define RELOC_EXT_BITS_EXTERN_LITTLE 0x01
+
+#define RELOC_EXT_BITS_TYPE_BIG 0x1F
+#define RELOC_EXT_BITS_TYPE_SH_BIG 0
+#define RELOC_EXT_BITS_TYPE_LITTLE 0xF8
+#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
+
+#define RELOC_EXT_SIZE 12 /* Bytes per relocation entry */
+
+struct reloc_info_extended
+{
+ unsigned long r_address;
+ unsigned int r_index:24;
+# define r_symbolnum r_index
+ unsigned r_extern:1;
+ unsigned :2;
+ /* RS/6000 compiler does not support enum bitfield
+ enum reloc_type r_type:5; */
+ enum reloc_type r_type;
+ long int r_addend;
+};
+
+/* The standard, old-fashioned, Berkeley compatible relocation struct */
+
+struct reloc_std_bytes {
+ unsigned char r_address[4];
+ unsigned char r_index[3];
+ unsigned char r_bits[1];
+};
+
+#define RELOC_STD_BITS_PCREL_BIG 0x80
+#define RELOC_STD_BITS_PCREL_LITTLE 0x01
+
+#define RELOC_STD_BITS_LENGTH_BIG 0x60
+#define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */
+#define RELOC_STD_BITS_LENGTH_LITTLE 0x06
+#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1
+
+#define RELOC_STD_BITS_EXTERN_BIG 0x10
+#define RELOC_STD_BITS_EXTERN_LITTLE 0x08
+
+#define RELOC_STD_BITS_BASEREL_BIG 0x08
+#define RELOC_STD_BITS_BASEREL_LITTLE 0x08
+
+#define RELOC_STD_BITS_JMPTABLE_BIG 0x04
+#define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04
+
+#define RELOC_STD_BITS_RELATIVE_BIG 0x02
+#define RELOC_STD_BITS_RELATIVE_LITTLE 0x02
+
+#define RELOC_STD_SIZE 8 /* Bytes per relocation entry */
+
+#ifndef CUSTOM_RELOC_FORMAT
+struct relocation_info {
+ /* Address (within segment) to be relocated. */
+ int r_address;
+ /* The meaning of r_symbolnum depends on r_extern. */
+#if defined(TC_NS32K) && !defined(TE_SEQUENT)
+ unsigned int r_symbolnum:22;
+ unsigned int r_copy:1;
+ unsigned int r_relative:1;
+#else
+ unsigned int r_symbolnum:24;
+#endif
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in file's the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+#ifdef TC_NS32K
+#ifdef TE_SEQUENT
+ unsigned int r_bsr:1;
+#else
+ unsigned int r_jmptable:1;
+#endif
+ unsigned int r_disp:2;
+ unsigned int r_baserel:1;
+#else
+ /* The next three bits are for SunOS shared libraries, and seem to
+ be undocumented. */
+ unsigned int r_baserel:1; /* Linkage table relative */
+ unsigned int r_jmptable:1; /* pc-relative to jump table */
+ unsigned int r_relative:1; /* "relative relocation" */
+ /* unused */
+ unsigned int r_pad:1; /* Padding -- set to zero */
+#endif
+};
+#endif /* CUSTOM_RELOC_FORMAT */
+
+#endif /* __A_OUT_GNU_H__ */
+
+/* end of aout.h */
diff --git a/gnu/usr.bin/as/config/atof-ieee.c b/gnu/usr.bin/as/config/atof-ieee.c
new file mode 100644
index 0000000..5b5ff85
--- /dev/null
+++ b/gnu/usr.bin/as/config/atof-ieee.c
@@ -0,0 +1,525 @@
+/* atof_ieee.c - turn a Flonum into an IEEE floating point number
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+
+extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */
+
+#ifndef NULL
+#define NULL (0)
+#endif
+
+extern char EXP_CHARS[];
+/* Precision in LittleNums. */
+#define MAX_PRECISION (6)
+#define F_PRECISION (2)
+#define D_PRECISION (4)
+#define X_PRECISION (6)
+#define P_PRECISION (6)
+
+/* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+static unsigned long mask[] = {
+ 0x00000000,
+ 0x00000001,
+ 0x00000003,
+ 0x00000007,
+ 0x0000000f,
+ 0x0000001f,
+ 0x0000003f,
+ 0x0000007f,
+ 0x000000ff,
+ 0x000001ff,
+ 0x000003ff,
+ 0x000007ff,
+ 0x00000fff,
+ 0x00001fff,
+ 0x00003fff,
+ 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff,
+ 0x00ffffff,
+ 0x01ffffff,
+ 0x03ffffff,
+ 0x07ffffff,
+ 0x0fffffff,
+ 0x1fffffff,
+ 0x3fffffff,
+ 0x7fffffff,
+ 0xffffffff,
+};
+
+
+static int bits_left_in_littlenum;
+static int littlenums_left;
+static LITTLENUM_TYPE *littlenum_pointer;
+
+static int
+ next_bits (number_of_bits)
+int number_of_bits;
+{
+ int return_value;
+
+ if (!littlenums_left)
+ return(0);
+ if (number_of_bits >= bits_left_in_littlenum) {
+ return_value = mask[bits_left_in_littlenum] & *littlenum_pointer;
+ number_of_bits -= bits_left_in_littlenum;
+ return_value <<= number_of_bits;
+
+ if (--littlenums_left) {
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+ --littlenum_pointer;
+ return_value |= (*littlenum_pointer >> bits_left_in_littlenum) & mask[number_of_bits];
+ }
+ } else {
+ bits_left_in_littlenum -= number_of_bits;
+ return_value = mask[number_of_bits] & (*littlenum_pointer >> bits_left_in_littlenum);
+ }
+ return(return_value);
+}
+
+/* Num had better be less than LITTLENUM_NUMBER_OF_BITS */
+static void
+ unget_bits(num)
+int num;
+{
+ if (!littlenums_left) {
+ ++littlenum_pointer;
+ ++littlenums_left;
+ bits_left_in_littlenum = num;
+ } else if (bits_left_in_littlenum + num > LITTLENUM_NUMBER_OF_BITS) {
+ bits_left_in_littlenum = num - (LITTLENUM_NUMBER_OF_BITS - bits_left_in_littlenum);
+ ++littlenum_pointer;
+ ++littlenums_left;
+ } else
+ bits_left_in_littlenum += num;
+}
+
+static void
+ make_invalid_floating_point_number(words)
+LITTLENUM_TYPE *words;
+{
+ as_bad("cannot create floating-point number");
+ /* Zero the leftmost bit */
+ words[0] = (LITTLENUM_TYPE) ((unsigned) -1) >> 1;
+ words[1] = (LITTLENUM_TYPE) -1;
+ words[2] = (LITTLENUM_TYPE) -1;
+ words[3] = (LITTLENUM_TYPE) -1;
+ words[4] = (LITTLENUM_TYPE) -1;
+ words[5] = (LITTLENUM_TYPE) -1;
+}
+
+/***********************************************************************\
+ * Warning: this returns 16-bit LITTLENUMs. It is up to the caller *
+ * to figure out any alignment problems and to conspire for the *
+ * bytes/word to be emitted in the right order. Bigendians beware! *
+ * *
+ \***********************************************************************/
+
+/* Note that atof-ieee always has X and P precisions enabled. it is up
+ to md_atof to filter them out if the target machine does not support
+ them. */
+
+char * /* Return pointer past text consumed. */
+ atof_ieee(str, what_kind, words)
+char *str; /* Text to convert to binary. */
+char what_kind; /* 'd', 'f', 'g', 'h' */
+LITTLENUM_TYPE *words; /* Build the binary here. */
+{
+ static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
+ /* Extra bits for zeroed low-order bits. */
+ /* The 1st MAX_PRECISION are zeroed, */
+ /* the last contain flonum bits. */
+ char *return_value;
+ int precision; /* Number of 16-bit words in the format. */
+ long exponent_bits;
+ FLONUM_TYPE save_gen_flonum;
+
+ /* We have to save the generic_floating_point_number because it
+ contains storage allocation about the array of LITTLENUMs
+ where the value is actually stored. We will allocate our
+ own array of littlenums below, but have to restore the global
+ one on exit. */
+ save_gen_flonum = generic_floating_point_number;
+
+ return_value = str;
+ generic_floating_point_number.low = bits + MAX_PRECISION;
+ generic_floating_point_number.high = NULL;
+ generic_floating_point_number.leader = NULL;
+ generic_floating_point_number.exponent = 0;
+ generic_floating_point_number.sign = '\0';
+
+ /* Use more LittleNums than seems */
+ /* necessary: the highest flonum may have */
+ /* 15 leading 0 bits, so could be useless. */
+
+ memset(bits, '\0', sizeof(LITTLENUM_TYPE) * MAX_PRECISION);
+
+ switch (what_kind) {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ precision = F_PRECISION;
+ exponent_bits = 8;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ precision = D_PRECISION;
+ exponent_bits = 11;
+ break;
+
+ case 'x':
+ case 'X':
+ case 'e':
+ case 'E':
+ precision = X_PRECISION;
+ exponent_bits = 15;
+ break;
+
+ case 'p':
+ case 'P':
+
+ precision = P_PRECISION;
+ exponent_bits = -1;
+ break;
+
+ default:
+ make_invalid_floating_point_number(words);
+ return(NULL);
+ }
+
+ generic_floating_point_number.high = generic_floating_point_number.low + precision - 1 + GUARD;
+
+ if (atof_generic(&return_value, ".", EXP_CHARS, &generic_floating_point_number)) {
+ /* as_bad("Error converting floating point number (Exponent overflow?)"); */
+ make_invalid_floating_point_number(words);
+ return(NULL);
+ }
+ gen_to_words(words, precision, exponent_bits);
+
+ /* Restore the generic_floating_point_number's storage alloc
+ (and everything else). */
+ generic_floating_point_number = save_gen_flonum;
+
+ return(return_value);
+}
+
+/* Turn generic_floating_point_number into a real float/double/extended */
+int gen_to_words(words, precision, exponent_bits)
+LITTLENUM_TYPE *words;
+int precision;
+long exponent_bits;
+{
+ int return_value = 0;
+
+ long exponent_1;
+ long exponent_2;
+ long exponent_3;
+ long exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+ LITTLENUM_TYPE *lp;
+
+ if (generic_floating_point_number.low > generic_floating_point_number.leader) {
+ /* 0.0e0 seen. */
+ if (generic_floating_point_number.sign == '+')
+ words[0] = 0x0000;
+ else
+ words[0] = 0x8000;
+ memset(&words[1], '\0', sizeof(LITTLENUM_TYPE) * (precision - 1));
+ return(return_value);
+ }
+
+ /* NaN: Do the right thing */
+ if (generic_floating_point_number.sign == 0) {
+ if (precision == F_PRECISION) {
+ words[0] = 0x7fff;
+ words[1] = 0xffff;
+ } else {
+ words[0] = 0x7fff;
+ words[1] = 0xffff;
+ words[2] = 0xffff;
+ words[3] = 0xffff;
+ }
+ return return_value;
+ } else if (generic_floating_point_number.sign == 'P') {
+ /* +INF: Do the right thing */
+ if (precision == F_PRECISION) {
+ words[0] = 0x7f80;
+ words[1] = 0;
+ } else {
+ words[0] = 0x7ff0;
+ words[1] = 0;
+ words[2] = 0;
+ words[3] = 0;
+ }
+ return(return_value);
+ } else if (generic_floating_point_number.sign == 'N') {
+ /* Negative INF */
+ if (precision == F_PRECISION) {
+ words[0] = 0xff80;
+ words[1] = 0x0;
+ } else {
+ words[0] = 0xfff0;
+ words[1] = 0x0;
+ words[2] = 0x0;
+ words[3] = 0x0;
+ }
+ return(return_value);
+ }
+ /*
+ * The floating point formats we support have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word(s) are the next most significant bits.
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = generic_floating_point_number.leader;
+ littlenums_left = 1 + generic_floating_point_number.leader - generic_floating_point_number.low;
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0; !next_bits(1); ++exponent_skippage) ;;
+ exponent_1 = generic_floating_point_number.exponent + generic_floating_point_number.leader
+ + 1 - generic_floating_point_number.low;
+ /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2);
+ /* Offset exponent. */
+
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ word1 = (generic_floating_point_number.sign == '+') ? 0 : (1 << (LITTLENUM_NUMBER_OF_BITS - 1));
+
+ /* Assume 2's complement integers. */
+ if (exponent_4 < 1 && exponent_4 >= -62) {
+ int prec_bits;
+ int num_bits;
+
+ unget_bits(1);
+ num_bits = -exponent_4;
+ prec_bits = LITTLENUM_NUMBER_OF_BITS * precision - (exponent_bits + 1 + num_bits);
+ if (precision == X_PRECISION && exponent_bits == 15)
+ prec_bits -= LITTLENUM_NUMBER_OF_BITS + 1;
+
+ if (num_bits >= LITTLENUM_NUMBER_OF_BITS - exponent_bits) {
+ /* Bigger than one littlenum */
+ num_bits -= (LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits;
+ *lp++ = word1;
+ if (num_bits + exponent_bits + 1 >= precision * LITTLENUM_NUMBER_OF_BITS) {
+ /* Exponent overflow */
+ make_invalid_floating_point_number(words);
+ return(return_value);
+ }
+ if (precision == X_PRECISION && exponent_bits == 15) {
+ *lp++ = 0;
+ *lp++ = 0;
+ num_bits -= LITTLENUM_NUMBER_OF_BITS - 1;
+ }
+ while (num_bits >= LITTLENUM_NUMBER_OF_BITS) {
+ num_bits -= LITTLENUM_NUMBER_OF_BITS;
+ *lp++ = 0;
+ }
+ if (num_bits)
+ *lp++ = next_bits(LITTLENUM_NUMBER_OF_BITS - (num_bits));
+ } else {
+ if (precision == X_PRECISION && exponent_bits == 15) {
+ *lp++ = word1;
+ *lp++ = 0;
+ if (num_bits == LITTLENUM_NUMBER_OF_BITS) {
+ *lp++ = 0;
+ *lp++ = next_bits(LITTLENUM_NUMBER_OF_BITS - 1);
+ } else if (num_bits == LITTLENUM_NUMBER_OF_BITS - 1)
+ *lp++ = 0;
+ else
+ *lp++ = next_bits(LITTLENUM_NUMBER_OF_BITS - 1 - num_bits);
+ num_bits = 0;
+ } else {
+ word1 |= next_bits((LITTLENUM_NUMBER_OF_BITS - 1) - (exponent_bits + num_bits));
+ *lp++ = word1;
+ }
+ }
+ while (lp < words + precision)
+ *lp++ = next_bits(LITTLENUM_NUMBER_OF_BITS);
+
+ /* Round the mantissa up, but don't change the number */
+ if (next_bits(1)) {
+ --lp;
+ if (prec_bits > LITTLENUM_NUMBER_OF_BITS) {
+ int n = 0;
+ int tmp_bits;
+
+ n = 0;
+ tmp_bits = prec_bits;
+ while (tmp_bits > LITTLENUM_NUMBER_OF_BITS) {
+ if (lp[n] != (LITTLENUM_TYPE) - 1)
+ break;
+ --n;
+ tmp_bits -= LITTLENUM_NUMBER_OF_BITS;
+ }
+ if (tmp_bits > LITTLENUM_NUMBER_OF_BITS || (lp[n] & mask[tmp_bits]) != mask[tmp_bits]) {
+ unsigned long carry;
+
+ for (carry = 1; carry && (lp >= words); lp --) {
+ carry = *lp + carry;
+ *lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+ }
+ } else if ((*lp & mask[prec_bits]) != mask[prec_bits])
+ lp++;
+ }
+
+ return return_value;
+ } else if (exponent_4 & ~ mask[exponent_bits]) {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ make_invalid_floating_point_number (words);
+ return return_value;
+ } else {
+ word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits))
+ | next_bits ((LITTLENUM_NUMBER_OF_BITS - 1) - exponent_bits);
+ }
+
+ *lp++ = word1;
+
+ /* X_PRECISION is special: it has 16 bits of zero in the middle,
+ followed by a 1 bit. */
+ if (exponent_bits == 15 && precision == X_PRECISION) {
+ *lp++ = 0;
+ *lp++ = 1 << (LITTLENUM_NUMBER_OF_BITS) | next_bits(LITTLENUM_NUMBER_OF_BITS - 1);
+ }
+
+ /* The rest of the words are just mantissa bits. */
+ while (lp < words + precision)
+ *lp++ = next_bits(LITTLENUM_NUMBER_OF_BITS);
+
+ if (next_bits(1)) {
+ unsigned long carry;
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+ /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+ #endif */
+ for (carry = 1, lp--; carry && (lp >= words); lp--) {
+ carry = *lp + carry;
+ *lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+ if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) {
+ /* We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ *words &= ~(1 << (LITTLENUM_NUMBER_OF_BITS - 1));
+ /* make_invalid_floating_point_number (words); */
+ /* return return_value; */
+ }
+ }
+ return (return_value);
+}
+
+/* This routine is a real kludge. Someone really should do it better, but
+ I'm too lazy, and I don't understand this stuff all too well anyway
+ (JF)
+ */
+void
+ int_to_gen(x)
+long x;
+{
+ char buf[20];
+ char *bufp;
+
+ sprintf(buf,"%ld",x);
+ bufp = &buf[0];
+ if (atof_generic(&bufp, ".", EXP_CHARS, &generic_floating_point_number))
+ as_bad("Error converting number to floating point (Exponent overflow?)");
+}
+
+#ifdef TEST
+char *
+ print_gen(gen)
+FLONUM_TYPE *gen;
+{
+ FLONUM_TYPE f;
+ LITTLENUM_TYPE arr[10];
+ double dv;
+ float fv;
+ static char sbuf[40];
+
+ if (gen) {
+ f = generic_floating_point_number;
+ generic_floating_point_number = *gen;
+ }
+ gen_to_words(&arr[0], 4, 11);
+ memcpy(&dv, &arr[0], sizeof(double));
+ sprintf(sbuf, "%x %x %x %x %.14G ", arr[0], arr[1], arr[2], arr[3], dv);
+ gen_to_words(&arr[0], 2, 8);
+ memcpy(&fv, &arr[0], sizeof(float));
+ sprintf(sbuf + strlen(sbuf), "%x %x %.12g\n", arr[0], arr[1], fv);
+
+ if (gen) {
+ generic_floating_point_number = f;
+ }
+
+ return(sbuf);
+}
+#endif
+
+/* end of atof-ieee.c */
diff --git a/gnu/usr.bin/as/config/atof-ns32k.c b/gnu/usr.bin/as/config/atof-ns32k.c
new file mode 100644
index 0000000..06b748e
--- /dev/null
+++ b/gnu/usr.bin/as/config/atof-ns32k.c
@@ -0,0 +1,437 @@
+/* atof_ns32k.c - turn a Flonum into a ns32k floating point number
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* this is atof-m68k.c hacked for ns32k */
+
+#include "as.h"
+
+extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */
+
+extern char EXP_CHARS[];
+ /* Precision in LittleNums. */
+#define MAX_PRECISION (4)
+#define F_PRECISION (2)
+#define D_PRECISION (4)
+
+ /* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+int /* Number of chars in flonum type 'letter'. */
+atof_sizeof (letter)
+ char letter;
+{
+ int return_value;
+
+ /*
+ * Permitting uppercase letters is probably a bad idea.
+ * Please use only lower-cased letters in case the upper-cased
+ * ones become unsupported!
+ */
+ switch (letter)
+ {
+ case 'f':
+ return_value = F_PRECISION;
+ break;
+
+ case 'd':
+ return_value = D_PRECISION;
+ break;
+
+ default:
+ return_value = 0;
+ break;
+ }
+ return (return_value);
+}
+
+static unsigned long int mask[] = {
+ 0x00000000,
+ 0x00000001,
+ 0x00000003,
+ 0x00000007,
+ 0x0000000f,
+ 0x0000001f,
+ 0x0000003f,
+ 0x0000007f,
+ 0x000000ff,
+ 0x000001ff,
+ 0x000003ff,
+ 0x000007ff,
+ 0x00000fff,
+ 0x00001fff,
+ 0x00003fff,
+ 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff,
+ 0x00ffffff,
+ 0x01ffffff,
+ 0x03ffffff,
+ 0x07ffffff,
+ 0x0fffffff,
+ 0x1fffffff,
+ 0x3fffffff,
+ 0x7fffffff,
+ 0xffffffff
+ };
+
+static int bits_left_in_littlenum;
+static int littlenums_left;
+static LITTLENUM_TYPE * littlenum_pointer;
+
+static int
+next_bits (number_of_bits)
+ int number_of_bits;
+{
+ int return_value;
+
+ if (!littlenums_left)
+ return 0;
+ if (number_of_bits >= bits_left_in_littlenum)
+ {
+ return_value = mask[bits_left_in_littlenum] & *littlenum_pointer;
+ number_of_bits -= bits_left_in_littlenum;
+ return_value <<= number_of_bits;
+ if (littlenums_left) {
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+ littlenum_pointer --;
+ --littlenums_left;
+ return_value |= (*littlenum_pointer>>bits_left_in_littlenum) & mask[number_of_bits];
+ }
+ }
+ else
+ {
+ bits_left_in_littlenum -= number_of_bits;
+ return_value = mask[number_of_bits] & (*littlenum_pointer>>bits_left_in_littlenum);
+ }
+ return (return_value);
+}
+
+static void
+make_invalid_floating_point_number (words)
+ LITTLENUM_TYPE * words;
+{
+ /* Zero the leftmost bit */
+ words[0]= (LITTLENUM_TYPE) ((unsigned)-1)>>1;
+ words[1]= (LITTLENUM_TYPE) -1;
+ words[2]= (LITTLENUM_TYPE) -1;
+ words[3]= (LITTLENUM_TYPE) -1;
+}
+
+/***********************************************************************\
+* *
+* Warning: this returns 16-bit LITTLENUMs, because that is *
+* what the VAX thinks in. It is up to the caller to figure *
+* out any alignment problems and to conspire for the bytes/word *
+* to be emitted in the right order. Bigendians beware! *
+* *
+\***********************************************************************/
+
+char * /* Return pointer past text consumed. */
+atof_ns32k (str, what_kind, words)
+ char * str; /* Text to convert to binary. */
+ char what_kind; /* 'd', 'f', 'g', 'h' */
+ LITTLENUM_TYPE * words; /* Build the binary here. */
+{
+ FLONUM_TYPE f;
+ LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
+ /* Extra bits for zeroed low-order bits. */
+ /* The 1st MAX_PRECISION are zeroed, */
+ /* the last contain flonum bits. */
+ char * return_value;
+ int precision; /* Number of 16-bit words in the format. */
+ long int exponent_bits;
+
+ long int exponent_1;
+ long int exponent_2;
+ long int exponent_3;
+ long int exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+ LITTLENUM_TYPE * lp;
+
+ return_value = str;
+ f.low = bits + MAX_PRECISION;
+ f.high = NULL;
+ f.leader = NULL;
+ f.exponent = NULL;
+ f.sign = '\0';
+
+ /* Use more LittleNums than seems */
+ /* necessary: the highest flonum may have */
+ /* 15 leading 0 bits, so could be useless. */
+
+ bzero (bits, sizeof(LITTLENUM_TYPE) * MAX_PRECISION);
+
+ switch (what_kind) {
+ case 'f':
+ precision = F_PRECISION;
+ exponent_bits = 8;
+ break;
+
+ case 'd':
+ precision = D_PRECISION;
+ exponent_bits = 11;
+ break;
+
+ default:
+ make_invalid_floating_point_number (words);
+ return NULL;
+ }
+
+ f.high = f.low + precision - 1 + GUARD;
+
+ if (atof_generic (& return_value, ".", EXP_CHARS, & f)) {
+ as_warn("Error converting floating point number (Exponent overflow?)");
+ make_invalid_floating_point_number (words);
+ return NULL;
+ }
+
+ if (f.low > f.leader) {
+ /* 0.0e0 seen. */
+ bzero (words, sizeof(LITTLENUM_TYPE) * precision);
+ return return_value;
+ }
+
+ if (f.sign != '+' && f.sign != '-') {
+ make_invalid_floating_point_number(words);
+ return NULL;
+ }
+
+
+ /*
+ * All vaxen floating_point formats (so far) have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word are the next most significant bits.
+ * And so on for each other word.
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = f.leader;
+ littlenums_left = 1 + f.leader-f.low;
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0;! next_bits(1); exponent_skippage ++)
+ ;
+ exponent_1 = f.exponent + f.leader + 1 - f.low;
+ /* Radix LITTLENUM_RADIX, point just higher than f.leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2);
+ /* Offset exponent. */
+
+ if (exponent_4 & ~ mask[exponent_bits]) {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+
+ as_warn("Exponent overflow in floating-point number");
+ make_invalid_floating_point_number (words);
+ return return_value;
+ }
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ /* Assume 2's complement integers. */
+ word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) |
+ ((f.sign == '+') ? 0 : 0x8000) | next_bits (15 - exponent_bits);
+ * lp ++ = word1;
+
+ /* The rest of the words are just mantissa bits. */
+ for (; lp < words + precision; lp++)
+ * lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
+
+ if (next_bits (1)) {
+ unsigned long int carry;
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+
+/* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+#endif */
+ for (carry = 1, lp --; carry && (lp >= words); lp --) {
+ carry = * lp + carry;
+ * lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+ if ( (word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)) ) {
+ /* We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ make_invalid_floating_point_number (words);
+ return return_value;
+ }
+ }
+ return (return_value);
+}
+
+/* This is really identical to atof_ns32k except for some details */
+
+gen_to_words(words,precision,exponent_bits)
+LITTLENUM_TYPE *words;
+long int exponent_bits;
+{
+ int return_value=0;
+
+ long int exponent_1;
+ long int exponent_2;
+ long int exponent_3;
+ long int exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+ LITTLENUM_TYPE * lp;
+
+ if (generic_floating_point_number.low > generic_floating_point_number.leader) {
+ /* 0.0e0 seen. */
+ bzero (words, sizeof(LITTLENUM_TYPE) * precision);
+ return return_value;
+ }
+
+ /*
+ * All vaxen floating_point formats (so far) have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word are the next most significant bits.
+ * And so on for each other word.
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = generic_floating_point_number.leader;
+ littlenums_left = 1+generic_floating_point_number.leader - generic_floating_point_number.low;
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0;! next_bits(1); exponent_skippage ++)
+ ;
+ exponent_1 = generic_floating_point_number.exponent + generic_floating_point_number.leader + 1 -
+ generic_floating_point_number.low;
+ /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2);
+ /* Offset exponent. */
+
+ if (exponent_4 & ~ mask[exponent_bits]) {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+
+ make_invalid_floating_point_number (words);
+ return return_value;
+ }
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ /* Assume 2's complement integers. */
+ word1 = ((exponent_4 & mask[exponent_bits]) << (15 - exponent_bits)) |
+ ((generic_floating_point_number.sign == '+') ? 0 : 0x8000) | next_bits (15 - exponent_bits);
+ * lp ++ = word1;
+
+ /* The rest of the words are just mantissa bits. */
+ for (; lp < words + precision; lp++)
+ * lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
+
+ if (next_bits (1)) {
+ unsigned long int carry;
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+
+/* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+#endif */
+ for (carry = 1, lp --; carry && (lp >= words); lp --) {
+ carry = * lp + carry;
+ * lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+ if ( (word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)) ) {
+ /* We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ make_invalid_floating_point_number (words);
+ return return_value;
+ }
+ }
+ return (return_value);
+}
+
+/* This routine is a real kludge. Someone really should do it better, but
+ I'm too lazy, and I don't understand this stuff all too well anyway
+ (JF)
+ */
+void int_to_gen(x)
+long x;
+{
+ char buf[20];
+ char *bufp;
+
+ sprintf(buf,"%ld",x);
+ bufp= &buf[0];
+ if (atof_generic(&bufp,".", EXP_CHARS, &generic_floating_point_number))
+ as_warn("Error converting number to floating point (Exponent overflow?)");
+}
diff --git a/gnu/usr.bin/as/config/atof-tahoe.c b/gnu/usr.bin/as/config/atof-tahoe.c
new file mode 100644
index 0000000..64d00ea
--- /dev/null
+++ b/gnu/usr.bin/as/config/atof-tahoe.c
@@ -0,0 +1,428 @@
+/* atof_tahoe.c - turn a string into a Tahoe floating point number
+ Copyright (C) 1987 Free Software Foundation, Inc.
+ */
+
+/* This is really a simplified version of atof_vax.c. I glommed it wholesale
+ and then shaved it down. I don't even know how it works. (Don't you find
+ my honesty refreshing? bowen@cs.Buffalo.EDU (Devon E Bowen)
+
+ I don't allow uppercase letters in the precision descrpitors. Ie 'f' and
+ 'd' are allowed but 'F' and 'D' aren't */
+
+#include "as.h"
+
+/* Precision in LittleNums. */
+#define MAX_PRECISION (4)
+#define D_PRECISION (4)
+#define F_PRECISION (2)
+
+/* Precision in chars. */
+#define D_PRECISION_CHARS (8)
+#define F_PRECISION_CHARS (4)
+
+ /* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+static const long int mask [] = {
+ 0x00000000,
+ 0x00000001,
+ 0x00000003,
+ 0x00000007,
+ 0x0000000f,
+ 0x0000001f,
+ 0x0000003f,
+ 0x0000007f,
+ 0x000000ff,
+ 0x000001ff,
+ 0x000003ff,
+ 0x000007ff,
+ 0x00000fff,
+ 0x00001fff,
+ 0x00003fff,
+ 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff,
+ 0x00ffffff,
+ 0x01ffffff,
+ 0x03ffffff,
+ 0x07ffffff,
+ 0x0fffffff,
+ 0x1fffffff,
+ 0x3fffffff,
+ 0x7fffffff,
+ 0xffffffff
+ };
+
+
+/* Shared between flonum_gen2tahoe and next_bits */
+static int bits_left_in_littlenum;
+static LITTLENUM_TYPE * littlenum_pointer;
+static LITTLENUM_TYPE * littlenum_end;
+
+#if __STDC__ == 1
+
+int flonum_gen2tahoe(int format_letter, FLONUM_TYPE *f, LITTLENUM_TYPE *words);
+
+#else /* not __STDC__ */
+
+int flonum_gen2tahoe();
+
+#endif /* not __STDC__ */
+
+
+static int
+next_bits (number_of_bits)
+ int number_of_bits;
+{
+ int return_value;
+
+ if(littlenum_pointer<littlenum_end)
+ return 0;
+ if (number_of_bits >= bits_left_in_littlenum)
+ {
+ return_value = mask [bits_left_in_littlenum] & * littlenum_pointer;
+ number_of_bits -= bits_left_in_littlenum;
+ return_value <<= number_of_bits;
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+ littlenum_pointer --;
+ if(littlenum_pointer>=littlenum_end)
+ return_value |= ((*littlenum_pointer) >> (bits_left_in_littlenum)) &
+ mask [number_of_bits];
+ }
+ else
+ {
+ bits_left_in_littlenum -= number_of_bits;
+ return_value = mask [number_of_bits] &
+ ((*littlenum_pointer) >> bits_left_in_littlenum);
+ }
+ return (return_value);
+}
+
+static void
+make_invalid_floating_point_number (words)
+ LITTLENUM_TYPE * words;
+{
+ *words = 0x8000; /* Floating Reserved Operand Code */
+}
+
+static int /* 0 means letter is OK. */
+what_kind_of_float (letter, precisionP, exponent_bitsP)
+ char letter; /* In: lowercase please. What kind of float? */
+ int * precisionP; /* Number of 16-bit words in the float. */
+ long int * exponent_bitsP; /* Number of exponent bits. */
+{
+ int retval; /* 0: OK. */
+
+ retval = 0;
+ switch (letter)
+ {
+ case 'f':
+ * precisionP = F_PRECISION;
+ * exponent_bitsP = 8;
+ break;
+
+ case 'd':
+ * precisionP = D_PRECISION;
+ * exponent_bitsP = 8;
+ break;
+
+ default:
+ retval = 69;
+ break;
+ }
+ return (retval);
+}
+
+/***********************************************************************\
+* *
+* Warning: this returns 16-bit LITTLENUMs, because that is *
+* what the VAX thinks in. It is up to the caller to figure *
+* out any alignment problems and to conspire for the bytes/word *
+* to be emitted in the right order. Bigendians beware! *
+* *
+\***********************************************************************/
+
+char * /* Return pointer past text consumed. */
+atof_tahoe (str, what_kind, words)
+ char * str; /* Text to convert to binary. */
+ char what_kind; /* 'd', 'f', 'g', 'h' */
+ LITTLENUM_TYPE * words; /* Build the binary here. */
+{
+ FLONUM_TYPE f;
+ LITTLENUM_TYPE bits [MAX_PRECISION + MAX_PRECISION + GUARD];
+ /* Extra bits for zeroed low-order bits. */
+ /* The 1st MAX_PRECISION are zeroed, */
+ /* the last contain flonum bits. */
+ char * return_value;
+ int precision; /* Number of 16-bit words in the format. */
+ long int exponent_bits;
+
+ return_value = str;
+ f . low = bits + MAX_PRECISION;
+ f . high = NULL;
+ f . leader = NULL;
+ f . exponent = NULL;
+ f . sign = '\0';
+
+ if (what_kind_of_float (what_kind, & precision, & exponent_bits))
+ {
+ return_value = NULL; /* We lost. */
+ make_invalid_floating_point_number (words);
+ }
+ if (return_value)
+ {
+ memset(bits, '\0', sizeof(LITTLENUM_TYPE) * MAX_PRECISION);
+
+ /* Use more LittleNums than seems */
+ /* necessary: the highest flonum may have */
+ /* 15 leading 0 bits, so could be useless. */
+ f . high = f . low + precision - 1 + GUARD;
+
+ if (atof_generic (& return_value, ".", "eE", & f))
+ {
+ make_invalid_floating_point_number (words);
+ return_value = NULL; /* we lost */
+ }
+ else
+ {
+ if (flonum_gen2tahoe (what_kind, & f, words))
+ {
+ return_value = NULL;
+ }
+ }
+ }
+ return (return_value);
+}
+
+/*
+ * In: a flonum, a Tahoe floating point format.
+ * Out: a Tahoe floating-point bit pattern.
+ */
+
+int /* 0: OK. */
+flonum_gen2tahoe (format_letter, f, words)
+ char format_letter; /* One of 'd' 'f'. */
+ FLONUM_TYPE * f;
+ LITTLENUM_TYPE * words; /* Deliver answer here. */
+{
+ LITTLENUM_TYPE * lp;
+ int precision;
+ long int exponent_bits;
+ int return_value; /* 0 == OK. */
+
+ return_value = what_kind_of_float(format_letter,&precision,&exponent_bits);
+ if (return_value != 0)
+ {
+ make_invalid_floating_point_number (words);
+ }
+ else
+ {
+ if (f -> low > f -> leader)
+ {
+ /* 0.0e0 seen. */
+ memset(words, '\0', sizeof(LITTLENUM_TYPE) * precision);
+ }
+ else
+ {
+ long int exponent_1;
+ long int exponent_2;
+ long int exponent_3;
+ long int exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+
+ /* JF: Deal with new Nan, +Inf and -Inf codes */
+ if(f->sign!='-' && f->sign!='+') {
+ make_invalid_floating_point_number(words);
+ return return_value;
+ }
+ /*
+ * All tahoe floating_point formats have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word are the next most significant bits.
+ * And so on for each other word.
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = f -> leader;
+ littlenum_end = f->low;
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0;
+ ! next_bits(1);
+ exponent_skippage ++)
+ {
+ }
+ exponent_1 = f -> exponent + f -> leader + 1 - f -> low;
+ /* Radix LITTLENUM_RADIX, point just higher than f -> leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + (1 << (exponent_bits - 1));
+ /* Offset exponent. */
+
+ if (exponent_4 & ~ mask [exponent_bits])
+ {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ make_invalid_floating_point_number (words);
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ }
+ else
+ {
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ /* Assume 2's complement integers. */
+ word1 = ((exponent_4 & mask [exponent_bits]) << (15 - exponent_bits))
+ | ((f -> sign == '+') ? 0 : 0x8000)
+ | next_bits (15 - exponent_bits);
+ * lp ++ = word1;
+
+ /* The rest of the words are just mantissa bits. */
+ for (; lp < words + precision; lp++)
+ {
+ * lp = next_bits (LITTLENUM_NUMBER_OF_BITS);
+ }
+
+ if (next_bits (1))
+ {
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+ unsigned long int carry;
+
+ /*
+ #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+ #endif
+ */
+ for (carry = 1, lp --;
+ carry && (lp >= words);
+ lp --)
+ {
+ carry = * lp + carry;
+ * lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ if ( (word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)) )
+ {
+ make_invalid_floating_point_number (words);
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ }
+ } /* if (we needed to round up) */
+ } /* if (exponent overflow) */
+ } /* if (0.0e0) */
+ } /* if (float_type was OK) */
+ return (return_value);
+}
+
+/*
+ * md_atof()
+ *
+ * In: input_line_pointer -> the 1st character of a floating-point
+ * number.
+ * 1 letter denoting the type of statement that wants a
+ * binary floating point number returned.
+ * Address of where to build floating point literal.
+ * Assumed to be 'big enough'.
+ * Address of where to return size of literal (in chars).
+ *
+ * Out: Input_line_pointer -> of next char after floating number.
+ * Error message, or "".
+ * Floating point literal.
+ * Number of chars we used for the literal.
+ */
+
+char *
+md_atof (what_statement_type, literalP, sizeP)
+ char what_statement_type;
+ char * literalP;
+ int * sizeP;
+{
+ LITTLENUM_TYPE words [MAX_PRECISION];
+ register char kind_of_float;
+ register int number_of_chars;
+ register LITTLENUM_TYPE * littlenum_pointer;
+
+ switch (what_statement_type)
+ {
+ case 'f': /* .ffloat */
+ case 'd': /* .dfloat */
+ kind_of_float = what_statement_type;
+ break;
+
+ default:
+ kind_of_float = 0;
+ break;
+ };
+
+ if (kind_of_float)
+ {
+ register LITTLENUM_TYPE * limit;
+
+ input_line_pointer = atof_tahoe (input_line_pointer,
+ kind_of_float,
+ words);
+ /*
+ * The atof_tahoe() builds up 16-bit numbers.
+ * Since the assembler may not be running on
+ * a different-endian machine, be very careful about
+ * converting words to chars.
+ */
+ number_of_chars = (kind_of_float == 'f' ? F_PRECISION_CHARS :
+ (kind_of_float == 'd' ? D_PRECISION_CHARS : 0));
+ know(number_of_chars<=MAX_PRECISION*sizeof(LITTLENUM_TYPE));
+ limit = words + (number_of_chars / sizeof(LITTLENUM_TYPE));
+ for (littlenum_pointer = words;
+ littlenum_pointer < limit;
+ littlenum_pointer ++)
+ {
+ md_number_to_chars(literalP,*littlenum_pointer,
+ sizeof(LITTLENUM_TYPE));
+ literalP += sizeof(LITTLENUM_TYPE);
+ };
+ }
+ else
+ {
+ number_of_chars = 0;
+ };
+
+ * sizeP = number_of_chars;
+ return (kind_of_float ? "" : "Bad call to md_atof()");
+} /* md_atof() */
+
+/* atof_tahoe.c */
diff --git a/gnu/usr.bin/as/config/atof-vax.c b/gnu/usr.bin/as/config/atof-vax.c
new file mode 100644
index 0000000..56ad35a
--- /dev/null
+++ b/gnu/usr.bin/as/config/atof-vax.c
@@ -0,0 +1,497 @@
+/* atof_vax.c - turn a Flonum into a VAX floating point number
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* JF added these two for md_atof() */
+#include "as.h"
+
+/* Precision in LittleNums. */
+#define MAX_PRECISION (8)
+#define H_PRECISION (8)
+#define G_PRECISION (4)
+#define D_PRECISION (4)
+#define F_PRECISION (2)
+
+/* Length in LittleNums of guard bits. */
+#define GUARD (2)
+
+#if __STDC__ == 1
+
+int flonum_gen2vax(int format_letter, FLONUM_TYPE *f, LITTLENUM_TYPE *words);
+
+#else /* not __STDC__ */
+
+int flonum_gen2vax();
+
+#endif /* not __STDC__ */
+
+int /* Number of chars in flonum type 'letter'. */
+ atof_vax_sizeof (letter)
+char letter;
+{
+ int return_value;
+
+ /*
+ * Permitting uppercase letters is probably a bad idea.
+ * Please use only lower-cased letters in case the upper-cased
+ * ones become unsupported!
+ */
+ switch (letter)
+ {
+ case 'f':
+ case 'F':
+ return_value = 4;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'g':
+ case 'G':
+ return_value = 8;
+ break;
+
+ case 'h':
+ case 'H':
+ return_value = 16;
+ break;
+
+ default:
+ return_value = 0;
+ break;
+ }
+ return (return_value);
+} /* atof_vax_sizeof */
+
+static const long mask[] = {
+ 0x00000000,
+ 0x00000001,
+ 0x00000003,
+ 0x00000007,
+ 0x0000000f,
+ 0x0000001f,
+ 0x0000003f,
+ 0x0000007f,
+ 0x000000ff,
+ 0x000001ff,
+ 0x000003ff,
+ 0x000007ff,
+ 0x00000fff,
+ 0x00001fff,
+ 0x00003fff,
+ 0x00007fff,
+ 0x0000ffff,
+ 0x0001ffff,
+ 0x0003ffff,
+ 0x0007ffff,
+ 0x000fffff,
+ 0x001fffff,
+ 0x003fffff,
+ 0x007fffff,
+ 0x00ffffff,
+ 0x01ffffff,
+ 0x03ffffff,
+ 0x07ffffff,
+ 0x0fffffff,
+ 0x1fffffff,
+ 0x3fffffff,
+ 0x7fffffff,
+ 0xffffffff
+ };
+
+
+/* Shared between flonum_gen2vax and next_bits */
+static int bits_left_in_littlenum;
+static LITTLENUM_TYPE * littlenum_pointer;
+static LITTLENUM_TYPE * littlenum_end;
+
+static int
+ next_bits (number_of_bits)
+int number_of_bits;
+{
+ int return_value;
+
+ if (littlenum_pointer<littlenum_end)
+ return 0;
+ if (number_of_bits >= bits_left_in_littlenum)
+ {
+ return_value = mask[bits_left_in_littlenum] & * littlenum_pointer;
+ number_of_bits -= bits_left_in_littlenum;
+ return_value <<= number_of_bits;
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits;
+ littlenum_pointer --;
+ if (littlenum_pointer >= littlenum_end)
+ return_value |= ( (* littlenum_pointer) >> (bits_left_in_littlenum) ) & mask[number_of_bits];
+ }
+ else
+ {
+ bits_left_in_littlenum -= number_of_bits;
+ return_value = mask[number_of_bits] & ( (* littlenum_pointer) >> bits_left_in_littlenum);
+ }
+ return (return_value);
+}
+
+static void
+ make_invalid_floating_point_number (words)
+LITTLENUM_TYPE * words;
+{
+ * words = 0x8000; /* Floating Reserved Operand Code */
+}
+
+static int /* 0 means letter is OK. */
+ what_kind_of_float (letter, precisionP, exponent_bitsP)
+char letter; /* In: lowercase please. What kind of float? */
+int * precisionP; /* Number of 16-bit words in the float. */
+long * exponent_bitsP; /* Number of exponent bits. */
+{
+ int retval; /* 0: OK. */
+
+ retval = 0;
+ switch (letter)
+ {
+ case 'f':
+ * precisionP = F_PRECISION;
+ * exponent_bitsP = 8;
+ break;
+
+ case 'd':
+ * precisionP = D_PRECISION;
+ * exponent_bitsP = 8;
+ break;
+
+ case 'g':
+ * precisionP = G_PRECISION;
+ * exponent_bitsP = 11;
+ break;
+
+ case 'h':
+ * precisionP = H_PRECISION;
+ * exponent_bitsP = 15;
+ break;
+
+ default:
+ retval = 69;
+ break;
+ }
+ return (retval);
+}
+
+/***********************************************************************\
+ * *
+ * Warning: this returns 16-bit LITTLENUMs, because that is *
+ * what the VAX thinks in. It is up to the caller to figure *
+ * out any alignment problems and to conspire for the bytes/word *
+ * to be emitted in the right order. Bigendians beware! *
+ * *
+ \***********************************************************************/
+
+char * /* Return pointer past text consumed. */
+ atof_vax(str, what_kind, words)
+char *str; /* Text to convert to binary. */
+char what_kind; /* 'd', 'f', 'g', 'h' */
+LITTLENUM_TYPE *words; /* Build the binary here. */
+{
+ FLONUM_TYPE f;
+ LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
+ /* Extra bits for zeroed low-order bits. */
+ /* The 1st MAX_PRECISION are zeroed, */
+ /* the last contain flonum bits. */
+ char *return_value;
+ int precision; /* Number of 16-bit words in the format. */
+ long exponent_bits;
+
+ return_value = str;
+ f.low = bits + MAX_PRECISION;
+ f.high = NULL;
+ f.leader = NULL;
+ f.exponent = NULL;
+ f.sign = '\0';
+
+ if (what_kind_of_float (what_kind, & precision, & exponent_bits)) {
+ return_value = NULL; /* We lost. */
+ make_invalid_floating_point_number (words);
+ }
+
+ if (return_value) {
+ memset(bits, '\0', sizeof(LITTLENUM_TYPE) * MAX_PRECISION);
+
+ /* Use more LittleNums than seems */
+ /* necessary: the highest flonum may have */
+ /* 15 leading 0 bits, so could be useless. */
+ f.high = f.low + precision - 1 + GUARD;
+
+ if (atof_generic (& return_value, ".", "eE", & f)) {
+ make_invalid_floating_point_number (words);
+ return_value = NULL; /* we lost */
+ } else {
+ if (flonum_gen2vax(what_kind, & f, words)) {
+ return_value = NULL;
+ }
+ }
+ }
+ return(return_value);
+} /* atof_vax() */
+
+/*
+ * In: a flonum, a vax floating point format.
+ * Out: a vax floating-point bit pattern.
+ */
+
+int /* 0: OK. */
+ flonum_gen2vax (format_letter, f, words)
+char format_letter; /* One of 'd' 'f' 'g' 'h'. */
+FLONUM_TYPE *f;
+LITTLENUM_TYPE *words; /* Deliver answer here. */
+{
+ LITTLENUM_TYPE *lp;
+ int precision;
+ long exponent_bits;
+ int return_value; /* 0 == OK. */
+
+ return_value = what_kind_of_float(format_letter, &precision, &exponent_bits);
+
+ if (return_value != 0) {
+ make_invalid_floating_point_number (words);
+ } else {
+ if (f->low > f->leader) {
+ /* 0.0e0 seen. */
+memset(words, '\0', sizeof(LITTLENUM_TYPE) * precision);
+ } else {
+ long exponent_1;
+ long exponent_2;
+ long exponent_3;
+ long exponent_4;
+ int exponent_skippage;
+ LITTLENUM_TYPE word1;
+
+ /* JF: Deal with new Nan, +Inf and -Inf codes */
+ if (f->sign != '-' && f->sign != '+') {
+ make_invalid_floating_point_number(words);
+ return return_value;
+ }
+ /*
+ * All vaxen floating_point formats (so far) have:
+ * Bit 15 is sign bit.
+ * Bits 14:n are excess-whatever exponent.
+ * Bits n-1:0 (if any) are most significant bits of fraction.
+ * Bits 15:0 of the next word are the next most significant bits.
+ * And so on for each other word.
+ *
+ * All this to be compatible with a KF11?? (Which is still faster
+ * than lots of vaxen I can think of, but it also has higher
+ * maintenance costs ... sigh).
+ *
+ * So we need: number of bits of exponent, number of bits of
+ * mantissa.
+ */
+
+#ifdef NEVER /******* This zeroing seems redundant - Dean 3may86 **********/
+ /*
+ * No matter how few bits we got back from the atof()
+ * routine, add enough zero littlenums so the rest of the
+ * code won't run out of "significant" bits in the mantissa.
+ */
+ {
+ LITTLENUM_TYPE *ltp;
+ for (ltp = f->leader + 1;
+ ltp <= f->low + precision;
+ ltp++) {
+ *ltp = 0;
+ }
+ }
+#endif
+
+ bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS;
+ littlenum_pointer = f->leader;
+ littlenum_end = f->low;
+ /* Seek (and forget) 1st significant bit */
+ for (exponent_skippage = 0;
+ ! next_bits(1);
+ exponent_skippage ++) ;;
+
+ exponent_1 = f->exponent + f->leader + 1 - f->low;
+ /* Radix LITTLENUM_RADIX, point just higher than f->leader. */
+ exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS;
+ /* Radix 2. */
+ exponent_3 = exponent_2 - exponent_skippage;
+ /* Forget leading zeros, forget 1st bit. */
+ exponent_4 = exponent_3 + (1 << (exponent_bits - 1));
+ /* Offset exponent. */
+
+ if (exponent_4 & ~mask[exponent_bits]) {
+ /*
+ * Exponent overflow. Lose immediately.
+ */
+
+ make_invalid_floating_point_number (words);
+
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ } else {
+ lp = words;
+
+ /* Word 1. Sign, exponent and perhaps high bits. */
+ /* Assume 2's complement integers. */
+ word1 = (((exponent_4 &mask[exponent_bits]) << (15 - exponent_bits))
+ | ((f->sign == '+') ? 0 : 0x8000)
+ | next_bits(15 - exponent_bits));
+ *lp++ = word1;
+
+ /* The rest of the words are just mantissa bits. */
+ for (; lp < words + precision; lp++) {
+ *lp = next_bits(LITTLENUM_NUMBER_OF_BITS);
+ }
+
+ if (next_bits (1)) {
+ /*
+ * Since the NEXT bit is a 1, round UP the mantissa.
+ * The cunning design of these hidden-1 floats permits
+ * us to let the mantissa overflow into the exponent, and
+ * it 'does the right thing'. However, we lose if the
+ * highest-order bit of the lowest-order word flips.
+ * Is that clear?
+ */
+
+ unsigned long carry;
+
+ /*
+ #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2)
+ Please allow at least 1 more bit in carry than is in a LITTLENUM.
+ We need that extra bit to hold a carry during a LITTLENUM carry
+ propagation. Another extra bit (kept 0) will assure us that we
+ don't get a sticky sign bit after shifting right, and that
+ permits us to propagate the carry without any masking of bits.
+ #endif
+ */
+ for (carry = 1, lp--;
+ carry && (lp >= words);
+ lp--) {
+ carry = *lp + carry;
+ *lp = carry;
+ carry >>= LITTLENUM_NUMBER_OF_BITS;
+ }
+
+ if ((word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1))) {
+ make_invalid_floating_point_number(words);
+ /*
+ * We leave return_value alone: admit we read the
+ * number, but return a floating exception
+ * because we can't encode the number.
+ */
+ }
+ } /* if (we needed to round up) */
+ } /* if (exponent overflow) */
+ } /* if (0.0e0) */
+ } /* if (float_type was OK) */
+ return(return_value);
+} /* flonum_gen2vax() */
+
+
+/* JF this used to be in vax.c but this looks like a better place for it */
+
+/*
+ * md_atof()
+ *
+ * In: input_line_pointer->the 1st character of a floating-point
+ * number.
+ * 1 letter denoting the type of statement that wants a
+ * binary floating point number returned.
+ * Address of where to build floating point literal.
+ * Assumed to be 'big enough'.
+ * Address of where to return size of literal (in chars).
+ *
+ * Out: Input_line_pointer->of next char after floating number.
+ * Error message, or "".
+ * Floating point literal.
+ * Number of chars we used for the literal.
+ */
+
+#define MAXIMUM_NUMBER_OF_LITTLENUMS (8) /* For .hfloats. */
+
+char *
+ md_atof (what_statement_type, literalP, sizeP)
+char what_statement_type;
+char * literalP;
+int * sizeP;
+{
+ LITTLENUM_TYPE words[MAXIMUM_NUMBER_OF_LITTLENUMS];
+ register char kind_of_float;
+ register int number_of_chars;
+ register LITTLENUM_TYPE * littlenum_pointer;
+
+ switch (what_statement_type)
+ {
+ case 'F': /* .float */
+ case 'f': /* .ffloat */
+ kind_of_float = 'f';
+ break;
+
+ case 'D': /* .double */
+ case 'd': /* .dfloat */
+ kind_of_float = 'd';
+ break;
+
+ case 'g': /* .gfloat */
+ kind_of_float = 'g';
+ break;
+
+ case 'h': /* .hfloat */
+ kind_of_float = 'h';
+ break;
+
+ default:
+ kind_of_float = 0;
+ break;
+ };
+
+ if (kind_of_float)
+ {
+ register LITTLENUM_TYPE * limit;
+
+ input_line_pointer = atof_vax (input_line_pointer,
+ kind_of_float,
+ words);
+ /*
+ * The atof_vax() builds up 16-bit numbers.
+ * Since the assembler may not be running on
+ * a little-endian machine, be very careful about
+ * converting words to chars.
+ */
+ number_of_chars = atof_vax_sizeof (kind_of_float);
+ know( number_of_chars <= MAXIMUM_NUMBER_OF_LITTLENUMS * sizeof(LITTLENUM_TYPE) );
+ limit = words + (number_of_chars / sizeof(LITTLENUM_TYPE));
+ for (littlenum_pointer = words;
+ littlenum_pointer < limit;
+ littlenum_pointer ++)
+ {
+ md_number_to_chars (literalP, * littlenum_pointer, sizeof(LITTLENUM_TYPE));
+ literalP += sizeof(LITTLENUM_TYPE);
+ };
+ }
+ else
+ {
+ number_of_chars = 0;
+ };
+
+ * sizeP = number_of_chars;
+ return (kind_of_float ? "" : "Bad call to md_atof()");
+} /* md_atof() */
+
+/* end of atof-vax.c */
diff --git a/gnu/usr.bin/as/config/coff.h b/gnu/usr.bin/as/config/coff.h
new file mode 100644
index 0000000..a54f35b
--- /dev/null
+++ b/gnu/usr.bin/as/config/coff.h
@@ -0,0 +1,783 @@
+/* coff.h
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * At this point I'm sure this file is right for i960 and I'm pretty sure it's
+ * right for a29k, although it hasn't been tested rigorously. Please feel free
+ * to add your own machine's description here. Without that info, it isn't
+ * possible to build cross development tools from elsewhere nor is it easy to
+ * continue to support your machines format.
+ *
+ * The TC_foo ifdef's are mine. They are what gas uses. The other ifdef's
+ * remain for documentation from other scavenged files. xoxorich.
+ */
+
+/********************** FILE HEADER **********************/
+
+struct filehdr {
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ long f_timdat; /* time & date stamp */
+ long f_symptr; /* file pointer to symtab */
+ long f_nsyms; /* number of symtab entries */
+ unsigned short f_opthdr; /* sizeof(optional hdr) */
+ unsigned short f_flags; /* flags */
+};
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved externel references)
+ * F_LNNO line nunbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+
+#ifdef TC_I960
+#define F_AR32WR (0x0010) /* File has 32 bits per word, least
+ significant byte first. */
+#else /* TC_I960 */
+#define F_AR32WR (0x0100)
+#endif /* TC_I960 */
+
+#define F_MINMAL (0x0010) /* ??? */
+#define F_UPDATE (0x0020) /* ??? */
+#define F_SWABD (0x0040) /* ??? */
+#define F_AR16WR (0x0080) /* File has the byte ordering used by
+ the PDP*-11/70 processor. */
+#define F_AR32W (0x0200) /* File has 32 bits per word, most
+ significant byte first. */
+
+/*
+ * Intel 80960 (I960) processor flags.
+ * F_I960TYPE == mask for processor type field.
+ */
+
+#define F_I960TYPE (0xf000)
+#define F_I960CORE (0x1000)
+#define F_I960KB (0x2000)
+#define F_I960SB (0x2000)
+#define F_I960MC (0x3000)
+#define F_I960XA (0x4000)
+#define F_I960CA (0x5000)
+#define F_I960KA (0x6000)
+#define F_I960SA (0x6000)
+
+/*
+ * i80960 Magic Numbers
+ */
+
+#define I960ROMAGIC (0x160) /* read-only text segments */
+#define I960RWMAGIC (0x161) /* read-write text segments */
+
+#define I960BADMAG(x) (((x).f_magic != I960ROMAGIC) && ((x).f_magic != I960RWMAGIC))
+
+#define SIPFBOMAGIC (0x17a) /* Am29000 (Byte 0 is MSB - Big Endian) */
+#define SIPRBOMAGIC (0x17b) /* Am29000 (Byte 0 is LSB - Little Endian) */
+
+#define A29KBADMAG(x) (((x).f_magic != SIPFBOMAGIC) && ((x).f_magic != SIPRBOMAGIC))
+
+#ifdef TE_I386AIX
+# define I386MAGIC (0x175) /* Danbury AIX C compiler */
+# define I386SVMAGIC (0x14c) /* System V C Compiler */
+# define I386BADMAG(x) (((x).f_magic != I386MAGIC) && \
+ ((x).f_magic != I386SVMAGIC))
+#else /* not TE_I386AIX */
+# define I386MAGIC 0x14c
+# define I386BADMAG(x) (((x).f_magic != I386MAGIC))
+#endif /* not TE_I386AIX */
+
+
+#define FILHDR struct filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+typedef struct {
+ unsigned long phys_addr;
+ unsigned long bitarray;
+} TAGBITS;
+
+/* These appear to be used only by exec(2). I don't know who cares
+ about them in a cross development environment. In any case, this
+ is my collection after researching the issue for a few hours.
+ Apparently, most have these have remained essentially unchanged
+ since v7 days, although a few new ones have been added. xoxorich. */
+
+#define BAD0MAGIC (0401) /* (?) "lpd (UNIX/RT)" */
+#define BAD1MAGIC (0405) /* (?) overlay */
+#define OMAGIC (0407) /* old impure format. data immediately
+ follows text. both sections are rw. */
+#define NMAGIC (0410) /* split i&d, read-only text */
+#define A_MAGIC3 (0411) /* (?) "separated I&D" */
+#define ZMAGIC (0413) /* like NMAGIC, but demand loaded */
+#define PAGEMAGIC2 (0414) /* (?) like ZMAGIC, but address zero
+ explicitly unmapped. */
+#define REGMAGIC (0414) /* (?) a PAGEMAGIC2 alias? */
+#define PAGEMAGIC3 (0415) /* (?) like ZMAGIC, but address zero mapped. */
+#define A_MAGIC5 (0437) /* (?) "system overlay, separated I&D" */
+/* intended for non-unix cross development */
+#define SASMAGIC (010000) /* Single Address Space */
+#define MASMAGIC (020000) /* (?) "Multiple (separate I & D) Address Spaces" */
+
+typedef struct aouthdr {
+ short magic; /* type of file */
+ short vstamp; /* version stamp */
+ unsigned long tsize; /* text size in bytes, padded to FW bdry*/
+ unsigned long dsize; /* initialized data " " */
+ unsigned long bsize; /* uninitialized data " " */
+#if U3B
+ unsigned long dum1;
+ unsigned long dum2; /* pad to entry point */
+#endif
+ unsigned long entry; /* entry pt. */
+ unsigned long text_start; /* base of text used for this file */
+ unsigned long data_start; /* base of data used for this file */
+ /* CAREFUL: some formats omit the tagentries member. */
+ unsigned long tagentries; /* number of tag entries to
+ follow (always zero for i960) */
+} AOUTHDR;
+
+/* return a pointer to the tag bits array */
+
+#define TAGPTR(aout) ((TAGBITS *) (&(aout.tagentries)+1))
+
+/* compute size of a header */
+
+/*#define AOUTSZ(aout) (sizeof(AOUTHDR)+(aout.tagentries*sizeof(TAGBITS)))*/
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+/********************** STORAGE CLASSES **********************/
+
+#define C_EFCN -1 /* physical end of function */
+#define C_NULL 0
+#define C_AUTO 1 /* automatic variable */
+#define C_EXT 2 /* external symbol */
+#define C_STAT 3 /* static */
+#define C_REG 4 /* register variable */
+#define C_EXTDEF 5 /* external definition */
+#define C_LABEL 6 /* label */
+#define C_ULABEL 7 /* undefined label */
+#define C_MOS 8 /* member of structure */
+#define C_ARG 9 /* function argument */
+#define C_STRTAG 10 /* structure tag */
+#define C_MOU 11 /* member of union */
+#define C_UNTAG 12 /* union tag */
+#define C_TPDEF 13 /* type definition */
+#define C_USTATIC 14 /* undefined static */
+#define C_ENTAG 15 /* enumeration tag */
+#define C_MOE 16 /* member of enumeration */
+#define C_REGPARM 17 /* register parameter */
+#define C_FIELD 18 /* bit field */
+
+#ifdef TC_I960
+#define C_AUTOARG 19 /* auto argument */
+#define C_LASTENT 20 /* dummy entry (end of block) */
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+#define C_GLBLREG 19 /* global register */
+#define C_EXTREG 20 /* external global register */
+#define C_DEFREG 21 /* ext. def. of global register */
+#define C_STARTOF 22 /* as29 $SIZEOF and $STARTOF symbols */
+#endif /* TC_A29K */
+
+#define C_BLOCK 100 /* ".bb" or ".eb" */
+#define C_FCN 101 /* ".bf" or ".ef" */
+#define C_EOS 102 /* end of structure */
+#define C_FILE 103 /* file name */
+#define C_LINE 104 /* line # reformatted as symbol table entry */
+#define C_ALIAS 105 /* duplicate tag */
+#define C_HIDDEN 106 /* ext symbol in dmert public lib. like static,
+ used to avoid name conflicts. */
+
+#ifdef TC_I960
+/* New storage classes for 80960 */
+#define C_SCALL 107 /* Procedure reachable via system call */
+/* C_LEAFPROC is obsolete. Use C_LEAFEXT or C_LEAFSTAT */
+#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */
+#define C_LEAFEXT 108
+#define C_OPTVAR 109 /* Optimized variable */
+#define C_DEFINE 110 /* Preprocessor #define */
+#define C_PRAGMA 111 /* Advice to compiler or linker */
+#define C_SEGMENT 112 /* 80960 segment name */
+#define C_LEAFSTAT 113 /* Static leaf */
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+#define C_SHADOW 107 /* shadow symbol */
+#endif /* TC_A29K */
+
+/********************** SECTION HEADER **********************/
+
+struct scnhdr {
+ char s_name[8]; /* section name */
+ long s_paddr; /* physical address, aliased s_nlib */
+ long s_vaddr; /* virtual address */
+ long s_size; /* section size */
+ long s_scnptr; /* file ptr to raw data for section */
+ long s_relptr; /* file ptr to relocation */
+ long s_lnnoptr; /* file ptr to line numbers */
+ unsigned short s_nreloc; /* number of relocation entries */
+ unsigned short s_nlnno; /* number of line number entries */
+ long s_flags; /* flags */
+
+#ifdef TC_I960
+ unsigned long s_align; /* section alignment */
+#endif /* TC_I960 */
+};
+
+#define SCNHDR struct scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text" /* executable code section */
+#define _DATA ".data" /* initialized data */
+#define _BSS ".bss" /* un-initialized data */
+#define _DEBUG ".debug" /* special section used by dbx */
+#define _COMMENT ".comment" /* version info */
+#define _LIB ".lib" /* shared lib info section */
+#define _TV ".tv"
+
+/*
+ * s_flags "type"
+ */
+
+/*
+ * In instances where it is necessary for a linker to
+ * produce an output file which contains text or data not
+ * based at virtual address 0, e.g. for a ROM, then the
+ * linker should accept address base information as command
+ * input and use PAD sections to skip over unused addresses.
+ * (at least for a29k. Maybe others.)
+ */
+
+#define STYP_REG (0x0000) /* "regular" section: allocated, relocated, loaded */
+#define STYP_DSECT (0x0001) /* "dummy" section: not allocated, relocated, not loaded */
+#define STYP_NOLOAD (0x0002) /* "noload" section: allocated, relocated, not loaded */
+#define STYP_GROUP (0x0004) /* "grouped" section: formed of input sections */
+#define STYP_PAD (0x0008) /* "padding" section: not allocated, not relocated, loaded */
+#define STYP_COPY (0x0010) /* "copy" section: for decision function used by field update; not allocated, not relocated,
+ loaded; reloc & lineno entries processed normally */
+#define STYP_TEXT (0x0020) /* section contains text only */
+#define S_SHRSEG (0x0020) /* In 3b Update files (output of ogen), sections which appear in SHARED segments of the Pfile
+ will have the S_SHRSEG flag set by ogen, to inform dufr that updating 1 copy of the proc. will
+ update all process invocations. */
+#define STYP_DATA (0x0040) /* section contains data only */
+#define STYP_BSS (0x0080) /* section contains bss only */
+#define S_NEWFCN (0x0100) /* In a minimal file or an update file, a new function (as compared with a replaced function) */
+#define STYP_INFO (0x0200) /* comment section : not allocated not relocated, not loaded */
+#define STYP_OVER (0x0400) /* overlay section : relocated not allocated or loaded */
+#define STYP_LIB (0x0800) /* for .lib section : same as INFO */
+#define STYP_MERGE (0x2000) /* merge section -- combines with text, data or bss sections only */
+#define STYP_REVERSE_PAD (0x4000) /* section will be padded with no-op instructions wherever padding is necessary and there is a
+ word of contiguous bytes beginning on a word boundary. */
+
+#ifdef TC_A29K
+/* NOTE: The use of STYP_BSSREG for relocation is not yet defined. */
+#define STYP_BSSREG 0x1200 /* Global register area (like STYP_INFO) */
+#define STYP_ENVIR 0x2200 /* Environment (like STYP_INFO) */
+#define STYP_ABS 0x4000 /* Absolute (allocated, not reloc, loaded) */
+#define STYP_LIT 0x8020 /* Literal data (like STYP_TEXT) */
+#endif /* TC_A29K */
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct lineno {
+ union {
+ long l_symndx; /* symbol index of function name, iff l_lnno == 0*/
+ long l_paddr; /* (physical) address of line number */
+ } l_addr;
+ unsigned short l_lnno; /* line number */
+#ifdef TC_I960
+ /* not used on a29k */
+ char padding[2]; /* force alignment */
+#endif /* TC_I960 */
+};
+
+#define LINENO struct lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define SYMNMLEN 8 /* # characters in a symbol name */
+#define FILNMLEN 14 /* # characters in a file name */
+#define DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct syment {
+ union {
+ char _n_name[SYMNMLEN]; /* old COFF version */
+ struct {
+ long _n_zeroes; /* new == 0 */
+ long _n_offset; /* offset into string table */
+ } _n_n;
+ char *_n_nptr[2]; /* allows for overlaying */
+ } _n;
+ long n_value; /* value of symbol */
+ short n_scnum; /* section number */
+
+#ifdef TC_I960
+ /* This isn't yet used on the i960. In some formats this
+ is two bytes of padding. In others, it is missing entirely. */
+ unsigned short n_flags; /* copy of flags from filhdr */
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+ unsigned short n_type; /* type and derived type */
+#else /* TC_A29K */
+ /* at least i960 uses long */
+ unsigned long n_type; /* type and derived type */
+#endif /* TC_A29K */
+
+ char n_sclass; /* storage class */
+ char n_numaux; /* number of aux. entries */
+
+#ifndef TC_A29K
+ char pad2[2]; /* force alignment */
+#endif /* TC_A29K */
+};
+
+#define SYMENT struct syment
+#define SYMESZ sizeof(SYMENT) /* This had better also be sizeof(AUXENT) */
+
+#define n_name _n._n_name
+#define n_ptr _n._n_nptr[1]
+#define n_zeroes _n._n_n._n_zeroes
+#define n_offset _n._n_n._n_offset
+
+ /*
+ * Relocatable symbols have number of the section in which they are defined,
+ * or one of the following:
+ */
+
+#define N_SCNUM ((short) 1-65535) /* section num where symbol defined */
+#define N_UNDEF ((short)0) /* undefined symbol */
+#define N_ABS ((short)-1) /* value of symbol is absolute */
+#define N_DEBUG ((short)-2) /* debugging symbol -- symbol value is meaningless */
+#define N_TV ((short)-3) /* indicates symbol needs preload transfer vector */
+#define P_TV ((short)-4) /* indicates symbol needs transfer vector (postload) */
+
+/*
+ * Type of a symbol, in low 4 bits of the word
+ */
+#define T_NULL 0 /* type not assigned */
+#define T_VOID 1 /* function argument (only used by compiler) (but now real void). */
+#define T_CHAR 2 /* character */
+#define T_SHORT 3 /* short integer */
+#define T_INT 4 /* integer */
+#define T_LONG 5 /* long integer */
+#define T_FLOAT 6 /* floating point */
+#define T_DOUBLE 7 /* double word */
+#define T_STRUCT 8 /* structure */
+#define T_UNION 9 /* union */
+#define T_ENUM 10 /* enumeration */
+#define T_MOE 11 /* member of enumeration */
+#define T_UCHAR 12 /* unsigned character */
+#define T_USHORT 13 /* unsigned short */
+#define T_UINT 14 /* unsigned integer */
+#define T_ULONG 15 /* unsigned long */
+
+#ifdef TC_I960
+#define T_LNGDBL 16 /* long double */
+#endif /* TC_I960 */
+
+/*
+ * derived types, in n_type
+ */
+#define DT_NON (0) /* no derived type */
+#define DT_PTR (1) /* pointer */
+#define DT_FCN (2) /* function */
+#define DT_ARY (3) /* array */
+
+#ifndef TC_I960
+
+#define N_BTMASK (0x0f)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+#else /* TC_I960 */
+
+#define N_BTMASK (0x1f)
+#define N_TMASK (0x60)
+#define N_BTSHFT (5)
+#define N_TSHIFT (2)
+
+#endif /* TC_I960 */
+
+#define BTYPE(x) ((x) & N_BTMASK)
+
+#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
+#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
+#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
+
+#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
+
+union auxent {
+ struct {
+ long x_tagndx; /* str, un, or enum tag indx */
+ union {
+ struct {
+ unsigned short x_lnno; /* declaration line number */
+ unsigned short x_size; /* str/union/array size */
+ } x_lnsz;
+ long x_fsize; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ long x_lnnoptr; /* ptr to fcn line # */
+ long x_endndx; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ unsigned short x_dimen[DIMNUM];
+ } x_ary;
+ } x_fcnary;
+ unsigned short x_tvndx; /* tv index */
+ } x_sym;
+
+ /* This was just a struct x_file with x_fname only in a29k. xoxorich. */
+ union {
+ char x_fname[FILNMLEN];
+ struct {
+ long x_zeroes;
+ long x_offset;
+ } x_n;
+ } x_file;
+
+ struct {
+ long x_scnlen; /* section length */
+ unsigned short x_nreloc; /* # relocation entries */
+ unsigned short x_nlinno; /* # line numbers */
+ } x_scn;
+
+ struct {
+ long x_tvfill; /* tv fill value */
+ unsigned short x_tvlen; /* length of .tv */
+
+ /* This field was typo'd x_tvrna on a29k. xoxorich. */
+ unsigned short x_tvran[2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+#ifdef TC_I960
+ /******************************************
+ * I960-specific *2nd* aux. entry formats
+ ******************************************/
+ struct {
+ /* This is a very old typo that keeps getting propogated. */
+#define x_stdindx x_stindx
+ long x_stindx; /* sys. table entry */
+ } x_sc; /* system call entry */
+
+ struct {
+ unsigned long x_balntry; /* BAL entry point */
+ } x_bal; /* BAL-callable function */
+
+ struct {
+ unsigned long x_timestamp; /* time stamp */
+ char x_idstring[20]; /* producer identity string */
+ } x_ident; /* Producer ident info */
+
+ char a[sizeof(struct syment)]; /* force auxent/syment sizes to match */
+#endif /* TC_I960 */
+};
+
+#define AUXENT union auxent
+#define AUXESZ sizeof(AUXENT) /* This had better also be sizeof(SYMENT) */
+
+#if VAX || I960
+# define _ETEXT "_etext"
+#else
+# define _ETEXT "etext"
+#endif
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct reloc {
+ long r_vaddr; /* Virtual address of reference */
+ long r_symndx; /* Index into symbol table */
+ unsigned short r_type; /* Relocation type */
+#ifdef TC_I960
+ /* not used for a29k */
+ char pad[2]; /* Unused */
+#endif /* TC_I960 */
+};
+
+#define RELOC struct reloc
+#define RELSZ sizeof(RELOC)
+
+#define R_ABS (0x00) /* reference is absolute */
+
+#ifdef TC_I960
+#define R_RELLONG (0x11) /* Direct 32-bit relocation */
+#define R_IPRSHORT (0x18)
+#define R_IPRMED (0x19) /* 24-bit ip-relative relocation */
+#define R_IPRLONG (0x1a)
+#define R_OPTCALL (0x1b) /* 32-bit optimizable call (leafproc/sysproc) */
+#define R_OPTCALLX (0x1c) /* 64-bit optimizable call (leafproc/sysproc) */
+#define R_GETSEG (0x1d)
+#define R_GETPA (0x1e)
+#define R_TAGWORD (0x1f)
+#endif /* TC_I960 */
+
+#ifdef TC_A29K
+/*
+ * NOTE: All the "I" forms refer to Am29000 instruction
+ * formats. The linker is expected to know how the numeric
+ * information is split and/or aligned within the
+ * instruction word(s). R_BYTE works for instructions, too.
+ *
+ * If the parameter to a CONSTH instruction is a relocatable
+ * type, two relocation records are written. The first has
+ * an r_type of R_IHIHALF (33 octal) and a normal r_vaddr
+ * and r_symndx. The second relocation record has an r_type
+ * of R_IHCONST (34 octal), a normal r_vaddr (which is
+ * redundant), and an r_symndx containing the 32-bit
+ * constant offset to the relocation instead of the actual
+ * symbol table index. This second record is always
+ * written, even if the constant offset is zero. The
+ * constant fields of the instruction are set to zero.
+ */
+
+#define R_IREL (0x18) /* instruction relative (jmp/call) */
+#define R_IABS (0x19) /* instruction absolute (jmp/call) */
+#define R_ILOHALF (0x1a) /* instruction low half (const) */
+#define R_IHIHALF (0x1b) /* instruction high half (consth) part 1 */
+#define R_IHCONST (0x1c) /* instruction high half (consth) part 2
+ constant offset of R_IHIHALF relocation */
+#define R_BYTE (0x1d) /* relocatable byte value */
+#define R_HWORD (0x1e) /* relocatable halfword value */
+#define R_WORD (0x1f) /* relocatable word value */
+#define R_IGLBLRC (0x20) /* instruction global register RC */
+#define R_IGLBLRA (0x21) /* instruction global register RA */
+#define R_IGLBLRB (0x22) /* instruction global register RB */
+#endif /* TC_A29K */
+
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 16
+/* For new sections we haven't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
+
+#if defined(TC_I386)
+/*
+ * X86 generic
+ * 8-bit offset reference in 8-bits
+ * 8-bit offset reference in 16-bits
+ * 12-bit segment reference
+ * auxiliary relocation entry
+ */
+#define R_OFF8 07
+#define R_OFF16 010
+#define R_SEG12 011
+#define R_AUX 013
+
+/*
+ * B16 and X86 generics
+ * 16-bit direct reference
+ * 16-bit "relative" reference
+ * 16-bit "indirect" (TV) reference
+ */
+#define R_DIR16 01
+#define R_REL16 02
+#define R_IND16 03
+
+/*
+ * 3B generic
+ * 24-bit direct reference
+ * 24-bit "relative" reference
+ * 16-bit optimized "indirect" TV reference
+ * 24-bit "indirect" TV reference
+ * 32-bit "indirect" TV reference
+ */
+#define R_DIR24 04
+#define R_REL24 05
+#define R_OPT16 014
+#define R_IND24 015
+#define R_IND32 016
+
+/*
+ * XL generics
+ * 10-bit direct reference
+ * 10-bit "relative" reference
+ * 32-bit "relative" reference
+ */
+#define R_DIR10 025
+#define R_REL10 026
+#define R_REL32 027
+
+/*
+ * 3B and M32 generics
+ * 32-bit direct reference
+ */
+#define R_DIR32 06
+
+/*
+ * M32 generic
+ * 32-bit direct reference with bytes swapped
+ */
+#define R_DIR32S 012
+
+#endif /* TC_I386 */
+
+#if defined(TE_I386AIX)
+
+#define UINFOSIZ 64 /* size of user info buffer */
+typedef char uinfo_t[UINFOSIZ];
+
+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];
+};
+
+#define CD_NAMELEN 16 /* length of most names in this header */
+#define CORHDRSIZ 2048 /* size to which header is padded out */
+#define MAX_CORE_SEGS 32 /* maximum segments in a core dump */
+#define NUM_FREGS 1 /* # of saved FP regs */
+
+/*
+ * These are defined such that 286 and 386 kernels can produce
+ * compatible dumps.
+ */
+#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
+#define NUM_REGS 16
+
+#ifndef SPATHLEN
+# define SPATHLEN 16 /* sys/param.h */
+#endif
+#ifndef NSIG
+# define NSIG 63 /* sys/signal.h */
+# define SIGSETSZ ((NSIG+31)/32)
+typedef struct ksigmask {
+ unsigned long sigs[SIGSETSZ];
+} ksigmask_t;
+#endif
+
+struct corehdr {
+ char cd_magic[4]; /* COR_MAGIC = "core" */
+
+ /* general information about the dump itself */
+ struct dumpseg { /* table of contents for dump */
+ long cs_type; /* seg. type; see below */
+ long cs_len; /* length (in bytes) of segment */
+ long cs_offset; /* offset (in dump) of segment */
+ long cs_address; /* address segment had in mem */
+ } cd_segs[MAX_CORE_SEGS];
+
+ /* general information about the process */
+ char cd_comm[CD_NAMELEN]; /* command being run */
+ char cd_mach[CD_NAMELEN]; /* type of machine it ran on */
+ char cd_site[CD_NAMELEN]; /* name of site it ran on */
+ long cd_ldtype; /* type of load module running */
+ char cd_intsize; /* sizeof(int) */
+ char cd_dptrsize; /* sizeof(char *) */
+ char cd_tptrsize; /* sizeof(int (*)()) */
+ char cd_unused;
+
+ /* user-mode program state */
+ long cd_regs[NUM_REGS]; /* user-mode general registers */
+ struct env387 cd_fpregs; /* user-mode floating-point state */
+
+ /* kernel-mode program state */
+ int (*cd_sig[NSIG])(); /* disposition of signals */
+ ksigmask_t cd_sigmask; /* signals to be blocked */
+ ksigmask_t cd_sigpend; /* signals currently pending */
+ long cd_cursig; /* signal that caused the dump */
+
+ long cd_pid; /* process ID of the corpse */
+ long cd_ppid; /* parent process ID of corpse */
+ short cd_uid; /* process effective user ID */
+ short cd_ruid; /* process real user ID */
+ short cd_gid; /* process effective group ID */
+ short cd_rgid; /* process real group ID */
+
+ uinfo_t cd_uinfo; /* buffer of user information */
+ char cd_locname[32]; /* name of /local */
+ char cd_uvers[CD_NAMELEN]; /* user version string */
+ unsigned short cd_spath[SPATHLEN]; /* sitepath */
+};
+
+#ifndef NOCHECKS
+/* this will generate an error if sizeof(struct corehdr) > CORHDRSIZ */
+struct { char xxcdxx[CORHDRSIZ+1-sizeof(struct corehdr)]; };
+#endif /* ! NOCHECKS */
+
+/*
+ * segment types (in cs_type)
+ * each segment in the address space appears here, whether or not it
+ * is actually dumped. Read/only segments will not actually be dumped.
+ * A segment that is not in the dump will have a cs_offset of zero.
+ */
+#define COR_TYPE_CODE 'x' /* process code - NOT IN DUMP */
+#define COR_TYPE_DATA 'd' /* process data segment */
+#define COR_TYPE_STACK 's' /* process stack segment */
+#define COR_TYPE_LIBCODE 'X' /* shared lib code - NOT IN DUMP*/
+#define COR_TYPE_LIBDATA 'D' /* shared lib data */
+#define COR_TYPE_READ 'r' /* other read/only - NOT IN DUMP*/
+#define COR_TYPE_WRITE 'w' /* other writeable */
+#define COR_TYPE_MSC '?' /* other, mapped in segment */
+
+#endif /* TE_I386AIX */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * End:
+ */
+
+/* end of coff.h */
diff --git a/gnu/usr.bin/as/config/cplus-dem.c b/gnu/usr.bin/as/config/cplus-dem.c
new file mode 100644
index 0000000..79d3279
--- /dev/null
+++ b/gnu/usr.bin/as/config/cplus-dem.c
@@ -0,0 +1,927 @@
+/* Demangler for GNU C++
+ Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+ written by James Clark (jjc@jclark.uucp)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 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 is for g++ 1.36.1 (November 6 version). It will probably
+ require changes for any other version. */
+
+/* This file exports one function
+
+ char *cplus_demangle (const char *name)
+
+ If `name' is a mangled function name produced by g++, then
+ a pointer to a malloced string giving a C++ representation
+ of the name will be returned; otherwise NULL will be returned.
+ It is the caller's responsibility to free the string which
+ is returned.
+
+ For example,
+
+ cplus_demangle ("_foo__1Ai")
+
+ returns
+
+ "A::foo(int)"
+
+ This file imports xmalloc and xrealloc, which are like malloc and
+ realloc except that they generate a fatal error if there is no
+ available memory. */
+
+/* #define nounderscore 1 /* define this is names don't start with _ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#if !defined(sequent) && !defined(NeXT)
+#include <memory.h>
+#else
+#define memcpy(s1, s2, n) strncpy(s1, s2, n)
+#define memcmp(s1, s2, n) strncmp(s1, s2, n)
+#define strchr(s, c) index(s, c)
+#endif
+
+#if __STDC__ != 1
+#define const
+#endif
+
+#if __STDC__ == 1
+extern char *cplus_demangle (const char *type);
+#else
+extern char *cplus_demangle ();
+#endif
+
+#if __STDC__ == 1
+extern char *xmalloc (int);
+extern char *xrealloc (char *, int);
+#else
+extern char *xmalloc ();
+extern char *xrealloc ();
+#endif
+
+static char **typevec = 0;
+static int ntypes = 0;
+static int typevec_size = 0;
+
+static struct {
+ const char *in;
+ const char *out;
+} optable[] = {
+ "new", " new",
+ "delete", " delete",
+ "ne", "!=",
+ "eq", "==",
+ "ge", ">=",
+ "gt", ">",
+ "le", "<=",
+ "lt", "<",
+ "plus", "+",
+ "minus", "-",
+ "mult", "*",
+ "negate", "-",
+ "trunc_mod", "%",
+ "trunc_div", "/",
+ "truth_andif", "&&",
+ "truth_orif", "||",
+ "postincrement", "++",
+ "postdecrement", "--",
+ "bit_ior", "|",
+ "bit_xor", "^",
+ "bit_and", "&",
+ "bit_not", "~",
+ "call", "()",
+ "cond", "?:",
+ "alshift", "<<",
+ "arshift", ">>",
+ "component", "->",
+ "nop", "", /* for operator= */
+};
+
+/* Beware: these aren't '\0' terminated. */
+
+typedef struct {
+ char *b; /* pointer to start of string */
+ char *p; /* pointer after last character */
+ char *e; /* pointer after end of allocated space */
+} string;
+
+#if __STDC__ == 1
+static void string_need (string *s, int n);
+static void string_delete (string *s);
+static void string_init (string *s);
+static void string_clear (string *s);
+static int string_empty (string *s);
+static void string_append (string *p, const char *s);
+static void string_appends (string *p, string *s);
+static void string_appendn (string *p, const char *s, int n);
+static void string_prepend (string *p, const char *s);
+#if 0
+static void string_prepends (string *p, string *s);
+#endif
+static void string_prependn (string *p, const char *s, int n);
+static int get_count (const char **type, int *count);
+static int do_args (const char **type, string *decl);
+static int do_type (const char **type, string *result);
+static int do_arg (const char **type, string *result);
+static int do_args (const char **type, string *decl);
+static void munge_function_name (string *name);
+#else
+static void string_need ();
+static void string_delete ();
+static void string_init ();
+static void string_clear ();
+static int string_empty ();
+static void string_append ();
+static void string_appends ();
+static void string_appendn ();
+static void string_prepend ();
+static void string_prepends ();
+static void string_prependn ();
+static int get_count ();
+static int do_args ();
+static int do_type ();
+static int do_arg ();
+static int do_args ();
+static void munge_function_name ();
+#endif
+
+char *
+ cplus_demangle (type)
+const char *type;
+{
+ string decl;
+ int n;
+ int success = 0;
+ int constructor = 0;
+ int const_flag = 0;
+ int i;
+ const char *p;
+
+ if (type == NULL || *type == '\0')
+ return NULL;
+#ifndef nounderscore
+ if (*type++ != '_')
+ return NULL;
+#endif
+ p = type;
+ while (*p != '\0' && !(*p == '_' && p[1] == '_'))
+ p++;
+ if (*p == '\0')
+ {
+ /* destructor */
+ if (type[0] == '_' && type[1] == '$' && type[2] == '_')
+ {
+ int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
+ char *tem = (char *) xmalloc (n);
+ strcpy (tem, type + 3);
+ strcat (tem, "::~");
+ strcat (tem, type + 3);
+ strcat (tem, "()");
+ return tem;
+ }
+ /* static data member */
+ if (*type != '_' && (p = strchr (type, '$')) != '\0')
+ {
+ int n = strlen (type) + 2;
+ char *tem = (char *) xmalloc (n);
+ memcpy (tem, type, p - type);
+ strcpy (tem + (p - type), "::");
+ strcpy (tem + (p - type) + 2, p + 1);
+ return tem;
+ }
+ return NULL;
+ }
+
+ string_init (&decl);
+
+ if (p == type)
+ {
+ if (!isdigit (p[2]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ constructor = 1;
+ }
+ else
+ {
+ string_appendn (&decl, type, p - type);
+ munge_function_name (&decl);
+ }
+ p += 2;
+
+ switch (*p)
+ {
+ case 'C':
+ /* a const member function */
+ if (!isdigit (p[1]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ p += 1;
+ const_flag = 1;
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (strlen (p) < n)
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ if (constructor)
+ {
+ string_appendn (&decl, p, n);
+ string_append (&decl, "::");
+ string_appendn (&decl, p, n);
+ }
+ else
+ {
+ string_prepend (&decl, "::");
+ string_prependn (&decl, p, n);
+ }
+ p += n;
+ success = do_args (&p, &decl);
+ if (const_flag)
+ string_append (&decl, " const");
+ break;
+ case 'F':
+ p += 1;
+ success = do_args (&p, &decl);
+ break;
+ }
+
+ for (i = 0; i < ntypes; i++)
+ if (typevec[i] != NULL)
+ free (typevec[i]);
+ ntypes = 0;
+ if (typevec != NULL)
+ {
+ free ((char *)typevec);
+ typevec = NULL;
+ typevec_size = 0;
+ }
+
+ if (success)
+ {
+ string_appendn (&decl, "", 1);
+ return decl.b;
+ }
+ else
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+}
+
+static int
+ get_count (type, count)
+const char **type;
+int *count;
+{
+ if (!isdigit (**type))
+ return 0;
+ *count = **type - '0';
+ *type += 1;
+ /* see flush_repeats in cplus-method.c */
+ if (isdigit (**type))
+ {
+ const char *p = *type;
+ int n = *count;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (*p == '_')
+ {
+ *type = p + 1;
+ *count = n;
+ }
+ }
+ return 1;
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+ do_type (type, result)
+const char **type;
+string *result;
+{
+ int n;
+ int done;
+ int non_empty;
+ int success;
+ string decl;
+ const char *remembered_type;
+
+ string_init (&decl);
+ string_init (result);
+
+ done = 0;
+ success = 1;
+ while (success && !done)
+ {
+ int member;
+ switch (**type)
+ {
+ case 'P':
+ *type += 1;
+ string_prepend (&decl, "*");
+ break;
+
+ case 'R':
+ *type += 1;
+ string_prepend (&decl, "&");
+ break;
+
+ case 'T':
+ *type += 1;
+ if (!get_count (type, &n) || n >= ntypes)
+ success = 0;
+ else
+ {
+ remembered_type = typevec[n];
+ type = &remembered_type;
+ }
+ break;
+
+ case 'F':
+ *type += 1;
+ if (!string_empty (&decl) && decl.b[0] == '*')
+ {
+ string_prepend (&decl, "(");
+ string_append (&decl, ")");
+ }
+ if (!do_args (type, &decl) || **type != '_')
+ success = 0;
+ else
+ *type += 1;
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ int constp = 0;
+ int volatilep = 0;
+
+ member = **type == 'M';
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_append (&decl, ")");
+ string_prepend (&decl, "::");
+ string_prependn (&decl, *type, n);
+ string_prepend (&decl, "(");
+ *type += n;
+ if (member)
+ {
+ if (**type == 'C')
+ {
+ *type += 1;
+ constp = 1;
+ }
+ if (**type == 'V')
+ {
+ *type += 1;
+ volatilep = 1;
+ }
+ if (*(*type)++ != 'F')
+ {
+ success = 0;
+ break;
+ }
+ }
+ if ((member && !do_args (type, &decl)) || **type != '_')
+ {
+ success = 0;
+ break;
+ }
+ *type += 1;
+ if (constp)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "const");
+ }
+ if (volatilep)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "volatilep");
+ }
+ break;
+ }
+
+ case 'C':
+ if ((*type)[1] == 'P')
+ {
+ *type += 1;
+ if (!string_empty (&decl))
+ string_prepend (&decl, " ");
+ string_prepend (&decl, "const");
+ break;
+ }
+
+ /* fall through */
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ done = 0;
+ non_empty = 0;
+ while (success && !done)
+ {
+ switch (**type)
+ {
+ case 'C':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "const");
+ break;
+ case 'U':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "unsigned");
+ break;
+ case 'V':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "volatile");
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ if (success)
+ switch (**type)
+ {
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "void");
+ break;
+ case 'l':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long");
+ break;
+ case 'i':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "int");
+ break;
+ case 's':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "short");
+ break;
+ case 'c':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "char");
+ break;
+ case 'r':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long double");
+ break;
+ case 'd':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "double");
+ break;
+ case 'f':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "float");
+ break;
+ case 'G':
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ if (non_empty)
+ string_append (result, " ");
+ string_appendn (result, *type, n);
+ *type += n;
+ break;
+ default:
+ success = 0;
+ break;
+ }
+
+ if (success)
+ {
+ if (!string_empty (&decl))
+ {
+ string_append (result, " ");
+ string_appends (result, &decl);
+ }
+ string_delete (&decl);
+ return 1;
+ }
+ else
+ {
+ string_delete (&decl);
+ string_delete (result);
+ return 0;
+ }
+}
+
+/* `result' will be initialised in do_type; it will be freed on failure */
+
+static int
+ do_arg (type, result)
+const char **type;
+string *result;
+{
+ char *tem;
+ int len;
+ const char *start;
+ const char *end;
+
+ start = *type;
+ if (!do_type (type, result))
+ return 0;
+ end = *type;
+ if (ntypes >= typevec_size)
+ {
+ if (typevec_size == 0)
+ {
+ typevec_size = 3;
+ typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
+ }
+ else
+ {
+ typevec_size *= 2;
+ typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
+ }
+ }
+ len = end - start;
+ tem = (char *) xmalloc (len + 1);
+ memcpy (tem, start, len);
+ tem[len] = '\0';
+ typevec[ntypes++] = tem;
+ return 1;
+}
+
+/* `decl' must be already initialised, usually non-empty;
+ it won't be freed on failure */
+
+static int
+ do_args (type, decl)
+const char **type;
+string *decl;
+{
+ string arg;
+ int need_comma = 0;
+
+ string_append (decl, "(");
+
+ while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
+ {
+ if (**type == 'N')
+ {
+ int r;
+ int t;
+ *type += 1;
+ if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
+ return 0;
+ while (--r >= 0)
+ {
+ const char *tem = typevec[t];
+ if (need_comma)
+ string_append (decl, ", ");
+ if (!do_arg (&tem, &arg))
+ return 0;
+ string_appends (decl, &arg);
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+ else
+ {
+ if (need_comma)
+ string_append (decl, ", ");
+ if (!do_arg (type, &arg))
+ return 0;
+ string_appends (decl, &arg);
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+
+ if (**type == 'v')
+ *type += 1;
+ else if (**type == 'e')
+ {
+ *type += 1;
+ if (need_comma)
+ string_append (decl, ",");
+ string_append (decl, "...");
+ }
+
+ string_append (decl, ")");
+ return 1;
+}
+
+static void
+ munge_function_name (name)
+string *name;
+{
+ if (!string_empty (name) && name->p - name->b >= 3
+ && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
+ {
+ int i;
+ /* see if it's an assignment expression */
+ if (name->p - name->b >= 10 /* op$assign_ */
+ && memcmp (name->b + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 10;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 10, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ string_append (name, "=");
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 3;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 3, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ return;
+ }
+ }
+ }
+ return;
+ }
+ else if (!string_empty (name) && name->p - name->b >= 5
+ && memcmp (name->b, "type$", 5) == 0)
+ {
+ /* type conversion operator */
+ string type;
+ const char *tem = name->b + 5;
+ if (do_type (&tem, &type))
+ {
+ string_clear (name);
+ string_append (name, "operator ");
+ string_appends (name, &type);
+ string_delete (&type);
+ return;
+ }
+ }
+}
+
+/* a mini string-handling package */
+
+static void
+ string_need (s, n)
+string *s;
+int n;
+{
+ if (s->b == NULL)
+ {
+ if (n < 32)
+ n = 32;
+ s->p = s->b = (char *) xmalloc (n);
+ s->e = s->b + n;
+ }
+ else if (s->e - s->p < n)
+ {
+ int tem = s->p - s->b;
+ n += tem;
+ n *= 2;
+ s->b = (char *) xrealloc (s->b, n);
+ s->p = s->b + tem;
+ s->e = s->b + n;
+ }
+}
+
+static void
+ string_delete (s)
+string *s;
+{
+ if (s->b != NULL)
+ {
+ free (s->b);
+ s->b = s->e = s->p = NULL;
+ }
+}
+
+static void
+ string_init (s)
+string *s;
+{
+ s->b = s->p = s->e = NULL;
+}
+
+static void
+ string_clear (s)
+string *s;
+{
+ s->p = s->b;
+}
+
+static int
+ string_empty (s)
+string *s;
+{
+ return s->b == s->p;
+}
+
+static void
+ string_append (p, s)
+string *p;
+const char *s;
+{
+ int n;
+ if (s == NULL || *s == '\0')
+ return;
+ n = strlen (s);
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+ string_appends (p, s)
+string *p, *s;
+{
+ int n;
+ if (s->b == s->p)
+ return;
+ n = s->p - s->b;
+ string_need (p, n);
+ memcpy (p->p, s->b, n);
+ p->p += n;
+}
+
+static void
+ string_appendn (p, s, n)
+string *p;
+const char *s;
+int n;
+{
+ if (n == 0)
+ return;
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+ string_prepend (p, s)
+string *p;
+const char *s;
+{
+ if (s == NULL || *s == '\0')
+ return;
+ string_prependn (p, s, strlen (s));
+}
+
+#if 0
+static void
+ string_prepends (p, s)
+string *p, *s;
+{
+ if (s->b == s->p)
+ return;
+ string_prependn (p, s->b, s->p - s->b);
+}
+#endif
+
+static void
+ string_prependn (p, s, n)
+string *p;
+const char *s;
+int n;
+{
+ char *q;
+
+ if (n == 0)
+ return;
+ string_need (p, n);
+ for (q = p->p - 1; q >= p->b; q--)
+ q[n] = q[0];
+ memcpy (p->b, s, n);
+ p->p += n;
+}
+
+/* end of cplus-dem.c */
diff --git a/gnu/usr.bin/as/config/ho-ansi.h b/gnu/usr.bin/as/config/ho-ansi.h
new file mode 100644
index 0000000..bd2d909
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-ansi.h
@@ -0,0 +1,29 @@
+/* ho-ansi.h Host-specific header file for generic ansi environments.
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define M_ANSI 1
+
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+
+#define sys_nerr _sys_nerr
+#define sys_errlist _sys_errlist
+
+/* end of ho-ansi.h */
diff --git a/gnu/usr.bin/as/config/ho-decstation.h b/gnu/usr.bin/as/config/ho-decstation.h
new file mode 100644
index 0000000..69a4699
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-decstation.h
@@ -0,0 +1,29 @@
+/* ho-pmax.h Host-specific header file for decstation 3100.
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+extern char *malloc();
+extern int free();
+
+#if !defined(__GNUC__)
+#define know(x)
+#endif /* not gcc */
+
+/* end of ho-decstation.h */
diff --git a/gnu/usr.bin/as/config/ho-generic.h b/gnu/usr.bin/as/config/ho-generic.h
new file mode 100644
index 0000000..7c7129f
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-generic.h
@@ -0,0 +1,30 @@
+/* ho-generic.h Generic host-specific header file.
+ Copyright 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* It is my intent that this become a file capable of config'ing and
+ compiling for nearly any host as aid for testing and porting.
+ xoxorich. */
+
+#define M_GENERIC 1
+
+#define HAVE_STRERROR
+
+extern int free();
+
+/* end of ho-generic.h */
diff --git a/gnu/usr.bin/as/config/ho-hpux.h b/gnu/usr.bin/as/config/ho-hpux.h
new file mode 100644
index 0000000..ebea9e2
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-hpux.h
@@ -0,0 +1,34 @@
+/* ho-hpux.h -- Header to compile the assembler under HP-UX
+ Copyright (C) 1988, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "ho-sysv.h"
+
+/* This header file contains the #defines specific
+ to HPUX changes sent me by cph@zurich.ai.mit.edu */
+#ifndef hpux
+#define hpux
+#endif
+
+#ifdef setbuffer
+#undef setbuffer
+#endif /* setbuffer */
+
+#define setbuffer(stream, buf, size)
+
+/* end of ho-hpux.h */
diff --git a/gnu/usr.bin/as/config/ho-i386.h b/gnu/usr.bin/as/config/ho-i386.h
new file mode 100644
index 0000000..949e78a
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-i386.h
@@ -0,0 +1,30 @@
+/* ho-i386.h i386 specific header file.
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+#define HO_I386 1
+
+#define NO_STDARG
+
+#include "ho-sysv.h"
+
+/* end of ho-i386.h */
diff --git a/gnu/usr.bin/as/config/ho-i386aix.h b/gnu/usr.bin/as/config/ho-i386aix.h
new file mode 100644
index 0000000..d439f74
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-i386aix.h
@@ -0,0 +1,24 @@
+/* ho-386aix.h AIX PS/2 i386 specific header file.
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HO_I386 1
+
+#include "ho-sysv.h"
+
+/* end of ho-i386aix.h */
diff --git a/gnu/usr.bin/as/config/ho-rs6000.h b/gnu/usr.bin/as/config/ho-rs6000.h
new file mode 100644
index 0000000..ed49484
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-rs6000.h
@@ -0,0 +1,22 @@
+/* ho-rs6000.h Rs6000 host-specific header file.
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define M_RS6000 1
+
+/* end of ho-rs6000.h */
diff --git a/gnu/usr.bin/as/config/ho-sun3.h b/gnu/usr.bin/as/config/ho-sun3.h
new file mode 100644
index 0000000..0d68e6f
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-sun3.h
@@ -0,0 +1,3 @@
+#include <ho-sunos.h>
+
+/* end of ho-sun3.h */
diff --git a/gnu/usr.bin/as/config/ho-sun386.h b/gnu/usr.bin/as/config/ho-sun386.h
new file mode 100644
index 0000000..6c74df4
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-sun386.h
@@ -0,0 +1,5 @@
+#include <ho-sunos.h>
+
+extern int sprintf();
+
+/* end of ho-sun386.h */
diff --git a/gnu/usr.bin/as/config/ho-sun4.h b/gnu/usr.bin/as/config/ho-sun4.h
new file mode 100644
index 0000000..cf619e8
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-sun4.h
@@ -0,0 +1,3 @@
+#include <ho-sunos.h>
+
+/* end of ho-sun4.h */
diff --git a/gnu/usr.bin/as/config/ho-sunos.h b/gnu/usr.bin/as/config/ho-sunos.h
new file mode 100644
index 0000000..9c6cc01
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-sunos.h
@@ -0,0 +1,81 @@
+/* This file is ho-sunos.h
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if __STDC__ != 1
+#define NO_STDARG
+#endif /* not __STDC__ */
+
+#if !defined(__GNUC__) && (__STDC__ != 1)
+#include <memory.h>
+#else
+extern int memset();
+#endif
+
+/* #include <sys/stdtypes.h> before <stddef.h> when compiling by GCC. */
+#include <sys/stdtypes.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <string.h>
+
+/* externs for system libraries. */
+
+/*extern int abort();*/
+/*extern int exit();*/
+extern char *malloc();
+extern char *realloc();
+extern char *strchr();
+extern char *strrchr();
+extern int _filbuf();
+extern int _flsbuf();
+extern int fclose();
+extern int fgetc();
+extern int fprintf();
+extern int fread();
+extern int free();
+extern int perror();
+extern int printf();
+extern int rewind();
+extern int setvbuf();
+extern int sscanf();
+extern int strcmp();
+extern int strlen();
+extern int strncmp();
+extern int time();
+extern int ungetc();
+extern int vfprintf();
+extern int vprintf();
+extern int vsprintf();
+extern long atol();
+
+#ifndef tolower
+extern int tolower();
+#endif /* tolower */
+
+#ifndef toupper
+extern int toupper();
+#endif /* toupper */
+
+/*
+ * Local Variables:
+ * fill-column: 80
+ * comment-column: 0
+ * End:
+ */
+
+/* end of ho-sunos.h */
diff --git a/gnu/usr.bin/as/config/ho-sysv.h b/gnu/usr.bin/as/config/ho-sysv.h
new file mode 100644
index 0000000..5407e5d
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-sysv.h
@@ -0,0 +1,27 @@
+/* ho-sysv.h System V specific header file.
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HO_USG
+
+#define setbuffer(stream, buf, size) setvbuf((stream), (buf), _IOLBF, (size))
+
+extern int free();
+extern char *malloc();
+
+/* end of ho-sysv.h */
diff --git a/gnu/usr.bin/as/config/ho-vax.h b/gnu/usr.bin/as/config/ho-vax.h
new file mode 100644
index 0000000..ea77e81
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-vax.h
@@ -0,0 +1,27 @@
+/* ho-vax.h Intended for vax ultrix
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if __STDC__ != 1
+#define NO_STDARG
+#endif /* not ansi */
+
+extern char *malloc();
+extern int free();
+
+/* end of ho-vax.h */
diff --git a/gnu/usr.bin/as/config/ho-vms.h b/gnu/usr.bin/as/config/ho-vms.h
new file mode 100644
index 0000000..63f448e
--- /dev/null
+++ b/gnu/usr.bin/as/config/ho-vms.h
@@ -0,0 +1,30 @@
+/* ho-vax.h Intended for vax vms
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HO_VAX 1
+
+#include "ho-vax.h"
+
+/* We get better performance if we use the macros rather than the functions.*/
+#include <ctype.h>
+
+/* We need this to make sure that sys_nerr has the right Psect hack. */
+#include <perror.h>
+
+/* end of ho-vms.h */
diff --git a/gnu/usr.bin/as/config/mh-i386 b/gnu/usr.bin/as/config/mh-i386
new file mode 100644
index 0000000..3375d42
--- /dev/null
+++ b/gnu/usr.bin/as/config/mh-i386
@@ -0,0 +1 @@
+ALLOCA=alloca.o
diff --git a/gnu/usr.bin/as/config/mh-i386aix b/gnu/usr.bin/as/config/mh-i386aix
new file mode 100644
index 0000000..a1e5d77
--- /dev/null
+++ b/gnu/usr.bin/as/config/mh-i386aix
@@ -0,0 +1,5 @@
+# Define SYSV as -DSYSV if you are using a System V operating system.
+SYSV = -DSYSV
+RANLIB = /bin/true
+CC = gcc
+MINUS_G = -O
diff --git a/gnu/usr.bin/as/config/mh-i386v4 b/gnu/usr.bin/as/config/mh-i386v4
new file mode 100644
index 0000000..5bfcd28
--- /dev/null
+++ b/gnu/usr.bin/as/config/mh-i386v4
@@ -0,0 +1 @@
+HLIBS=-lucb
diff --git a/gnu/usr.bin/as/config/mt-ebmon29k b/gnu/usr.bin/as/config/mt-ebmon29k
new file mode 100644
index 0000000..528e6fc
--- /dev/null
+++ b/gnu/usr.bin/as/config/mt-ebmon29k
@@ -0,0 +1,6 @@
+TARG_CPU_DEPENDENTS=
+LOCAL_LOADLIBES=../bfd$(subdir)/libbfd.a
+TDEFINES=-DBFD_HEADERS -DMANY_SEGMENTS -DBFD
+
+
+
diff --git a/gnu/usr.bin/as/config/mt-h8300 b/gnu/usr.bin/as/config/mt-h8300
new file mode 100644
index 0000000..d968db2
--- /dev/null
+++ b/gnu/usr.bin/as/config/mt-h8300
@@ -0,0 +1,5 @@
+TARG_CPU_DEPENDENTS=$(srcdir)/../include/opcode/h8300.h
+LOCAL_LOADLIBES=$(srcdir)/../bfd/$(srcdir)/libbfd.a
+TDEFINES=-DBFD_HEADERS -DMANY_SEGMENTS -DBFD
+
+CC=gcc
diff --git a/gnu/usr.bin/as/config/mt-h8300hds b/gnu/usr.bin/as/config/mt-h8300hds
new file mode 100644
index 0000000..1e6eb3c
--- /dev/null
+++ b/gnu/usr.bin/as/config/mt-h8300hds
@@ -0,0 +1,4 @@
+TARG_CPU_DEPENDENTS=$(srcdir)/../include/h8300-opcode.h
+LOCAL_LOADLIBES=$(srcdir)/../bfd/$(srcdir)/libbfd.a
+TDEFINES=-DBFD -DMANY_SEGMENTS
+
diff --git a/gnu/usr.bin/as/config/mt-i386aix b/gnu/usr.bin/as/config/mt-i386aix
new file mode 100644
index 0000000..225fc36
--- /dev/null
+++ b/gnu/usr.bin/as/config/mt-i386aix
@@ -0,0 +1,3 @@
+# TDEFINES = -DBFD_HEADERS
+CC = gcc
+MINUS_G = -O
diff --git a/gnu/usr.bin/as/config/mt-mips b/gnu/usr.bin/as/config/mt-mips
new file mode 100644
index 0000000..f40f51d
--- /dev/null
+++ b/gnu/usr.bin/as/config/mt-mips
@@ -0,0 +1 @@
+ALL=fake-as
diff --git a/gnu/usr.bin/as/config/mt-rs6000 b/gnu/usr.bin/as/config/mt-rs6000
new file mode 100644
index 0000000..f40f51d
--- /dev/null
+++ b/gnu/usr.bin/as/config/mt-rs6000
@@ -0,0 +1 @@
+ALL=fake-as
diff --git a/gnu/usr.bin/as/config/obj-aout.c b/gnu/usr.bin/as/config/obj-aout.c
new file mode 100644
index 0000000..9435d07
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-aout.c
@@ -0,0 +1,670 @@
+/* a.out object file format
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "as.h"
+#include "obstack.h"
+
+
+#include <stab.h>
+
+/* in: segT out: N_TYPE bits */
+const short seg_N_TYPE[] = {
+ N_ABS,
+ N_TEXT,
+ N_DATA,
+ N_BSS,
+ N_UNDF, /* unknown */
+ N_UNDF, /* absent */
+ N_UNDF, /* pass1 */
+ N_UNDF, /* error */
+ N_UNDF, /* bignum/flonum */
+ N_UNDF, /* difference */
+ N_UNDF, /* debug */
+ N_UNDF, /* ntv */
+ N_UNDF, /* ptv */
+ N_REGISTER, /* register */
+};
+
+const segT N_TYPE_seg[N_TYPE+2] = { /* N_TYPE == 0x1E = 32-2 */
+ SEG_UNKNOWN, SEG_GOOF, /* N_UNDF == 0 */
+ SEG_ABSOLUTE, SEG_GOOF, /* N_ABS == 2 */
+ SEG_TEXT, SEG_GOOF, /* N_TEXT == 4 */
+ SEG_DATA, SEG_GOOF, /* N_DATA == 6 */
+ SEG_BSS, SEG_GOOF, /* N_BSS == 8 */
+ SEG_GOOF, SEG_GOOF, /* N_INDR == 0xa */
+ SEG_GOOF, SEG_GOOF, /* 0xc */
+ SEG_GOOF, SEG_GOOF, /* 0xe */
+ SEG_GOOF, SEG_GOOF, /* 0x10 */
+ SEG_REGISTER, SEG_GOOF, /* 0x12 (dummy N_REGISTER) */
+ SEG_GOOF, SEG_GOOF, /* N_SETA == 0x14 */
+ SEG_GOOF, SEG_GOOF, /* N_SETT == 0x16 */
+ SEG_GOOF, SEG_GOOF, /* N_SETD == 0x18 */
+ SEG_GOOF, SEG_GOOF, /* N_SETB == 0x1a */
+ SEG_GOOF, SEG_GOOF, /* N_SETV == 0x1c */
+ SEG_GOOF, SEG_GOOF, /* N_WARNING == 0x1e */
+};
+
+#if __STDC__ == 1
+static void obj_aout_stab(int what);
+static void obj_aout_line(void);
+static void obj_aout_desc(void);
+#else /* not __STDC__ */
+static void obj_aout_desc();
+static void obj_aout_stab();
+static void obj_aout_line();
+#endif /* not __STDC__ */
+
+const pseudo_typeS obj_pseudo_table[] = {
+#ifndef IGNORE_DEBUG
+ /* stabs debug info */
+ { "line", obj_aout_line, 0 }, /* source code line number */
+ { "ln", obj_aout_line, 0 }, /* coff line number that we use anyway */
+ { "desc", obj_aout_desc, 0 }, /* desc */
+ { "stabd", obj_aout_stab, 'd' }, /* stabs */
+ { "stabn", obj_aout_stab, 'n' }, /* stabs */
+ { "stabs", obj_aout_stab, 's' }, /* stabs */
+#else /* IGNORE_DEBUG */
+ { "line", obj_aout_line, 0 }, /* source code line number */
+ { "ln", obj_aout_line, 0 }, /* coff line number that we use anyway */
+ { "desc", obj_aout_desc, 0 }, /* desc */
+ { "stabd", obj_aout_stab, 'd' }, /* stabs */
+ { "stabn", obj_aout_stab, 'n' }, /* stabs */
+ { "stabs", obj_aout_stab, 's' }, /* stabs */
+#endif /* IGNORE_DEBUG */
+
+ /* coff debug pseudos (ignored) */
+ { "def", s_ignore, 0 },
+ { "dim", s_ignore, 0 },
+ { "endef", s_ignore, 0 },
+ { "ident", s_ignore, 0 },
+ { "line", s_ignore, 0 },
+ { "ln", s_ignore, 0 },
+ { "scl", s_ignore, 0 },
+ { "size", s_size, 0 },
+ { "tag", s_ignore, 0 },
+ { "type", s_type, 0 },
+ { "val", s_ignore, 0 },
+ { "version", s_ignore, 0 },
+ { "weak", s_weak, 0 },
+
+ /* stabs-in-coff (?) debug pseudos (ignored) */
+ { "optim", s_ignore, 0 }, /* For sun386i cc (?) */
+
+ /* other stuff */
+ { "ABORT", s_abort, 0 },
+
+ { NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+
+/* Relocation. */
+
+/*
+ * emit_relocations()
+ *
+ * Crawl along a fixS chain. Emit the segment's relocations.
+ */
+void obj_emit_relocations(where, fixP, segment_address_in_file)
+char **where;
+fixS *fixP; /* Fixup chain for this segment. */
+relax_addressT segment_address_in_file;
+{
+ for (; fixP; fixP = fixP->fx_next) {
+ if (fixP->fx_addsy != NULL) {
+ tc_aout_fix_to_chars(*where, fixP, segment_address_in_file);
+ *where += md_reloc_size;
+ } /* if there is an add symbol */
+ } /* for each fix */
+
+ return;
+} /* obj_emit_relocations() */
+
+/* Aout file generation & utilities */
+void obj_header_append(where, headers)
+char **where;
+object_headers *headers;
+{
+ tc_headers_hook(headers);
+
+#if defined(NETBSD_AOUT)
+ /* `a_info' (magic, mid, flags) is in network byte-order */
+ (*where)[0] = ((char *)&headers->header.a_info)[0];
+ (*where)[1] = ((char *)&headers->header.a_info)[1];
+ (*where)[2] = ((char *)&headers->header.a_info)[2];
+ (*where)[3] = ((char *)&headers->header.a_info)[3];
+#else
+ md_number_to_chars(*where, headers->header.a_info,
+ sizeof(headers->header.a_info));
+#endif
+ *where += sizeof(headers->header.a_info);
+
+#ifdef TE_HPUX
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare1 */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare2 */
+#endif /* TE_HPUX */
+
+ md_number_to_chars(*where, headers->header.a_text, 4); *where += 4;
+ md_number_to_chars(*where, headers->header.a_data, 4); *where += 4;
+ md_number_to_chars(*where, headers->header.a_bss, 4); *where += 4;
+
+#ifndef TE_HPUX
+ md_number_to_chars(*where, headers->header.a_syms, 4); *where += 4;
+ md_number_to_chars(*where, headers->header.a_entry, 4); *where += 4;
+#endif /* not TE_HPUX */
+
+ md_number_to_chars(*where, headers->header.a_trsize, 4); *where += 4;
+ md_number_to_chars(*where, headers->header.a_drsize, 4); *where += 4;
+
+#ifdef TE_SEQUENT
+ memset(*where, '\0', 3 * 2 * 4); *where += 3 * 2 * 4; /* global descriptor table? */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* shdata - length of initialized shared data */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* shbss - length of uninitialized shared data */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* shdrsize - length of shared data relocation */
+
+ memset(*where, '\0', 11 * 4); *where += 11 * 4; /* boostrap for standalone */
+ memset(*where, '\0', 3 * 4); *where += 3 * 4; /* reserved */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* version */
+#endif /* TE_SEQUENT */
+
+#ifdef TE_HPUX
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare3 - HP = pascal interface size */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare4 - HP = symbol table size */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare5 - HP = debug name table size */
+
+ md_number_to_chars(*where, headers->header.a_entry, 4); *where += 4;
+
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare6 - HP = source line table size */
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare7 - HP = value table size */
+
+ md_number_to_chars(*where, headers->header.a_syms, 4); *where += 4;
+
+ md_number_to_chars(*where, 0, 4); *where += 4; /* a_spare8 */
+#endif /* TE_HPUX */
+
+ return;
+} /* obj_append_header() */
+
+void obj_symbol_to_chars(where, symbolP)
+char **where;
+symbolS *symbolP;
+{
+ md_number_to_chars((char *)&(S_GET_OFFSET(symbolP)), S_GET_OFFSET(symbolP), sizeof(S_GET_OFFSET(symbolP)));
+ md_number_to_chars((char *)&(S_GET_DESC(symbolP)), S_GET_DESC(symbolP), sizeof(S_GET_DESC(symbolP)));
+ md_number_to_chars((char *)&(S_GET_VALUE(symbolP)), S_GET_VALUE(symbolP), sizeof(S_GET_VALUE(symbolP)));
+
+ append(where, (char *)&symbolP->sy_symbol, sizeof(obj_symbol_type));
+} /* obj_symbol_to_chars() */
+
+void obj_emit_symbols(where, symbol_rootP)
+char **where;
+symbolS *symbol_rootP;
+{
+ symbolS * symbolP;
+
+ /*
+ * Emit all symbols left in the symbol chain.
+ */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ /* Used to save the offset of the name. It is used to point
+ to the string in memory but must be a file offset. */
+ register char *temp;
+
+ temp = S_GET_NAME(symbolP);
+ S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
+
+ /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
+ if (!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP))
+ S_SET_EXTERNAL(symbolP);
+
+ /*
+ * Put aux info in lower four bits of `n_other' field
+ * Do this only now, because things like S_IS_DEFINED()
+ * depend on S_GET_OTHER() for some unspecified reason.
+ */
+ S_SET_OTHER(symbolP,
+ (symbolP->sy_bind << 4) | (symbolP->sy_aux & 0xf));
+
+ if (S_GET_TYPE(symbolP) == N_SIZE) {
+ expressionS *exp = (expressionS*)symbolP->sy_sizexp;
+ long size = 0;
+
+ if (exp == NULL) {
+ as_bad("Internal error: no size expression");
+ return;
+ }
+
+ switch (exp->X_seg) {
+ case SEG_ABSOLUTE:
+ size = exp->X_add_number;
+ break;
+ case SEG_DIFFERENCE:
+ size = S_GET_VALUE(exp->X_add_symbol) -
+ S_GET_VALUE(exp->X_subtract_symbol) +
+ exp->X_add_number;
+ break;
+ default:
+ as_bad("Unsupported .size expression");
+ break;
+ }
+ S_SET_VALUE(symbolP, size);
+ }
+
+ obj_symbol_to_chars(where, symbolP);
+ S_SET_NAME(symbolP,temp);
+ }
+} /* emit_symbols() */
+
+#if comment
+/* uneeded if symbol is born zeroed. */
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+ S_SET_OTHER(symbolP, 0);
+ S_SET_DESC(symbolP, 0);
+ return;
+} /* obj_symbol_new_hook() */
+#endif /* comment */
+
+static void obj_aout_line() {
+ /* Assume delimiter is part of expression. */
+ /* BSD4.2 as fails with delightful bug, so we */
+ /* are not being incompatible here. */
+ new_logical_line((char *)NULL, (int)(get_absolute_expression()));
+ demand_empty_rest_of_line();
+} /* obj_aout_line() */
+
+/*
+ * stab()
+ *
+ * Handle .stabX directives, which used to be open-coded.
+ * So much creeping featurism overloaded the semantics that we decided
+ * to put all .stabX thinking in one place. Here.
+ *
+ * We try to make any .stabX directive legal. Other people's AS will often
+ * do assembly-time consistency checks: eg assigning meaning to n_type bits
+ * and "protecting" you from setting them to certain values. (They also zero
+ * certain bits before emitting symbols. Tut tut.)
+ *
+ * If an expression is not absolute we either gripe or use the relocation
+ * information. Other people's assemblers silently forget information they
+ * don't need and invent information they need that you didn't supply.
+ *
+ * .stabX directives always make a symbol table entry. It may be junk if
+ * the rest of your .stabX directive is malformed.
+ */
+static void obj_aout_stab(what)
+int what;
+{
+#ifndef NO_LISTING
+ extern int listing;
+#endif /* NO_LISTING */
+
+ register symbolS *symbolP = 0;
+ register char *string;
+ int saved_type = 0;
+ int length;
+ int goof; /* TRUE if we have aborted. */
+ long longint;
+
+ /*
+ * Enter with input_line_pointer pointing past .stabX and any following
+ * whitespace.
+ */
+ goof = 0; /* JF who forgot this?? */
+ if (what == 's') {
+ string = demand_copy_C_string(& length);
+ SKIP_WHITESPACE();
+ if (* input_line_pointer == ',')
+ input_line_pointer ++;
+ else {
+ as_bad("I need a comma after symbol's name");
+ goof = 1;
+ }
+ } else
+ string = "";
+
+ /*
+ * Input_line_pointer->after ','. String->symbol name.
+ */
+ if (! goof) {
+ symbolP = symbol_new(string,
+ SEG_UNKNOWN,
+ 0,
+ (struct frag *)0);
+ switch (what) {
+ case 'd':
+ S_SET_NAME(symbolP, NULL); /* .stabd feature. */
+ S_SET_VALUE(symbolP, obstack_next_free(&frags) - frag_now->fr_literal);
+ symbolP->sy_frag = frag_now;
+ break;
+
+ case 'n':
+ symbolP->sy_frag = &zero_address_frag;
+ break;
+
+ case 's':
+ symbolP->sy_frag = & zero_address_frag;
+ break;
+
+ default:
+ BAD_CASE(what);
+ break;
+ }
+
+ if (get_absolute_expression_and_terminator(&longint) == ',')
+ symbolP->sy_symbol.n_type = saved_type = longint;
+ else {
+ as_bad("I want a comma after the n_type expression");
+ goof = 1;
+ input_line_pointer --; /* Backup over a non-',' char. */
+ }
+ }
+
+ if (!goof) {
+ if (get_absolute_expression_and_terminator(&longint) == ',')
+ S_SET_OTHER(symbolP, longint);
+ else {
+ as_bad("I want a comma after the n_other expression");
+ goof = 1;
+ input_line_pointer--; /* Backup over a non-',' char. */
+ }
+ }
+
+ if (!goof) {
+ S_SET_DESC(symbolP, get_absolute_expression());
+ if (what == 's' || what == 'n') {
+ if (*input_line_pointer != ',') {
+ as_bad("I want a comma after the n_desc expression");
+ goof = 1;
+ } else {
+ input_line_pointer++;
+ }
+ }
+ }
+
+ if ((!goof) && (what == 's' || what == 'n')) {
+ pseudo_set(symbolP);
+ symbolP->sy_symbol.n_type = saved_type;
+ }
+#ifndef NO_LISTING
+ if (listing && !goof)
+ {
+ if (symbolP->sy_symbol.n_type == N_SLINE)
+ {
+
+ listing_source_line(symbolP->sy_symbol.n_desc);
+ }
+ else if (symbolP->sy_symbol.n_type == N_SO
+ || symbolP->sy_symbol.n_type == N_SOL)
+ {
+ listing_source_file(string);
+ }
+ }
+#endif
+
+ if (goof)
+ ignore_rest_of_line();
+ else
+ demand_empty_rest_of_line ();
+} /* obj_aout_stab() */
+
+static void obj_aout_desc() {
+ register char *name;
+ register char c;
+ register char *p;
+ register symbolS *symbolP;
+ register int temp;
+
+ /*
+ * Frob invented at RMS' request. Set the n_desc of a symbol.
+ */
+ name = input_line_pointer;
+ c = get_symbol_end();
+ p = input_line_pointer;
+ * p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ *p = 0;
+ as_bad("Expected comma after name \"%s\"", name);
+ *p = c;
+ ignore_rest_of_line();
+ } else {
+ input_line_pointer ++;
+ temp = get_absolute_expression();
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+ S_SET_DESC(symbolP,temp);
+ }
+ demand_empty_rest_of_line();
+} /* obj_aout_desc() */
+
+void obj_read_begin_hook() {
+ return;
+} /* obj_read_begin_hook() */
+
+void obj_crawl_symbol_chain(headers)
+object_headers *headers;
+{
+ symbolS *symbolP;
+ symbolS **symbolPP;
+ int symbol_number = 0;
+
+ /* JF deal with forward references first... */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ if (symbolP->sy_forward && symbolP->sy_forward != symbolP) {
+ switch (S_GET_TYPE(symbolP)) {
+
+ case N_SETA:
+ case N_SETT:
+ case N_SETD:
+ case N_SETB:
+ /*
+ * Don't change the segments of SET symbols,
+ * because that would turn them into regular
+ * symbols.
+ */
+ break;
+
+ default:
+ S_SET_SEGMENT(symbolP,
+ S_GET_SEGMENT(symbolP->sy_forward));
+ break;
+ }
+ S_SET_VALUE(symbolP, S_GET_VALUE(symbolP)
+ + S_GET_VALUE(symbolP->sy_forward)
+ + symbolP->sy_forward->sy_frag->fr_address);
+
+ symbolP->sy_aux |= symbolP->sy_forward->sy_aux;
+ symbolP->sy_sizexp = symbolP->sy_forward->sy_sizexp;
+ if (S_IS_EXTERNAL(symbolP->sy_forward))
+ S_SET_EXTERNAL(symbolP);
+ } /* if it has a forward reference */
+ symbolP->sy_forward=0;
+ } /* walk the symbol chain */
+
+ tc_crawl_symbol_chain(headers);
+
+ symbolPP = &symbol_rootP; /*->last symbol chain link. */
+ while ((symbolP = *symbolPP) != NULL) {
+ if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_DATA)) {
+ S_SET_SEGMENT(symbolP, SEG_TEXT);
+ } /* if pushing data into text */
+
+ S_SET_VALUE(symbolP, S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
+
+ /* OK, here is how we decide which symbols go out into the
+ brave new symtab. Symbols that do are:
+
+ * symbols with no name (stabd's?)
+ * symbols with debug info in their N_TYPE
+ * symbols marked "forceout" (to force out local `L'
+ symbols in PIC code)
+
+ Symbols that don't are:
+ * symbols that are registers
+ * symbols with \1 as their 3rd character (numeric labels)
+ * "local labels" as defined by S_LOCAL_NAME(name)
+ if the -L switch was passed to gas.
+
+ All other symbols are output. We complain if a deleted
+ symbol was marked external. */
+
+
+ if (!S_IS_REGISTER(symbolP)
+ && (!S_GET_NAME(symbolP)
+ || S_IS_DEBUG(symbolP)
+#ifdef TC_I960
+ /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */
+ || !S_IS_DEFINED(symbolP)
+ || S_IS_EXTERNAL(symbolP)
+#endif /* TC_I960 */
+ || (S_GET_NAME(symbolP)[0] != '\001' &&
+ (flagseen['L'] || ! S_LOCAL_NAME(symbolP))
+#ifdef PIC
+ || (picmode && symbolP->sy_forceout)
+#endif
+ )
+ )
+#ifdef PIC
+ && (!picmode ||
+ symbolP != GOT_symbol || got_referenced != 0
+ )
+#endif
+ ) {
+ symbolP->sy_number = symbol_number++;
+
+ /* The + 1 after strlen account for the \0 at the
+ end of each string */
+ if (!S_IS_STABD(symbolP)) {
+ /* Ordinary case. */
+ symbolP->sy_name_offset = string_byte_count;
+ string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+ }
+ else /* .Stabd case. */
+ symbolP->sy_name_offset = 0;
+
+ /*
+ * If symbol has a known size, output an extra symbol
+ * of type N_SIZE and with the same name.
+ * We cannot evaluate the size expression just yet, as
+ * some its terms may not have had their final values
+ * set. We defer this until `obj_emit_symbols()'
+ */
+ if (picmode &&
+ S_GET_TYPE(symbolP) != N_SIZE &&
+#ifndef GRACE_PERIOD_EXPIRED
+ /*Can be enabled when no more old ld's around*/
+ (symbolP->sy_aux == AUX_OBJECT) &&
+#endif
+ symbolP->sy_sizexp) {
+
+ symbolS *addme;
+
+ /* Put a new symbol on the chain */
+#ifdef NSIZE_PREFIX /*XXX*/
+ char buf[BUFSIZ];
+
+ buf[0] = NSIZE_PREFIX;
+ strncpy(buf+1, S_GET_NAME(symbolP), BUFSIZ-2);
+ addme = symbol_make(buf);
+#else
+ addme = symbol_make(S_GET_NAME(symbolP));
+#endif
+ /* Set type and transfer size expression */
+ addme->sy_symbol.n_type = N_SIZE;
+ addme->sy_sizexp = symbolP->sy_sizexp;
+ symbolP->sy_sizexp = NULL;
+
+ /* Set external if symbolP is */
+ if (S_IS_EXTERN(symbolP))
+ S_SET_EXTERNAL(addme);
+
+ }
+ symbolPP = &(symbol_next(symbolP));
+ } else {
+ if ((S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP))
+#ifdef PIC
+ && (!picmode ||
+ symbolP != GOT_symbol || got_referenced != 0
+ )
+#endif
+ ) {
+ as_bad("Local symbol %s never defined.", decode_local_label_name(S_GET_NAME(symbolP)));
+ } /* oops. */
+
+ /* Unhook it from the chain */
+ *symbolPP = symbol_next(symbolP);
+ } /* if this symbol should be in the output */
+ } /* for each symbol */
+
+ H_SET_SYMBOL_TABLE_SIZE(headers, symbol_number);
+
+ return;
+} /* obj_crawl_symbol_chain() */
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+void obj_emit_strings(where)
+char **where;
+{
+ symbolS *symbolP;
+
+#ifdef CROSS_COMPILE
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ md_number_to_chars(*where, string_byte_count, sizeof(string_byte_count));
+ *where += sizeof(string_byte_count);
+#else /* CROSS_COMPILE */
+ append (where, (char *)&string_byte_count, (unsigned long)sizeof(string_byte_count));
+#endif /* CROSS_COMPILE */
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ if (S_GET_NAME(symbolP))
+ append(&next_object_file_charP, S_GET_NAME(symbolP),
+ (unsigned long)(strlen (S_GET_NAME(symbolP)) + 1));
+ } /* walk symbol chain */
+
+ return;
+} /* obj_emit_strings() */
+
+void obj_pre_write_hook(headers)
+object_headers *headers;
+{
+ H_SET_INFO(headers,
+ DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE,
+ AOUT_MACHTYPE,
+ AOUT_FLAGS,
+ AOUT_VERSION);
+
+ H_SET_ENTRY_POINT(headers, 0);
+
+ tc_aout_pre_write_hook(headers);
+ return;
+} /* obj_pre_write_hook() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-aout.c */
diff --git a/gnu/usr.bin/as/config/obj-aout.h b/gnu/usr.bin/as/config/obj-aout.h
new file mode 100644
index 0000000..7f63e3b
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-aout.h
@@ -0,0 +1,305 @@
+/* obj-aout.h, a.out object file format for gas, the assembler.
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $FreeBSD$
+ */
+
+
+/* Tag to validate a.out object file format processing */
+#define OBJ_AOUT 1
+
+#include "targ-cpu.h"
+
+#include "aout.h" /* Needed to define struct nlist. Sigh. */
+
+#ifndef AOUT_MACHTYPE
+#define AOUT_MACHTYPE 0
+#endif
+
+#ifndef AOUT_VERSION
+#define AOUT_VERSION 0
+#endif
+
+#ifndef AOUT_FLAGS
+#define AOUT_FLAGS 0
+#endif
+
+extern const short seg_N_TYPE[];
+extern const segT N_TYPE_seg[];
+#define N_REGISTER 0x12 /* Fake register type */
+
+#ifndef DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (OMAGIC)
+#endif /* DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE */
+
+/* First character of operand in `.type' directives */
+#define TYPE_OPERAND_FMT '@'
+
+/* SYMBOL TABLE */
+/* Symbol table entry data type */
+
+typedef struct nlist obj_symbol_type; /* Symbol table entry */
+
+/* Symbol table macros and constants */
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT)
+
+/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */
+#define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_OTHER(s) != 0) || (S_GET_DESC(s) != 0))
+
+#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER)
+
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name begin with ^A is a gas internal pseudo symbol
+ nameless symbols come from .stab directives. */
+#define S_IS_LOCAL(s) (S_GET_NAME(s) && \
+ !S_IS_DEBUG(s) && \
+ (S_GET_NAME(s)[0] == '\001' || \
+ (S_LOCAL_NAME(s) && !flagseen['L'])))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT)
+/* True if the symbol has been generated because of a .stabd directive */
+#define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0)
+
+/* Accessors */
+/* The value of the symbol */
+#define S_GET_VALUE(s) (((s)->sy_symbol.n_value))
+/* The name of the symbol */
+#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx)
+/* The type of the symbol */
+#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE)
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)])
+/* The n_other expression value */
+#define S_GET_OTHER(s) ((s)->sy_symbol.n_other)
+/* The n_desc expression value */
+#define S_GET_DESC(s) ((s)->sy_symbol.n_desc)
+
+/* Modifiers */
+/* Set the value of the symbol */
+#define S_SET_VALUE(s,v) ((s)->sy_symbol.n_value = (unsigned long) (v))
+/* Assume that a symbol cannot be simultaneously in more than on segment */
+/* set segment */
+#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg))
+/* The symbol is external */
+#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT)
+/* The symbol is not external */
+#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT)
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v))
+/* Set the offset in the string table */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v))
+/* Set the n_other expression value */
+#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v))
+/* Set the n_desc expression value */
+#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v))
+
+/* File header macro and type definition */
+
+#define H_GET_FILE_SIZE(h) (H_GET_HEADER_SIZE(h) \
+ + H_GET_TEXT_SIZE(h) \
+ + H_GET_DATA_SIZE(h) \
+ + H_GET_SYMBOL_TABLE_SIZE(h) \
+ + H_GET_TEXT_RELOCATION_SIZE(h) \
+ + H_GET_DATA_RELOCATION_SIZE(h) \
+ + H_GET_STRING_SIZE(h))
+
+#ifndef H_GET_HEADER_SIZE
+#define H_GET_HEADER_SIZE(h) (sizeof(struct exec))
+#endif /* not H_GET_HEADER_SIZE */
+
+#define H_GET_TEXT_SIZE(h) ((h)->header.a_text)
+#define H_GET_DATA_SIZE(h) ((h)->header.a_data)
+#define H_GET_BSS_SIZE(h) ((h)->header.a_bss)
+#define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize)
+#define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize)
+#define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms)
+#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry)
+#define H_GET_STRING_SIZE(h) ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h) (0)
+
+#if defined(FREEBSD_AOUT) || defined(NETBSD_AOUT)
+
+#if defined(FREEBSD_AOUT)
+/* duplicate part of <sys/imgact_aout.h> */
+#define H_GET_FLAGS(h) \
+ ( (((h)->header.a_info)&0xffff) \
+ ? ((h)->header.a_info >> 26) & 0x3f ) \
+ : 0 \
+ )
+#define H_GET_MACHTYPE(h) \
+ ( (((h)->header.a_info)&0xffff) \
+ ? ((h)->header.a_info >>16 ) & 0x3ff) \
+ : 0 \
+ )
+
+#define H_GET_MAGIC_NUMBER(h) \
+ ( (((h)->header.a_info)&0xffff) \
+ ? ((h)->header.a_info & 0xffff) \
+ : (ntohl(((h)->header.a_info))&0xffff) \
+ )
+
+#define H_SET_INFO(h,mag,mid,f,v) \
+ ( (h)->header.a_info = \
+ (((f)&0x3f)<<26) | (((mid)&0x03ff)<<16) | (((mag)&0xffff)) )
+
+#endif /* FREEBSD_AOUT */
+
+#if defined(NETBSD_AOUT)
+/* SH*T, duplicate part of <a.out.h> */
+#define H_GET_FLAGS(h) \
+ ( (((h)->header.a_info)&0xffff0000) \
+ ? ((ntohl(((h)->header.a_info))>>26)&0x3f) \
+ : 0 \
+ )
+
+#define H_GET_MACHTYPE(h) \
+ ( (((h)->header.a_info)&0xffff0000) \
+ ? ((ntohl(((h)->header.a_info))>>16)&0x3ff) \
+ : 0 \
+ )
+
+#define H_GET_MAGIC_NUMBER(h) \
+ ( (((h)->header.a_info)&0xffff0000) \
+ ? (ntohl(((h)->header.a_info))&0xffff) \
+ : ((h)->header.a_info & 0xffff) \
+ )
+
+#define H_SET_INFO(h,mag,mid,f,v) \
+ ( (h)->header.a_info = \
+ htonl( (((f)&0x3f)<<26) | (((mid)&0x03ff)<<16) | (((mag)&0xffff)) ) )
+
+#endif /* NETBSD_AOUT */
+
+#define EX_DYNAMIC 0x20
+#define EX_PIC 0x10
+#undef AOUT_FLAGS
+#define AOUT_FLAGS (picmode ? EX_PIC : 0)
+
+#define H_GET_DYNAMIC(h) (H_GET_FLAGS(h) & EX_DYNAMIC)
+
+#define H_GET_VERSION(h) (0)
+
+#define H_SET_DYNAMIC(h,v) \
+ H_SET_INFO(h, H_GET_MAGIC_NUMBER(h), H_GET_MACHTYPE(h), \
+ (v)?(H_GET_FLAGS(h)|0x20):(H_GET_FLAGS(h)&(~0x20)), 0)
+
+#define H_SET_VERSION(h,v)
+
+#define H_SET_MACHTYPE(h,v) \
+ H_SET_INFO(h, H_GET_MAGIC_NUMBER(h), (v), H_GET_FLAGS(h), 0)
+
+#define H_SET_MAGIC_NUMBER(h,v) \
+ H_SET_INFO(h, (v), H_GET_MACHTYPE(h), H_GET_FLAGS(h), 0)
+
+#else /* !(FREEBSD_AOUT || NETBSD_AOUT) */
+
+#define H_GET_DYNAMIC(h) ((h)->header.a_info >> 31)
+#define H_GET_VERSION(h) (((h)->header.a_info >> 24) & 0x7f)
+#define H_GET_MACHTYPE(h) (((h)->header.a_info >> 16) & 0xff)
+#define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info & 0xffff)
+
+#define H_SET_DYNAMIC(h,v) ((h)->header.a_info = \
+ (((v) << 31) \
+ | (H_GET_VERSION(h) << 24) \
+ | (H_GET_MACHTYPE(h) << 16) \
+ | (H_GET_MAGIC_NUMBER(h))))
+
+#define H_SET_VERSION(h,v) ((h)->header.a_info = \
+ ((H_GET_DYNAMIC(h) << 31) \
+ | ((v) << 24) \
+ | (H_GET_MACHTYPE(h) << 16) \
+ | (H_GET_MAGIC_NUMBER(h))))
+
+#define H_SET_MACHTYPE(h,v) ((h)->header.a_info = \
+ ((H_GET_DYNAMIC(h) << 31) \
+ | (H_GET_VERSION(h) << 24) \
+ | ((v) << 16) \
+ | (H_GET_MAGIC_NUMBER(h))))
+
+#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_info = \
+ ((H_GET_DYNAMIC(h) << 31) \
+ | (H_GET_VERSION(h) << 24) \
+ | (H_GET_MACHTYPE(h) << 16) \
+ | ((v))))
+#define H_SET_INFO(h,mag,mid,f,v) ((h)->header.a_info = \
+ ((((f)==0x20) << 31) \
+ | ((v) << 24) \
+ | ((mid) << 16) \
+ | ((mag))) )
+#endif /* FREEBSD_AOUT || NETBSD_AOUT */
+
+#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v)))
+#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v)))
+#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v)))
+
+#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\
+ H_SET_DATA_RELOCATION_SIZE((h),(d)))
+
+#define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v))
+#define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \
+ sizeof(struct nlist))
+
+#define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v))
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+
+/*
+ * Current means for getting the name of a segment.
+ * This will change for infinite-segments support (e.g. COFF).
+ */
+#define segment_name(seg) (seg_name[(int)(seg)])
+extern char *const seg_name[];
+
+typedef struct {
+ struct exec header; /* a.out header */
+ long string_table_size; /* names + '\0' + sizeof(int) */
+} object_headers;
+
+/* line numbering stuff. */
+#define OBJ_EMIT_LINENO(a, b, c) {;}
+
+#define obj_symbol_new_hook(s) {;}
+
+#if __STDC__ == 1
+struct fix;
+void tc_aout_fix_to_chars(char *where, struct fix *fixP, relax_addressT segment_address);
+#else /* not __STDC__ */
+void tc_aout_fix_to_chars();
+#endif /* not __STDC__ */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-aout.h */
diff --git a/gnu/usr.bin/as/config/obj-bfd-sunos.c b/gnu/usr.bin/as/config/obj-bfd-sunos.c
new file mode 100644
index 0000000..6db63de5
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-bfd-sunos.c
@@ -0,0 +1,71 @@
+/* obj-bfd-sunos.c
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "as.h"
+
+static
+
+ const short seg_N_TYPE[] = {
+ N_ABS,
+ N_TEXT,
+ N_DATA,
+ N_BSS,
+ N_UNDF, /* unknown */
+ N_UNDF, /* absent */
+ N_UNDF, /* pass1 */
+ N_UNDF, /* error */
+ N_UNDF, /* bignum/flonum */
+ N_UNDF, /* difference */
+ N_REGISTER, /* register */
+ };
+
+const segT N_TYPE_seg[N_TYPE+2] = { /* N_TYPE == 0x1E = 32-2 */
+ SEG_UNKNOWN, /* N_UNDF == 0 */
+ SEG_GOOF,
+ SEG_ABSOLUTE, /* N_ABS == 2 */
+ SEG_GOOF,
+ SEG_TEXT, /* N_TEXT == 4 */
+ SEG_GOOF,
+ SEG_DATA, /* N_DATA == 6 */
+ SEG_GOOF,
+ SEG_BSS, /* N_BSS == 8 */
+ SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
+ SEG_GOOF,
+};
+
+
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+ return;
+} /* obj_symbol_new_hook() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-bfd-sunos.c */
diff --git a/gnu/usr.bin/as/config/obj-bfd-sunos.h b/gnu/usr.bin/as/config/obj-bfd-sunos.h
new file mode 100644
index 0000000..122594e
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-bfd-sunos.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file is obj-bfd-sunos.h.
+ */
+
+/* define an obj specific macro off which target cpu back ends may key. */
+#define OBJ_BFD
+#define OBJ_BFD_SUNOS
+
+#include "bfd.h"
+
+/* include whatever target cpu is appropriate. */
+#include "targ-cpu.h"
+
+/*
+ * SYMBOLS
+ */
+
+/*
+ * If your object format needs to reorder symbols, define this. When
+ * defined, symbols are kept on a doubly linked list and functions are
+ * made available for push, insert, append, and delete. If not defined,
+ * symbols are kept on a singly linked list, only the append and clear
+ * facilities are available, and they are macros.
+ */
+
+/* #define SYMBOLS_NEED_PACKPOINTERS */
+
+typedef asymbol obj_symbol_type;
+typedef void *object_headers;
+
+#define S_SET_NAME(s, v) ((s)->sy_symbol.name = (v))
+#define S_GET_NAME(s) ((s)->sy_symbol.name)
+#define S_SET_SEGMENT(s,v) ((s)->sy_symbol.udata = (v))
+#define S_GET_SEGMENT(s) ((s)->sy_symbol.udata)
+#define S_SET_EXTERNAL(s) ((s)->sy_symbol.flags |= BSF_GLOBAL)
+#define S_SET_VALUE(s,v) ((s)->sy_symbol.value = (v))
+#define S_GET_VALUE(s) ((s)->sy_symbol.value)
+#define S_IS_DEFINED(s) (!((s)->sy_symbol.flags & BSF_UNDEFINED))
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0) /* your magic number */
+#define OBJ_EMIT_LINENO(a,b,c) /* must be *something*. This no-op's it out. */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-bfd-sunos.h */
diff --git a/gnu/usr.bin/as/config/obj-bout.c b/gnu/usr.bin/as/config/obj-bout.c
new file mode 100644
index 0000000..734f3a3
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-bout.c
@@ -0,0 +1,476 @@
+/* b.out object file format
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "as.h"
+#include "obstack.h"
+
+#ifndef NO_LISTING
+#include "aout/stab_gnu.h"
+#endif /* NO_LISTING */
+
+const short /* in: segT out: N_TYPE bits */
+ seg_N_TYPE[] = {
+ N_ABS,
+ N_TEXT,
+ N_DATA,
+ N_BSS,
+ N_UNDF, /* unknown */
+ N_UNDF, /* absent */
+ N_UNDF, /* pass1 */
+ N_UNDF, /* error */
+ N_UNDF, /* bignum/flonum */
+ N_UNDF, /* difference */
+ N_REGISTER, /* register */
+ };
+
+const segT N_TYPE_seg[N_TYPE+2] = { /* N_TYPE == 0x1E = 32-2 */
+ SEG_UNKNOWN, /* N_UNDF == 0 */
+ SEG_GOOF,
+ SEG_ABSOLUTE, /* N_ABS == 2 */
+ SEG_GOOF,
+ SEG_TEXT, /* N_TEXT == 4 */
+ SEG_GOOF,
+ SEG_DATA, /* N_DATA == 6 */
+ SEG_GOOF,
+ SEG_BSS, /* N_BSS == 8 */
+ SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
+ SEG_GOOF,
+};
+
+#if __STDC__ == 1
+static void obj_bout_stab(int what);
+static void obj_bout_line(void);
+static void obj_bout_desc(void);
+#else /* not __STDC__ */
+static void obj_bout_desc();
+static void obj_bout_stab();
+static void obj_bout_line();
+#endif /* not __STDC__ */
+
+const pseudo_typeS obj_pseudo_table[] = {
+ /* stabs (aka a.out aka b.out directives for debug symbols) */
+ { "desc", obj_bout_desc, 0 }, /* def */
+ { "line", obj_bout_line, 0 }, /* source code line number */
+ { "stabd", obj_bout_stab, 'd' }, /* stabs */
+ { "stabn", obj_bout_stab, 'n' }, /* stabs */
+ { "stabs", obj_bout_stab, 's' }, /* stabs */
+
+ /* coff debugging directives. Currently ignored silently */
+ { "def", s_ignore, 0 },
+ { "dim", s_ignore, 0 },
+ { "endef", s_ignore, 0 },
+ { "ln", s_ignore, 0 },
+ { "scl", s_ignore, 0 },
+ { "size", s_ignore, 0 },
+ { "tag", s_ignore, 0 },
+ { "type", s_ignore, 0 },
+ { "val", s_ignore, 0 },
+
+ /* other stuff we don't handle */
+ { "ABORT", s_ignore, 0 },
+ { "ident", s_ignore, 0 },
+
+ { NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+/* Relocation. */
+
+/*
+ * emit_relocations()
+ *
+ * Crawl along a fixS chain. Emit the segment's relocations.
+ */
+void obj_emit_relocations(where, fixP, segment_address_in_file)
+char **where;
+fixS *fixP; /* Fixup chain for this segment. */
+relax_addressT segment_address_in_file;
+{
+ for (; fixP; fixP = fixP->fx_next) {
+ if (fixP->fx_addsy != NULL) {
+ tc_bout_fix_to_chars(*where, fixP, segment_address_in_file);
+ *where += sizeof(struct relocation_info);
+ } /* if there's a symbol */
+ } /* for each fixup */
+
+} /* emit_relocations() */
+
+/* Aout file generation & utilities */
+
+/* Convert a lvalue to machine dependent data */
+void obj_header_append(where, headers)
+char **where;
+object_headers *headers;
+{
+ /* Always leave in host byte order */
+
+ headers->header.a_talign = section_alignment[SEG_TEXT];
+
+ if (headers->header.a_talign < 2){
+ headers->header.a_talign = 2;
+ } /* force to at least 2 */
+
+ headers->header.a_dalign = section_alignment[SEG_DATA];
+ headers->header.a_balign = section_alignment[SEG_BSS];
+
+ headers->header.a_tload = 0;
+ headers->header.a_dload = md_section_align(SEG_DATA, H_GET_TEXT_SIZE(headers));
+
+ append(where, (char *) &headers->header, sizeof(headers->header));
+} /* a_header_append() */
+
+void obj_symbol_to_chars(where, symbolP)
+char **where;
+symbolS *symbolP;
+{
+ /* leave in host byte order */
+ append(where, (char *)&symbolP->sy_symbol, sizeof(obj_symbol_type));
+} /* obj_symbol_to_chars() */
+
+void obj_emit_symbols(where, symbol_rootP)
+char **where;
+symbolS *symbol_rootP;
+{
+ symbolS * symbolP;
+
+ /*
+ * Emit all symbols left in the symbol chain.
+ */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ /* Used to save the offset of the name. It is used to point
+ to the string in memory but must be a file offset. */
+ char *temp;
+
+ temp = S_GET_NAME(symbolP);
+ S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
+
+ /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
+ if (!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP)) S_SET_EXTERNAL(symbolP);
+
+ obj_symbol_to_chars(where, symbolP);
+ S_SET_NAME(symbolP,temp);
+ }
+} /* emit_symbols() */
+
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+ S_SET_OTHER(symbolP, 0);
+ S_SET_DESC(symbolP, 0);
+ return;
+} /* obj_symbol_new_hook() */
+
+static void obj_bout_line() {
+ /* Assume delimiter is part of expression. */
+ /* BSD4.2 as fails with delightful bug, so we */
+ /* are not being incompatible here. */
+ new_logical_line ((char *)NULL, (int)(get_absolute_expression ()));
+ demand_empty_rest_of_line();
+} /* obj_bout_line() */
+
+/*
+ * stab()
+ *
+ * Handle .stabX directives, which used to be open-coded.
+ * So much creeping featurism overloaded the semantics that we decided
+ * to put all .stabX thinking in one place. Here.
+ *
+ * We try to make any .stabX directive legal. Other people's AS will often
+ * do assembly-time consistency checks: eg assigning meaning to n_type bits
+ * and "protecting" you from setting them to certain values. (They also zero
+ * certain bits before emitting symbols. Tut tut.)
+ *
+ * If an expression is not absolute we either gripe or use the relocation
+ * information. Other people's assemblers silently forget information they
+ * don't need and invent information they need that you didn't supply.
+ *
+ * .stabX directives always make a symbol table entry. It may be junk if
+ * the rest of your .stabX directive is malformed.
+ */
+static void obj_bout_stab(what)
+int what;
+{
+ register symbolS * symbolP = 0;
+ register char * string;
+ int saved_type = 0;
+ int length;
+ int goof; /* TRUE if we have aborted. */
+ long longint;
+
+ /*
+ * Enter with input_line_pointer pointing past .stabX and any following
+ * whitespace.
+ */
+ goof = 0; /* JF who forgot this?? */
+ if (what == 's') {
+ string = demand_copy_C_string(& length);
+ SKIP_WHITESPACE();
+ if (*input_line_pointer == ',')
+ input_line_pointer ++;
+ else {
+ as_bad("I need a comma after symbol's name");
+ goof = 1;
+ }
+ } else
+ string = "";
+
+ /*
+ * Input_line_pointer->after ','. String->symbol name.
+ */
+ if (!goof) {
+ symbolP = symbol_new(string,
+ SEG_UNKNOWN,
+ 0,
+ (struct frag *)0);
+ switch (what) {
+ case 'd':
+ S_SET_NAME(symbolP,NULL); /* .stabd feature. */
+ S_SET_VALUE(symbolP,obstack_next_free(&frags) -
+ frag_now->fr_literal);
+ symbolP->sy_frag = frag_now;
+ break;
+
+ case 'n':
+ symbolP->sy_frag = &zero_address_frag;
+ break;
+
+ case 's':
+ symbolP->sy_frag = & zero_address_frag;
+ break;
+
+ default:
+ BAD_CASE(what);
+ break;
+ }
+ if (get_absolute_expression_and_terminator(& longint) == ',')
+ symbolP->sy_symbol.n_type = saved_type = longint;
+ else {
+ as_bad("I want a comma after the n_type expression");
+ goof = 1;
+ input_line_pointer--; /* Backup over a non-',' char. */
+ }
+ }
+ if (! goof) {
+ if (get_absolute_expression_and_terminator (& longint) == ',')
+ S_SET_OTHER(symbolP,longint);
+ else {
+ as_bad("I want a comma after the n_other expression");
+ goof = 1;
+ input_line_pointer--; /* Backup over a non-',' char. */
+ }
+ }
+ if (! goof) {
+ S_SET_DESC(symbolP, get_absolute_expression ());
+ if (what == 's' || what == 'n') {
+ if (* input_line_pointer != ',') {
+ as_bad("I want a comma after the n_desc expression");
+ goof = 1;
+ } else {
+ input_line_pointer ++;
+ }
+ }
+ }
+ if ((!goof) && (what == 's' || what == 'n')) {
+ pseudo_set(symbolP);
+ symbolP->sy_symbol.n_type = saved_type;
+ }
+#ifndef NO_LISTING
+ {
+ extern int listing;
+
+ if (listing && !goof) {
+ if (symbolP->sy_symbol.n_type == N_SLINE) {
+
+ listing_source_line(symbolP->sy_symbol.n_desc);
+ } else if (symbolP->sy_symbol.n_type == N_SO
+ || symbolP->sy_symbol.n_type == N_SOL) {
+ listing_source_file(string);
+ }
+ }
+ }
+
+#endif
+
+ if (goof)
+ ignore_rest_of_line ();
+ else
+ demand_empty_rest_of_line ();
+} /* obj_bout_stab() */
+
+static void obj_bout_desc() {
+ register char *name;
+ register char c;
+ register char *p;
+ register symbolS * symbolP;
+ register int temp;
+
+ /*
+ * Frob invented at RMS' request. Set the n_desc of a symbol.
+ */
+ name = input_line_pointer;
+ c = get_symbol_end();
+ p = input_line_pointer;
+ * p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ *p = 0;
+ as_bad("Expected comma after name \"%s\"", name);
+ *p = c;
+ ignore_rest_of_line();
+ } else {
+ input_line_pointer ++;
+ temp = get_absolute_expression ();
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+ S_SET_DESC(symbolP,temp);
+ }
+ demand_empty_rest_of_line();
+} /* obj_bout_desc() */
+
+void obj_read_begin_hook() {
+ return;
+} /* obj_read_begin_hook() */
+
+void obj_crawl_symbol_chain(headers)
+object_headers *headers;
+{
+ symbolS **symbolPP;
+ symbolS *symbolP;
+ int symbol_number = 0;
+
+ /* JF deal with forward references first... */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ if (symbolP->sy_forward) {
+ S_SET_VALUE(symbolP, S_GET_VALUE(symbolP)
+ + S_GET_VALUE(symbolP->sy_forward)
+ + symbolP->sy_forward->sy_frag->fr_address);
+
+ symbolP->sy_forward=0;
+ } /* if it has a forward reference */
+ } /* walk the symbol chain */
+
+ tc_crawl_symbol_chain(headers);
+
+ symbolPP = & symbol_rootP; /*->last symbol chain link. */
+ while ((symbolP = *symbolPP) != NULL) {
+ if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_DATA)) {
+ S_SET_SEGMENT(symbolP, SEG_TEXT);
+ } /* if pusing data into text */
+
+ S_SET_VALUE(symbolP, S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
+
+ /* OK, here is how we decide which symbols go out into the
+ brave new symtab. Symbols that do are:
+
+ * symbols with no name (stabd's?)
+ * symbols with debug info in their N_TYPE
+
+ Symbols that don't are:
+ * symbols that are registers
+ * symbols with \1 as their 3rd character (numeric labels)
+ * "local labels" as defined by S_LOCAL_NAME(name)
+ if the -L switch was passed to gas.
+
+ All other symbols are output. We complain if a deleted
+ symbol was marked external. */
+
+
+ if (1
+ && !S_IS_REGISTER(symbolP)
+ && (!S_GET_NAME(symbolP)
+ || S_IS_DEBUG(symbolP)
+#ifdef TC_I960
+ /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */
+ || !S_IS_DEFINED(symbolP)
+ || S_IS_EXTERNAL(symbolP)
+#endif /* TC_I960 */
+ || (S_GET_NAME(symbolP)[0] != '\001' && (flagseen['L'] || ! S_LOCAL_NAME(symbolP))))) {
+ symbolP->sy_number = symbol_number++;
+
+ /* The + 1 after strlen account for the \0 at the
+ end of each string */
+ if (!S_IS_STABD(symbolP)) {
+ /* Ordinary case. */
+ symbolP->sy_name_offset = string_byte_count;
+ string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+ }
+ else /* .Stabd case. */
+ symbolP->sy_name_offset = 0;
+ symbolPP = &(symbol_next(symbolP));
+ } else {
+ if (S_IS_EXTERNAL(symbolP) || !S_IS_DEFINED(symbolP)) {
+ as_bad("Local symbol %s never defined", S_GET_NAME(symbolP));
+ } /* oops. */
+
+ /* Unhook it from the chain */
+ *symbolPP = symbol_next(symbolP);
+ } /* if this symbol should be in the output */
+ } /* for each symbol */
+
+ H_SET_SYMBOL_TABLE_SIZE(headers, symbol_number);
+
+ return;
+} /* obj_crawl_symbol_chain() */
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+void obj_emit_strings(where)
+char **where;
+{
+ symbolS *symbolP;
+
+#ifdef CROSS_COMPILE
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ md_number_to_chars(*where, string_byte_count, sizeof(string_byte_count));
+ *where += sizeof(string_byte_count);
+#else /* CROSS_COMPILE */
+ append(where, (char *) &string_byte_count, (unsigned long) sizeof(string_byte_count));
+#endif /* CROSS_COMPILE */
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ if (S_GET_NAME(symbolP))
+ append(where, S_GET_NAME(symbolP), (unsigned long)(strlen (S_GET_NAME(symbolP)) + 1));
+ } /* walk symbol chain */
+
+ return;
+} /* obj_emit_strings() */
+
+void obj_pre_write_hook(headers)
+object_headers *headers;
+{
+ H_SET_MAGIC_NUMBER(headers, BMAGIC);
+ H_SET_ENTRY_POINT(headers, 0);
+
+ return;
+} /* obj_pre_write_hook() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-bout.c */
diff --git a/gnu/usr.bin/as/config/obj-bout.h b/gnu/usr.bin/as/config/obj-bout.h
new file mode 100644
index 0000000..6de818a
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-bout.h
@@ -0,0 +1,313 @@
+/* b.out object file format
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 675 Mass Ave, Cambridge, MA
+ 02139, USA. */
+
+/*
+ * This file is a modified version of 'a.out.h'. It is to be used in all GNU
+ * tools modified to support the i80960 b.out format (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 OBJ_BOUT 1
+
+#include "targ-cpu.h"
+
+/* bout uses host byte order for headers */
+#ifdef CROSS_COMPILE
+#undef CROSS_COMPILE
+#endif /* CROSS_COMPILE */
+
+/* We want \v. */
+#define BACKSLASH_V 1
+
+#define OBJ_DEFAULT_OUTPUT_FILE_NAME "b.out"
+
+extern const short seg_N_TYPE[];
+extern const segT N_TYPE_seg[];
+
+#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;
+};
+
+typedef struct nlist obj_symbol_type;
+
+/* 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 */
+
+#ifndef CUSTOM_RELOC_FORMAT
+struct relocation_info {
+ int r_address; /* File address of item to be relocated */
+ unsigned
+ r_index: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 */
+};
+#endif /* CUSTOM_RELOC_FORMAT */
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* Predicates */
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT)
+
+/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */
+#define S_IS_DEFINED(s) ((S_GET_TYPE(s) != N_UNDF) || (S_GET_DESC(s) != 0))
+#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER)
+
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name begin with ^A is a gas internal pseudo symbol
+ nameless symbols come from .stab directives. */
+#define S_IS_LOCAL(s) (S_GET_NAME(s) && \
+ !S_IS_DEBUG(s) && \
+ (S_GET_NAME(s)[0] == '\001' || \
+ (S_LOCAL_NAME(s) && !flagseen['L'])))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT)
+/* True if the symbol has been generated because of a .stabd directive */
+#define S_IS_STABD(s) (S_GET_NAME(s) == NULL)
+
+/* Accessors */
+/* The value of the symbol */
+#define S_GET_VALUE(s) ((unsigned long) ((s)->sy_symbol.n_value))
+/* The name of the symbol */
+#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx)
+/* The type of the symbol */
+#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE)
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)])
+/* The n_other expression value */
+#define S_GET_OTHER(s) ((s)->sy_symbol.n_other)
+/* The n_desc expression value */
+#define S_GET_DESC(s) ((s)->sy_symbol.n_desc)
+
+/* Modifiers */
+/* Set the value of the symbol */
+#define S_SET_VALUE(s,v) ((s)->sy_symbol.n_value = (unsigned long) (v))
+/* Assume that a symbol cannot be simultaneously in more than on segment */
+/* set segment */
+#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg))
+/* The symbol is external */
+#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT)
+/* The symbol is not external */
+#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT)
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v))
+/* Set the offset in the string table */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v))
+/* Set the n_other expression value */
+#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v))
+/* Set the n_desc expression value */
+#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v))
+
+/* File header macro and type definition */
+
+#define H_GET_FILE_SIZE(h) (sizeof(struct exec) + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_SYMBOL_TABLE_SIZE(h) + \
+ H_GET_TEXT_RELOCATION_SIZE(h) + \
+ H_GET_DATA_RELOCATION_SIZE(h) + \
+ (h)->string_table_size)
+
+#define H_GET_HEADER_SIZE(h) (sizeof(struct exec))
+#define H_GET_TEXT_SIZE(h) ((h)->header.a_text)
+#define H_GET_DATA_SIZE(h) ((h)->header.a_data)
+#define H_GET_BSS_SIZE(h) ((h)->header.a_bss)
+#define H_GET_TEXT_RELOCATION_SIZE(h) ((h)->header.a_trsize)
+#define H_GET_DATA_RELOCATION_SIZE(h) ((h)->header.a_drsize)
+#define H_GET_SYMBOL_TABLE_SIZE(h) ((h)->header.a_syms)
+#define H_GET_MAGIC_NUMBER(h) ((h)->header.a_info)
+#define H_GET_ENTRY_POINT(h) ((h)->header.a_entry)
+#define H_GET_STRING_SIZE(h) ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h) (0)
+
+#ifdef EXEC_MACHINE_TYPE
+#define H_GET_MACHINE_TYPE(h) ((h)->header.a_machtype)
+#endif /* EXEC_MACHINE_TYPE */
+#ifdef EXEC_VERSION
+#define H_GET_VERSION(h) ((h)->header.a_version)
+#endif /* EXEC_VERSION */
+
+#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = (v))
+#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = (v))
+#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = (v))
+
+#define H_SET_RELOCATION_SIZE(h,t,d) (H_SET_TEXT_RELOCATION_SIZE((h),(t)),\
+ H_SET_DATA_RELOCATION_SIZE((h),(d)))
+
+#define H_SET_TEXT_RELOCATION_SIZE(h,v) ((h)->header.a_trsize = (v))
+#define H_SET_DATA_RELOCATION_SIZE(h,v) ((h)->header.a_drsize = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \
+ sizeof(struct nlist))
+
+#define H_SET_MAGIC_NUMBER(h,v) ((h)->header.a_magic = (v))
+
+#define H_SET_ENTRY_POINT(h,v) ((h)->header.a_entry = (v))
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+#ifdef EXEC_MACHINE_TYPE
+#define H_SET_MACHINE_TYPE(h,v) ((h)->header.a_machtype = (v))
+#endif /* EXEC_MACHINE_TYPE */
+#ifdef EXEC_VERSION
+#define H_SET_VERSION(h,v) ((h)->header.a_version = (v))
+#endif /* EXEC_VERSION */
+
+/*
+ * Current means for getting the name of a segment.
+ * This will change for infinite-segments support (e.g. COFF).
+ */
+#define segment_name(seg) ( seg_name[(int)(seg)] )
+extern char *const seg_name[];
+
+typedef struct {
+ struct exec header; /* a.out header */
+ long string_table_size; /* names + '\0' + sizeof(int) */
+} object_headers;
+
+/* unused hooks. */
+#define OBJ_EMIT_LINENO(a, b, c) {;}
+
+#if __STDC__
+struct fix;
+void tc_aout_fix_to_chars(char *where, struct fix *fixP, relax_addressT segment_address);
+#else /* not __STDC__ */
+void tc_aout_fix_to_chars();
+#endif /* not __STDC__ */
+
+enum reloc_type {
+ NO_RELOC, RELOC_32,
+};
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-bout.h */
diff --git a/gnu/usr.bin/as/config/obj-coff.c b/gnu/usr.bin/as/config/obj-coff.c
new file mode 100644
index 0000000..b57c6cd
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-coff.c
@@ -0,0 +1,1978 @@
+/* coff object file format
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "as.h"
+
+#include "obstack.h"
+
+lineno* lineno_rootP;
+
+const short seg_N_TYPE[] = { /* in: segT out: N_TYPE bits */
+ C_ABS_SECTION,
+ C_TEXT_SECTION,
+ C_DATA_SECTION,
+ C_BSS_SECTION,
+ C_UNDEF_SECTION, /* SEG_UNKNOWN */
+ C_UNDEF_SECTION, /* SEG_ABSENT */
+ C_UNDEF_SECTION, /* SEG_PASS1 */
+ C_UNDEF_SECTION, /* SEG_GOOF */
+ C_UNDEF_SECTION, /* SEG_BIG */
+ C_UNDEF_SECTION, /* SEG_DIFFERENCE */
+ C_DEBUG_SECTION, /* SEG_DEBUG */
+ C_NTV_SECTION, /* SEG_NTV */
+ C_PTV_SECTION, /* SEG_PTV */
+ C_REGISTER_SECTION, /* SEG_REGISTER */
+};
+
+
+/* Add 4 to the real value to get the index and compensate the negatives */
+
+const segT N_TYPE_seg[32] =
+{
+ SEG_PTV, /* C_PTV_SECTION == -4 */
+ SEG_NTV, /* C_NTV_SECTION == -3 */
+ SEG_DEBUG, /* C_DEBUG_SECTION == -2 */
+ SEG_ABSOLUTE, /* C_ABS_SECTION == -1 */
+ SEG_UNKNOWN, /* C_UNDEF_SECTION == 0 */
+ SEG_TEXT, /* C_TEXT_SECTION == 1 */
+ SEG_DATA, /* C_DATA_SECTION == 2 */
+ SEG_BSS, /* C_BSS_SECTION == 3 */
+ SEG_REGISTER, /* C_REGISTER_SECTION == 4 */
+ SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,
+ SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,
+ SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF,SEG_GOOF
+ };
+
+#if __STDC__ == 1
+
+char *s_get_name(symbolS *s);
+static symbolS *tag_find_or_make(char *name);
+static symbolS* tag_find(char *name);
+#ifdef BFD_HEADERS
+static void obj_coff_section_header_append(char **where, struct internal_scnhdr *header);
+#else
+static void obj_coff_section_header_append(char **where, SCNHDR *header);
+#endif
+static void obj_coff_def(int what);
+static void obj_coff_dim(void);
+static void obj_coff_endef(void);
+static void obj_coff_line(void);
+static void obj_coff_ln(void);
+static void obj_coff_scl(void);
+static void obj_coff_size(void);
+static void obj_coff_stab(int what);
+static void obj_coff_tag(void);
+static void obj_coff_type(void);
+static void obj_coff_val(void);
+static void tag_init(void);
+static void tag_insert(char *name, symbolS *symbolP);
+
+#else /* not __STDC__ */
+
+char *s_get_name();
+static symbolS *tag_find();
+static symbolS *tag_find_or_make();
+static void obj_coff_section_header_append();
+static void obj_coff_def();
+static void obj_coff_dim();
+static void obj_coff_endef();
+static void obj_coff_line();
+static void obj_coff_ln();
+static void obj_coff_scl();
+static void obj_coff_size();
+static void obj_coff_stab();
+static void obj_coff_tag();
+static void obj_coff_type();
+static void obj_coff_val();
+static void tag_init();
+static void tag_insert();
+
+#endif /* not __STDC__ */
+
+static struct hash_control *tag_hash;
+static symbolS *def_symbol_in_progress = NULL;
+
+const pseudo_typeS obj_pseudo_table[] = {
+#ifndef IGNORE_DEBUG
+ { "def", obj_coff_def, 0 },
+ { "dim", obj_coff_dim, 0 },
+ { "endef", obj_coff_endef, 0 },
+ { "line", obj_coff_line, 0 },
+ { "ln", obj_coff_ln, 0 },
+ { "scl", obj_coff_scl, 0 },
+ { "size", obj_coff_size, 0 },
+ { "tag", obj_coff_tag, 0 },
+ { "type", obj_coff_type, 0 },
+ { "val", obj_coff_val, 0 },
+#else
+ { "def", s_ignore, 0 },
+ { "dim", s_ignore, 0 },
+ { "endef", s_ignore, 0 },
+ { "line", s_ignore, 0 },
+ { "ln", s_ignore, 0 },
+ { "scl", s_ignore, 0 },
+ { "size", s_ignore, 0 },
+ { "tag", s_ignore, 0 },
+ { "type", s_ignore, 0 },
+ { "val", s_ignore, 0 },
+#endif /* ignore debug */
+
+ { "ident", s_ignore, 0 }, /* we don't yet handle this. */
+
+
+ /* stabs aka a.out aka b.out directives for debug symbols.
+ Currently ignored silently. Except for .line at which
+ we guess from context. */
+ { "desc", s_ignore, 0 }, /* def */
+ /* { "line", s_ignore, 0 }, */ /* source code line number */
+ { "stabd", obj_coff_stab, 'd' }, /* stabs */
+ { "stabn", obj_coff_stab, 'n' }, /* stabs */
+ { "stabs", obj_coff_stab, 's' }, /* stabs */
+
+ /* stabs-in-coff (?) debug pseudos (ignored) */
+ { "optim", s_ignore, 0 }, /* For sun386i cc (?) */
+ /* other stuff */
+ { "ABORT", s_abort, 0 },
+
+ { NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+
+/* obj dependant output values */
+#ifdef BFD_HEADERS
+static struct internal_scnhdr bss_section_header;
+struct internal_scnhdr data_section_header;
+struct internal_scnhdr text_section_header;
+#else
+static SCNHDR bss_section_header;
+SCNHDR data_section_header;
+SCNHDR text_section_header;
+#endif
+/* Relocation. */
+
+static int reloc_compare(p1, p2)
+#ifdef BFD_HEADERS
+struct internal_reloc *p1, *p2;
+#else
+RELOC *p1, *p2;
+#endif
+{
+ return (int)(p1->r_vaddr - p2->r_vaddr);
+}
+
+/*
+ * emit_relocations()
+ *
+ * Crawl along a fixS chain. Emit the segment's relocations.
+ */
+
+void obj_emit_relocations(where, fixP, segment_address_in_file)
+char **where;
+fixS *fixP; /* Fixup chain for this segment. */
+relax_addressT segment_address_in_file;
+{
+#ifdef BFD_HEADERS
+ struct internal_reloc *ri_table;
+#else
+ RELOC *ri_table;
+#endif
+ symbolS *symbolP;
+ int i, count;
+ fixS *p;
+
+ for (count = 0, p = fixP; p ; p = p->fx_next)
+ if (p->fx_addsy) count++;
+ if (!count)
+ return;
+
+#ifdef BFD_HEADERS
+ ri_table = (struct internal_reloc *) calloc(sizeof(*ri_table),count);
+#else
+ ri_table = (RELOC *) calloc(sizeof(*ri_table),count);
+#endif
+ if (!ri_table)
+ as_fatal ("obj_emit_relocations: Could not malloc relocation table");
+
+#ifdef TC_I960
+ callj_table = (char *)malloc (sizeof(char)*count);
+ if (!callj_table)
+ as_fatal ("obj_emit_relocations: Could not malloc callj table");
+#endif
+
+ for (i = 0; fixP; fixP = fixP->fx_next) {
+ if (symbolP = fixP->fx_addsy) {
+#if defined(TC_M68K)
+ ri_table[i].r_type = (fixP->fx_pcrel ?
+ (fixP->fx_size == 1 ? R_PCRBYTE :
+ fixP->fx_size == 2 ? R_PCRWORD :
+ R_PCRLONG):
+ (fixP->fx_size == 1 ? R_RELBYTE :
+ fixP->fx_size == 2 ? R_RELWORD :
+ R_RELLONG));
+#elif defined(TC_I386)
+ /* FIXME-SOON R_OFF8 & R_DIR16 are a vague guess, completly
+ untested. */
+ ri_table[i].r_type = (fixP->fx_pcrel ?
+ (fixP->fx_size == 1 ? R_PCRBYTE :
+ fixP->fx_size == 2 ? R_PCRWORD :
+ R_PCRLONG):
+ (fixP->fx_size == 1 ? R_OFF8 :
+ fixP->fx_size == 2 ? R_DIR16 :
+ R_DIR32));
+#elif defined(TC_I960)
+ ri_table[i].r_type = (fixP->fx_pcrel
+ ? R_IPRMED
+ : R_RELLONG);
+ callj_table[i] = fixP->fx_callj ? 1 : 0;
+#elif defined(TC_A29K)
+ ri_table[i].r_type = tc_coff_fix2rtype(fixP);
+
+#else
+#error you lose
+#endif /* TC_M68K || TC_I386 */
+ ri_table[i].r_vaddr = (fixP->fx_frag->fr_address
+ + fixP->fx_where);
+ /* If symbol associated to relocation entry is a bss symbol
+ or undefined symbol just remember the index of the symbol.
+ Otherwise store the index of the symbol describing the
+ section the symbol belong to. This heuristic speeds up ld.
+ */
+ /* Local symbols can generate relocation information. In case
+ of structure return for instance. But they have no symbol
+ number because they won't be emitted in the final object.
+ In the case where they are in the BSS section, this leads
+ to an incorrect r_symndx.
+ Under bsd the loader do not care if the symbol reference
+ is incorrect. But the SYS V ld complains about this. To
+ avoid this we associate the symbol to the associated
+ section, *even* if it is the BSS section. */
+ /* If someone can tell me why the other symbols of the bss
+ section are not associated with the .bss section entry,
+ I'd be gratefull. I guess that it has to do with the special
+ nature of the .bss section. Or maybe this is because the
+ bss symbols are declared in the common section and can
+ be resized later. Can it break code some where ? */
+ ri_table[i].r_symndx = (S_GET_SEGMENT(symbolP) == SEG_TEXT
+ ? dot_text_symbol->sy_number
+ : (S_GET_SEGMENT(symbolP) == SEG_DATA
+ ? dot_data_symbol->sy_number
+ : ((SF_GET_LOCAL(symbolP)
+ ? dot_bss_symbol->sy_number
+ : symbolP->sy_number)))); /* bss or undefined */
+
+ /* md_ri_to_chars((char *) &ri, ri); */ /* Last step : write md f */
+
+ i++;
+ } /* if there's a symbol */
+ } /* for each fixP */
+
+ /*
+ * AIX ld prefer to have the reloc table with r_vaddr sorted.
+ * But sorting it should not hurt any other ld.
+ */
+ qsort (ri_table, count, sizeof(*ri_table), reloc_compare);
+
+ for (i = 0; i < count; i++)
+ {
+#ifdef BFD_HEADERS
+ *where += bfd_coff_swap_reloc_out(stdoutput, &ri_table[i], *where);
+# ifdef TC_A29K
+ /* The 29k has a special kludge for the high 16 bit reloc.
+ Two relocations are emmited, R_IHIHALF, and R_IHCONST.
+ The second one doesn't contain a symbol, but uses the
+ value for offset */
+ if (ri_table[i].r_type == R_IHIHALF)
+ {
+ /* now emit the second bit */
+ ri_table[i].r_type = R_IHCONST;
+ ri_table[i].r_symndx = fixP->fx_addnumber;
+ *where += bfd_coff_swap_reloc_out(stdoutput, &ri_table[i],
+ *where);
+ }
+# endif /* TC_A29K */
+
+#else /* not BFD_HEADERS */
+ append(where, (char *) &ri_table[i], RELSZ);
+#endif /* not BFD_HEADERS */
+
+#ifdef TC_I960
+ if (callj_table[i])
+ {
+ ri_table[i].r_type = R_OPTCALL;
+# ifdef BFD_HEADERS
+ *where += bfd_coff_swap_reloc_out(stdoutput, &ri_table[i],
+ *where);
+# else
+ append(where, (char *) &ri_table[i], (unsigned long)RELSZ);
+# endif /* BFD_HEADERS */
+ } /* if it's a callj, do it again for the opcode */
+#endif /* TC_I960 */
+ }
+
+ free (ri_table);
+#ifdef TC_I960
+ free (callj_table);
+#endif
+
+ return;
+} /* obj_emit_relocations() */
+
+/* Coff file generation & utilities */
+
+#ifdef BFD_HEADERS
+void obj_header_append(where, headers)
+char **where;
+object_headers *headers;
+{
+ tc_headers_hook(headers);
+ *where += bfd_coff_swap_filehdr_out(stdoutput, &(headers->filehdr), *where);
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+ *where += bfd_coff_swap_aouthdr_out(stdoutput, &(headers->aouthdr), *where);
+#endif
+ obj_coff_section_header_append(where, &text_section_header);
+ obj_coff_section_header_append(where, &data_section_header);
+ obj_coff_section_header_append(where, &bss_section_header);
+
+}
+
+#else
+
+void obj_header_append(where, headers)
+char **where;
+object_headers *headers;
+{
+ tc_headers_hook(headers);
+
+#ifdef CROSS_COMPILE
+ /* Eventually swap bytes for cross compilation for file header */
+ md_number_to_chars(*where, headers->filehdr.f_magic, sizeof(headers->filehdr.f_magic));
+ *where += sizeof(headers->filehdr.f_magic);
+ md_number_to_chars(*where, headers->filehdr.f_nscns, sizeof(headers->filehdr.f_nscns));
+ *where += sizeof(headers->filehdr.f_nscns);
+ md_number_to_chars(*where, headers->filehdr.f_timdat, sizeof(headers->filehdr.f_timdat));
+ *where += sizeof(headers->filehdr.f_timdat);
+ md_number_to_chars(*where, headers->filehdr.f_symptr, sizeof(headers->filehdr.f_symptr));
+ *where += sizeof(headers->filehdr.f_symptr);
+ md_number_to_chars(*where, headers->filehdr.f_nsyms, sizeof(headers->filehdr.f_nsyms));
+ *where += sizeof(headers->filehdr.f_nsyms);
+ md_number_to_chars(*where, headers->filehdr.f_opthdr, sizeof(headers->filehdr.f_opthdr));
+ *where += sizeof(headers->filehdr.f_opthdr);
+ md_number_to_chars(*where, headers->filehdr.f_flags, sizeof(headers->filehdr.f_flags));
+ *where += sizeof(headers->filehdr.f_flags);
+
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+ /* Eventually swap bytes for cross compilation for a.out header */
+ md_number_to_chars(*where, headers->aouthdr.magic, sizeof(headers->aouthdr.magic));
+ *where += sizeof(headers->aouthdr.magic);
+ md_number_to_chars(*where, headers->aouthdr.vstamp, sizeof(headers->aouthdr.vstamp));
+ *where += sizeof(headers->aouthdr.vstamp);
+ md_number_to_chars(*where, headers->aouthdr.tsize, sizeof(headers->aouthdr.tsize));
+ *where += sizeof(headers->aouthdr.tsize);
+ md_number_to_chars(*where, headers->aouthdr.dsize, sizeof(headers->aouthdr.dsize));
+ *where += sizeof(headers->aouthdr.dsize);
+ md_number_to_chars(*where, headers->aouthdr.bsize, sizeof(headers->aouthdr.bsize));
+ *where += sizeof(headers->aouthdr.bsize);
+ md_number_to_chars(*where, headers->aouthdr.entry, sizeof(headers->aouthdr.entry));
+ *where += sizeof(headers->aouthdr.entry);
+ md_number_to_chars(*where, headers->aouthdr.text_start, sizeof(headers->aouthdr.text_start));
+ *where += sizeof(headers->aouthdr.text_start);
+ md_number_to_chars(*where, headers->aouthdr.data_start, sizeof(headers->aouthdr.data_start));
+ *where += sizeof(headers->aouthdr.data_start);
+ md_number_to_chars(*where, headers->aouthdr.tagentries, sizeof(headers->aouthdr.tagentries));
+ *where += sizeof(headers->aouthdr.tagentries);
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#else /* CROSS_COMPILE */
+
+ append(where, (char *) &headers->filehdr, sizeof(headers->filehdr));
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+ append(where, (char *) &headers->aouthdr, sizeof(headers->aouthdr));
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#endif /* CROSS_COMPILE */
+
+ /* Output the section headers */
+ obj_coff_section_header_append(where, &text_section_header);
+ obj_coff_section_header_append(where, &data_section_header);
+ obj_coff_section_header_append(where, &bss_section_header);
+
+ return;
+} /* obj_header_append() */
+#endif
+void obj_symbol_to_chars(where, symbolP)
+char **where;
+symbolS *symbolP;
+{
+#ifdef BFD_HEADERS
+ unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
+ unsigned int i;
+
+ if (S_GET_SEGMENT(symbolP) == SEG_REGISTER) {
+ S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
+ }
+ *where += bfd_coff_swap_sym_out(stdoutput, &symbolP->sy_symbol.ost_entry,
+ *where);
+
+ for (i = 0; i < numaux; i++)
+ {
+ *where += bfd_coff_swap_aux_out(stdoutput,
+ &symbolP->sy_symbol.ost_auxent[i],
+ S_GET_DATA_TYPE(symbolP),
+ S_GET_STORAGE_CLASS(symbolP),
+ *where);
+ }
+
+#else /* BFD_HEADERS */
+ SYMENT *syment = &symbolP->sy_symbol.ost_entry;
+ int i;
+ char numaux = syment->n_numaux;
+ unsigned short type = S_GET_DATA_TYPE(symbolP);
+
+#ifdef CROSS_COMPILE
+ md_number_to_chars(*where, syment->n_value, sizeof(syment->n_value));
+ *where += sizeof(syment->n_value);
+ md_number_to_chars(*where, syment->n_scnum, sizeof(syment->n_scnum));
+ *where += sizeof(syment->n_scnum);
+ md_number_to_chars(*where, 0, sizeof(short)); /* pad n_flags */
+ *where += sizeof(short);
+ md_number_to_chars(*where, syment->n_type, sizeof(syment->n_type));
+ *where += sizeof(syment->n_type);
+ md_number_to_chars(*where, syment->n_sclass, sizeof(syment->n_sclass));
+ *where += sizeof(syment->n_sclass);
+ md_number_to_chars(*where, syment->n_numaux, sizeof(syment->n_numaux));
+ *where += sizeof(syment->n_numaux);
+#else /* CROSS_COMPILE */
+ append(where, (char *) syment, sizeof(*syment));
+#endif /* CROSS_COMPILE */
+
+ /* Should do the following : if (.file entry) MD(..)... else if (static entry) MD(..) */
+ if (numaux > OBJ_COFF_MAX_AUXENTRIES) {
+ as_bad("Internal error? too many auxents for symbol");
+ } /* too many auxents */
+
+ for (i = 0; i < numaux; ++i) {
+#ifdef CROSS_COMPILE
+#if 0 /* This code has never been tested */
+ /* The most common case, x_sym entry. */
+ if ((SF_GET(symbolP) & (SF_FILE | SF_STATICS)) == 0) {
+ md_number_to_chars(*where, auxP->x_sym.x_tagndx, sizeof(auxP->x_sym.x_tagndx));
+ *where += sizeof(auxP->x_sym.x_tagndx);
+ if (ISFCN(type)) {
+ md_number_to_chars(*where, auxP->x_sym.x_misc.x_fsize, sizeof(auxP->x_sym.x_misc.x_fsize));
+ *where += sizeof(auxP->x_sym.x_misc.x_fsize);
+ } else {
+ md_number_to_chars(*where, auxP->x_sym.x_misc.x_lnno, sizeof(auxP->x_sym.x_misc.x_lnno));
+ *where += sizeof(auxP->x_sym.x_misc.x_lnno);
+ md_number_to_chars(*where, auxP->x_sym.x_misc.x_size, sizeof(auxP->x_sym.x_misc.x_size));
+ *where += sizeof(auxP->x_sym.x_misc.x_size);
+ }
+ if (ISARY(type)) {
+ register int index;
+ for (index = 0; index < DIMNUM; index++)
+ md_number_to_chars(*where, auxP->x_sym.x_fcnary.x_ary.x_dimen[index], sizeof(auxP->x_sym.x_fcnary.x_ary.x_dimen[index]));
+ *where += sizeof(auxP->x_sym.x_fcnary.x_ary.x_dimen[index]);
+ } else {
+ md_number_to_chars(*where, auxP->x_sym.x_fcnary.x_fcn.x_lnnoptr, sizeof(auxP->x_sym.x_fcnary.x_fcn.x_lnnoptr));
+ *where += sizeof(auxP->x_sym.x_fcnary.x_fcn.x_lnnoptr);
+ md_number_to_chars(*where, auxP->x_sym.x_fcnary.x_fcn.x_endndx, sizeof(auxP->x_sym.x_fcnary.x_fcn.x_endndx));
+ *where += sizeof(auxP->x_sym.x_fcnary.x_fcn.x_endndx);
+ }
+ md_number_to_chars(*where, auxP->x_sym.x_tvndx, sizeof(auxP->x_sym.x_tvndx));
+ *where += sizeof(auxP->x_sym.x_tvndx);
+ } else if (SF_GET_FILE(symbolP)) { /* .file */
+ ;
+ } else if (SF_GET_STATICS(symbolP)) { /* .text, .data, .bss symbols */
+ md_number_to_chars(*where, auxP->x_scn.x_scnlen, sizeof(auxP->x_scn.x_scnlen));
+ *where += sizeof(auxP->x_scn.x_scnlen);
+ md_number_to_chars(*where, auxP->x_scn.x_nreloc, sizeof(auxP->x_scn.x_nreloc));
+ *where += sizeof(auxP->x_scn.x_nreloc);
+ md_number_to_chars(*where, auxP->x_scn.x_nlinno, sizeof(auxP->x_scn.x_nlinno));
+ *where += sizeof(auxP->x_scn.x_nlinno);
+ }
+#endif /* 0 */
+#else /* CROSS_COMPILE */
+ append(where, (char *) &symbolP->sy_symbol.ost_auxent[i], sizeof(symbolP->sy_symbol.ost_auxent[i]));
+#endif /* CROSS_COMPILE */
+
+ }; /* for each aux in use */
+#endif /* BFD_HEADERS */
+ return;
+} /* obj_symbol_to_chars() */
+
+#ifdef BFD_HEADERS
+static void obj_coff_section_header_append(where, header)
+char **where;
+struct internal_scnhdr *header;
+{
+ *where += bfd_coff_swap_scnhdr_out(stdoutput, header, *where);
+}
+#else
+static void obj_coff_section_header_append(where, header)
+char **where;
+SCNHDR *header;
+{
+#ifdef CROSS_COMPILE
+ memcpy(*where, header->s_name, sizeof(header->s_name));
+ *where += sizeof(header->s_name);
+
+ md_number_to_chars(*where, header->s_paddr, sizeof(header->s_paddr));
+ *where += sizeof(header->s_paddr);
+
+ md_number_to_chars(*where, header->s_vaddr, sizeof(header->s_vaddr));
+ *where += sizeof(header->s_vaddr);
+
+ md_number_to_chars(*where, header->s_size, sizeof(header->s_size));
+ *where += sizeof(header->s_size);
+
+ md_number_to_chars(*where, header->s_scnptr, sizeof(header->s_scnptr));
+ *where += sizeof(header->s_scnptr);
+
+ md_number_to_chars(*where, header->s_relptr, sizeof(header->s_relptr));
+ *where += sizeof(header->s_relptr);
+
+ md_number_to_chars(*where, header->s_lnnoptr, sizeof(header->s_lnnoptr));
+ *where += sizeof(header->s_lnnoptr);
+
+ md_number_to_chars(*where, header->s_nreloc, sizeof(header->s_nreloc));
+ *where += sizeof(header->s_nreloc);
+
+ md_number_to_chars(*where, header->s_nlnno, sizeof(header->s_nlnno));
+ *where += sizeof(header->s_nlnno);
+
+ md_number_to_chars(*where, header->s_flags, sizeof(header->s_flags));
+ *where += sizeof(header->s_flags);
+
+#ifdef TC_I960
+ md_number_to_chars(*where, header->s_align, sizeof(header->s_align));
+ *where += sizeof(header->s_align);
+#endif /* TC_I960 */
+
+#else /* CROSS_COMPILE */
+
+ append(where, (char *) header, sizeof(*header));
+
+#endif /* CROSS_COMPILE */
+
+ return;
+} /* obj_coff_section_header_append() */
+
+#endif
+void obj_emit_symbols(where, symbol_rootP)
+char **where;
+symbolS *symbol_rootP;
+{
+ symbolS *symbolP;
+ /*
+ * Emit all symbols left in the symbol chain.
+ */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ /* Used to save the offset of the name. It is used to point
+ to the string in memory but must be a file offset. */
+ register char * temp;
+
+ tc_coff_symbol_emit_hook(symbolP);
+
+ temp = S_GET_NAME(symbolP);
+ if (SF_GET_STRING(symbolP)) {
+ S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
+ S_SET_ZEROES(symbolP, 0);
+ } else {
+ memset(symbolP->sy_symbol.ost_entry.n_name, '\0', SYMNMLEN);
+ strncpy(symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
+ }
+ obj_symbol_to_chars(where, symbolP);
+ S_SET_NAME(symbolP,temp);
+ }
+} /* obj_emit_symbols() */
+
+/* Merge a debug symbol containing debug information into a normal symbol. */
+
+void c_symbol_merge(debug, normal)
+symbolS *debug;
+symbolS *normal;
+{
+ S_SET_DATA_TYPE(normal, S_GET_DATA_TYPE(debug));
+ S_SET_STORAGE_CLASS(normal, S_GET_STORAGE_CLASS(debug));
+
+ if (S_GET_NUMBER_AUXILIARY(debug) > S_GET_NUMBER_AUXILIARY(normal)) {
+ S_SET_NUMBER_AUXILIARY(normal, S_GET_NUMBER_AUXILIARY(debug));
+ } /* take the most we have */
+
+ if (S_GET_NUMBER_AUXILIARY(debug) > 0) {
+ memcpy((char*)&normal->sy_symbol.ost_auxent[0], (char*)&debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
+ } /* Move all the auxiliary information */
+
+ /* Move the debug flags. */
+ SF_SET_DEBUG_FIELD(normal, SF_GET_DEBUG_FIELD(debug));
+} /* c_symbol_merge() */
+
+static symbolS *previous_file_symbol = NULL;
+
+void c_dot_file_symbol(filename)
+char *filename;
+{
+ symbolS* symbolP;
+
+ symbolP = symbol_new(".file",
+ SEG_DEBUG,
+ 0,
+ &zero_address_frag);
+
+ S_SET_STORAGE_CLASS(symbolP, C_FILE);
+ S_SET_NUMBER_AUXILIARY(symbolP, 1);
+ SA_SET_FILE_FNAME(symbolP, filename);
+ SF_SET_DEBUG(symbolP);
+ S_SET_VALUE(symbolP, (long) previous_file_symbol);
+
+ previous_file_symbol = symbolP;
+
+ /* Make sure that the symbol is first on the symbol chain */
+ if (symbol_rootP != symbolP) {
+ if (symbolP == symbol_lastP) {
+ symbol_lastP = symbol_lastP->sy_previous;
+ } /* if it was the last thing on the list */
+
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_insert(symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
+ symbol_rootP = symbolP;
+ } /* if not first on the list */
+
+} /* c_dot_file_symbol() */
+/*
+ * Build a 'section static' symbol.
+ */
+
+char *c_section_symbol(name, value, length, nreloc, nlnno)
+char *name;
+long value;
+long length;
+unsigned short nreloc;
+unsigned short nlnno;
+{
+ symbolS *symbolP;
+
+ symbolP = symbol_new(name,
+ (name[1] == 't'
+ ? SEG_TEXT
+ : (name[1] == 'd'
+ ? SEG_DATA
+ : SEG_BSS)),
+ value,
+ &zero_address_frag);
+
+ S_SET_STORAGE_CLASS(symbolP, C_STAT);
+ S_SET_NUMBER_AUXILIARY(symbolP, 1);
+
+ SA_SET_SCN_SCNLEN(symbolP, length);
+ SA_SET_SCN_NRELOC(symbolP, nreloc);
+ SA_SET_SCN_NLINNO(symbolP, nlnno);
+
+ SF_SET_STATICS(symbolP);
+
+ return (char*)symbolP;
+} /* c_section_symbol() */
+
+void c_section_header(header,
+ name,
+ core_address,
+ size,
+ data_ptr,
+ reloc_ptr,
+ lineno_ptr,
+ reloc_number,
+ lineno_number,
+ alignment)
+#ifdef BFD_HEADERS
+struct internal_scnhdr *header;
+#else
+SCNHDR *header;
+#endif
+char *name;
+long core_address;
+long size;
+long data_ptr;
+long reloc_ptr;
+long lineno_ptr;
+long reloc_number;
+long lineno_number;
+long alignment;
+{
+ strncpy(header->s_name, name, 8);
+ header->s_paddr = header->s_vaddr = core_address;
+ header->s_scnptr = ((header->s_size = size) != 0) ? data_ptr : 0;
+ header->s_relptr = reloc_ptr;
+ header->s_lnnoptr = lineno_ptr;
+ header->s_nreloc = reloc_number;
+ header->s_nlnno = lineno_number;
+
+#ifdef OBJ_COFF_SECTION_HEADER_HAS_ALIGNMENT
+#ifdef OBJ_COFF_BROKEN_ALIGNMENT
+ header->s_align = ((name[1] == 'b' || (size > 0)) ? 16 : 0);
+#else
+ header->s_align = ((alignment == 0)
+ ? 0
+ : (1 << alignment));
+#endif /* OBJ_COFF_BROKEN_ALIGNMENT */
+#endif /* OBJ_COFF_SECTION_HEADER_HAS_ALIGNMENT */
+
+ header->s_flags = STYP_REG | (name[1] == 't'
+ ? STYP_TEXT
+ : (name[1] == 'd'
+ ? STYP_DATA
+ : (name[1] == 'b'
+ ? STYP_BSS
+ : STYP_INFO)));
+ return;
+} /* c_section_header() */
+
+/* Line number handling */
+
+int function_lineoff = -1; /* Offset in line#s where the last function
+ started (the odd entry for line #0) */
+int text_lineno_number = 0;
+int our_lineno_number = 0; /* we use this to build pointers from .bf's
+ into the linetable. It should match
+ exactly the values that are later
+ assigned in text_lineno_number by
+ write.c. */
+lineno* lineno_lastP = (lineno*)0;
+
+int
+ c_line_new(paddr, line_number, frag)
+long paddr;
+unsigned short line_number;
+fragS* frag;
+{
+ lineno* new_line = (lineno*)xmalloc(sizeof(lineno));
+
+ new_line->line.l_addr.l_paddr = paddr;
+ new_line->line.l_lnno = line_number;
+ new_line->frag = (char*)frag;
+ new_line->next = (lineno*)0;
+
+ if (lineno_rootP == (lineno*)0)
+ lineno_rootP = new_line;
+ else
+ lineno_lastP->next = new_line;
+ lineno_lastP = new_line;
+ return LINESZ * our_lineno_number++;
+}
+
+void obj_emit_lineno(where, line, file_start)
+char **where;
+lineno *line;
+char *file_start;
+{
+#ifdef BFD_HEADERS
+ struct bfd_internal_lineno *line_entry;
+#else
+ LINENO *line_entry;
+#endif
+ for (; line; line = line->next) {
+ line_entry = &line->line;
+
+ /* FIXME-SOMEDAY Resolving the sy_number of function linno's used to be done in
+ write_object_file() but their symbols need a fileptr to the lnno, so
+ I moved this resolution check here. xoxorich. */
+
+ if (line_entry->l_lnno == 0) {
+ /* There is a good chance that the symbol pointed to
+ is not the one that will be emitted and that the
+ sy_number is not accurate. */
+ /* char *name; */
+ symbolS *symbolP;
+
+ symbolP = (symbolS *) line_entry->l_addr.l_symndx;
+
+ line_entry->l_addr.l_symndx = symbolP->sy_number;
+ symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr = *where - file_start;
+
+ } /* if this is a function linno */
+#ifdef BFD_HEADERS
+ *where += bfd_coff_swap_lineno_out(stdoutput, line_entry, *where);
+#else
+ /* No matter which member of the union we process, they are
+ both long. */
+#ifdef CROSS_COMPILE
+ md_number_to_chars(*where, line_entry->l_addr.l_paddr, sizeof(line_entry->l_addr.l_paddr));
+ *where += sizeof(line_entry->l_addr.l_paddr);
+
+ md_number_to_chars(*where, line_entry->l_lnno, sizeof(line_entry->l_lnno));
+ *where += sizeof(line_entry->l_lnno);
+
+#ifdef TC_I960
+ **where = '0';
+ ++*where;
+ **where = '0';
+ ++*where;
+#endif /* TC_I960 */
+
+#else /* CROSS_COMPILE */
+ append(where, (char *) line_entry, LINESZ);
+#endif /* CROSS_COMPILE */
+#endif /* BFD_HEADERS */
+ } /* for each line number */
+
+ return ;
+} /* obj_emit_lineno() */
+
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+ char underscore = 0; /* Symbol has leading _ */
+
+ /* Effective symbol */
+ /* Store the pointer in the offset. */
+ S_SET_ZEROES(symbolP, 0L);
+ S_SET_DATA_TYPE(symbolP, T_NULL);
+ S_SET_STORAGE_CLASS(symbolP, 0);
+ S_SET_NUMBER_AUXILIARY(symbolP, 0);
+ /* Additional information */
+ symbolP->sy_symbol.ost_flags = 0;
+ /* Auxiliary entries */
+ memset((char*) &symbolP->sy_symbol.ost_auxent[0], '\0', AUXESZ);
+
+#ifdef STRIP_UNDERSCORE
+ /* Remove leading underscore at the beginning of the symbol.
+ * This is to be compatible with the standard librairies.
+ */
+ if (*S_GET_NAME(symbolP) == '_') {
+ underscore = 1;
+ S_SET_NAME(symbolP, S_GET_NAME(symbolP) + 1);
+ } /* strip underscore */
+#endif /* STRIP_UNDERSCORE */
+
+ if (S_IS_STRING(symbolP))
+ SF_SET_STRING(symbolP);
+ if (!underscore && S_IS_LOCAL(symbolP))
+ SF_SET_LOCAL(symbolP);
+
+ return;
+} /* obj_symbol_new_hook() */
+
+/* stack stuff */
+stack* stack_init(chunk_size, element_size)
+unsigned long chunk_size;
+unsigned long element_size;
+{
+ stack* st;
+
+ if ((st = (stack*)malloc(sizeof(stack))) == (stack*)0)
+ return (stack*)0;
+ if ((st->data = malloc(chunk_size)) == (char*)0) {
+ free(st);
+ return (stack*)0;
+ }
+ st->pointer = 0;
+ st->size = chunk_size;
+ st->chunk_size = chunk_size;
+ st->element_size = element_size;
+ return st;
+} /* stack_init() */
+
+void stack_delete(st)
+stack* st;
+{
+ free(st->data);
+ free(st);
+}
+
+char *stack_push(st, element)
+stack *st;
+char *element;
+{
+ if (st->pointer + st->element_size >= st->size) {
+ st->size += st->chunk_size;
+ if ((st->data = xrealloc(st->data, st->size)) == (char*)0)
+ return (char*)0;
+ }
+ memcpy(st->data + st->pointer, element, st->element_size);
+ st->pointer += st->element_size;
+ return st->data + st->pointer;
+} /* stack_push() */
+
+char* stack_pop(st)
+stack* st;
+{
+ if ((st->pointer -= st->element_size) < 0) {
+ st->pointer = 0;
+ return (char*)0;
+ }
+ return st->data + st->pointer;
+}
+
+char* stack_top(st)
+stack* st;
+{
+ return st->data + st->pointer - st->element_size;
+}
+
+
+/*
+ * Handle .ln directives.
+ */
+
+static void obj_coff_ln() {
+ if (def_symbol_in_progress != NULL) {
+ as_warn(".ln pseudo-op inside .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* wrong context */
+
+ c_line_new(obstack_next_free(&frags) - frag_now->fr_literal,
+ get_absolute_expression(),
+ frag_now);
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_line() */
+
+/*
+ * def()
+ *
+ * Handle .def directives.
+ *
+ * One might ask : why can't we symbol_new if the symbol does not
+ * already exist and fill it with debug information. Because of
+ * the C_EFCN special symbol. It would clobber the value of the
+ * function symbol before we have a chance to notice that it is
+ * a C_EFCN. And a second reason is that the code is more clear this
+ * way. (at least I think it is :-).
+ *
+ */
+
+#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
+#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
+ *input_line_pointer == '\t') \
+ input_line_pointer++;
+
+static void obj_coff_def(what)
+int what;
+{
+ char name_end; /* Char after the end of name */
+ char *symbol_name; /* Name of the debug symbol */
+ char *symbol_name_copy; /* Temporary copy of the name */
+ unsigned int symbol_name_length;
+ /*$char* directiveP;$ */ /* Name of the pseudo opcode */
+ /*$char directive[MAX_DIRECTIVE];$ */ /* Backup of the directive */
+ /*$char end = 0;$ */ /* If 1, stop parsing */
+
+ if (def_symbol_in_progress != NULL) {
+ as_warn(".def pseudo-op used inside of .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ SKIP_WHITESPACES();
+
+ def_symbol_in_progress = (symbolS *) obstack_alloc(&notes, sizeof(*def_symbol_in_progress));
+ memset(def_symbol_in_progress, '\0', sizeof(*def_symbol_in_progress));
+
+ symbol_name = input_line_pointer;
+ name_end = get_symbol_end();
+ symbol_name_length = strlen(symbol_name);
+ symbol_name_copy = xmalloc(symbol_name_length + 1);
+ strcpy(symbol_name_copy, symbol_name);
+
+ /* Initialize the new symbol */
+#ifdef STRIP_UNDERSCORE
+ S_SET_NAME(def_symbol_in_progress, (*symbol_name_copy == '_'
+ ? symbol_name_copy + 1
+ : symbol_name_copy));
+#else /* STRIP_UNDERSCORE */
+ S_SET_NAME(def_symbol_in_progress, symbol_name_copy);
+#endif /* STRIP_UNDERSCORE */
+ /* free(symbol_name_copy); */
+ def_symbol_in_progress->sy_name_offset = ~0;
+ def_symbol_in_progress->sy_number = ~0;
+ def_symbol_in_progress->sy_frag = &zero_address_frag;
+
+ if (S_IS_STRING(def_symbol_in_progress)) {
+ SF_SET_STRING(def_symbol_in_progress);
+ } /* "long" name */
+
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_def() */
+
+unsigned int dim_index;
+static void obj_coff_endef() {
+ symbolS *symbolP;
+ /* DIM BUG FIX sac@cygnus.com */
+ dim_index =0;
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".endef pseudo-op used outside of .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ /* Set the section number according to storage class. */
+ switch (S_GET_STORAGE_CLASS(def_symbol_in_progress)) {
+ case C_STRTAG:
+ case C_ENTAG:
+ case C_UNTAG:
+ SF_SET_TAG(def_symbol_in_progress);
+ /* intentional fallthrough */
+ case C_FILE:
+ case C_TPDEF:
+ SF_SET_DEBUG(def_symbol_in_progress);
+ S_SET_SEGMENT(def_symbol_in_progress, SEG_DEBUG);
+ break;
+
+ case C_EFCN:
+ SF_SET_LOCAL(def_symbol_in_progress); /* Do not emit this symbol. */
+ /* intentional fallthrough */
+ case C_BLOCK:
+ SF_SET_PROCESS(def_symbol_in_progress); /* Will need processing before writing */
+ /* intentional fallthrough */
+ case C_FCN:
+ S_SET_SEGMENT(def_symbol_in_progress, SEG_TEXT);
+
+ if (def_symbol_in_progress->sy_symbol.ost_entry.n_name[1] == 'b') { /* .bf */
+ if (function_lineoff < 0) {
+ fprintf(stderr, "`.bf' symbol without preceding function\n");
+ } /* missing function symbol */
+ SA_GET_SYM_LNNOPTR(def_symbol_in_progress) = function_lineoff;
+ SF_SET_PROCESS(def_symbol_in_progress); /* Will need relocating */
+ function_lineoff = -1;
+ }
+ break;
+
+#ifdef C_AUTOARG
+ case C_AUTOARG:
+#endif /* C_AUTOARG */
+ case C_AUTO:
+ case C_REG:
+ case C_MOS:
+ case C_MOE:
+ case C_MOU:
+ case C_ARG:
+ case C_REGPARM:
+ case C_FIELD:
+ case C_EOS:
+ SF_SET_DEBUG(def_symbol_in_progress);
+ S_SET_SEGMENT(def_symbol_in_progress, SEG_ABSOLUTE);
+ break;
+
+ case C_EXT:
+ case C_STAT:
+ case C_LABEL:
+ /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
+ break;
+
+ case C_USTATIC:
+ case C_EXTDEF:
+ case C_ULABEL:
+ as_warn("unexpected storage class %d", S_GET_STORAGE_CLASS(def_symbol_in_progress));
+ break;
+ } /* switch on storage class */
+
+ /* Now that we have built a debug symbol, try to
+ find if we should merge with an existing symbol
+ or not. If a symbol is C_EFCN or SEG_ABSOLUTE or
+ untagged SEG_DEBUG it never merges. */
+
+ /* Two cases for functions. Either debug followed
+ by definition or definition followed by debug.
+ For definition first, we will merge the debug
+ symbol into the definition. For debug first, the
+ lineno entry MUST point to the definition
+ function or else it will point off into space
+ when obj_crawl_symbol_chain() merges the debug
+ symbol into the real symbol. Therefor, let's
+ presume the debug symbol is a real function
+ reference. */
+
+ /* FIXME-SOON If for some reason the definition
+ label/symbol is never seen, this will probably
+ leave an undefined symbol at link time. */
+
+ if (S_GET_STORAGE_CLASS(def_symbol_in_progress) == C_EFCN
+ || (S_GET_SEGMENT(def_symbol_in_progress) == SEG_DEBUG
+ && !SF_GET_TAG(def_symbol_in_progress))
+ || S_GET_SEGMENT(def_symbol_in_progress) == SEG_ABSOLUTE
+ || (symbolP = symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP)) == NULL) {
+
+ symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ } else {
+ /* This symbol already exists, merge the
+ newly created symbol into the old one.
+ This is not mandatory. The linker can
+ handle duplicate symbols correctly. But I
+ guess that it save a *lot* of space if
+ the assembly file defines a lot of
+ symbols. [loic] */
+
+ /* The debug entry (def_symbol_in_progress)
+ is merged into the previous definition. */
+
+ c_symbol_merge(def_symbol_in_progress, symbolP);
+ /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
+ def_symbol_in_progress = symbolP;
+
+ if (SF_GET_FUNCTION(def_symbol_in_progress)
+ || SF_GET_TAG(def_symbol_in_progress)) {
+ /* For functions, and tags, the symbol *must* be where the debug symbol
+ appears. Move the existing symbol to the current place. */
+ /* If it already is at the end of the symbol list, do nothing */
+ if (def_symbol_in_progress != symbol_lastP) {
+ symbol_remove(def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
+ symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+ } /* if not already in place */
+ } /* if function */
+ } /* normal or mergable */
+
+ if (SF_GET_TAG(def_symbol_in_progress)
+ && symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP) == NULL) {
+ tag_insert(S_GET_NAME(def_symbol_in_progress), def_symbol_in_progress);
+ } /* If symbol is a {structure,union} tag, associate symbol to its name. */
+
+ if (SF_GET_FUNCTION(def_symbol_in_progress)) {
+ know(sizeof(def_symbol_in_progress) <= sizeof(long));
+ function_lineoff = c_line_new((long) def_symbol_in_progress, 0, &zero_address_frag);
+ SF_SET_PROCESS(def_symbol_in_progress);
+
+ if (symbolP == NULL) {
+ /* That is, if this is the first
+ time we've seen the function... */
+ symbol_table_insert(def_symbol_in_progress);
+ } /* definition follows debug */
+ } /* Create the line number entry pointing to the function being defined */
+
+ def_symbol_in_progress = NULL;
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_endef() */
+
+static void obj_coff_dim()
+{
+ register int dim_index;
+
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".dim pseudo-op used outside of .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+
+ for (dim_index = 0; dim_index < DIMNUM; dim_index++) {
+ SKIP_WHITESPACES();
+ SA_SET_SYM_DIMEN(def_symbol_in_progress, dim_index, get_absolute_expression());
+
+ switch (*input_line_pointer) {
+
+ case ',':
+ input_line_pointer++;
+ break;
+
+ default:
+ as_warn("badly formed .dim directive ignored");
+ /* intentional fallthrough */
+ case '\n':
+ case ';':
+ dim_index = DIMNUM;
+ break;
+ } /* switch on following character */
+ } /* for each dimension */
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_dim() */
+
+static void obj_coff_line() {
+ if (def_symbol_in_progress == NULL) {
+ obj_coff_ln();
+ return;
+ } /* if it looks like a stabs style line */
+
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+ SA_SET_SYM_LNNO(def_symbol_in_progress, get_absolute_expression());
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_line() */
+
+static void obj_coff_size() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".size pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+ SA_SET_SYM_SIZE(def_symbol_in_progress, get_absolute_expression());
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_size() */
+
+static void obj_coff_scl() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".scl pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_STORAGE_CLASS(def_symbol_in_progress, get_absolute_expression());
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_scl() */
+
+static void obj_coff_tag() {
+ char *symbol_name;
+ char name_end;
+
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".tag pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+ symbol_name = input_line_pointer;
+ name_end = get_symbol_end();
+
+ /* Assume that the symbol referred to by .tag is always defined. */
+ /* This was a bad assumption. I've added find_or_make. xoxorich. */
+ SA_SET_SYM_TAGNDX(def_symbol_in_progress, (long) tag_find_or_make(symbol_name));
+ if (SA_GET_SYM_TAGNDX(def_symbol_in_progress) == 0L) {
+ as_warn("tag not found for .tag %s", symbol_name);
+ } /* not defined */
+
+ SF_SET_TAGGED(def_symbol_in_progress);
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_tag() */
+
+static void obj_coff_type() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".type pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_DATA_TYPE(def_symbol_in_progress, get_absolute_expression());
+
+ if (ISFCN(S_GET_DATA_TYPE(def_symbol_in_progress)) &&
+ S_GET_STORAGE_CLASS(def_symbol_in_progress) != C_TPDEF) {
+ SF_SET_FUNCTION(def_symbol_in_progress);
+ } /* is a function */
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_type() */
+
+static void obj_coff_val() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".val pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ if (is_name_beginner(*input_line_pointer)) {
+ char *symbol_name = input_line_pointer;
+ char name_end = get_symbol_end();
+
+ if (!strcmp(symbol_name, ".")) {
+ def_symbol_in_progress->sy_frag = frag_now;
+ S_SET_VALUE(def_symbol_in_progress, obstack_next_free(&frags) - frag_now->fr_literal);
+ /* If the .val is != from the .def (e.g. statics) */
+ } else if (strcmp(S_GET_NAME(def_symbol_in_progress), symbol_name)) {
+ def_symbol_in_progress->sy_forward = symbol_find_or_make(symbol_name);
+
+ /* If the segment is undefined when the forward
+ reference is solved, then copy the segment id
+ from the forward symbol. */
+ SF_SET_GET_SEGMENT(def_symbol_in_progress);
+ }
+ /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
+ *input_line_pointer = name_end;
+ } else {
+ S_SET_VALUE(def_symbol_in_progress, get_absolute_expression());
+ } /* if symbol based */
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_val() */
+
+/*
+ * Maintain a list of the tagnames of the structres.
+ */
+
+static void tag_init() {
+ tag_hash = hash_new();
+ return ;
+} /* tag_init() */
+
+static void tag_insert(name, symbolP)
+char *name;
+symbolS *symbolP;
+{
+ register char * error_string;
+
+ if (*(error_string = hash_jam(tag_hash, name, (char *)symbolP))) {
+ as_fatal("Inserting \"%s\" into structure table failed: %s",
+ name, error_string);
+ }
+ return ;
+} /* tag_insert() */
+
+static symbolS *tag_find_or_make(name)
+char *name;
+{
+ symbolS *symbolP;
+
+ if ((symbolP = tag_find(name)) == NULL) {
+ symbolP = symbol_new(name,
+ SEG_UNKNOWN,
+ 0,
+ &zero_address_frag);
+
+ tag_insert(S_GET_NAME(symbolP), symbolP);
+ symbol_table_insert(symbolP);
+ } /* not found */
+
+ return(symbolP);
+} /* tag_find_or_make() */
+
+static symbolS *tag_find(name)
+char *name;
+{
+#ifdef STRIP_UNDERSCORE
+ if (*name == '_') name++;
+#endif /* STRIP_UNDERSCORE */
+ return((symbolS*)hash_find(tag_hash, name));
+} /* tag_find() */
+
+void obj_read_begin_hook() {
+ /* These had better be the same. Usually 18 bytes. */
+#ifndef BFD_HEADERS
+ know(sizeof(SYMENT) == sizeof(AUXENT));
+ know(SYMESZ == AUXESZ);
+#endif
+ tag_init();
+
+ return;
+} /* obj_read_begin_hook() */
+
+void obj_crawl_symbol_chain(headers)
+object_headers *headers;
+{
+ int symbol_number = 0;
+ lineno *lineP;
+ symbolS *last_functionP = NULL;
+ symbolS *last_tagP;
+ symbolS *symbolP;
+ symbolS *symbol_externP = NULL;
+ symbolS *symbol_extern_lastP = NULL;
+
+ /* Initialize the stack used to keep track of the matching .bb .be */
+ stack* block_stack = stack_init(512, sizeof(symbolS*));
+
+ /* JF deal with forward references first... */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+
+ if (symbolP->sy_forward) {
+ S_SET_VALUE(symbolP, (S_GET_VALUE(symbolP)
+ + S_GET_VALUE(symbolP->sy_forward)
+ + symbolP->sy_forward->sy_frag->fr_address));
+
+ if (
+#ifndef TE_I386AIX
+ SF_GET_GET_SEGMENT(symbolP)
+#else
+ SF_GET_GET_SEGMENT(symbolP)
+ && S_GET_SEGMENT(symbolP) == SEG_UNKNOWN
+#endif /* TE_I386AIX */
+ ) {
+ S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
+ } /* forward segment also */
+
+ symbolP->sy_forward=0;
+ } /* if it has a forward reference */
+ } /* walk the symbol chain */
+
+ tc_crawl_symbol_chain(headers);
+
+ /* The symbol list should be ordered according to the following sequence
+ * order :
+ * . .file symbol
+ * . debug entries for functions
+ * . fake symbols for .text .data and .bss
+ * . defined symbols
+ * . undefined symbols
+ * But this is not mandatory. The only important point is to put the
+ * undefined symbols at the end of the list.
+ */
+
+ if (symbol_rootP == NULL
+ || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
+ know(!previous_file_symbol);
+ c_dot_file_symbol("fake");
+ } /* Is there a .file symbol ? If not insert one at the beginning. */
+
+ /*
+ * Build up static symbols for .text, .data and .bss
+ */
+ dot_text_symbol = (symbolS*)
+ c_section_symbol(".text",
+ 0,
+ H_GET_TEXT_SIZE(headers),
+ 0/*text_relocation_number */,
+ 0/*text_lineno_number */);
+#ifdef TE_I386AIX
+ symbol_remove(dot_text_symbol, &symbol_rootP, &symbol_lastP);
+ symbol_append(dot_text_symbol, previous_file_symbol,
+ &symbol_rootP, &symbol_lastP);
+#endif /* TE_I386AIX */
+
+ dot_data_symbol = (symbolS*)
+ c_section_symbol(".data",
+ H_GET_TEXT_SIZE(headers),
+ H_GET_DATA_SIZE(headers),
+ 0/*data_relocation_number */,
+ 0); /* There are no data lineno entries */
+#ifdef TE_I386AIX
+ symbol_remove(dot_data_symbol, &symbol_rootP, &symbol_lastP);
+ symbol_append(dot_data_symbol, dot_text_symbol,
+ &symbol_rootP, &symbol_lastP);
+#endif /* TE_I386AIX */
+
+ dot_bss_symbol = (symbolS*)
+ c_section_symbol(".bss",
+ H_GET_TEXT_SIZE(headers) + H_GET_DATA_SIZE(headers),
+ H_GET_BSS_SIZE(headers),
+ 0, /* No relocation for a bss section. */
+ 0); /* There are no bss lineno entries */
+#ifdef TE_I386AIX
+ symbol_remove(dot_bss_symbol, &symbol_rootP, &symbol_lastP);
+ symbol_append(dot_bss_symbol, dot_data_symbol,
+ &symbol_rootP, &symbol_lastP);
+#endif /* TE_I386AIX */
+
+#if defined(DEBUG)
+ verify_symbol_chain(symbol_rootP, symbol_lastP);
+#endif /* DEBUG */
+
+ /* Three traversals of symbol chains here. The
+ first traversal yanks externals into a temporary
+ chain, removing the externals from the global
+ chain, numbers symbols, and does some other guck.
+ The second traversal is on the temporary chain of
+ externals and just appends them to the global
+ chain again, numbering them as we go. The third
+ traversal patches pointers to symbols (using sym
+ indexes). The last traversal was once done as
+ part of the first pass, but that fails when a
+ reference preceeds a definition as the definition
+ has no number at the time we process the
+ reference. */
+
+ /* Note that symbolP will be NULL at the end of a loop
+ if an external was at the beginning of the list (it
+ gets moved off the list). Hence the weird check in
+ the loop control.
+ */
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbolP ? symbol_next(symbolP) : symbol_rootP) {
+ if (!SF_GET_DEBUG(symbolP)) {
+ /* Debug symbols do not need all this rubbish */
+ symbolS* real_symbolP;
+
+ /* L* and C_EFCN symbols never merge. */
+ if (!SF_GET_LOCAL(symbolP)
+ && (real_symbolP = symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP))
+ && real_symbolP != symbolP) {
+ /* FIXME-SOON: where do dups come from? Maybe tag references before definitions? xoxorich. */
+ /* Move the debug data from the debug symbol to the
+ real symbol. Do NOT do the oposite (i.e. move from
+ real symbol to debug symbol and remove real symbol from the
+ list.) Because some pointers refer to the real symbol
+ whereas no pointers refer to the debug symbol. */
+ c_symbol_merge(symbolP, real_symbolP);
+ /* Replace the current symbol by the real one */
+ /* The symbols will never be the last or the first
+ because : 1st symbol is .file and 3 last symbols are
+ .text, .data, .bss */
+ symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+ symbolP = real_symbolP;
+ } /* if not local but dup'd */
+
+ if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_DATA)) {
+ S_SET_SEGMENT(symbolP, SEG_TEXT);
+ } /* push data into text */
+
+ S_SET_VALUE(symbolP, S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
+
+ if (!S_IS_DEFINED(symbolP) && !SF_GET_LOCAL(symbolP)) {
+ S_SET_EXTERNAL(symbolP);
+ } else if (S_GET_STORAGE_CLASS(symbolP) == C_NULL) {
+ if (S_GET_SEGMENT(symbolP) == SEG_TEXT){
+ S_SET_STORAGE_CLASS(symbolP, C_LABEL);
+ } else {
+ S_SET_STORAGE_CLASS(symbolP, C_STAT);
+ }
+ } /* no storage class yet */
+
+ /* Mainly to speed up if not -g */
+ if (SF_GET_PROCESS(symbolP)) {
+ /* Handle the nested blocks auxiliary info. */
+ if (S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
+ if (!strcmp(S_GET_NAME(symbolP), ".bb"))
+ stack_push(block_stack, (char *) &symbolP);
+ else { /* .eb */
+ register symbolS* begin_symbolP;
+ begin_symbolP = *(symbolS**)stack_pop(block_stack);
+ if (begin_symbolP == (symbolS*)0)
+ as_warn("mismatched .eb");
+ else
+ SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number+2);
+ }
+ }
+ /* If we are able to identify the type of a function, and we
+ are out of a function (last_functionP == 0) then, the
+ function symbol will be associated with an auxiliary
+ entry. */
+ if (last_functionP == (symbolS*)0 &&
+ SF_GET_FUNCTION(symbolP)) {
+ last_functionP = symbolP;
+
+ if (S_GET_NUMBER_AUXILIARY(symbolP) < 1) {
+ S_SET_NUMBER_AUXILIARY(symbolP, 1);
+ } /* make it at least 1 */
+
+ /* Clobber possible stale .dim information. */
+ memset(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
+ '\0', sizeof(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
+ }
+ /* The C_FCN doesn't need any additional information.
+ I don't even know if this is needed for sdb. But the
+ standard assembler generates it, so...
+ */
+ if (S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
+ if (last_functionP == (symbolS*)0)
+ as_fatal("C_EFCN symbol out of scope");
+ SA_SET_SYM_FSIZE(last_functionP,
+ (long)(S_GET_VALUE(symbolP) -
+ S_GET_VALUE(last_functionP)));
+ SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
+ last_functionP = (symbolS*)0;
+ }
+ }
+ } else if (SF_GET_TAG(symbolP)) {
+ /* First descriptor of a structure must point to
+ the first slot after the structure description. */
+ last_tagP = symbolP;
+
+ } else if (S_GET_STORAGE_CLASS(symbolP) == C_EOS) {
+ /* +2 take in account the current symbol */
+ SA_SET_SYM_ENDNDX(last_tagP, symbol_number + 2);
+ } else if (S_GET_STORAGE_CLASS(symbolP) == C_FILE) {
+ if (S_GET_VALUE(symbolP)) {
+ S_SET_VALUE((symbolS *) S_GET_VALUE(symbolP), symbol_number);
+ S_SET_VALUE(symbolP, 0);
+ } /* no one points at the first .file symbol */
+ } /* if debug or tag or eos or file */
+
+ /* We must put the external symbols apart. The loader
+ does not bomb if we do not. But the references in
+ the endndx field for a .bb symbol are not corrected
+ if an external symbol is removed between .bb and .be.
+ I.e in the following case :
+ [20] .bb endndx = 22
+ [21] foo external
+ [22] .be
+ ld will move the symbol 21 to the end of the list but
+ endndx will still be 22 instead of 21. */
+
+
+ if (SF_GET_LOCAL(symbolP)) {
+ /* remove C_EFCN and LOCAL (L...) symbols */
+ /* next pointer remains valid */
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+
+ } else if (
+#ifdef TE_I386AIX
+ S_GET_STORAGE_CLASS(symbolP) == C_EXT && !SF_GET_FUNCTION(symbolP)
+#else /* not TE_I386AIX */
+ !S_IS_DEFINED(symbolP) && !S_IS_DEBUG(symbolP) && !SF_GET_STATICS(symbolP)
+#endif /* not TE_I386AIX */
+ ) {
+ /* if external, Remove from the list */
+ symbolS *hold = symbol_previous(symbolP);
+
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_clear_list_pointers(symbolP);
+ symbol_append(symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
+ symbolP = hold;
+ } else {
+ if (SF_GET_STRING(symbolP)) {
+ symbolP->sy_name_offset = string_byte_count;
+ string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+ } else {
+ symbolP->sy_name_offset = 0;
+ } /* fix "long" names */
+
+ symbolP->sy_number = symbol_number;
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
+ } /* if local symbol */
+ } /* traverse the symbol list */
+
+ for (symbolP = symbol_externP; symbol_externP;) {
+ symbolS *tmp = symbol_externP;
+
+ /* append */
+ symbol_remove(tmp, &symbol_externP, &symbol_extern_lastP);
+ symbol_append(tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ /* and process */
+ if (SF_GET_STRING(tmp)) {
+ tmp->sy_name_offset = string_byte_count;
+ string_byte_count += strlen(S_GET_NAME(tmp)) + 1;
+ } else {
+ tmp->sy_name_offset = 0;
+ } /* fix "long" names */
+
+ tmp->sy_number = symbol_number;
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY(tmp);
+ } /* append the entire extern chain */
+
+ /* When a tag reference preceeds the tag definition,
+ the definition will not have a number at the time
+ we process the reference during the first
+ traversal. Thus, a second traversal. */
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ if (SF_GET_TAGGED(symbolP)) {
+ SA_SET_SYM_TAGNDX(symbolP, ((symbolS*) SA_GET_SYM_TAGNDX(symbolP))->sy_number);
+ } /* If the symbol has a tagndx entry, resolve it */
+ } /* second traversal */
+
+ know(symbol_externP == NULL);
+ know(symbol_extern_lastP == NULL);
+
+ /* FIXME-SOMEDAY I'm counting line no's here so we know what to put in the section
+ headers, and I'm resolving the addresses since I'm not sure how to
+ do it later. I am NOT resolving the linno's representing functions.
+ Their symbols need a fileptr pointing to this linno when emitted.
+ Thus, I resolve them on emit. xoxorich. */
+
+ for (lineP = lineno_rootP; lineP; lineP = lineP->next) {
+ if (lineP->line.l_lnno > 0) {
+ lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
+ } else {
+ ;
+ }
+ text_lineno_number++;
+ } /* for each line number */
+
+ H_SET_SYMBOL_TABLE_SIZE(headers, symbol_number);
+
+ return;
+} /* obj_crawl_symbol_chain() */
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+void obj_emit_strings(where)
+char **where;
+{
+ symbolS *symbolP;
+
+#ifdef CROSS_COMPILE
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ md_number_to_chars(*where, string_byte_count, sizeof(string_byte_count));
+ *where += sizeof(string_byte_count);
+#else /* CROSS_COMPILE */
+ append(where, (char *) &string_byte_count, (unsigned long) sizeof(string_byte_count));
+#endif /* CROSS_COMPILE */
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ if (SF_GET_STRING(symbolP)) {
+ append(where, S_GET_NAME(symbolP), (unsigned long)(strlen(S_GET_NAME(symbolP)) + 1));
+ } /* if it has a string */
+ } /* walk the symbol chain */
+
+ return;
+} /* obj_emit_strings() */
+
+void obj_pre_write_hook(headers)
+object_headers *headers;
+{
+ register int text_relocation_number = 0;
+ register int data_relocation_number = 0;
+ register fixS *fixP;
+
+ H_SET_MAGIC_NUMBER(headers, FILE_HEADER_MAGIC);
+ H_SET_ENTRY_POINT(headers, 0);
+
+ /* FIXME-SOMEDAY this should be done at
+ fixup_segment time but I'm going to wait until I
+ do multiple segments. xoxorich. */
+ /* Count the number of relocation entries for text and data */
+ for (fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
+ if (fixP->fx_addsy) {
+ ++text_relocation_number;
+#ifdef TC_I960
+ /* two relocs per callj under coff. */
+ if (fixP->fx_callj) {
+ ++text_relocation_number;
+ } /* if callj and not already fixed. */
+#endif /* TC_I960 */
+#ifdef TC_A29K
+ /* Count 2 for a constH */
+ if (fixP->fx_r_type == RELOC_CONSTH) {
+ ++text_relocation_number;
+ }
+#endif
+
+ } /* if not yet fixed */
+ } /* for each fix */
+
+ SA_SET_SCN_NRELOC(dot_text_symbol, text_relocation_number);
+ /* Assign the number of line number entries for the text section */
+ SA_SET_SCN_NLINNO(dot_text_symbol, text_lineno_number);
+ /* Assign the size of the section */
+ SA_SET_SCN_SCNLEN(dot_text_symbol, H_GET_TEXT_SIZE(headers));
+
+ for (fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
+ if (fixP->fx_addsy) {
+ ++data_relocation_number;
+ } /* if still relocatable */
+#ifdef TC_A29K
+ /* Count 2 for a constH */
+ if (fixP->fx_r_type == RELOC_CONSTH) {
+ ++data_relocation_number;
+ }
+#endif
+
+ } /* for each fix */
+
+
+ SA_SET_SCN_NRELOC(dot_data_symbol, data_relocation_number);
+ /* Assign the size of the section */
+ SA_SET_SCN_SCNLEN(dot_data_symbol, H_GET_DATA_SIZE(headers));
+
+ /* Assign the size of the section */
+ SA_SET_SCN_SCNLEN(dot_bss_symbol, H_GET_BSS_SIZE(headers));
+
+ /* pre write hook can add relocs (for 960 and 29k coff) so */
+ headers->relocation_size = text_relocation_number * RELSZ +
+ data_relocation_number *RELSZ;
+
+
+
+ /* Fill in extra coff fields */
+
+ /* Initialize general line number information. */
+ H_SET_LINENO_SIZE(headers, text_lineno_number * LINESZ);
+
+ /* filehdr */
+ H_SET_FILE_MAGIC_NUMBER(headers, FILE_HEADER_MAGIC);
+ H_SET_NUMBER_OF_SECTIONS(headers, 3); /* text+data+bss */
+#ifndef OBJ_COFF_OMIT_TIMESTAMP
+ H_SET_TIME_STAMP(headers, (long)time((long*)0));
+#else /* OBJ_COFF_OMIT_TIMESTAMP */
+ H_SET_TIME_STAMP(headers, 0);
+#endif /* OBJ_COFF_OMIT_TIMESTAMP */
+ H_SET_SYMBOL_TABLE_POINTER(headers, H_GET_SYMBOL_TABLE_FILE_OFFSET(headers));
+#if 0
+ printf("FILHSZ %x\n", FILHSZ);
+ printf("OBJ_COFF_AOUTHDRSZ %x\n", OBJ_COFF_AOUTHDRSZ);
+ printf("section headers %x\n", H_GET_NUMBER_OF_SECTIONS(headers) * SCNHSZ);
+ printf("get text size %x\n", H_GET_TEXT_SIZE(headers));
+ printf("get data size %x\n", H_GET_DATA_SIZE(headers));
+ printf("get relocation size %x\n", H_GET_RELOCATION_SIZE(headers));
+ printf("get lineno size %x\n", H_GET_LINENO_SIZE(headers));
+#endif
+ /* symbol table size allready set */
+ H_SET_SIZEOF_OPTIONAL_HEADER(headers, OBJ_COFF_AOUTHDRSZ);
+
+ /* do not added the F_RELFLG for the standard COFF.
+ * The AIX linker complain on file with relocation info striped flag.
+ */
+#ifdef KEEP_RELOC_INFO
+ H_SET_FLAGS(headers, (text_lineno_number == 0 ? F_LNNO : 0)
+ | BYTE_ORDERING);
+#else
+ H_SET_FLAGS(headers, (text_lineno_number == 0 ? F_LNNO : 0)
+ | ((text_relocation_number + data_relocation_number) ? 0 : F_RELFLG)
+ | BYTE_ORDERING);
+#endif
+ /* aouthdr */
+ /* magic number allready set */
+ H_SET_VERSION_STAMP(headers, 0);
+ /* Text, data, bss size; entry point; text_start and data_start are already set */
+
+ /* Build section headers */
+
+ c_section_header(&text_section_header,
+ ".text",
+ 0,
+ H_GET_TEXT_SIZE(headers),
+ H_GET_TEXT_FILE_OFFSET(headers),
+ (SA_GET_SCN_NRELOC(dot_text_symbol)
+ ? H_GET_RELOCATION_FILE_OFFSET(headers)
+ : 0),
+ (text_lineno_number
+ ? H_GET_LINENO_FILE_OFFSET(headers)
+ : 0),
+ SA_GET_SCN_NRELOC(dot_text_symbol),
+ text_lineno_number,
+ section_alignment[(int) SEG_TEXT]);
+
+ c_section_header(&data_section_header,
+ ".data",
+ H_GET_TEXT_SIZE(headers),
+ H_GET_DATA_SIZE(headers),
+ (H_GET_DATA_SIZE(headers)
+ ? H_GET_DATA_FILE_OFFSET(headers)
+ : 0),
+ (SA_GET_SCN_NRELOC(dot_data_symbol)
+ ? (H_GET_RELOCATION_FILE_OFFSET(headers)
+ + text_section_header.s_nreloc * RELSZ)
+ : 0),
+ 0, /* No line number information */
+ SA_GET_SCN_NRELOC(dot_data_symbol),
+ 0, /* No line number information */
+ section_alignment[(int) SEG_DATA]);
+
+ c_section_header(&bss_section_header,
+ ".bss",
+ H_GET_TEXT_SIZE(headers) + H_GET_DATA_SIZE(headers),
+ H_GET_BSS_SIZE(headers),
+ 0, /* No file offset */
+ 0, /* No relocation information */
+ 0, /* No line number information */
+ 0, /* No relocation information */
+ 0, /* No line number information */
+ section_alignment[(int) SEG_BSS]);
+
+ return;
+} /* obj_pre_write_hook() */
+
+/* This is a copy from aout. All I do is neglect to actually build the symbol. */
+
+static void obj_coff_stab(what)
+int what;
+{
+ char *string;
+ expressionS e;
+ int goof = 0; /* TRUE if we have aborted. */
+ int length;
+ int saved_type = 0;
+ long longint;
+ symbolS *symbolP = 0;
+
+ if (what == 's') {
+ string = demand_copy_C_string(&length);
+ SKIP_WHITESPACE();
+
+ if (*input_line_pointer == ',') {
+ input_line_pointer++;
+ } else {
+ as_bad("I need a comma after symbol's name");
+ goof = 1;
+ } /* better be a comma */
+ } /* skip the string */
+
+ /*
+ * Input_line_pointer->after ','. String->symbol name.
+ */
+ if (!goof) {
+ if (get_absolute_expression_and_terminator(&longint) != ',') {
+ as_bad("I want a comma after the n_type expression");
+ goof = 1;
+ input_line_pointer--; /* Backup over a non-',' char. */
+ } /* on error */
+ } /* no error */
+
+ if (!goof) {
+ if (get_absolute_expression_and_terminator(&longint) != ',') {
+ as_bad("I want a comma after the n_other expression");
+ goof = 1;
+ input_line_pointer--; /* Backup over a non-',' char. */
+ } /* on error */
+ } /* no error */
+
+ if (!goof) {
+ get_absolute_expression();
+
+ if (what == 's' || what == 'n') {
+ if (*input_line_pointer != ',') {
+ as_bad("I want a comma after the n_desc expression");
+ goof = 1;
+ } else {
+ input_line_pointer++;
+ } /* on goof */
+ } /* not stabd */
+ } /* no error */
+
+ expression(&e);
+
+ if (goof) {
+ ignore_rest_of_line();
+ } else {
+ demand_empty_rest_of_line();
+ } /* on error */
+} /* obj_coff_stab() */
+
+#ifdef DEBUG
+/* for debugging */
+char *s_get_name(s)
+symbolS *s;
+{
+ return((s == NULL) ? "(NULL)" : S_GET_NAME(s));
+} /* s_get_name() */
+
+void symbol_dump() {
+ symbolS *symbolP;
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ printf("%3ld: 0x%lx \"%s\" type = %ld, class = %d, segment = %d\n",
+ symbolP->sy_number,
+ (unsigned long) symbolP,
+ S_GET_NAME(symbolP),
+ (long) S_GET_DATA_TYPE(symbolP),
+ S_GET_STORAGE_CLASS(symbolP),
+ (int) S_GET_SEGMENT(symbolP));
+ } /* traverse symbols */
+
+ return;
+} /* symbol_dump() */
+#endif /* DEBUG */
+
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-coff.c */
diff --git a/gnu/usr.bin/as/config/obj-coff.h b/gnu/usr.bin/as/config/obj-coff.h
new file mode 100644
index 0000000..3f1f7ea
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-coff.h
@@ -0,0 +1,598 @@
+/* coff object file format
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define OBJ_COFF 1
+
+#include "targ-cpu.h"
+
+
+
+#ifdef BFD_HEADERS
+#ifdef TC_A29K
+#include "bfd.h"
+#include "coff/a29k.h"
+
+/* This internal_lineno crap is to stop namespace pollution from the bfd internal
+ coff headerfile. */
+
+#define internal_lineno bfd_internal_lineno
+#include "coff/internal.h"
+#undef internal_lineno
+/*
+ #undef RELOC
+ #undef SYMENT
+ #undef AUXENT
+ #undef LINENO
+ #undef FILHDR
+ #undef SCNHDR
+ #define RELOC struct internal_reloc
+ #define SYMENT struct internal_syment
+ #define AUXENT union internal_auxent
+ #define SCNHDR struct internal_scnhdr
+ #define LINENO struct bfd_internal_lineno
+ #define AOUTHDR struct internal_aouthdr
+ #define FILHDR struct internal_filehdr
+ #define AOUTHDRSZ sizeof(struct external_aouthdr)
+ */
+/*#define x_endndx x_endndx.l
+ #define x_tagndx x_tagndx.l*/
+#define TARGET_FORMAT "coff-a29k-big"
+extern bfd *stdoutput;
+
+#else /* not TC_A29K */
+# ifdef TC_I386
+# include "bfd.h"
+# include "coff/i386.h"
+# define internal_lineno bfd_internal_lineno
+# include "coff/internal.h"
+# undef internal_lineno
+# define TARGET_FORMAT "coff-i386"
+extern bfd *stdoutput;
+
+#else /* not TC_I386 */
+#error help me
+#endif /* not TC_I386 */
+
+#endif /* not TC_A29K */
+
+#else /* not BFD_HEADERS */
+
+#ifdef USE_NATIVE_HEADERS
+#include <filehdr.h>
+#include <aouthdr.h>
+#include <scnhdr.h>
+#include <storclass.h>
+#include <linenum.h>
+#include <syms.h>
+#include <reloc.h>
+#include <sys/types.h>
+#else /* not USE_NATIVE_HEADERS */
+#include "coff.h"
+#endif /* not USE_NATIVE_HEADERS */
+
+#endif /* not BFD_HEADERS */
+
+/* Define some processor dependent values according to the processor we are on. */
+#ifdef TC_M68K
+
+#define BYTE_ORDERING F_AR32W /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC MC68MAGIC /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_I386)
+
+#define BYTE_ORDERING F_AR32WR /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC I386MAGIC /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_I960)
+
+#define BYTE_ORDERING F_AR32WR /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC I960ROMAGIC /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_A29K)
+
+#define BYTE_ORDERING F_AR32W /* big endian. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC SIPFBOMAGIC
+#endif /* FILE_HEADER_MAGIC */
+
+#else
+you lose
+#endif
+
+#ifndef OBJ_COFF_MAX_AUXENTRIES
+#define OBJ_COFF_MAX_AUXENTRIES 1
+#endif /* OBJ_COFF_MAX_AUXENTRIES */
+
+ extern const short seg_N_TYPE[];
+extern const segT N_TYPE_seg[];
+
+#ifndef BFD_HEADERS
+
+/* Add these definitions to have a consistent convention for all the
+ types used in COFF format. */
+#define AOUTHDR struct aouthdr
+#define AOUTHDRSZ sizeof(AOUTHDR)
+#endif
+
+/* SYMBOL TABLE */
+
+/* targets may also set this */
+#ifndef SYMBOLS_NEED_BACKPOINTERS
+#define SYMBOLS_NEED_BACKPOINTERS 1
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+/* Symbol table entry data type */
+
+typedef struct {
+#ifdef BFD_HEADERS
+ struct internal_syment ost_entry; /* Basic symbol */
+ union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; /* Auxiliary entry. */
+#else
+ SYMENT ost_entry; /* Basic symbol */
+ AUXENT ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; /* Auxiliary entry. */
+#endif
+ unsigned int ost_flags; /* obj_coff internal use only flags */
+} obj_symbol_type;
+
+#define DO_NOT_STRIP 0
+#define DO_STRIP 1
+
+/* Symbol table macros and constants */
+
+/* Possible and usefull section number in symbol table
+ * The values of TEXT, DATA and BSS may not be portable.
+ */
+
+#define C_TEXT_SECTION ((short)1)
+#define C_DATA_SECTION ((short)2)
+#define C_BSS_SECTION ((short)3)
+#define C_ABS_SECTION N_ABS
+#define C_UNDEF_SECTION N_UNDEF
+#define C_DEBUG_SECTION N_DEBUG
+#define C_NTV_SECTION N_TV
+#define C_PTV_SECTION P_TV
+#define C_REGISTER_SECTION 4
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* Predicates */
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION)
+/* True if symbol has been defined, ie :
+ section > 0 (DATA, TEXT or BSS)
+ section == 0 and value > 0 (external bss symbol) */
+#define S_IS_DEFINED(s) ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION || \
+ ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION && \
+ (s)->sy_symbol.ost_entry.n_value > 0))
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name begin with ^A is a gas internal pseudo symbol */
+#define S_IS_LOCAL(s) (S_GET_NAME(s)[0] == '\001' || \
+ (s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION || \
+ (S_LOCAL_NAME(s) && !flagseen['L']))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value == 0)
+/*
+ * True if a symbol can be multiply defined (bss symbols have this def
+ * though it is bad practice)
+ */
+#define S_IS_COMMON(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value != 0)
+/* True if a symbol name is in the string table, i.e. its length is > 8. */
+#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0)
+
+/* Accessors */
+/* The name of the symbol */
+#define S_GET_NAME(s) ((char*)(s)->sy_symbol.ost_entry.n_offset)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.ost_entry.n_offset)
+/* The zeroes if symbol name is longer than 8 chars */
+#define S_GET_ZEROES(s) ((s)->sy_symbol.ost_entry.n_zeroes)
+/* The value of the symbol */
+#define S_GET_VALUE(s) ((unsigned) ((s)->sy_symbol.ost_entry.n_value))
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) (N_TYPE_seg[(s)->sy_symbol.ost_entry.n_scnum+4])
+/* The data type */
+#define S_GET_DATA_TYPE(s) ((s)->sy_symbol.ost_entry.n_type)
+/* The storage class */
+#define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass)
+/* The number of auxiliary entries */
+#define S_GET_NUMBER_AUXILIARY(s) ((s)->sy_symbol.ost_entry.n_numaux)
+
+/* Modifiers */
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v))
+/* Set the offset of the symbol */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.ost_entry.n_offset = (v))
+/* The zeroes if symbol name is longer than 8 chars */
+#define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v))
+/* Set the value of the symbol */
+#define S_SET_VALUE(s,v) ((s)->sy_symbol.ost_entry.n_value = (v))
+/* The numeric value of the segment */
+#define S_SET_SEGMENT(s,v) ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v))
+/* The data type */
+#define S_SET_DATA_TYPE(s,v) ((s)->sy_symbol.ost_entry.n_type = (v))
+/* The storage class */
+#define S_SET_STORAGE_CLASS(s,v) ((s)->sy_symbol.ost_entry.n_sclass = (v))
+/* The number of auxiliary entries */
+#define S_SET_NUMBER_AUXILIARY(s,v) ((s)->sy_symbol.ost_entry.n_numaux = (v))
+
+/* Additional modifiers */
+/* The symbol is external (does not mean undefined) */
+#define S_SET_EXTERNAL(s) { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); }
+
+/* Auxiliary entry macros. SA_ stands for symbol auxiliary */
+/* Omit the tv related fields */
+/* Accessors */
+#ifdef BFD_HEADERS
+#define SA_GET_SYM_TAGNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l)
+#else
+#define SA_GET_SYM_TAGNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx)
+#endif
+#define SA_GET_SYM_LNNO(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno)
+#define SA_GET_SYM_SIZE(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size)
+#define SA_GET_SYM_FSIZE(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize)
+#define SA_GET_SYM_LNNOPTR(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#ifdef BFD_HEADERS
+#define SA_GET_SYM_ENDNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l)
+#else
+#define SA_GET_SYM_ENDNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx)
+#endif
+#define SA_GET_SYM_DIMEN(s,i) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)])
+#define SA_GET_FILE_FNAME(s) ((s)->sy_symbol.ost_auxent[0].x_file.x_fname)
+#define SA_GET_SCN_SCNLEN(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen)
+#define SA_GET_SCN_NRELOC(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc)
+#define SA_GET_SCN_NLINNO(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno)
+
+/* Modifiers */
+#ifdef BFD_HEADERS
+#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l=(v))
+#else
+#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx=(v))
+#endif
+#define SA_SET_SYM_LNNO(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno=(v))
+#define SA_SET_SYM_SIZE(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size=(v))
+#define SA_SET_SYM_FSIZE(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize=(v))
+#define SA_SET_SYM_LNNOPTR(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr=(v))
+#ifdef BFD_HEADERS
+#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l=(v))
+#else
+#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx=(v))
+#endif
+#define SA_SET_SYM_DIMEN(s,i,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v))
+#define SA_SET_FILE_FNAME(s,v) strncpy((s)->sy_symbol.ost_auxent[0].x_file.x_fname,(v),FILNMLEN)
+#define SA_SET_SCN_SCNLEN(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen=(v))
+#define SA_SET_SCN_NRELOC(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc=(v))
+#define SA_SET_SCN_NLINNO(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno=(v))
+
+/*
+ * Internal use only definitions. SF_ stands for symbol flags.
+ *
+ * These values can be assigned to sy_symbol.ost_flags field of a symbolS.
+ *
+ * You'll break i960 if you shift the SYSPROC bits anywhere else. for
+ * more on the balname/callname hack, see tc-i960.h. b.out is done
+ * differently.
+ */
+
+#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */
+#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */
+#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */
+#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */
+#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */
+
+#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */
+
+#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */
+#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */
+#define SF_STRING (0x00004000) /* Symbol name length > 8 */
+#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */
+
+#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */
+
+#define SF_FUNCTION (0x00010000) /* The symbol is a function */
+#define SF_PROCESS (0x00020000) /* Process symbol before write */
+#define SF_TAGGED (0x00040000) /* Is associated with a tag */
+#define SF_TAG (0x00080000) /* Is a tag */
+#define SF_DEBUG (0x00100000) /* Is in debug or abs section */
+#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */
+/* All other bits are unused. */
+
+/* Accessors */
+#define SF_GET(s) ((s)->sy_symbol.ost_flags)
+#define SF_GET_NORMAL_FIELD(s) ((s)->sy_symbol.ost_flags & SF_NORMAL_MASK)
+#define SF_GET_DEBUG_FIELD(s) ((s)->sy_symbol.ost_flags & SF_DEBUG_MASK)
+#define SF_GET_FILE(s) ((s)->sy_symbol.ost_flags & SF_FILE)
+#define SF_GET_STATICS(s) ((s)->sy_symbol.ost_flags & SF_STATICS)
+#define SF_GET_DEFINED(s) ((s)->sy_symbol.ost_flags & SF_DEFINED)
+#define SF_GET_STRING(s) ((s)->sy_symbol.ost_flags & SF_STRING)
+#define SF_GET_LOCAL(s) ((s)->sy_symbol.ost_flags & SF_LOCAL)
+#define SF_GET_FUNCTION(s) ((s)->sy_symbol.ost_flags & SF_FUNCTION)
+#define SF_GET_PROCESS(s) ((s)->sy_symbol.ost_flags & SF_PROCESS)
+#define SF_GET_DEBUG(s) ((s)->sy_symbol.ost_flags & SF_DEBUG)
+#define SF_GET_TAGGED(s) ((s)->sy_symbol.ost_flags & SF_TAGGED)
+#define SF_GET_TAG(s) ((s)->sy_symbol.ost_flags & SF_TAG)
+#define SF_GET_GET_SEGMENT(s) ((s)->sy_symbol.ost_flags & SF_GET_SEGMENT)
+#define SF_GET_I960(s) ((s)->sy_symbol.ost_flags & SF_I960_MASK) /* used by i960 */
+#define SF_GET_BALNAME(s) ((s)->sy_symbol.ost_flags & SF_BALNAME) /* used by i960 */
+#define SF_GET_CALLNAME(s) ((s)->sy_symbol.ost_flags & SF_CALLNAME) /* used by i960 */
+#define SF_GET_IS_SYSPROC(s) ((s)->sy_symbol.ost_flags & SF_IS_SYSPROC) /* used by i960 */
+#define SF_GET_SYSPROC(s) ((s)->sy_symbol.ost_flags & SF_SYSPROC) /* used by i960 */
+
+/* Modifiers */
+#define SF_SET(s,v) ((s)->sy_symbol.ost_flags = (v))
+#define SF_SET_NORMAL_FIELD(s,v)((s)->sy_symbol.ost_flags |= ((v) & SF_NORMAL_MASK))
+#define SF_SET_DEBUG_FIELD(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_DEBUG_MASK))
+#define SF_SET_FILE(s) ((s)->sy_symbol.ost_flags |= SF_FILE)
+#define SF_SET_STATICS(s) ((s)->sy_symbol.ost_flags |= SF_STATICS)
+#define SF_SET_DEFINED(s) ((s)->sy_symbol.ost_flags |= SF_DEFINED)
+#define SF_SET_STRING(s) ((s)->sy_symbol.ost_flags |= SF_STRING)
+#define SF_SET_LOCAL(s) ((s)->sy_symbol.ost_flags |= SF_LOCAL)
+#define SF_CLEAR_LOCAL(s) ((s)->sy_symbol.ost_flags &= ~SF_LOCAL)
+#define SF_SET_FUNCTION(s) ((s)->sy_symbol.ost_flags |= SF_FUNCTION)
+#define SF_SET_PROCESS(s) ((s)->sy_symbol.ost_flags |= SF_PROCESS)
+#define SF_SET_DEBUG(s) ((s)->sy_symbol.ost_flags |= SF_DEBUG)
+#define SF_SET_TAGGED(s) ((s)->sy_symbol.ost_flags |= SF_TAGGED)
+#define SF_SET_TAG(s) ((s)->sy_symbol.ost_flags |= SF_TAG)
+#define SF_SET_GET_SEGMENT(s) ((s)->sy_symbol.ost_flags |= SF_GET_SEGMENT)
+#define SF_SET_I960(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_I960_MASK)) /* used by i960 */
+#define SF_SET_BALNAME(s) ((s)->sy_symbol.ost_flags |= SF_BALNAME) /* used by i960 */
+#define SF_SET_CALLNAME(s) ((s)->sy_symbol.ost_flags |= SF_CALLNAME) /* used by i960 */
+#define SF_SET_IS_SYSPROC(s) ((s)->sy_symbol.ost_flags |= SF_IS_SYSPROC) /* used by i960 */
+#define SF_SET_SYSPROC(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_SYSPROC)) /* used by i960 */
+
+/* File header macro and type definition */
+
+/*
+ * File position calculators. Beware to use them when all the
+ * appropriate fields are set in the header.
+ */
+
+#ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define OBJ_COFF_AOUTHDRSZ (0)
+#else
+#define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ)
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_FILE_SIZE(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \
+ H_GET_SYMBOL_TABLE_SIZE(h) + \
+ (h)->string_table_size)
+#define H_GET_TEXT_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)
+#define H_GET_DATA_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h))
+#define H_GET_BSS_FILE_OFFSET(h) 0
+#define H_GET_RELOCATION_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h))
+#define H_GET_LINENO_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h))
+#define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h))
+
+/* Accessors */
+/* aouthdr */
+#define H_GET_MAGIC_NUMBER(h) ((h)->aouthdr.magic)
+#define H_GET_VERSION_STAMP(h) ((h)->aouthdr.vstamp)
+#define H_GET_TEXT_SIZE(h) ((h)->aouthdr.tsize)
+#define H_GET_DATA_SIZE(h) ((h)->aouthdr.dsize)
+#define H_GET_BSS_SIZE(h) ((h)->aouthdr.bsize)
+#define H_GET_ENTRY_POINT(h) ((h)->aouthdr.entry)
+#define H_GET_TEXT_START(h) ((h)->aouthdr.text_start)
+#define H_GET_DATA_START(h) ((h)->aouthdr.data_start)
+/* filehdr */
+#define H_GET_FILE_MAGIC_NUMBER(h) ((h)->filehdr.f_magic)
+#define H_GET_NUMBER_OF_SECTIONS(h) ((h)->filehdr.f_nscns)
+#define H_GET_TIME_STAMP(h) ((h)->filehdr.f_timdat)
+#define H_GET_SYMBOL_TABLE_POINTER(h) ((h)->filehdr.f_symptr)
+#define H_GET_SYMBOL_COUNT(h) ((h)->filehdr.f_nsyms)
+#define H_GET_SYMBOL_TABLE_SIZE(h) (H_GET_SYMBOL_COUNT(h) * SYMESZ)
+#define H_GET_SIZEOF_OPTIONAL_HEADER(h) ((h)->filehdr.f_opthdr)
+#define H_GET_FLAGS(h) ((h)->filehdr.f_flags)
+/* Extra fields to achieve bsd a.out compatibility and for convenience */
+#define H_GET_RELOCATION_SIZE(h) ((h)->relocation_size)
+#define H_GET_STRING_SIZE(h) ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h) ((h)->lineno_size)
+
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \
+ + sizeof(AOUTHDR)\
+ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \
+ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_TEXT_RELOCATION_SIZE(h) (text_section_header.s_nreloc * RELSZ)
+#define H_GET_DATA_RELOCATION_SIZE(h) (data_section_header.s_nreloc * RELSZ)
+
+/* Modifiers */
+/* aouthdr */
+#define H_SET_MAGIC_NUMBER(h,v) ((h)->aouthdr.magic = (v))
+#define H_SET_VERSION_STAMP(h,v) ((h)->aouthdr.vstamp = (v))
+#define H_SET_TEXT_SIZE(h,v) ((h)->aouthdr.tsize = (v))
+#define H_SET_DATA_SIZE(h,v) ((h)->aouthdr.dsize = (v))
+#define H_SET_BSS_SIZE(h,v) ((h)->aouthdr.bsize = (v))
+#define H_SET_ENTRY_POINT(h,v) ((h)->aouthdr.entry = (v))
+#define H_SET_TEXT_START(h,v) ((h)->aouthdr.text_start = (v))
+#define H_SET_DATA_START(h,v) ((h)->aouthdr.data_start = (v))
+/* filehdr */
+#define H_SET_FILE_MAGIC_NUMBER(h,v) ((h)->filehdr.f_magic = (v))
+#define H_SET_NUMBER_OF_SECTIONS(h,v) ((h)->filehdr.f_nscns = (v))
+#define H_SET_TIME_STAMP(h,v) ((h)->filehdr.f_timdat = (v))
+#define H_SET_SYMBOL_TABLE_POINTER(h,v) ((h)->filehdr.f_symptr = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->filehdr.f_nsyms = (v))
+#define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v))
+#define H_SET_FLAGS(h,v) ((h)->filehdr.f_flags = (v))
+/* Extra fields to achieve bsd a.out compatibility and for convinience */
+#define H_SET_RELOCATION_SIZE(h,t,d) ((h)->relocation_size = (t)+(d))
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+#define H_SET_LINENO_SIZE(h,v) ((h)->lineno_size = (v))
+
+/* Segment flipping */
+#define segment_name(v) (seg_name[(int) (v)])
+
+typedef struct {
+#ifdef BFD_HEADERS
+ struct internal_aouthdr aouthdr; /* a.out header */
+ struct internal_filehdr filehdr; /* File header, not machine dep. */
+#else
+ AOUTHDR aouthdr; /* a.out header */
+ FILHDR filehdr; /* File header, not machine dep. */
+#endif
+ long string_table_size; /* names + '\0' + sizeof(int) */
+ long relocation_size; /* Cumulated size of relocation
+ information for all sections in
+ bytes. */
+ long lineno_size; /* Size of the line number information
+ table in bytes */
+} object_headers;
+
+/* -------------- Line number handling ------- */
+extern int text_lineno_number;
+
+/* line numbering stuff. */
+
+typedef struct internal_lineno {
+#ifdef BFD_HEADERS
+ struct bfd_internal_lineno line;
+#else
+ LINENO line; /* The lineno structure itself */
+#endif
+ char* frag; /* Frag to which the line number is related */
+ struct internal_lineno* next; /* Forward chain pointer */
+} lineno;
+
+extern lineno *lineno_lastP;
+extern lineno *lineno_rootP;
+#define OBJ_EMIT_LINENO(a, b, c) obj_emit_lineno((a),(b),(c))
+
+#if __STDC__ == 1
+void obj_emit_lineno(char **where, lineno *line, char *file_start);
+#else /* not __STDC__ */
+void obj_emit_lineno();
+#endif /* not __STDC__ */
+
+/* stack stuff */
+typedef struct {
+ unsigned long chunk_size;
+ unsigned long element_size;
+ unsigned long size;
+ char* data;
+ unsigned long pointer;
+} stack;
+
+#if __STDC__ == 1
+
+char *stack_pop(stack *st);
+char *stack_push(stack *st, char *element);
+char *stack_top(stack *st);
+stack *stack_init(unsigned long chunk_size, unsigned long element_size);
+void c_dot_file_symbol(char *filename);
+void obj_extra_stuff(object_headers *headers);
+void stack_delete(stack *st);
+
+#ifndef tc_headers_hook
+void tc_headers_hook(object_headers *headers);
+#endif /* tc_headers_hook */
+
+#ifndef tc_coff_symbol_emit_hook
+void tc_coff_symbol_emit_hook(); /* really tc_coff_symbol_emit_hook(symbolS *symbolP) */
+#endif /* tc_coff_symbol_emit_hook */
+
+void c_section_header(
+#ifdef BFD_HEADERS
+ struct internal_scnhdr *header,
+#else
+ SCNHDR *header,
+#endif
+
+ char *name,
+ long core_address,
+ long size,
+ long data_ptr,
+ long reloc_ptr,
+ long lineno_ptr,
+ long reloc_number,
+ long lineno_number,
+ long alignment);
+
+#else /* not __STDC__ */
+
+char *stack_pop();
+char *stack_push();
+char *stack_top();
+stack *stack_init();
+void c_dot_file_symbol();
+void c_section_header();
+void obj_extra_stuff();
+void stack_delete();
+void tc_headers_hook();
+void tc_coff_symbol_emit_hook();
+
+#endif /* not __STDC__ */
+
+
+/* sanity check */
+
+#ifdef TC_I960
+#ifndef C_LEAFSTAT
+hey! Where is the C_LEAFSTAT definition? i960-coff support is depending on it.
+#endif /* no C_LEAFSTAT */
+#endif /* TC_I960 */
+#ifdef BFD_HEADERS
+ extern struct internal_scnhdr data_section_header;
+extern struct internal_scnhdr text_section_header;
+#else
+extern SCNHDR data_section_header;
+extern SCNHDR text_section_header;
+#endif
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-coff.h */
diff --git a/gnu/usr.bin/as/config/obj-coffbfd.c b/gnu/usr.bin/as/config/obj-coffbfd.c
new file mode 100644
index 0000000..352893a
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-coffbfd.c
@@ -0,0 +1,2182 @@
+/* coff object file format with bfd
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+
+ How does this releate to the rest of GAS ?
+
+ Well, all the other files in gas are more or less a black box. It
+ takes care of opening files, parsing command lines, stripping blanks
+ etc etc. This module gets a chance to register what it wants to do by
+ saying that it is interested in various pseduo ops. The other big
+ change is write_object_file. This runs through all the data
+ structures that gas builds, and outputs the file in the format of our
+ choice.
+
+ Hacked for BFDness by steve chamberlain
+
+ This object module now supports the Hitachi H8/300 and the AMD 29k
+
+ sac@cygnus.com
+ */
+
+#include "as.h"
+#include "obstack.h"
+#include "subsegs.h"
+#include "frags.h"
+#include "../bfd/libbfd.h"
+
+
+/* This vector is used to turn an internal segment into a section #
+ suitable for insertion into a coff symbol table
+ */
+
+const short seg_N_TYPE[] = { /* in: segT out: N_TYPE bits */
+ C_ABS_SECTION,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ C_UNDEF_SECTION, /* SEG_UNKNOWN */
+ C_UNDEF_SECTION, /* SEG_ABSENT */
+ C_UNDEF_SECTION, /* SEG_PASS1 */
+ C_UNDEF_SECTION, /* SEG_GOOF */
+ C_UNDEF_SECTION, /* SEG_BIG */
+ C_UNDEF_SECTION, /* SEG_DIFFERENCE */
+ C_DEBUG_SECTION, /* SEG_DEBUG */
+ C_NTV_SECTION, /* SEG_NTV */
+ C_PTV_SECTION, /* SEG_PTV */
+ C_REGISTER_SECTION, /* SEG_REGISTER */
+};
+
+
+int function_lineoff = -1; /* Offset in line#s where the last function
+ started (the odd entry for line #0) */
+
+int our_lineno_number = 0; /* we use this to build pointers from .bf's
+ into the linetable. It should match
+ exactly the values that are later
+ assigned in text_lineno_number by
+ write.c. */
+
+int text_lineno_number = 0;
+
+/* Add 4 to the real value to get the index and compensate the
+ negatives. This vector is used by S_GET_SEGMENT to turn a coff
+ section number into a segment number
+ */
+static symbolS *previous_file_symbol = NULL;
+void c_symbol_merge();
+static int line_base;
+
+symbolS *c_section_symbol();
+bfd *abfd;
+void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
+ bfd *abfd));
+
+static void EXFUN(fixup_segment,(fixS * fixP,
+ segT this_segment_type));
+
+static void EXFUN(fill_section,(bfd *abfd ,
+ struct internal_filehdr *f, unsigned
+ long *));
+
+
+char *EXFUN(s_get_name,(symbolS *s));
+static symbolS *EXFUN(tag_find_or_make,(char *name));
+static symbolS* EXFUN(tag_find,(char *name));
+
+
+static int
+ EXFUN(c_line_new,(
+ symbolS *symbol,
+ long paddr,
+ unsigned short line_number,
+ fragS* frag));
+
+
+static void EXFUN(w_symbols,
+ (bfd *abfd ,
+ char *where ,
+ symbolS *symbol_rootP));
+
+
+
+static void EXFUN( obj_coff_def,(int what));
+static void EXFUN( obj_coff_lcomm,(void));
+static void EXFUN( obj_coff_dim,(void));
+static void EXFUN( obj_coff_text,(void));
+static void EXFUN( obj_coff_data,(void));
+static void EXFUN( obj_coff_endef,(void));
+static void EXFUN( obj_coff_line,(void));
+static void EXFUN( obj_coff_ln,(void));
+static void EXFUN( obj_coff_scl,(void));
+static void EXFUN( obj_coff_size,(void));
+static void EXFUN( obj_coff_tag,(void));
+static void EXFUN( obj_coff_type,(void));
+static void EXFUN( obj_coff_val,(void));
+static void EXFUN( obj_coff_section,(void));
+static void EXFUN( tag_init,(void));
+static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
+
+
+static struct hash_control *tag_hash;
+static symbolS *def_symbol_in_progress = NULL;
+
+const pseudo_typeS obj_pseudo_table[] = {
+ { "def", obj_coff_def, 0 },
+ { "dim", obj_coff_dim, 0 },
+ { "endef", obj_coff_endef, 0 },
+ { "line", obj_coff_line, 0 },
+ { "ln", obj_coff_ln, 0 },
+ { "scl", obj_coff_scl, 0 },
+ { "size", obj_coff_size, 0 },
+ { "tag", obj_coff_tag, 0 },
+ { "type", obj_coff_type, 0 },
+ { "val", obj_coff_val, 0 },
+ { "section", obj_coff_section, 0 },
+ { "text", obj_coff_text, 0 },
+ { "data", obj_coff_data, 0 },
+ /* we don't yet handle this. */
+ { "ident", s_ignore, 0 },
+ { "ABORT", s_abort, 0 },
+ { "lcomm", obj_coff_lcomm, 0},
+ { NULL} /* end sentinel */
+}; /* obj_pseudo_table */
+
+
+
+/* Section stuff
+
+ We allow more than just the standard 3 sections, infact, we allow
+ 10 sections, (though the usual three have to be there).
+
+ This structure performs the mappings for us:
+
+ */
+
+/* OBS stuff
+ static struct internal_scnhdr bss_section_header;
+ struct internal_scnhdr data_section_header;
+ struct internal_scnhdr text_section_header;
+
+ const segT N_TYPE_seg[32] =
+ {
+
+ };
+
+ */
+
+#define N_SEG 32
+typedef struct
+{
+ segT seg_t;
+ int i;
+} seg_info_type;
+
+seg_info_type seg_info_off_by_4[N_SEG] =
+{
+ {SEG_PTV, },
+ {SEG_NTV, },
+ {SEG_DEBUG, },
+ {SEG_ABSOLUTE, },
+ {SEG_UNKNOWN, },
+ {SEG_E0},
+ {SEG_E1},
+ {SEG_E2},
+ {SEG_E3},
+ {SEG_E4},
+ {SEG_E5},
+ {SEG_E6},
+ {SEG_E7},
+ {SEG_E8},
+ {SEG_E9},
+ {15},
+ {16},
+ {17},
+ {18},
+ {19},
+ {20},
+ {0},
+ {0},
+ {0},
+ {SEG_REGISTER},0,0,0,0};
+
+#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
+#define SEG_INFO_FROM_SEG_NUMBER(x) (seg_info_off_by_4[(x)])
+
+
+relax_addressT
+ DEFUN(relax_align,(address, alignment),
+ register relax_addressT address AND
+ register long alignment )
+{
+ relax_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~ ( (~0) << alignment );
+ new_address = (address + mask) & (~ mask);
+ return (new_address - address);
+} /* relax_align() */
+
+
+segT
+ DEFUN(s_get_segment,(x) ,
+ symbolS* x)
+{
+ return SEG_INFO_FROM_SECTION_NUMBER(x->sy_symbol.ost_entry.n_scnum).seg_t;
+}
+
+
+
+/* calculate the size of the frag chain and fill in the section header
+ to contain all of it, also fill in the addr of the sections */
+static unsigned int DEFUN(size_section,(abfd, idx),
+ bfd *abfd AND
+ unsigned int idx)
+{
+
+ unsigned int size = 0;
+ fragS *frag = segment_info[idx].frchainP->frch_root;
+ while (frag) {
+ if (frag->fr_address != size) {
+ printf("Out of step\n");
+ size = frag->fr_address;
+ }
+ size += frag->fr_fix;
+ switch (frag->fr_type) {
+ case rs_fill:
+ case rs_org:
+ size += frag->fr_offset * frag->fr_var;
+ break;
+ case rs_align:
+ size += relax_align(size, frag->fr_offset);
+ }
+ frag = frag->fr_next;
+ }
+ segment_info[idx].scnhdr.s_size = size;
+ return size;
+}
+
+
+static unsigned int DEFUN(count_entries_in_chain,(idx),
+ unsigned int idx)
+{
+ unsigned int nrelocs;
+ fixS *fixup_ptr;
+
+ /* Count the relocations */
+ fixup_ptr = segment_info[idx].fix_root;
+ nrelocs = 0;
+ while (fixup_ptr != (fixS *)NULL)
+ {
+ if (TC_COUNT_RELOC(fixup_ptr))
+ {
+
+#ifdef TC_A29K
+
+ if (fixup_ptr->fx_r_type == RELOC_CONSTH)
+ nrelocs+=2;
+ else
+ nrelocs++;
+#else
+ nrelocs++;
+#endif
+ }
+
+ fixup_ptr = fixup_ptr->fx_next;
+ }
+ return nrelocs;
+}
+
+/* output all the relocations for a section */
+void DEFUN(do_relocs_for,(abfd, file_cursor),
+ bfd *abfd AND
+ unsigned long *file_cursor)
+{
+ unsigned int nrelocs;
+ unsigned int idx;
+
+ for (idx = SEG_E0; idx < SEG_E9; idx++)
+ {
+ if (segment_info[idx].scnhdr.s_name[0])
+ {
+
+ struct external_reloc *ext_ptr;
+ struct external_reloc *external_reloc_vec;
+ unsigned int external_reloc_size;
+ unsigned int count = 0;
+ unsigned int base = segment_info[idx].scnhdr.s_paddr;
+ fixS * fix_ptr = segment_info[idx].fix_root;
+ nrelocs = count_entries_in_chain(idx);
+ external_reloc_size = nrelocs * RELSZ;
+ external_reloc_vec =
+ (struct external_reloc*)malloc(external_reloc_size);
+
+
+
+ ext_ptr = external_reloc_vec;
+
+ /* Fill in the internal coff style reloc struct from the
+ internal fix list */
+ while (fix_ptr)
+ {
+ symbolS *symbol_ptr;
+ struct internal_reloc intr;
+
+ /* Only output some of the relocations */
+ if (TC_COUNT_RELOC(fix_ptr))
+ {
+#ifdef TC_RELOC_MANGLE
+ TC_RELOC_MANGLE(fix_ptr, &intr, base);
+
+#else
+ symbolS *dot;
+ symbol_ptr = fix_ptr->fx_addsy;
+
+ intr.r_type = TC_COFF_FIX2RTYPE(fix_ptr);
+ intr.r_vaddr =
+ base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where ;
+
+ intr.r_offset = fix_ptr->fx_offset;
+
+ intr.r_offset = 0;
+
+ /* Turn the segment of the symbol into an offset
+ */
+ if (symbol_ptr)
+ {
+ dot = segment_info[S_GET_SEGMENT(symbol_ptr)].dot;
+ if (dot)
+ {
+ intr.r_symndx = dot->sy_number;
+ }
+ else
+ {
+ intr.r_symndx = symbol_ptr->sy_number;
+ }
+
+ }
+ else
+ {
+ intr.r_symndx = -1;
+
+
+ }
+#endif
+
+ (void)bfd_coff_swap_reloc_out(abfd, &intr, ext_ptr);
+ ext_ptr++;
+
+#if defined(TC_A29K)
+ /* The 29k has a special kludge for the high 16 bit reloc.
+ Two relocations are emmited, R_IHIHALF, and
+ R_IHCONST. The second one doesn't contain a symbol,
+ but uses the value for offset */
+
+ if (intr.r_type == R_IHIHALF)
+ {
+ /* now emit the second bit */
+ intr.r_type = R_IHCONST;
+ intr.r_symndx = fix_ptr->fx_addnumber;
+ (void)bfd_coff_swap_reloc_out(abfd,&intr,ext_ptr);
+ ext_ptr++;
+ }
+#endif
+ }
+
+ fix_ptr = fix_ptr->fx_next;
+ }
+
+ /* Write out the reloc table */
+ segment_info[idx].scnhdr.s_relptr = *file_cursor;
+ segment_info[idx].scnhdr.s_nreloc = nrelocs;
+ bfd_write((PTR)external_reloc_vec, 1, external_reloc_size, abfd);
+ *file_cursor += external_reloc_size;
+ free( external_reloc_vec);
+ }
+ }
+}
+
+
+/* run through a frag chain and write out the data to go with it, fill
+ in the scnhdrs with the info on the file postions
+ */
+static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
+ bfd *abfd AND
+ struct internal_filehdr *filehdr AND
+ unsigned long *file_cursor)
+{
+
+ unsigned int i;
+ unsigned int paddr = 0;
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ unsigned int offset = 0;
+
+ struct internal_scnhdr *s = &( segment_info[i].scnhdr);
+
+ if (s->s_name[0])
+ {
+ fragS *frag = segment_info[i].frchainP->frch_root;
+ char *buffer = malloc(s->s_size);
+ s->s_scnptr = *file_cursor;
+ s->s_paddr = paddr;
+ s->s_vaddr = paddr;
+
+ s->s_flags = STYP_REG;
+ if (strcmp(s->s_name,".text") == 0)
+ s->s_flags |= STYP_TEXT;
+ else if (strcmp(s->s_name,".data") == 0)
+ s->s_flags |= STYP_DATA;
+ else if (strcmp(s->s_name,".bss") == 0)
+ s->s_flags |= STYP_BSS | STYP_NOLOAD;
+
+ while (frag) {
+ unsigned int fill_size;
+ switch (frag->fr_type) {
+
+ case rs_fill:
+ case rs_align:
+ case rs_org:
+ if (frag->fr_fix)
+ {
+ memcpy(buffer + frag->fr_address,
+ frag->fr_literal,
+ frag->fr_fix);
+ offset += frag->fr_fix;
+ }
+
+ fill_size = frag->fr_var;
+ if (fill_size)
+ {
+ unsigned int count ;
+ unsigned int off = frag->fr_fix;
+ for (count = frag->fr_offset; count; count--)
+ {
+ memcpy(buffer + frag->fr_address + off,
+ frag->fr_literal + frag->fr_fix,
+ fill_size);
+ off += fill_size;
+ offset += fill_size;
+
+ }
+
+ }
+ break;
+ default:
+ abort();
+ }
+ frag = frag->fr_next;
+ }
+
+
+ bfd_write(buffer, s->s_size,1,abfd);
+ free(buffer);
+
+ *file_cursor += s->s_size;
+ paddr += s->s_size;
+ }
+ }
+
+}
+
+
+
+/* Coff file generation & utilities */
+
+
+static void
+ DEFUN(coff_header_append,(abfd, filehdr, aouthdr),
+ bfd *abfd AND
+ struct internal_filehdr *filehdr AND
+ struct internal_aouthdr *aouthdr)
+{
+ unsigned int i;
+ char buffer[1000];
+ char buffero[1000];
+
+ bfd_seek(abfd, 0, 0);
+#if 0
+ filehdr.f_opthdr = bfd_coff_swap_aouthdr_out(abfd, aouthdr,
+ buffero);
+#else
+ filehdr->f_opthdr = 0;
+#endif
+ i = bfd_coff_swap_filehdr_out(abfd, filehdr, buffer);
+
+ bfd_write(buffer, i ,1, abfd);
+ bfd_write(buffero, filehdr->f_opthdr, 1, abfd);
+
+ for (i = SEG_E0; i < SEG_E9; i++)
+ {
+ if (segment_info[i].scnhdr.s_name[0])
+ {
+ unsigned int size =
+ bfd_coff_swap_scnhdr_out(abfd,
+ &(segment_info[i].scnhdr),
+ buffer);
+ bfd_write(buffer, size, 1, abfd);
+ }
+ }
+}
+
+
+char *
+ DEFUN(symbol_to_chars,(abfd, where, symbolP),
+ bfd*abfd AND
+ char *where AND
+ symbolS *symbolP)
+{
+ unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
+ unsigned int i;
+
+ /* Turn any symbols with register attributes into abs symbols */
+ if (S_GET_SEGMENT(symbolP) == SEG_REGISTER)
+ {
+ S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
+ }
+ /* At the same time, relocate all symbols to their output value */
+
+ S_SET_VALUE(symbolP,
+ segment_info[S_GET_SEGMENT(symbolP)].scnhdr.s_paddr
+ + S_GET_VALUE(symbolP));
+
+ where += bfd_coff_swap_sym_out(abfd, &symbolP->sy_symbol.ost_entry,
+ where);
+
+ for (i = 0; i < numaux; i++)
+ {
+ where += bfd_coff_swap_aux_out(abfd,
+ &symbolP->sy_symbol.ost_auxent[i],
+ S_GET_DATA_TYPE(symbolP),
+ S_GET_STORAGE_CLASS(symbolP),
+ where);
+ }
+ return where;
+
+}
+
+
+
+
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+ char underscore = 0; /* Symbol has leading _ */
+
+ /* Effective symbol */
+ /* Store the pointer in the offset. */
+ S_SET_ZEROES(symbolP, 0L);
+ S_SET_DATA_TYPE(symbolP, T_NULL);
+ S_SET_STORAGE_CLASS(symbolP, 0);
+ S_SET_NUMBER_AUXILIARY(symbolP, 0);
+ /* Additional information */
+ symbolP->sy_symbol.ost_flags = 0;
+ /* Auxiliary entries */
+ memset((char*) &symbolP->sy_symbol.ost_auxent[0], '\0', AUXESZ);
+
+#ifdef STRIP_UNDERSCORE
+ /* Remove leading underscore at the beginning of the symbol.
+ * This is to be compatible with the standard librairies.
+ */
+ if (*S_GET_NAME(symbolP) == '_') {
+ underscore = 1;
+ S_SET_NAME(symbolP, S_GET_NAME(symbolP) + 1);
+ } /* strip underscore */
+#endif /* STRIP_UNDERSCORE */
+
+ if (S_IS_STRING(symbolP))
+ SF_SET_STRING(symbolP);
+ if (!underscore && S_IS_LOCAL(symbolP))
+ SF_SET_LOCAL(symbolP);
+
+ return;
+} /* obj_symbol_new_hook() */
+
+/* stack stuff */
+stack* stack_init(chunk_size, element_size)
+unsigned long chunk_size;
+unsigned long element_size;
+{
+ stack* st;
+
+ if ((st = (stack*)malloc(sizeof(stack))) == (stack*)0)
+ return (stack*)0;
+ if ((st->data = malloc(chunk_size)) == (char*)0) {
+ free(st);
+ return (stack*)0;
+ }
+ st->pointer = 0;
+ st->size = chunk_size;
+ st->chunk_size = chunk_size;
+ st->element_size = element_size;
+ return st;
+} /* stack_init() */
+
+void stack_delete(st)
+stack* st;
+{
+ free(st->data);
+ free(st);
+}
+
+char *stack_push(st, element)
+stack *st;
+char *element;
+{
+ if (st->pointer + st->element_size >= st->size) {
+ st->size += st->chunk_size;
+ if ((st->data = xrealloc(st->data, st->size)) == (char*)0)
+ return (char*)0;
+ }
+ memcpy(st->data + st->pointer, element, st->element_size);
+ st->pointer += st->element_size;
+ return st->data + st->pointer;
+} /* stack_push() */
+
+char* stack_pop(st)
+stack* st;
+{
+ if ((st->pointer -= st->element_size) < 0) {
+ st->pointer = 0;
+ return (char*)0;
+ }
+
+ return st->data + st->pointer;
+}
+
+char* stack_top(st)
+stack* st;
+{
+ return st->data + st->pointer - st->element_size;
+}
+
+
+/*
+ * Handle .ln directives.
+ */
+
+static void obj_coff_ln()
+{
+ int l;
+
+ if (def_symbol_in_progress != NULL) {
+ as_warn(".ln pseudo-op inside .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* wrong context */
+
+ c_line_new(0,
+ obstack_next_free(&frags) - frag_now->fr_literal,
+ l = get_absolute_expression(),
+ frag_now);
+#ifndef NO_LISTING
+ {
+ extern int listing;
+
+ if (listing)
+ {
+ listing_source_line(l + line_base - 1);
+ }
+
+ }
+#endif
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_line() */
+
+/*
+ * def()
+ *
+ * Handle .def directives.
+ *
+ * One might ask : why can't we symbol_new if the symbol does not
+ * already exist and fill it with debug information. Because of
+ * the C_EFCN special symbol. It would clobber the value of the
+ * function symbol before we have a chance to notice that it is
+ * a C_EFCN. And a second reason is that the code is more clear this
+ * way. (at least I think it is :-).
+ *
+ */
+
+#define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
+#define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
+ *input_line_pointer == '\t') \
+ input_line_pointer++;
+
+static void
+ DEFUN(obj_coff_def,(what),
+ int what)
+{
+ char name_end; /* Char after the end of name */
+ char *symbol_name; /* Name of the debug symbol */
+ char *symbol_name_copy; /* Temporary copy of the name */
+ unsigned int symbol_name_length;
+ /*$char* directiveP;$ */ /* Name of the pseudo opcode */
+ /*$char directive[MAX_DIRECTIVE];$ */ /* Backup of the directive */
+ /*$char end = 0;$ */ /* If 1, stop parsing */
+
+ if (def_symbol_in_progress != NULL) {
+ as_warn(".def pseudo-op used inside of .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ SKIP_WHITESPACES();
+
+ def_symbol_in_progress = (symbolS *) obstack_alloc(&notes, sizeof(*def_symbol_in_progress));
+ memset(def_symbol_in_progress, '\0', sizeof(*def_symbol_in_progress));
+
+ symbol_name = input_line_pointer;
+ name_end = get_symbol_end();
+ symbol_name_length = strlen(symbol_name);
+ symbol_name_copy = xmalloc(symbol_name_length + 1);
+ strcpy(symbol_name_copy, symbol_name);
+
+ /* Initialize the new symbol */
+#ifdef STRIP_UNDERSCORE
+ S_SET_NAME(def_symbol_in_progress, (*symbol_name_copy == '_'
+ ? symbol_name_copy + 1
+ : symbol_name_copy));
+#else /* STRIP_UNDERSCORE */
+ S_SET_NAME(def_symbol_in_progress, symbol_name_copy);
+#endif /* STRIP_UNDERSCORE */
+ /* free(symbol_name_copy); */
+ def_symbol_in_progress->sy_name_offset = ~0;
+ def_symbol_in_progress->sy_number = ~0;
+ def_symbol_in_progress->sy_frag = &zero_address_frag;
+
+ if (S_IS_STRING(def_symbol_in_progress)) {
+ SF_SET_STRING(def_symbol_in_progress);
+ } /* "long" name */
+
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_def() */
+
+unsigned int dim_index;
+static void
+ DEFUN_VOID(obj_coff_endef)
+{
+ symbolS *symbolP = 0;
+ /* DIM BUG FIX sac@cygnus.com */
+ dim_index =0;
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".endef pseudo-op used outside of .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ /* Set the section number according to storage class. */
+ switch (S_GET_STORAGE_CLASS(def_symbol_in_progress)) {
+ case C_STRTAG:
+ case C_ENTAG:
+ case C_UNTAG:
+ SF_SET_TAG(def_symbol_in_progress);
+ /* intentional fallthrough */
+ case C_FILE:
+ case C_TPDEF:
+ SF_SET_DEBUG(def_symbol_in_progress);
+ S_SET_SEGMENT(def_symbol_in_progress, SEG_DEBUG);
+ break;
+
+ case C_EFCN:
+ SF_SET_LOCAL(def_symbol_in_progress); /* Do not emit this symbol. */
+ /* intentional fallthrough */
+ case C_BLOCK:
+ SF_SET_PROCESS(def_symbol_in_progress); /* Will need processing before writing */
+ /* intentional fallthrough */
+ case C_FCN:
+ S_SET_SEGMENT(def_symbol_in_progress, SEG_E0);
+
+ if (def_symbol_in_progress->sy_symbol.ost_entry.n_name[1] == 'b') { /* .bf */
+ if (function_lineoff < 0) {
+ fprintf(stderr, "`.bf' symbol without preceding function\n");
+ } /* missing function symbol */
+ SA_GET_SYM_LNNOPTR(def_symbol_in_progress) = function_lineoff;
+ SF_SET_PROCESS(def_symbol_in_progress); /* Will need relocating */
+ function_lineoff = -1;
+ }
+ break;
+
+#ifdef C_AUTOARG
+ case C_AUTOARG:
+#endif /* C_AUTOARG */
+ case C_AUTO:
+ case C_REG:
+ case C_MOS:
+ case C_MOE:
+ case C_MOU:
+ case C_ARG:
+ case C_REGPARM:
+ case C_FIELD:
+ case C_EOS:
+ SF_SET_DEBUG(def_symbol_in_progress);
+ S_SET_SEGMENT(def_symbol_in_progress, SEG_ABSOLUTE);
+ break;
+
+ case C_EXT:
+ case C_STAT:
+ case C_LABEL:
+ /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
+ break;
+
+ case C_USTATIC:
+ case C_EXTDEF:
+ case C_ULABEL:
+ as_warn("unexpected storage class %d", S_GET_STORAGE_CLASS(def_symbol_in_progress));
+ break;
+ } /* switch on storage class */
+
+ /* Now that we have built a debug symbol, try to
+ find if we should merge with an existing symbol
+ or not. If a symbol is C_EFCN or SEG_ABSOLUTE or
+ untagged SEG_DEBUG it never merges. */
+
+ /* Two cases for functions. Either debug followed
+ by definition or definition followed by debug.
+ For definition first, we will merge the debug
+ symbol into the definition. For debug first, the
+ lineno entry MUST point to the definition
+ function or else it will point off into space
+ when crawl_symbols() merges the debug
+ symbol into the real symbol. Therefor, let's
+ presume the debug symbol is a real function
+ reference. */
+
+ /* FIXME-SOON If for some reason the definition
+ label/symbol is never seen, this will probably
+ leave an undefined symbol at link time. */
+
+ if (S_GET_STORAGE_CLASS(def_symbol_in_progress) == C_EFCN
+ || (S_GET_SEGMENT(def_symbol_in_progress) == SEG_DEBUG
+ && !SF_GET_TAG(def_symbol_in_progress))
+ || S_GET_SEGMENT(def_symbol_in_progress) == SEG_ABSOLUTE
+ || (symbolP = symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP)) == NULL) {
+
+ symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ } else {
+ /* This symbol already exists, merge the
+ newly created symbol into the old one.
+ This is not mandatory. The linker can
+ handle duplicate symbols correctly. But I
+ guess that it save a *lot* of space if
+ the assembly file defines a lot of
+ symbols. [loic] */
+
+ /* The debug entry (def_symbol_in_progress)
+ is merged into the previous definition. */
+
+ c_symbol_merge(def_symbol_in_progress, symbolP);
+ /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
+ def_symbol_in_progress = symbolP;
+
+ if (SF_GET_FUNCTION(def_symbol_in_progress)
+ || SF_GET_TAG(def_symbol_in_progress)) {
+ /* For functions, and tags, the symbol *must* be where the debug symbol
+ appears. Move the existing symbol to the current place. */
+ /* If it already is at the end of the symbol list, do nothing */
+ if (def_symbol_in_progress != symbol_lastP) {
+ symbol_remove(def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
+ symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+ } /* if not already in place */
+ } /* if function */
+ } /* normal or mergable */
+
+ if (SF_GET_TAG(def_symbol_in_progress)
+ && symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP) == NULL) {
+ tag_insert(S_GET_NAME(def_symbol_in_progress), def_symbol_in_progress);
+ } /* If symbol is a {structure,union} tag, associate symbol to its name. */
+
+ if (SF_GET_FUNCTION(def_symbol_in_progress)) {
+ know(sizeof(def_symbol_in_progress) <= sizeof(long));
+ function_lineoff
+ = c_line_new(def_symbol_in_progress,0, 0, &zero_address_frag);
+
+
+
+ SF_SET_PROCESS(def_symbol_in_progress);
+
+ if (symbolP == NULL) {
+ /* That is, if this is the first
+ time we've seen the function... */
+ symbol_table_insert(def_symbol_in_progress);
+ } /* definition follows debug */
+ } /* Create the line number entry pointing to the function being defined */
+
+ def_symbol_in_progress = NULL;
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_endef() */
+
+static void
+ DEFUN_VOID(obj_coff_dim)
+{
+ register int dim_index;
+
+ if (def_symbol_in_progress == NULL)
+ {
+ as_warn(".dim pseudo-op used outside of .def/.endef: ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+
+ for (dim_index = 0; dim_index < DIMNUM; dim_index++)
+ {
+ SKIP_WHITESPACES();
+ SA_SET_SYM_DIMEN(def_symbol_in_progress, dim_index, get_absolute_expression());
+
+ switch (*input_line_pointer)
+ {
+
+ case ',':
+ input_line_pointer++;
+ break;
+
+ default:
+ as_warn("badly formed .dim directive ignored");
+ /* intentional fallthrough */
+ case '\n':
+ case ';':
+ dim_index = DIMNUM;
+ break;
+ } /* switch on following character */
+ } /* for each dimension */
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_dim() */
+
+static void obj_coff_line()
+{
+ int this_base;
+
+ if (def_symbol_in_progress == NULL) {
+ obj_coff_ln();
+ return;
+ } /* if it looks like a stabs style line */
+
+ this_base = get_absolute_expression();
+ if (this_base > line_base)
+ {
+ line_base = this_base;
+ }
+
+
+#ifndef NO_LISTING
+ {
+ extern int listing;
+ if (listing && 0) {
+ listing_source_line(line_base);
+ }
+ }
+#endif
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+ SA_SET_SYM_LNNO(def_symbol_in_progress, line_base);
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_line() */
+
+static void obj_coff_size() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".size pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+ SA_SET_SYM_SIZE(def_symbol_in_progress, get_absolute_expression());
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_size() */
+
+static void obj_coff_scl() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".scl pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_STORAGE_CLASS(def_symbol_in_progress, get_absolute_expression());
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_scl() */
+
+static void obj_coff_tag() {
+ char *symbol_name;
+ char name_end;
+
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".tag pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
+ symbol_name = input_line_pointer;
+ name_end = get_symbol_end();
+
+ /* Assume that the symbol referred to by .tag is always defined. */
+ /* This was a bad assumption. I've added find_or_make. xoxorich. */
+ SA_SET_SYM_TAGNDX(def_symbol_in_progress, (long) tag_find_or_make(symbol_name));
+ if (SA_GET_SYM_TAGNDX(def_symbol_in_progress) == 0L) {
+ as_warn("tag not found for .tag %s", symbol_name);
+ } /* not defined */
+
+ SF_SET_TAGGED(def_symbol_in_progress);
+ *input_line_pointer = name_end;
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_tag() */
+
+static void obj_coff_type() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".type pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ S_SET_DATA_TYPE(def_symbol_in_progress, get_absolute_expression());
+
+ if (ISFCN(S_GET_DATA_TYPE(def_symbol_in_progress)) &&
+ S_GET_STORAGE_CLASS(def_symbol_in_progress) != C_TPDEF) {
+ SF_SET_FUNCTION(def_symbol_in_progress);
+ } /* is a function */
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_type() */
+
+static void obj_coff_val() {
+ if (def_symbol_in_progress == NULL) {
+ as_warn(".val pseudo-op used outside of .def/.endef ignored.");
+ demand_empty_rest_of_line();
+ return;
+ } /* if not inside .def/.endef */
+
+ if (is_name_beginner(*input_line_pointer)) {
+ char *symbol_name = input_line_pointer;
+ char name_end = get_symbol_end();
+
+ if (!strcmp(symbol_name, ".")) {
+ def_symbol_in_progress->sy_frag = frag_now;
+ S_SET_VALUE(def_symbol_in_progress, obstack_next_free(&frags) - frag_now->fr_literal);
+ /* If the .val is != from the .def (e.g. statics) */
+ } else if (strcmp(S_GET_NAME(def_symbol_in_progress), symbol_name)) {
+ def_symbol_in_progress->sy_forward = symbol_find_or_make(symbol_name);
+
+ /* If the segment is undefined when the forward
+ reference is solved, then copy the segment id
+ from the forward symbol. */
+ SF_SET_GET_SEGMENT(def_symbol_in_progress);
+ }
+ /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
+ *input_line_pointer = name_end;
+ } else {
+ S_SET_VALUE(def_symbol_in_progress, get_absolute_expression());
+ } /* if symbol based */
+
+ demand_empty_rest_of_line();
+ return;
+} /* obj_coff_val() */
+
+/*
+ * Maintain a list of the tagnames of the structres.
+ */
+
+static void tag_init() {
+ tag_hash = hash_new();
+ return ;
+} /* tag_init() */
+
+static void tag_insert(name, symbolP)
+char *name;
+symbolS *symbolP;
+{
+ register char * error_string;
+
+ if (*(error_string = hash_jam(tag_hash, name, (char *)symbolP))) {
+ as_fatal("Inserting \"%s\" into structure table failed: %s",
+ name, error_string);
+ }
+ return ;
+} /* tag_insert() */
+
+static symbolS *tag_find_or_make(name)
+char *name;
+{
+ symbolS *symbolP;
+
+ if ((symbolP = tag_find(name)) == NULL) {
+ symbolP = symbol_new(name,
+ SEG_UNKNOWN,
+ 0,
+ &zero_address_frag);
+
+ tag_insert(S_GET_NAME(symbolP), symbolP);
+ symbol_table_insert(symbolP);
+ } /* not found */
+
+ return(symbolP);
+} /* tag_find_or_make() */
+
+static symbolS *tag_find(name)
+char *name;
+{
+#ifdef STRIP_UNDERSCORE
+ if (*name == '_') name++;
+#endif /* STRIP_UNDERSCORE */
+ return((symbolS*)hash_find(tag_hash, name));
+} /* tag_find() */
+
+void obj_read_begin_hook() {
+ /* These had better be the same. Usually 18 bytes. */
+#ifndef BFD_HEADERS
+ know(sizeof(SYMENT) == sizeof(AUXENT));
+ know(SYMESZ == AUXESZ);
+#endif
+ tag_init();
+
+ return;
+} /* obj_read_begin_hook() */
+
+/* This function runs through the symbol table and puts all the
+ externals onto another chain */
+
+/* The chain of externals */
+symbolS *symbol_externP = NULL;
+symbolS *symbol_extern_lastP = NULL;
+
+stack*block_stack;
+symbolS *last_functionP = NULL;
+symbolS *last_tagP;
+
+
+static unsigned int DEFUN_VOID(yank_symbols)
+{
+ symbolS *symbolP;
+ unsigned int symbol_number =0;
+
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbolP ? symbol_next(symbolP) : symbol_rootP) {
+ if (!SF_GET_DEBUG(symbolP)) {
+ /* Debug symbols do not need all this rubbish */
+ symbolS* real_symbolP;
+
+ /* L* and C_EFCN symbols never merge. */
+ if (!SF_GET_LOCAL(symbolP)
+ && (real_symbolP = symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP))
+ && real_symbolP != symbolP) {
+ /* FIXME-SOON: where do dups come from?
+ Maybe tag references before definitions? xoxorich. */
+ /* Move the debug data from the debug symbol to the
+ real symbol. Do NOT do the oposite (i.e. move from
+ real symbol to debug symbol and remove real symbol from the
+ list.) Because some pointers refer to the real symbol
+ whereas no pointers refer to the debug symbol. */
+ c_symbol_merge(symbolP, real_symbolP);
+ /* Replace the current symbol by the real one */
+ /* The symbols will never be the last or the first
+ because : 1st symbol is .file and 3 last symbols are
+ .text, .data, .bss */
+ symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+ symbolP = real_symbolP;
+ } /* if not local but dup'd */
+
+ if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_E1)) {
+ S_SET_SEGMENT(symbolP, SEG_E0);
+ } /* push data into text */
+
+ S_SET_VALUE(symbolP,
+ S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
+
+ if (!S_IS_DEFINED(symbolP) && !SF_GET_LOCAL(symbolP))
+ {
+ S_SET_EXTERNAL(symbolP);
+ }
+ else if (S_GET_STORAGE_CLASS(symbolP) == C_NULL)
+ {
+ if (S_GET_SEGMENT(symbolP) == SEG_E0)
+ {
+ S_SET_STORAGE_CLASS(symbolP, C_LABEL);
+ }
+ else
+ {
+ S_SET_STORAGE_CLASS(symbolP, C_STAT);
+ }
+ }
+
+ /* Mainly to speed up if not -g */
+ if (SF_GET_PROCESS(symbolP))
+ {
+ /* Handle the nested blocks auxiliary info. */
+ if (S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
+ if (!strcmp(S_GET_NAME(symbolP), ".bb"))
+ stack_push(block_stack, (char *) &symbolP);
+ else { /* .eb */
+ register symbolS* begin_symbolP;
+ begin_symbolP = *(symbolS**)stack_pop(block_stack);
+ if (begin_symbolP == (symbolS*)0)
+ as_warn("mismatched .eb");
+ else
+ SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number+2);
+ }
+ }
+ /* If we are able to identify the type of a function, and we
+ are out of a function (last_functionP == 0) then, the
+ function symbol will be associated with an auxiliary
+ entry. */
+ if (last_functionP == (symbolS*)0 &&
+ SF_GET_FUNCTION(symbolP)) {
+ last_functionP = symbolP;
+
+ if (S_GET_NUMBER_AUXILIARY(symbolP) < 1) {
+ S_SET_NUMBER_AUXILIARY(symbolP, 1);
+ } /* make it at least 1 */
+
+ /* Clobber possible stale .dim information. */
+ memset(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
+ '\0', sizeof(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
+ }
+ /* The C_FCN doesn't need any additional information.
+ I don't even know if this is needed for sdb. But the
+ standard assembler generates it, so...
+ */
+ if (S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
+ if (last_functionP == (symbolS*)0)
+ as_fatal("C_EFCN symbol out of scope");
+ SA_SET_SYM_FSIZE(last_functionP,
+ (long)(S_GET_VALUE(symbolP) -
+ S_GET_VALUE(last_functionP)));
+ SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
+ last_functionP = (symbolS*)0;
+ }
+ }
+ } else if (SF_GET_TAG(symbolP)) {
+ /* First descriptor of a structure must point to
+ the first slot after the structure description. */
+ last_tagP = symbolP;
+
+ } else if (S_GET_STORAGE_CLASS(symbolP) == C_EOS) {
+ /* +2 take in account the current symbol */
+ SA_SET_SYM_ENDNDX(last_tagP, symbol_number + 2);
+ } else if (S_GET_STORAGE_CLASS(symbolP) == C_FILE) {
+ if (S_GET_VALUE(symbolP)) {
+ S_SET_VALUE((symbolS *) S_GET_VALUE(symbolP), symbol_number);
+ S_SET_VALUE(symbolP, 0);
+ } /* no one points at the first .file symbol */
+ } /* if debug or tag or eos or file */
+
+ /* We must put the external symbols apart. The loader
+ does not bomb if we do not. But the references in
+ the endndx field for a .bb symbol are not corrected
+ if an external symbol is removed between .bb and .be.
+ I.e in the following case :
+ [20] .bb endndx = 22
+ [21] foo external
+ [22] .be
+ ld will move the symbol 21 to the end of the list but
+ endndx will still be 22 instead of 21. */
+
+
+ if (SF_GET_LOCAL(symbolP)) {
+ /* remove C_EFCN and LOCAL (L...) symbols */
+ /* next pointer remains valid */
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+
+ }
+ else if (!S_IS_DEFINED(symbolP)
+ && !S_IS_DEBUG(symbolP)
+ && !SF_GET_STATICS(symbolP) &&
+ S_GET_STORAGE_CLASS(symbolP) == C_EXT)
+ { /* C_EXT && !SF_GET_FUNCTION(symbolP)) */
+ /* if external, Remove from the list */
+ symbolS *hold = symbol_previous(symbolP);
+
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_clear_list_pointers(symbolP);
+ symbol_append(symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
+ symbolP = hold;
+ } else {
+ if (SF_GET_STRING(symbolP)) {
+ symbolP->sy_name_offset = string_byte_count;
+ string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
+ } else {
+ symbolP->sy_name_offset = 0;
+ } /* fix "long" names */
+
+ symbolP->sy_number = symbol_number;
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
+ } /* if local symbol */
+ } /* traverse the symbol list */
+ return symbol_number;
+
+}
+
+
+static unsigned int DEFUN_VOID(glue_symbols)
+{
+ unsigned int symbol_number = 0;
+ symbolS *symbolP;
+ for (symbolP = symbol_externP; symbol_externP;) {
+ symbolS *tmp = symbol_externP;
+
+ /* append */
+ symbol_remove(tmp, &symbol_externP, &symbol_extern_lastP);
+ symbol_append(tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ /* and process */
+ if (SF_GET_STRING(tmp)) {
+ tmp->sy_name_offset = string_byte_count;
+ string_byte_count += strlen(S_GET_NAME(tmp)) + 1;
+ } else {
+ tmp->sy_name_offset = 0;
+ } /* fix "long" names */
+
+ tmp->sy_number = symbol_number;
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY(tmp);
+ } /* append the entire extern chain */
+ return symbol_number;
+
+}
+
+static unsigned int DEFUN_VOID(tie_tags)
+{
+ unsigned int symbol_number = 0;
+
+ symbolS*symbolP;
+ for (symbolP = symbol_rootP; symbolP; symbolP =
+ symbol_next(symbolP))
+ {
+ symbolP->sy_number = symbol_number;
+
+
+
+ if (SF_GET_TAGGED(symbolP))
+ {
+ SA_SET_SYM_TAGNDX
+ (symbolP,
+ ((symbolS*) SA_GET_SYM_TAGNDX(symbolP))->sy_number);
+ }
+
+ symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
+ }
+ return symbol_number;
+
+}
+
+static void
+ DEFUN(crawl_symbols,(headers, abfd),
+ struct internal_filehdr *headers AND
+ bfd *abfd)
+{
+
+ unsigned int i;
+ unsigned int ptr = 0;
+
+
+ symbolS *symbolP;
+
+ /* Initialize the stack used to keep track of the matching .bb .be */
+
+ block_stack = stack_init(512, sizeof(symbolS*));
+ /* JF deal with forward references first... */
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbol_next(symbolP))
+ {
+
+ if (symbolP->sy_forward) {
+ S_SET_VALUE(symbolP, (S_GET_VALUE(symbolP)
+ + S_GET_VALUE(symbolP->sy_forward)
+ + symbolP->sy_forward->sy_frag->fr_address));
+
+ if (SF_GET_GET_SEGMENT(symbolP)) {
+ S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
+ } /* forward segment also */
+
+ symbolP->sy_forward=0;
+ } /* if it has a forward reference */
+ } /* walk the symbol chain */
+
+
+ /* The symbol list should be ordered according to the following sequence
+ * order :
+ * . .file symbol
+ * . debug entries for functions
+ * . fake symbols for the sections, including.text .data and .bss
+ * . defined symbols
+ * . undefined symbols
+ * But this is not mandatory. The only important point is to put the
+ * undefined symbols at the end of the list.
+ */
+
+ if (symbol_rootP == NULL
+ || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
+ c_dot_file_symbol("fake");
+ }
+ /* Is there a .file symbol ? If not insert one at the beginning. */
+
+ /*
+ * Build up static symbols for the sections, they are filled in later
+ */
+
+
+ for (i = SEG_E0; i < SEG_E9; i++)
+ {
+ if (segment_info[i].scnhdr.s_name[0])
+ {
+ segment_info[i].dot =
+ c_section_symbol(segment_info[i].scnhdr.s_name,
+ i-SEG_E0+1);
+
+ }
+ }
+
+
+ /* Take all the externals out and put them into another chain */
+ headers->f_nsyms = yank_symbols();
+ /* Take the externals and glue them onto the end.*/
+ headers->f_nsyms += glue_symbols();
+
+ headers->f_nsyms = tie_tags();
+ know(symbol_externP == NULL);
+ know(symbol_extern_lastP == NULL);
+
+ return;
+}
+
+/*
+ * Find strings by crawling along symbol table chain.
+ */
+
+void DEFUN(w_strings,(where),
+ char *where)
+{
+ symbolS *symbolP;
+
+ /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
+ md_number_to_chars(where, string_byte_count, sizeof(string_byte_count));
+ where += sizeof(string_byte_count);
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbol_next(symbolP))
+ {
+ unsigned int size;
+
+ if (SF_GET_STRING(symbolP)) {
+ size = strlen(S_GET_NAME(symbolP)) + 1;
+
+ memcpy(where, S_GET_NAME(symbolP),size);
+ where += size;
+
+ }
+ }
+
+}
+
+
+
+
+
+static void
+ DEFUN(do_linenos_for,(abfd, file_cursor),
+ bfd *abfd AND
+ unsigned long *file_cursor)
+{
+ unsigned int idx;
+
+ for (idx = SEG_E0; idx < SEG_E9; idx++)
+ {
+ segment_info_type *s = segment_info + idx;
+
+
+ if (s->scnhdr.s_nlnno != 0)
+ {
+ struct lineno_list *line_ptr ;
+
+ struct external_lineno *buffer =
+ (struct external_lineno *)xmalloc(s->scnhdr.s_nlnno * LINESZ);
+
+ struct external_lineno *dst= buffer;
+
+ /* Run through the table we've built and turn it into its external
+ form, take this chance to remove duplicates */
+
+ for (line_ptr = s->lineno_list_head;
+ line_ptr != (struct lineno_list *)NULL;
+ line_ptr = line_ptr->next)
+ {
+
+ if (line_ptr->line.l_lnno == 0)
+ {
+ /* Turn a pointer to a symbol into the symbols' index */
+ line_ptr->line.l_addr.l_symndx =
+ ( (symbolS *)line_ptr->line.l_addr.l_symndx)->sy_number;
+ }
+ else
+ {
+ line_ptr->line.l_addr.l_paddr += ((struct frag * )(line_ptr->frag))->fr_address;
+ }
+
+
+ (void) bfd_coff_swap_lineno_out(abfd, &(line_ptr->line), dst);
+ dst++;
+
+ }
+
+ s->scnhdr.s_lnnoptr = *file_cursor;
+
+ bfd_write(buffer, 1, s->scnhdr.s_nlnno* LINESZ, abfd);
+ free(buffer);
+
+ *file_cursor += s->scnhdr.s_nlnno * LINESZ;
+ }
+ }
+}
+
+
+/* Now we run through the list of frag chains in a segment and
+ make all the subsegment frags appear at the end of the
+ list, as if the seg 0 was extra long */
+
+static void DEFUN_VOID(remove_subsegs)
+{
+ unsigned int i;
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ frchainS *head = segment_info[i].frchainP;
+ fragS dummy;
+ fragS * prev_frag = &dummy;
+
+ while (head && head->frch_seg == i)
+ {
+ prev_frag->fr_next = head->frch_root;
+ prev_frag = head->frch_last;
+ head = head->frch_next;
+ }
+ prev_frag->fr_next = 0;
+ }
+}
+
+
+extern void DEFUN_VOID(write_object_file)
+{
+ int i;
+ struct frchain *frchain_ptr;
+
+ struct internal_filehdr filehdr;
+ struct internal_aouthdr aouthdr;
+ unsigned long file_cursor;
+ bfd *abfd;
+ unsigned int addr = 0;
+ abfd = bfd_openw(out_file_name, TARGET_FORMAT);
+
+
+ if (abfd == 0) {
+ as_perror ("FATAL: Can't create %s", out_file_name);
+ exit(42);
+ }
+ bfd_set_format(abfd, bfd_object);
+ bfd_set_arch_mach(abfd, BFD_ARCH, 0);
+
+
+
+ string_byte_count = 4;
+
+ for (frchain_ptr = frchain_root;
+ frchain_ptr != (struct frchain *)NULL;
+ frchain_ptr = frchain_ptr->frch_next) {
+ /* Run through all the sub-segments and align them up. Also close any
+ open frags. We tack a .fill onto the end of the frag chain so
+ that any .align's size can be worked by looking at the next
+ frag */
+
+ subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#define SUB_SEGMENT_ALIGN 1
+ frag_align(SUB_SEGMENT_ALIGN,0);
+ frag_wane(frag_now);
+ frag_now->fr_fix = 0;
+ know( frag_now->fr_next == NULL );
+ }
+
+
+ remove_subsegs();
+
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ relax_segment(segment_info[i].frchainP->frch_root, i);
+ }
+
+
+
+
+
+ filehdr.f_nscns = 0;
+
+ /* Find out how big the sections are */
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+
+ if (segment_info[i].scnhdr.s_name[0])
+ {
+ filehdr.f_nscns++;
+ }
+ segment_info[i].scnhdr.s_paddr = addr;
+ if (i == SEG_E2) {
+ /* THis is a special case, we leave the size alone, which will have */
+ /* been made up from all and any lcomms seen */
+ }
+ else {
+ addr += size_section(abfd, i);
+ }
+ }
+
+
+
+ /* Turn the gas native symbol table shape into a coff symbol table */
+ crawl_symbols(&filehdr, abfd);
+#ifndef TC_H8300
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+ fixup_segment(segment_info[i].fix_root, i);
+ }
+#endif
+
+ file_cursor = FILHSZ + SCNHSZ * filehdr.f_nscns ;
+
+ bfd_seek(abfd, file_cursor, 0);
+
+
+ do_relocs_for(abfd, &file_cursor);
+
+ do_linenos_for(abfd, &file_cursor);
+
+
+ /* Plant the data */
+
+ fill_section(abfd,&filehdr, &file_cursor);
+
+ filehdr.f_magic = COFF_MAGIC;
+ filehdr.f_timdat = 0;
+ filehdr.f_flags = 0;
+
+
+
+ {
+
+ unsigned int symtable_size = filehdr.f_nsyms * SYMESZ;
+ char *buffer1 = malloc(symtable_size + string_byte_count + 4);
+ char *ptr = buffer1;
+ filehdr.f_symptr = bfd_tell(abfd);
+ w_symbols(abfd, buffer1, symbol_rootP);
+ w_strings(buffer1 + symtable_size);
+ bfd_write(buffer1, 1,symtable_size + string_byte_count + 4, abfd);
+ free(buffer1);
+
+ }
+ coff_header_append(abfd, &filehdr, &aouthdr);
+
+ bfd_close_all_done(abfd);
+}
+
+
+static void DEFUN(change_to_section,(name, len, exp),
+ char *name AND
+ unsigned int len AND
+ unsigned int exp)
+{
+ unsigned int i;
+ /* Find out if we've already got a section of this name etc */
+ for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0] ; i++)
+ {
+ if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0)
+ {
+ subseg_new(i, exp);
+ return;
+
+ }
+ }
+ /* No section, add one */
+ strncpy(segment_info[i].scnhdr.s_name, name, 8);
+ subseg_new(i, exp);
+}
+
+static void
+ DEFUN_VOID(obj_coff_section)
+{
+ /* Strip out the section name */
+ char *section_name ;
+ char *section_name_end;
+ char c;
+
+ unsigned int len;
+ unsigned int exp;
+
+ section_name = input_line_pointer;
+ c = get_symbol_end();
+ section_name_end = input_line_pointer;
+
+ len = section_name_end - section_name ;
+ input_line_pointer++;
+ SKIP_WHITESPACE();
+ if (c == ',')
+ {
+ exp = get_absolute_expression();
+ }
+ else if ( *input_line_pointer == ',')
+ {
+
+ input_line_pointer++;
+ exp = get_absolute_expression();
+ }
+ else
+ {
+ exp = 0;
+ }
+
+ change_to_section(section_name, len,exp);
+ *section_name_end = c;
+
+}
+
+
+static void obj_coff_text()
+{
+ change_to_section(".text",5, get_absolute_expression());
+}
+
+
+static void obj_coff_data()
+{
+ change_to_section(".data",5, get_absolute_expression());
+}
+
+void c_symbol_merge(debug, normal)
+symbolS *debug;
+symbolS *normal;
+{
+ S_SET_DATA_TYPE(normal, S_GET_DATA_TYPE(debug));
+ S_SET_STORAGE_CLASS(normal, S_GET_STORAGE_CLASS(debug));
+
+ if (S_GET_NUMBER_AUXILIARY(debug) > S_GET_NUMBER_AUXILIARY(normal)) {
+ S_SET_NUMBER_AUXILIARY(normal, S_GET_NUMBER_AUXILIARY(debug));
+ } /* take the most we have */
+
+ if (S_GET_NUMBER_AUXILIARY(debug) > 0) {
+ memcpy((char*)&normal->sy_symbol.ost_auxent[0], (char*)&debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
+ } /* Move all the auxiliary information */
+
+ /* Move the debug flags. */
+ SF_SET_DEBUG_FIELD(normal, SF_GET_DEBUG_FIELD(debug));
+} /* c_symbol_merge() */
+
+static int
+ DEFUN(c_line_new,(symbol, paddr, line_number, frag),
+ symbolS *symbol AND
+ long paddr AND
+ unsigned short line_number AND
+ fragS* frag)
+{
+ struct lineno_list* new_line =
+ (struct lineno_list *)xmalloc(sizeof(struct lineno_list));
+
+ segment_info_type *s = segment_info + now_seg;
+ new_line->line.l_lnno = line_number;
+
+ if (line_number == 0)
+ {
+ new_line->line.l_addr.l_symndx = (long)symbol;
+ }
+ else
+ {
+ new_line->line.l_addr.l_paddr = paddr;
+ }
+
+ new_line->frag = (char*)frag;
+ new_line->next = (struct lineno_list*)NULL;
+
+
+ if (s->lineno_list_head == (struct lineno_list *)NULL)
+ {
+ s->lineno_list_head = new_line;
+ }
+ else
+ {
+ s->lineno_list_tail->next = new_line;
+ }
+ s->lineno_list_tail = new_line;
+ return LINESZ * s->scnhdr.s_nlnno ++;
+}
+
+void c_dot_file_symbol(filename)
+char *filename;
+{
+ symbolS* symbolP;
+
+ symbolP = symbol_new(".file",
+ SEG_DEBUG,
+ 0,
+ &zero_address_frag);
+
+ S_SET_STORAGE_CLASS(symbolP, C_FILE);
+ S_SET_NUMBER_AUXILIARY(symbolP, 1);
+ SA_SET_FILE_FNAME(symbolP, filename);
+#ifndef NO_LISTING
+ {
+ extern int listing;
+ if (listing)
+ {
+ listing_source_file(filename);
+ }
+
+ }
+
+#endif
+ SF_SET_DEBUG(symbolP);
+ S_SET_VALUE(symbolP, (long) previous_file_symbol);
+
+ previous_file_symbol = symbolP;
+
+ /* Make sure that the symbol is first on the symbol chain */
+ if (symbol_rootP != symbolP) {
+ if (symbolP == symbol_lastP) {
+ symbol_lastP = symbol_lastP->sy_previous;
+ } /* if it was the last thing on the list */
+
+ symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
+ symbol_insert(symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
+ symbol_rootP = symbolP;
+ } /* if not first on the list */
+
+} /* c_dot_file_symbol() */
+
+/*
+ * Build a 'section static' symbol.
+ */
+
+symbolS *c_section_symbol(name,idx)
+char *name;
+int idx;
+{
+ symbolS *symbolP;
+
+ symbolP = symbol_new(name,idx,
+ 0,
+ &zero_address_frag);
+
+ S_SET_STORAGE_CLASS(symbolP, C_STAT);
+ S_SET_NUMBER_AUXILIARY(symbolP, 1);
+
+ SF_SET_STATICS(symbolP);
+
+ return symbolP;
+} /* c_section_symbol() */
+
+static void
+ DEFUN(w_symbols,(abfd, where, symbol_rootP),
+ bfd *abfd AND
+ char *where AND
+ symbolS *symbol_rootP)
+{
+ symbolS *symbolP;
+ unsigned int i;
+
+ /* First fill in those values we have only just worked out */
+ for (i = SEG_E0; i < SEG_E9; i++)
+ {
+ symbolP = segment_info[i].dot;
+ if (symbolP)
+ {
+
+ SA_SET_SCN_SCNLEN(symbolP, segment_info[i].scnhdr.s_size);
+ SA_SET_SCN_NRELOC(symbolP, segment_info[i].scnhdr.s_nreloc);
+ SA_SET_SCN_NLINNO(symbolP, segment_info[i].scnhdr.s_nlnno);
+
+ }
+ }
+
+ /*
+ * Emit all symbols left in the symbol chain.
+ */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+ /* Used to save the offset of the name. It is used to point
+ to the string in memory but must be a file offset. */
+ register char * temp;
+
+ tc_coff_symbol_emit_hook(symbolP);
+
+ temp = S_GET_NAME(symbolP);
+ if (SF_GET_STRING(symbolP)) {
+ S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
+ S_SET_ZEROES(symbolP, 0);
+ } else {
+ memset(symbolP->sy_symbol.ost_entry.n_name, '\0', SYMNMLEN);
+ strncpy(symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
+ }
+ where = symbol_to_chars(abfd, where, symbolP);
+ S_SET_NAME(symbolP,temp);
+ }
+
+} /* w_symbols() */
+
+static void DEFUN_VOID(obj_coff_lcomm)
+{
+ char *name;
+ char c;
+ int temp;
+ char *p;
+ symbolS *symbolP;
+ name = input_line_pointer;
+
+
+
+ c = get_symbol_end();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after name");
+ ignore_rest_of_line();
+ return;
+ }
+ if (*input_line_pointer == '\n') {
+ as_bad("Missing size expression");
+ return;
+ }
+ input_line_pointer++;
+ if ((temp = get_absolute_expression ()) < 0) {
+ as_warn("lcomm length (%d.) <0! Ignored.", temp);
+ ignore_rest_of_line();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
+ S_SET_SEGMENT(symbolP, SEG_E2);
+ segment_info[SEG_E2].scnhdr.s_size += temp;
+ S_SET_STORAGE_CLASS(symbolP, C_STAT);
+ demand_empty_rest_of_line();
+}
+
+
+#if 1
+static void DEFUN(fixup_segment,(fixP, this_segment_type),
+ register fixS * fixP AND
+ segT this_segment_type)
+{
+ register symbolS *add_symbolP;
+ register symbolS *sub_symbolP;
+ register long add_number;
+ register int size;
+ register char *place;
+ register long where;
+ register char pcrel;
+ register fragS *fragP;
+ register segT add_symbol_segment = SEG_ABSOLUTE;
+
+
+ for ( ; fixP; fixP = fixP->fx_next)
+ {
+ fragP = fixP->fx_frag;
+ know(fragP);
+ where = fixP->fx_where;
+ place = fragP->fr_literal + where;
+ size = fixP->fx_size;
+ add_symbolP = fixP->fx_addsy;
+#ifdef TC_I960
+ if (fixP->fx_callj && TC_S_IS_CALLNAME(add_symbolP)) {
+ /* Relocation should be done via the
+ associated 'bal' entry point
+ symbol. */
+
+ if (!TC_S_IS_BALNAME(tc_get_bal_of_call(add_symbolP))) {
+ as_bad("No 'bal' entry point for leafproc %s",
+ S_GET_NAME(add_symbolP));
+ continue;
+ }
+ fixP->fx_addsy = add_symbolP = tc_get_bal_of_call(add_symbolP);
+ } /* callj relocation */
+#endif
+ sub_symbolP = fixP->fx_subsy;
+ add_number = fixP->fx_offset;
+ pcrel = fixP->fx_pcrel;
+
+ if (add_symbolP) {
+ add_symbol_segment = S_GET_SEGMENT(add_symbolP);
+ } /* if there is an addend */
+
+ if (sub_symbolP) {
+ if (!add_symbolP) {
+ /* Its just -sym */
+ if (S_GET_SEGMENT(sub_symbolP) != SEG_ABSOLUTE) {
+ as_bad("Negative of non-absolute symbol %s", S_GET_NAME(sub_symbolP));
+ } /* not absolute */
+
+ add_number -= S_GET_VALUE(sub_symbolP);
+
+ /* if sub_symbol is in the same segment that add_symbol
+ and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
+ } else if ((S_GET_SEGMENT(sub_symbolP) == add_symbol_segment)
+ && (SEG_NORMAL(add_symbol_segment)
+ || (add_symbol_segment == SEG_ABSOLUTE))) {
+ /* Difference of 2 symbols from same segment. */
+ /* Can't make difference of 2 undefineds: 'value' means */
+ /* something different for N_UNDF. */
+#ifdef TC_I960
+ /* Makes no sense to use the difference of 2 arbitrary symbols
+ * as the target of a call instruction.
+ */
+ if (fixP->fx_callj) {
+ as_bad("callj to difference of 2 symbols");
+ }
+#endif /* TC_I960 */
+ add_number += S_GET_VALUE(add_symbolP) -
+ S_GET_VALUE(sub_symbolP);
+
+ add_symbolP = NULL;
+ fixP->fx_addsy = NULL;
+ } else {
+ /* Different segments in subtraction. */
+ know(!(S_IS_EXTERNAL(sub_symbolP) && (S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)));
+
+ if ((S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)) {
+ add_number -= S_GET_VALUE(sub_symbolP);
+ } else {
+ as_bad("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
+ segment_name(S_GET_SEGMENT(sub_symbolP)),
+ S_GET_NAME(sub_symbolP), fragP->fr_address + where);
+ } /* if absolute */
+ }
+ } /* if sub_symbolP */
+
+ if (add_symbolP) {
+ if (add_symbol_segment == this_segment_type && pcrel) {
+ /*
+ * This fixup was made when the symbol's segment was
+ * SEG_UNKNOWN, but it is now in the local segment.
+ * So we know how to do the address without relocation.
+ */
+#ifdef TC_I960
+ /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
+ * in which cases it modifies *fixP as appropriate. In the case
+ * of a 'calls', no further work is required, and *fixP has been
+ * set up to make the rest of the code below a no-op.
+ */
+ reloc_callj(fixP);
+#endif /* TC_I960 */
+
+ add_number += S_GET_VALUE(add_symbolP);
+ add_number -= md_pcrel_from (fixP);
+ pcrel = 0; /* Lie. Don't want further pcrel processing. */
+ fixP->fx_addsy = NULL; /* No relocations please. */
+ } else
+ {
+ switch (add_symbol_segment)
+ {
+ case SEG_ABSOLUTE:
+#ifdef TC_I960
+ reloc_callj(fixP); /* See comment about reloc_callj() above*/
+#endif /* TC_I960 */
+ add_number += S_GET_VALUE(add_symbolP);
+ fixP->fx_addsy = NULL;
+ add_symbolP = NULL;
+ break;
+ default:
+
+ add_number += S_GET_VALUE(add_symbolP) +
+ segment_info[S_GET_SEGMENT(add_symbolP)].scnhdr.s_paddr ;
+ break;
+
+ case SEG_UNKNOWN:
+#ifdef TC_I960
+ if ((int)fixP->fx_bit_fixP == 13) {
+ /* This is a COBR instruction. They have only a
+ * 13-bit displacement and are only to be used
+ * for local branches: flag as error, don't generate
+ * relocation.
+ */
+ as_bad("can't use COBR format with external label");
+ fixP->fx_addsy = NULL; /* No relocations please. */
+ continue;
+ } /* COBR */
+#endif /* TC_I960 */
+
+
+
+ break;
+
+
+ } /* switch on symbol seg */
+ } /* if not in local seg */
+ } /* if there was a + symbol */
+
+ if (pcrel) {
+ add_number -= md_pcrel_from(fixP);
+ if (add_symbolP == 0) {
+ fixP->fx_addsy = & abs_symbol;
+ } /* if there's an add_symbol */
+ } /* if pcrel */
+
+ if (!fixP->fx_bit_fixP) {
+ if ((size == 1
+ && (add_number & ~0xFF) && (add_number & ~0xFF != (-1 & ~0xFF))) ||
+ (size == 2
+ && (add_number & ~0xFFFF) && (add_number & ~0xFFFF != (-1 & ~0xFFFF)))) {
+ as_bad("Value of %d too large for field of %d bytes at 0x%x",
+ add_number, size, fragP->fr_address + where);
+ } /* generic error checking */
+ } /* not a bit fix */
+ /* once this fix has been applied, we don't have to output anything
+ nothing more need be done -*/
+ md_apply_fix(fixP, add_number);
+
+ } /* For each fixS in this segment. */
+
+
+} /* fixup_segment() */
+#endif
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-coffbfd.c */
diff --git a/gnu/usr.bin/as/config/obj-coffbfd.h b/gnu/usr.bin/as/config/obj-coffbfd.h
new file mode 100644
index 0000000..5ccefab
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-coffbfd.h
@@ -0,0 +1,516 @@
+/* coff object file format
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef OBJ_FORMAT_H
+#define OBJ_FORMAT_H
+
+#define OBJ_COFF 1
+
+#include "targ-cpu.h"
+
+#include "bfd.h"
+
+/*extern bfd *stdoutput;*/
+/* This internal_lineno crap is to stop namespace pollution from the
+ bfd internal coff headerfile. */
+
+#define internal_lineno bfd_internal_lineno
+#include "coff/internal.h"
+#undef internal_lineno
+
+#if defined(TC_H8300)
+#include "coff/h8300.h"
+#define TARGET_FORMAT "coff-h8300"
+#elif defined(TC_A29K)
+#include "coff/a29k.h"
+#define TARGET_FORMAT "coff-a29k-big"
+#else
+help me
+#endif
+
+#if 0
+ /* Define some processor dependent values according to the processor we are
+ on. */
+#if defined(TC_H8300)
+#define BYTE_ORDERING 0
+#define FILE_HEADER_MAGIC H8300MAGIC
+#elif defined(TC_M68K)
+
+#define BYTE_ORDERING F_AR32W /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC MC68MAGIC /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_I386)
+
+#define BYTE_ORDERING F_AR32WR /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC I386MAGIC /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_I960)
+
+#define BYTE_ORDERING F_AR32WR /* See filehdr.h for more info. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC I960ROMAGIC /* ... */
+#endif /* FILE_HEADER_MAGIC */
+
+#elif defined(TC_A29K)
+
+#define BYTE_ORDERING F_AR32W /* big endian. */
+#ifndef FILE_HEADER_MAGIC
+#define FILE_HEADER_MAGIC SIPFBOMAGIC
+#endif /* FILE_HEADER_MAGIC */
+
+#else
+you lose
+#endif
+
+#endif
+
+#ifndef OBJ_COFF_MAX_AUXENTRIES
+#define OBJ_COFF_MAX_AUXENTRIES 1
+#endif /* OBJ_COFF_MAX_AUXENTRIES */
+
+
+ extern const segT N_TYPE_seg[];
+
+/* Magic number of paged executable. */
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 0x8300
+
+
+/* SYMBOL TABLE */
+
+/* targets may also set this */
+#ifndef SYMBOLS_NEED_BACKPOINTERS
+#define SYMBOLS_NEED_BACKPOINTERS 1
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+/* Symbol table entry data type */
+
+typedef struct
+{
+ struct internal_syment ost_entry; /* Basic symbol */
+ union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; /* Auxiliary entry. */
+
+ unsigned int ost_flags; /* obj_coff internal use only flags */
+} obj_symbol_type;
+
+#ifndef DO_NOT_STRIP
+#define DO_NOT_STRIP 0
+#define DO_STRIP 1
+#endif
+/* Symbol table macros and constants */
+
+/* Possible and usefull section number in symbol table
+ * The values of TEXT, DATA and BSS may not be portable.
+ */
+
+#define C_ABS_SECTION N_ABS
+#define C_UNDEF_SECTION N_UNDEF
+#define C_DEBUG_SECTION N_DEBUG
+#define C_NTV_SECTION N_TV
+#define C_PTV_SECTION P_TV
+#define C_REGISTER_SECTION 20
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* Predicates */
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION)
+/* True if symbol has been defined, ie :
+ section > 0 (DATA, TEXT or BSS)
+ section == 0 and value > 0 (external bss symbol) */
+#define S_IS_DEFINED(s) ((s)->sy_symbol.ost_entry.n_scnum > C_UNDEF_SECTION || \
+ ((s)->sy_symbol.ost_entry.n_scnum == C_UNDEF_SECTION && \
+ (s)->sy_symbol.ost_entry.n_value > 0))
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.ost_entry.n_scnum == C_DEBUG_SECTION)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name begin with ^A is a gas internal pseudo symbol */
+#define S_IS_LOCAL(s) (S_GET_NAME(s)[0] == '\001' || \
+ (s)->sy_symbol.ost_entry.n_scnum == C_REGISTER_SECTION || \
+ (S_LOCAL_NAME(s) && !flagseen['L']))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value == 0)
+/*
+ * True if a symbol can be multiply defined (bss symbols have this def
+ * though it is bad practice)
+ */
+#define S_IS_COMMON(s) ((s)->sy_symbol.ost_entry.n_scnum == 0 && (s)->sy_symbol.ost_entry.n_value != 0)
+/* True if a symbol name is in the string table, i.e. its length is > 8. */
+#define S_IS_STRING(s) (strlen(S_GET_NAME(s)) > 8 ? 1 : 0)
+
+/* Accessors */
+/* The name of the symbol */
+#define S_GET_NAME(s) ((char*)(s)->sy_symbol.ost_entry.n_offset)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.ost_entry.n_offset)
+/* The zeroes if symbol name is longer than 8 chars */
+#define S_GET_ZEROES(s) ((s)->sy_symbol.ost_entry.n_zeroes)
+/* The value of the symbol */
+#define S_GET_VALUE(s) ((unsigned) ((s)->sy_symbol.ost_entry.n_value))
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) s_get_segment(s)
+/* The data type */
+#define S_GET_DATA_TYPE(s) ((s)->sy_symbol.ost_entry.n_type)
+/* The storage class */
+#define S_GET_STORAGE_CLASS(s) ((s)->sy_symbol.ost_entry.n_sclass)
+/* The number of auxiliary entries */
+#define S_GET_NUMBER_AUXILIARY(s) ((s)->sy_symbol.ost_entry.n_numaux)
+
+/* Modifiers */
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.ost_entry.n_offset = (unsigned long)(v))
+/* Set the offset of the symbol */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.ost_entry.n_offset = (v))
+/* The zeroes if symbol name is longer than 8 chars */
+#define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v))
+/* Set the value of the symbol */
+#define S_SET_VALUE(s,v) ((s)->sy_symbol.ost_entry.n_value = (v))
+/* The numeric value of the segment */
+#define S_SET_SEGMENT(s,v) ((s)->sy_symbol.ost_entry.n_scnum = SEGMENT_TO_SYMBOL_TYPE(v))
+/* The data type */
+#define S_SET_DATA_TYPE(s,v) ((s)->sy_symbol.ost_entry.n_type = (v))
+/* The storage class */
+#define S_SET_STORAGE_CLASS(s,v) ((s)->sy_symbol.ost_entry.n_sclass = (v))
+/* The number of auxiliary entries */
+#define S_SET_NUMBER_AUXILIARY(s,v) ((s)->sy_symbol.ost_entry.n_numaux = (v))
+
+/* Additional modifiers */
+/* The symbol is external (does not mean undefined) */
+#define S_SET_EXTERNAL(s) { S_SET_STORAGE_CLASS(s, C_EXT) ; SF_CLEAR_LOCAL(s); }
+
+/* Auxiliary entry macros. SA_ stands for symbol auxiliary */
+/* Omit the tv related fields */
+/* Accessors */
+#ifdef BFD_HEADERS
+#define SA_GET_SYM_TAGNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l)
+#else
+#define SA_GET_SYM_TAGNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx)
+#endif
+#define SA_GET_SYM_LNNO(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno)
+#define SA_GET_SYM_SIZE(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size)
+#define SA_GET_SYM_FSIZE(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize)
+#define SA_GET_SYM_LNNOPTR(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#ifdef BFD_HEADERS
+#define SA_GET_SYM_ENDNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l)
+#else
+#define SA_GET_SYM_ENDNDX(s) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx)
+#endif
+#define SA_GET_SYM_DIMEN(s,i) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)])
+#define SA_GET_FILE_FNAME(s) ((s)->sy_symbol.ost_auxent[0].x_file.x_fname)
+#define SA_GET_SCN_SCNLEN(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen)
+#define SA_GET_SCN_NRELOC(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc)
+#define SA_GET_SCN_NLINNO(s) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno)
+
+/* Modifiers */
+#ifdef BFD_HEADERS
+#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx.l=(v))
+#else
+#define SA_SET_SYM_TAGNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_tagndx=(v))
+#endif
+#define SA_SET_SYM_LNNO(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_lnno=(v))
+#define SA_SET_SYM_SIZE(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_lnsz.x_size=(v))
+#define SA_SET_SYM_FSIZE(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_misc.x_fsize=(v))
+#define SA_SET_SYM_LNNOPTR(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_lnnoptr=(v))
+#ifdef BFD_HEADERS
+#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx.l=(v))
+#else
+#define SA_SET_SYM_ENDNDX(s,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_fcn.x_endndx=(v))
+#endif
+#define SA_SET_SYM_DIMEN(s,i,v) ((s)->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen[(i)]=(v))
+#define SA_SET_FILE_FNAME(s,v) strncpy((s)->sy_symbol.ost_auxent[0].x_file.x_fname,(v),FILNMLEN)
+#define SA_SET_SCN_SCNLEN(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_scnlen=(v))
+#define SA_SET_SCN_NRELOC(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nreloc=(v))
+#define SA_SET_SCN_NLINNO(s,v) ((s)->sy_symbol.ost_auxent[0].x_scn.x_nlinno=(v))
+
+/*
+ * Internal use only definitions. SF_ stands for symbol flags.
+ *
+ * These values can be assigned to sy_symbol.ost_flags field of a symbolS.
+ *
+ * You'll break i960 if you shift the SYSPROC bits anywhere else. for
+ * more on the balname/callname hack, see tc-i960.h. b.out is done
+ * differently.
+ */
+
+#define SF_I960_MASK (0x000001ff) /* Bits 0-8 are used by the i960 port. */
+#define SF_SYSPROC (0x0000003f) /* bits 0-5 are used to store the sysproc number */
+#define SF_IS_SYSPROC (0x00000040) /* bit 6 marks symbols that are sysprocs */
+#define SF_BALNAME (0x00000080) /* bit 7 marks BALNAME symbols */
+#define SF_CALLNAME (0x00000100) /* bit 8 marks CALLNAME symbols */
+
+#define SF_NORMAL_MASK (0x0000ffff) /* bits 12-15 are general purpose. */
+
+#define SF_STATICS (0x00001000) /* Mark the .text & all symbols */
+#define SF_DEFINED (0x00002000) /* Symbol is defined in this file */
+#define SF_STRING (0x00004000) /* Symbol name length > 8 */
+#define SF_LOCAL (0x00008000) /* Symbol must not be emitted */
+
+#define SF_DEBUG_MASK (0xffff0000) /* bits 16-31 are debug info */
+
+#define SF_FUNCTION (0x00010000) /* The symbol is a function */
+#define SF_PROCESS (0x00020000) /* Process symbol before write */
+#define SF_TAGGED (0x00040000) /* Is associated with a tag */
+#define SF_TAG (0x00080000) /* Is a tag */
+#define SF_DEBUG (0x00100000) /* Is in debug or abs section */
+#define SF_GET_SEGMENT (0x00200000) /* Get the section of the forward symbol. */
+/* All other bits are unused. */
+
+/* Accessors */
+#define SF_GET(s) ((s)->sy_symbol.ost_flags)
+#define SF_GET_NORMAL_FIELD(s) ((s)->sy_symbol.ost_flags & SF_NORMAL_MASK)
+#define SF_GET_DEBUG_FIELD(s) ((s)->sy_symbol.ost_flags & SF_DEBUG_MASK)
+#define SF_GET_FILE(s) ((s)->sy_symbol.ost_flags & SF_FILE)
+#define SF_GET_STATICS(s) ((s)->sy_symbol.ost_flags & SF_STATICS)
+#define SF_GET_DEFINED(s) ((s)->sy_symbol.ost_flags & SF_DEFINED)
+#define SF_GET_STRING(s) ((s)->sy_symbol.ost_flags & SF_STRING)
+#define SF_GET_LOCAL(s) ((s)->sy_symbol.ost_flags & SF_LOCAL)
+#define SF_GET_FUNCTION(s) ((s)->sy_symbol.ost_flags & SF_FUNCTION)
+#define SF_GET_PROCESS(s) ((s)->sy_symbol.ost_flags & SF_PROCESS)
+#define SF_GET_DEBUG(s) ((s)->sy_symbol.ost_flags & SF_DEBUG)
+#define SF_GET_TAGGED(s) ((s)->sy_symbol.ost_flags & SF_TAGGED)
+#define SF_GET_TAG(s) ((s)->sy_symbol.ost_flags & SF_TAG)
+#define SF_GET_GET_SEGMENT(s) ((s)->sy_symbol.ost_flags & SF_GET_SEGMENT)
+#define SF_GET_I960(s) ((s)->sy_symbol.ost_flags & SF_I960_MASK) /* used by i960 */
+#define SF_GET_BALNAME(s) ((s)->sy_symbol.ost_flags & SF_BALNAME) /* used by i960 */
+#define SF_GET_CALLNAME(s) ((s)->sy_symbol.ost_flags & SF_CALLNAME) /* used by i960 */
+#define SF_GET_IS_SYSPROC(s) ((s)->sy_symbol.ost_flags & SF_IS_SYSPROC) /* used by i960 */
+#define SF_GET_SYSPROC(s) ((s)->sy_symbol.ost_flags & SF_SYSPROC) /* used by i960 */
+
+/* Modifiers */
+#define SF_SET(s,v) ((s)->sy_symbol.ost_flags = (v))
+#define SF_SET_NORMAL_FIELD(s,v)((s)->sy_symbol.ost_flags |= ((v) & SF_NORMAL_MASK))
+#define SF_SET_DEBUG_FIELD(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_DEBUG_MASK))
+#define SF_SET_FILE(s) ((s)->sy_symbol.ost_flags |= SF_FILE)
+#define SF_SET_STATICS(s) ((s)->sy_symbol.ost_flags |= SF_STATICS)
+#define SF_SET_DEFINED(s) ((s)->sy_symbol.ost_flags |= SF_DEFINED)
+#define SF_SET_STRING(s) ((s)->sy_symbol.ost_flags |= SF_STRING)
+#define SF_SET_LOCAL(s) ((s)->sy_symbol.ost_flags |= SF_LOCAL)
+#define SF_CLEAR_LOCAL(s) ((s)->sy_symbol.ost_flags &= ~SF_LOCAL)
+#define SF_SET_FUNCTION(s) ((s)->sy_symbol.ost_flags |= SF_FUNCTION)
+#define SF_SET_PROCESS(s) ((s)->sy_symbol.ost_flags |= SF_PROCESS)
+#define SF_SET_DEBUG(s) ((s)->sy_symbol.ost_flags |= SF_DEBUG)
+#define SF_SET_TAGGED(s) ((s)->sy_symbol.ost_flags |= SF_TAGGED)
+#define SF_SET_TAG(s) ((s)->sy_symbol.ost_flags |= SF_TAG)
+#define SF_SET_GET_SEGMENT(s) ((s)->sy_symbol.ost_flags |= SF_GET_SEGMENT)
+#define SF_SET_I960(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_I960_MASK)) /* used by i960 */
+#define SF_SET_BALNAME(s) ((s)->sy_symbol.ost_flags |= SF_BALNAME) /* used by i960 */
+#define SF_SET_CALLNAME(s) ((s)->sy_symbol.ost_flags |= SF_CALLNAME) /* used by i960 */
+#define SF_SET_IS_SYSPROC(s) ((s)->sy_symbol.ost_flags |= SF_IS_SYSPROC) /* used by i960 */
+#define SF_SET_SYSPROC(s,v) ((s)->sy_symbol.ost_flags |= ((v) & SF_SYSPROC)) /* used by i960 */
+
+/* File header macro and type definition */
+
+/*
+ * File position calculators. Beware to use them when all the
+ * appropriate fields are set in the header.
+ */
+
+#ifdef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define OBJ_COFF_AOUTHDRSZ (0)
+#else
+#define OBJ_COFF_AOUTHDRSZ (AOUTHDRSZ)
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_FILE_SIZE(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h) + \
+ H_GET_SYMBOL_TABLE_SIZE(h) + \
+ (h)->string_table_size)
+#define H_GET_TEXT_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ)
+#define H_GET_DATA_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h))
+#define H_GET_BSS_FILE_OFFSET(h) 0
+#define H_GET_RELOCATION_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h))
+#define H_GET_LINENO_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h))
+#define H_GET_SYMBOL_TABLE_FILE_OFFSET(h) \
+ (long)(FILHSZ + OBJ_COFF_AOUTHDRSZ + \
+ H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ + \
+ H_GET_TEXT_SIZE(h) + H_GET_DATA_SIZE(h) + \
+ H_GET_RELOCATION_SIZE(h) + H_GET_LINENO_SIZE(h))
+
+/* Accessors */
+/* aouthdr */
+#define H_GET_MAGIC_NUMBER(h) ((h)->aouthdr.magic)
+#define H_GET_VERSION_STAMP(h) ((h)->aouthdr.vstamp)
+#define H_GET_TEXT_SIZE(h) ((h)->aouthdr.tsize)
+#define H_GET_DATA_SIZE(h) ((h)->aouthdr.dsize)
+#define H_GET_BSS_SIZE(h) ((h)->aouthdr.bsize)
+#define H_GET_ENTRY_POINT(h) ((h)->aouthdr.entry)
+#define H_GET_TEXT_START(h) ((h)->aouthdr.text_start)
+#define H_GET_DATA_START(h) ((h)->aouthdr.data_start)
+/* filehdr */
+#define H_GET_FILE_MAGIC_NUMBER(h) ((h)->filehdr.f_magic)
+#define H_GET_NUMBER_OF_SECTIONS(h) ((h)->filehdr.f_nscns)
+#define H_GET_TIME_STAMP(h) ((h)->filehdr.f_timdat)
+#define H_GET_SYMBOL_TABLE_POINTER(h) ((h)->filehdr.f_symptr)
+#define H_GET_SYMBOL_COUNT(h) ((h)->filehdr.f_nsyms)
+#define H_GET_SYMBOL_TABLE_SIZE(h) (H_GET_SYMBOL_COUNT(h) * SYMESZ)
+#define H_GET_SIZEOF_OPTIONAL_HEADER(h) ((h)->filehdr.f_opthdr)
+#define H_GET_FLAGS(h) ((h)->filehdr.f_flags)
+/* Extra fields to achieve bsd a.out compatibility and for convenience */
+#define H_GET_RELOCATION_SIZE(h) ((h)->relocation_size)
+#define H_GET_STRING_SIZE(h) ((h)->string_table_size)
+#define H_GET_LINENO_SIZE(h) ((h)->lineno_size)
+
+#ifndef OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \
+ + sizeof(AOUTHDR)\
+ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#else /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+#define H_GET_HEADER_SIZE(h) (sizeof(FILHDR) \
+ + (H_GET_NUMBER_OF_SECTIONS(h) * SCNHSZ))
+#endif /* OBJ_COFF_OMIT_OPTIONAL_HEADER */
+
+#define H_GET_TEXT_RELOCATION_SIZE(h) (text_section_header.s_nreloc * RELSZ)
+#define H_GET_DATA_RELOCATION_SIZE(h) (data_section_header.s_nreloc * RELSZ)
+
+/* Modifiers */
+/* aouthdr */
+#define H_SET_MAGIC_NUMBER(h,v) ((h)->aouthdr.magic = (v))
+#define H_SET_VERSION_STAMP(h,v) ((h)->aouthdr.vstamp = (v))
+#define H_SET_TEXT_SIZE(h,v) ((h)->aouthdr.tsize = (v))
+#define H_SET_DATA_SIZE(h,v) ((h)->aouthdr.dsize = (v))
+#define H_SET_BSS_SIZE(h,v) ((h)->aouthdr.bsize = (v))
+#define H_SET_ENTRY_POINT(h,v) ((h)->aouthdr.entry = (v))
+#define H_SET_TEXT_START(h,v) ((h)->aouthdr.text_start = (v))
+#define H_SET_DATA_START(h,v) ((h)->aouthdr.data_start = (v))
+/* filehdr */
+#define H_SET_FILE_MAGIC_NUMBER(h,v) ((h)->filehdr.f_magic = (v))
+#define H_SET_NUMBER_OF_SECTIONS(h,v) ((h)->filehdr.f_nscns = (v))
+#define H_SET_TIME_STAMP(h,v) ((h)->filehdr.f_timdat = (v))
+#define H_SET_SYMBOL_TABLE_POINTER(h,v) ((h)->filehdr.f_symptr = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->filehdr.f_nsyms = (v))
+#define H_SET_SIZEOF_OPTIONAL_HEADER(h,v) ((h)->filehdr.f_opthdr = (v))
+#define H_SET_FLAGS(h,v) ((h)->filehdr.f_flags = (v))
+/* Extra fields to achieve bsd a.out compatibility and for convinience */
+#define H_SET_RELOCATION_SIZE(h,t,d) ((h)->relocation_size = (t)+(d))
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+#define H_SET_LINENO_SIZE(h,v) ((h)->lineno_size = (v))
+
+/* Segment flipping */
+#define segment_name(v) (seg_name[(int) (v)])
+
+typedef struct {
+#ifdef BFD_HEADERS
+ struct internal_aouthdr aouthdr; /* a.out header */
+ struct internal_filehdr filehdr; /* File header, not machine dep. */
+#else
+ AOUTHDR aouthdr; /* a.out header */
+ FILHDR filehdr; /* File header, not machine dep. */
+#endif
+ long string_table_size; /* names + '\0' + sizeof(int) */
+ long relocation_size; /* Cumulated size of relocation
+ information for all sections in
+ bytes. */
+ long lineno_size; /* Size of the line number information
+ table in bytes */
+} object_headers;
+
+
+
+struct lineno_list
+{
+
+ struct bfd_internal_lineno line;
+ char* frag; /* Frag to which the line number is related */
+ struct lineno_list* next; /* Forward chain pointer */
+} ;
+
+
+
+
+/* stack stuff */
+typedef struct {
+ unsigned long chunk_size;
+ unsigned long element_size;
+ unsigned long size;
+ char* data;
+ unsigned long pointer;
+} stack;
+
+
+
+char *EXFUN(stack_pop,(stack *st));
+char *EXFUN(stack_push,(stack *st, char *element));
+char *EXFUN(stack_top,(stack *st));
+stack *EXFUN(stack_init,(unsigned long chunk_size, unsigned long element_size));
+void EXFUN(c_dot_file_symbol,(char *filename));
+void EXFUN(obj_extra_stuff,(object_headers *headers));
+void EXFUN(stack_delete,(stack *st));
+
+
+
+void EXFUN(c_section_header,(
+
+ struct internal_scnhdr *header,
+ char *name,
+ long core_address,
+ long size,
+ long data_ptr,
+ long reloc_ptr,
+ long lineno_ptr,
+ long reloc_number,
+ long lineno_number,
+ long alignment));
+
+
+/* sanity check */
+
+#ifdef TC_I960
+#ifndef C_LEAFSTAT
+hey! Where is the C_LEAFSTAT definition? i960-coff support is depending on it.
+#endif /* no C_LEAFSTAT */
+#endif /* TC_I960 */
+#ifdef BFD_HEADERS
+ extern struct internal_scnhdr data_section_header;
+extern struct internal_scnhdr text_section_header;
+#else
+extern SCNHDR data_section_header;
+extern SCNHDR text_section_header;
+#endif
+#endif
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-coffbfd.h */
diff --git a/gnu/usr.bin/as/config/obj-generic.c b/gnu/usr.bin/as/config/obj-generic.c
new file mode 100644
index 0000000..2f69ce4
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-generic.c
@@ -0,0 +1,41 @@
+/* This file is obj-generic.c and is intended to be a template for
+ object format specific source files.
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment */
+const char comment_chars[] = "#";
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-generic.c */
diff --git a/gnu/usr.bin/as/config/obj-generic.h b/gnu/usr.bin/as/config/obj-generic.h
new file mode 100644
index 0000000..24a6ace
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-generic.h
@@ -0,0 +1,78 @@
+/* This file is obj-generic.h
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file is obj-generic.h and is intended to be a template for
+ * object format specific header files.
+ */
+
+/* define an obj specific macro off which target cpu back ends may key. */
+#define OBJ_GENERIC 1
+
+/* include whatever target cpu is appropriate. */
+#include "targ-cpu.h"
+
+/*
+ * SYMBOLS
+ */
+
+/*
+ * If your object format needs to reorder symbols, define this. When
+ * defined, symbols are kept on a doubly linked list and functions are
+ * made available for push, insert, append, and delete. If not defined,
+ * symbols are kept on a singly linked list, only the append and clear
+ * facilities are available, and they are macros.
+ */
+
+/* #define SYMBOLS_NEED_PACKPOINTERS */
+
+/* */
+typedef struct {
+ void *nothing;
+} obj_symbol_type; /* should be the format's symbol structure */
+
+typedef void *object_headers;
+
+/* symbols have names */
+#define S_GET_NAME(s) ("foo") /* get the name of a symbolP */
+#define S_SET_NAME(s,v) ;
+ /* symbols have segments */
+#define S_GET_SEGMENT(s) (SEG_UNKNOWN)
+#define S_SET_SEGMENT(s,v) ;
+ /* symbols have a value */
+#define S_GET_VALUE(s) (0)
+#define S_SET_VALUE(s,v) ;
+ /* symbols may be external */
+#define S_IS_EXTERNAL(s) (0)
+#define S_SET_EXTERNAL(s) ;
+
+ /* symbols may or may not be defined */
+#define S_IS_DEFINED(s) (0)
+
+
+#define OBJ_EMIT_LINENO(a,b,c) /* must be *something*. This no-op's it out. */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-generic.h */
diff --git a/gnu/usr.bin/as/config/obj-ieee.c b/gnu/usr.bin/as/config/obj-ieee.c
new file mode 100644
index 0000000..c190999
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-ieee.c
@@ -0,0 +1,539 @@
+/* obj-format for ieee-695 records.
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ created by
+
+ steve chamberlain steve@cygnus.com
+ */
+
+/*
+ this will hopefully become the port through which bfd and gas talk,
+ for the moment, only ieee is known to work well.
+ */
+
+#include "bfd.h"
+#include "as.h"
+#include "subsegs.h"
+#include "output-file.h"
+#include "frags.h"
+
+bfd *abfd;
+
+/* How many addresses does the .align take? */
+static relax_addressT relax_align(address, alignment)
+register relax_addressT address; /* Address now. */
+register long alignment; /* Alignment (binary). */
+{
+ relax_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~ ( (~0) << alignment );
+ new_address = (address + mask) & (~ mask);
+ return (new_address - address);
+} /* relax_align() */
+
+/* calculate the size of the frag chain and create a bfd section
+ to contain all of it */
+static void DEFUN(size_section,(abfd, idx),
+ bfd *abfd AND
+ unsigned int idx)
+{
+ asection *sec;
+ unsigned int size = 0;
+ fragS *frag = segment_info[idx].frag_root;
+ while (frag) {
+ if (frag->fr_address != size) {
+ printf("Out of step\n");
+ size = frag->fr_address;
+ }
+ size += frag->fr_fix;
+ switch (frag->fr_type) {
+ case rs_fill:
+ case rs_org:
+ size += frag->fr_offset * frag->fr_var;
+ break;
+ case rs_align:
+ size += relax_align(size, frag->fr_offset);
+ }
+ frag = frag->fr_next;
+ }
+ if (size) {
+ char *name = segment_info[idx].name;
+ if (name == (char *)NULL) {
+ name = ".data";
+ }
+ segment_info[idx].user_stuff = (char *)(sec = bfd_make_section(abfd, name));
+ /* Make it output through itself */
+ sec->output_section = sec;
+ sec->flags |= SEC_HAS_CONTENTS;
+ bfd_set_section_size(abfd, sec, size);
+ }
+}
+
+/* run through a frag chain and write out the data to go with it */
+static void DEFUN(fill_section,(abfd, idx),
+ bfd *abfd AND
+ unsigned int idx)
+{
+ asection *sec = segment_info[idx].user_stuff;
+ if (sec) {
+ fragS *frag = segment_info[idx].frag_root;
+ unsigned int offset = 0;
+ while (frag) {
+ unsigned int fill_size;
+ unsigned int count;
+ switch (frag->fr_type) {
+ case rs_fill:
+ case rs_align:
+ case rs_org:
+ if (frag->fr_fix)
+ {
+ bfd_set_section_contents(abfd,
+ sec,
+ frag->fr_literal,
+ frag->fr_address,
+ frag->fr_fix);
+ }
+ offset += frag->fr_fix;
+ fill_size = frag->fr_var;
+ if (fill_size)
+ {
+ unsigned int off = frag->fr_fix;
+ for (count = frag->fr_offset; count; count--)
+ {
+ bfd_set_section_contents(abfd, sec,
+ frag->fr_literal +
+ frag->fr_fix,
+ frag->fr_address + off,
+ fill_size);
+ off += fill_size;
+ }
+ }
+ break;
+ default:
+ abort();
+ }
+ frag = frag->fr_next;
+ }
+ }
+}
+
+/* Count the relocations in a chain */
+
+static unsigned int DEFUN(count_entries_in_chain,(idx),
+ unsigned int idx)
+{
+ unsigned int nrelocs;
+ fixS *fixup_ptr;
+
+ /* Count the relocations */
+ fixup_ptr = segment_info[idx].fix_root;
+ nrelocs = 0;
+ while (fixup_ptr != (fixS *)NULL)
+ {
+ fixup_ptr = fixup_ptr->fx_next;
+ nrelocs ++ ;
+ }
+ return nrelocs;
+}
+
+/* output all the relocations for a section */
+void DEFUN(do_relocs_for,(idx),
+ unsigned int idx)
+{
+ unsigned int nrelocs;
+ arelent **reloc_ptr_vector;
+ arelent *reloc_vector;
+ asymbol **ptrs;
+ asection *section = (asection *)(segment_info[idx].user_stuff);
+ unsigned int i;
+ fixS *from;
+ if (section) {
+ nrelocs = count_entries_in_chain(idx);
+
+ reloc_ptr_vector = (arelent**)malloc((nrelocs+1) * sizeof(arelent *));
+ reloc_vector = (arelent*)malloc(nrelocs * sizeof(arelent));
+ ptrs = (asymbol **)malloc(nrelocs * sizeof(asymbol *));
+ from = segment_info[idx].fix_root;
+ for (i = 0; i < nrelocs; i++)
+ {
+ arelent *to = reloc_vector + i;
+ asymbol *s ;
+ reloc_ptr_vector[i] = to;
+ to->howto = (reloc_howto_type *)(from->fx_r_type);
+
+ /* We can't represent complicated things in a reloc yet */
+ /* if (from->fx_addsy == 0 ||
+ from->fx_subsy != 0) abort();
+ */
+ s = &( from->fx_addsy->sy_symbol.sy);
+ to->address = ((char *)( from->fx_frag->fr_address +
+ from->fx_where))
+ - ((char *)(&(from->fx_frag->fr_literal)));
+ to->addend = from->fx_offset ;
+ /* If we know the symbol which we want to relocate to, turn this
+ reloaction into a section relative.
+
+ If this relocation is pcrelative, and we know the
+ destination, we still want to keep the relocation - since
+ the linker might relax some of the bytes, but it stops
+ being pc relative and turns into an absolute relocation.
+
+ */
+ if (s) {
+ if ((s->flags & BSF_UNDEFINED) == 0) {
+ to->section = s->section;
+ to->addend += s->value ;
+ to->sym_ptr_ptr = 0;
+ if (to->howto->pcrel_offset) {
+ /* This is a pcrel relocation, the addend should be adjusted */
+ to->addend -= to->address +1;
+ }
+ }
+ else {
+ to->section = 0;
+ *ptrs = &(from->fx_addsy->sy_symbol.sy);
+ to->sym_ptr_ptr = ptrs;
+
+ if (to->howto->pcrel_offset) {
+ /* This is a pcrel relocation, the addend should be adjusted */
+ to->addend -= to->address -1;
+ }
+ }
+
+ }
+ else {
+ to->section = 0;
+ }
+
+ ptrs++;
+ from = from->fx_next;
+ }
+
+ /* attatch to the section */
+ section->orelocation = reloc_ptr_vector;
+ section->reloc_count = nrelocs;
+ section->flags |= SEC_LOAD;
+ }
+}
+
+/* do the symbols.. */
+static void DEFUN(do_symbols, (abfd),
+ bfd *abfd)
+{
+ extern symbolS *symbol_rootP;
+ symbolS *ptr;
+ asymbol **symbol_ptr_vec;
+ asymbol *symbol_vec;
+ unsigned int count = 0;
+ unsigned int index;
+
+
+ for (ptr = symbol_rootP;
+ ptr != (symbolS *)NULL;
+ ptr = ptr->sy_next)
+ {
+ if (SEG_NORMAL(ptr->sy_symbol.seg))
+ {
+ ptr->sy_symbol.sy.section =
+ (asection *)(segment_info[ptr->sy_symbol.seg].user_stuff);
+ ptr->sy_symbol.sy.value += ptr->sy_frag->fr_address;
+ if (ptr->sy_symbol.sy.flags == 0) {
+ ptr->sy_symbol.sy.flags = BSF_LOCAL ;
+ }
+ }
+ else {
+ switch (ptr->sy_symbol.seg) {
+ case SEG_ABSOLUTE:
+ ptr->sy_symbol.sy.flags |= BSF_ABSOLUTE;
+ ptr->sy_symbol.sy.section = 0;
+ break;
+ case SEG_UNKNOWN:
+ ptr->sy_symbol.sy.flags = BSF_UNDEFINED ;
+ ptr->sy_symbol.sy.section = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+ count++;
+ }
+ symbol_ptr_vec = (asymbol **)malloc((count+1) * sizeof(asymbol *));
+
+ index = 0;
+ for (ptr = symbol_rootP;
+ ptr != (symbolS *)NULL;
+ ptr = ptr->sy_next)
+ {
+ symbol_ptr_vec[index] = &(ptr->sy_symbol.sy);
+ index++;
+ }
+ symbol_ptr_vec[index] =0;
+ abfd->outsymbols = symbol_ptr_vec;
+ abfd->symcount = count;
+}
+
+/* The generic as->bfd converter. Other backends may have special case
+ code */
+
+void DEFUN_VOID(bfd_as_write_hook)
+{
+ int i;
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++) {
+ size_section(abfd, i);
+ }
+
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ fill_section(abfd,i);
+
+ do_symbols(abfd);
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ do_relocs_for(i);
+
+}
+
+
+
+S_GET_VALUE(x)
+symbolS *x;
+{
+ return x->sy_symbol.sy.value;
+}
+
+S_SET_SEGMENT(x,y)
+symbolS *x ;
+int y;
+{
+ x->sy_symbol.seg = y;
+}
+
+S_IS_DEFINED(x)
+symbolS *x;
+{
+ if (SEG_NORMAL(x->sy_symbol.seg))
+ {
+ return 1;
+ }
+ switch (x->sy_symbol.seg)
+ {
+ case SEG_UNKNOWN:
+ return 0;
+ default:
+ abort();
+ }
+}
+
+S_IS_EXTERNAL(x) { abort(); }
+S_GET_DESC(x) { abort() ; }
+
+S_GET_SEGMENT(x)
+symbolS *x;
+{ return x->sy_symbol.seg; }
+
+S_SET_EXTERNAL(x)
+symbolS *x;
+{
+ x->sy_symbol.sy.flags |= BSF_GLOBAL | BSF_EXPORT;
+}
+
+S_SET_NAME(x,y)
+symbolS*x;
+char *y; {
+ x->sy_symbol.sy.name = y; }
+
+S_SET_VALUE(s,v)
+symbolS *s;
+long v;
+{
+ s->sy_symbol.sy.value = v;
+}
+
+S_GET_OTHER(x) { abort() ;}
+S_IS_DEBUG(x) { abort(); }
+
+char *segment_name() { abort(); }
+
+void obj_read_begin_hook() { }
+
+static void obj_ieee_section(ignore)
+int ignore;
+{
+ extern char *input_line_pointer;
+ extern char is_end_of_line[];
+ char *p= input_line_pointer;
+ char *s = p;
+ int i;
+ /* Look up the name, if it doesn't exist, make it */
+ while (*p &&* p != ' ' && *p != ',' && !is_end_of_line[*p]) {
+ p++;
+ }
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++) {
+ if (segment_info[i].hadone){
+ if (strncmp(segment_info[i].name, s, p-s) == 0) {
+ goto ok;
+
+ }
+ }
+ else break;
+ }
+ if (i == SEG_UNKNOWN) {
+ as_bad("too many sections");
+ return;
+ }
+
+ segment_info[i].hadone = 1;
+ segment_info[i].name = malloc(p-s + 1);
+ memcpy(segment_info[i].name, s, p-s);
+ segment_info[i].name[p-s] = 0;
+ ok:
+ subseg_new(i,0);
+ while (!is_end_of_line[*p])
+ p++;
+ input_line_pointer = p;
+
+}
+
+
+void cons();
+void s_ignore();
+
+
+/*
+ * stringer()
+ *
+ * We read 0 or more ',' seperated, double-quoted strings.
+ *
+ * Caller should have checked need_pass_2 is FALSE because we don't check it.
+ */
+
+void stringer();
+void s_globl();
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"section", obj_ieee_section, 0},
+ {"data.b", cons, 1},
+ {"data.w", cons, 2},
+ {"data.l", cons, 4},
+ {"export", s_globl, 0},
+ {"option", s_ignore, 0},
+ {"end", s_ignore, 0},
+ {"import", s_ignore, 0},
+ {"sdata", stringer, 0},
+ 0,
+
+};
+
+
+
+void obj_symbol_new_hook(symbolP)
+symbolS *symbolP;
+{
+ symbolP->sy_symbol.sy.the_bfd = abfd;
+}
+
+
+
+
+
+#if 1
+extern void DEFUN_VOID(write_object_file)
+{
+ int i;
+ struct frchain *frchain_ptr;
+ struct frag *frag_ptr;
+
+ abfd = bfd_openw(out_file_name, "ieee");
+
+ if (abfd == 0) {
+ as_perror ("FATAL: Can't create %s", out_file_name);
+ exit(42);
+ }
+ bfd_set_format(abfd, bfd_object);
+ bfd_set_arch_mach(abfd, bfd_arch_h8300, 0);
+ subseg_new(1,0);
+ subseg_new(2,0);
+ subseg_new(3,0);
+ for (frchain_ptr = frchain_root;
+ frchain_ptr != (struct frchain *)NULL;
+ frchain_ptr = frchain_ptr->frch_next) {
+ /* Run through all the sub-segments and align them up. Also close any
+ open frags. We tack a .fill onto the end of the frag chain so
+ that any .align's size can be worked by looking at the next
+ frag */
+
+ subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
+#define SUB_SEGMENT_ALIGN 2
+ frag_align(SUB_SEGMENT_ALIGN,0);
+ frag_wane(frag_now);
+ frag_now->fr_fix = 0;
+ know( frag_now->fr_next == NULL );
+ }
+
+ /* Now build one big frag chain for each segment, linked through
+ fr_next. */
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++)
+ {
+
+ fragS ** prev_frag_ptr_ptr ;
+ struct frchain *next_frchain_ptr;
+
+ /* struct frag **head_ptr = segment_info[i].frag_root;*/
+
+ segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
+#if 0
+ /* Im not sure what this is for */
+ for (frchain_ptr = segment_info[i].frchainP->frch_root;
+ frchain_ptr != (struct frchain *)NULL;
+ frchain_ptr = frchain_ptr->frch_next)
+ {
+ *head_ptr = frchain_ptr;
+ head_ptr = &frchain_ptr->next;
+ }
+
+
+#endif
+ }
+
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++) {
+ relax_segment(segment_info[i].frag_root, i);
+ }
+
+ /* Now the addresses of the frags are correct within the segment */
+
+ bfd_as_write_hook();
+ bfd_close(abfd);
+}
+
+#endif
+
+H_SET_TEXT_SIZE(a,b) { abort(); }
+H_GET_TEXT_SIZE() { abort(); }
+H_SET_BSS_SIZE() { abort(); }
+H_SET_STRING_SIZE() { abort(); }
+H_SET_RELOCATION_SIZE() { abort(); }
+H_SET_MAGIC_NUMBER() { abort(); }
+H_GET_FILE_SIZE() { abort(); }
+H_GET_TEXT_RELOCATION_SIZE() { abort(); }
+
+/* end of obj-ieee.c */
diff --git a/gnu/usr.bin/as/config/obj-ieee.h b/gnu/usr.bin/as/config/obj-ieee.h
new file mode 100644
index 0000000..b2864bc
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-ieee.h
@@ -0,0 +1,46 @@
+/* This file is obj-ieee.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define BFD 1
+
+#include <bfd.h>
+
+typedef struct
+{
+asymbol sy;
+int seg;
+} obj_symbol_type;
+
+#define S_GET_NAME(s) (((s)->sy_symbol.sy.name))
+
+typedef struct {
+int x;
+}
+object_headers;
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE 1
+
+
+int lineno_rootP;
+
+
+#define IEEE_STYLE
+
+/* end of obj-ieee.h */
diff --git a/gnu/usr.bin/as/config/obj-vms.c b/gnu/usr.bin/as/config/obj-vms.c
new file mode 100644
index 0000000..2a51ba9
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-vms.c
@@ -0,0 +1,5484 @@
+/* vms.c -- Write out a VAX/VMS object file
+ Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by David L. Kashtan */
+/* Modified by Eric Youngdale to write VMS debug records for program
+ variables */
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+
+/* What we do if there is a goof. */
+#define error as_fatal
+
+#ifdef HO_VMS /* These are of no use if we are cross assembling. */
+#include <fab.h> /* Define File Access Block */
+#include <nam.h> /* Define NAM Block */
+#include <xab.h> /* Define XAB - all different types*/
+#endif
+/*
+ * Version string of the compiler that produced the code we are
+ * assembling. (And this assembler, if we do not have compiler info.)
+ */
+extern const char version_string[];
+char *compiler_version_string;
+
+/* Flag that determines how we map names. This takes several values, and
+ * is set with the -h switch. A value of zero implies names should be
+ * upper case, and the presence of the -h switch inhibits the case hack.
+ * No -h switch at all sets vms_name_mapping to 0, and allows case hacking.
+ * A value of 2 (set with -h2) implies names should be
+ * all lower case, with no case hack. A value of 3 (set with -h3) implies
+ * that case should be preserved. */
+
+/* If the -+ switch is given, then the hash is appended to any name that is
+ * longer than 31 characters, irregardless of the setting of the -h switch.
+ */
+
+char vms_name_mapping = 0;
+
+
+extern char *strchr ();
+extern char *myname;
+static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
+
+/*
+ * We augment the "gas" symbol structure with this
+ */
+struct VMS_Symbol
+{
+ struct VMS_Symbol *Next;
+ struct symbol *Symbol;
+ int Size;
+ int Psect_Index;
+ int Psect_Offset;
+};
+struct VMS_Symbol *VMS_Symbols = 0;
+
+/* We need this to keep track of the various input files, so that we can
+ * give the debugger the correct source line.
+ */
+
+struct input_file
+{
+ struct input_file *next;
+ struct input_file *same_file_fpnt;
+ int file_number;
+ int max_line;
+ int min_line;
+ int offset;
+ char flag;
+ char *name;
+ symbolS *spnt;
+};
+
+static struct input_file *file_root = (struct input_file *) NULL;
+
+
+static struct input_file *find_file (symbolS *);
+
+/*
+ * This enum is used to keep track of the various types of variables that
+ * may be present.
+ */
+
+enum advanced_type
+{
+ BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, UNKNOWN
+};
+
+/*
+ * This structure contains the information from the stabs directives, and the
+ * information is filled in by VMS_typedef_parse. Everything that is needed
+ * to generate the debugging record for a given symbol is present here.
+ * This could be done more efficiently, using nested struct/unions, but for now
+ * I am happy that it works.
+ */
+struct VMS_DBG_Symbol
+{
+ struct VMS_DBG_Symbol *next;
+ enum advanced_type advanced; /* description of what this is */
+ int dbx_type; /* this record is for this type */
+ int type2; /* For advanced types this is the type referred to.
+ i.e. the type a pointer points to, or the type
+ of object that makes up an array */
+ int VMS_type; /* Use this type when generating a variable def */
+ int index_min; /* used for arrays - this will be present for all */
+ int index_max; /* entries, but will be meaningless for non-arrays */
+ int data_size; /* size in bytes of the data type. For an array, this
+ is the size of one element in the array */
+ int struc_numb; /* Number of the structure/union/enum - used for ref */
+};
+
+struct VMS_DBG_Symbol *VMS_Symbol_type_list =
+{(struct VMS_DBG_Symbol *) NULL};
+
+/*
+ * We need this structure to keep track of forward references to
+ * struct/union/enum that have not been defined yet. When they are ultimately
+ * defined, then we can go back and generate the TIR commands to make a back
+ * reference.
+ */
+
+struct forward_ref
+{
+ struct forward_ref *next;
+ int dbx_type;
+ int struc_numb;
+ char resolved;
+};
+
+struct forward_ref *f_ref_root =
+{(struct forward_ref *) NULL};
+
+/*
+ * This routine is used to compare the names of certain types to various
+ * fixed types that are known by the debugger.
+ */
+#define type_check(x) !strcmp( symbol_name , x )
+
+/*
+ * This variable is used to keep track of the name of the symbol we are
+ * working on while we are parsing the stabs directives.
+ */
+static char *symbol_name;
+
+/* We use this counter to assign numbers to all of the structures, unions
+ * and enums that we define. When we actually declare a variable to the
+ * debugger, we can simply do it by number, rather than describing the
+ * whole thing each time.
+ */
+
+static structure_count = 0;
+
+/* This variable is used to keep track of the current structure number
+ * for a given variable. If this is < 0, that means that the structure
+ * has not yet been defined to the debugger. This is still cool, since
+ * the VMS object language has ways of fixing things up after the fact,
+ * so we just make a note of this, and generate fixups at the end.
+ */
+static int struct_number;
+
+
+/*
+ * Variable descriptors are used tell the debugger the data types of certain
+ * more complicated variables (basically anything involving a structure,
+ * union, enum, array or pointer). Some non-pointer variables of the
+ * basic types that the debugger knows about do not require a variable
+ * descriptor.
+ *
+ * Since it is impossible to have a variable descriptor longer than 128
+ * bytes by virtue of the way that the VMS object language is set up,
+ * it makes not sense to make the arrays any longer than this, or worrying
+ * about dynamic sizing of the array.
+ *
+ * These are the arrays and counters that we use to build a variable
+ * descriptor.
+ */
+
+#define MAX_DEBUG_RECORD 128
+static char Local[MAX_DEBUG_RECORD]; /* buffer for variable descriptor */
+static char Asuffix[MAX_DEBUG_RECORD]; /* buffer for array descriptor */
+static int Lpnt; /* index into Local */
+static int Apoint; /* index into Asuffix */
+static char overflow; /* flag to indicate we have written too much*/
+static int total_len; /* used to calculate the total length of variable
+ descriptor plus array descriptor - used for len byte*/
+
+/* Flag if we have told user about finding global constants in the text
+ section. */
+static gave_compiler_message = 0;
+
+/* A pointer to the current routine that we are working on. */
+
+static symbolS *Current_Routine;
+
+/* The psect number for $code a.k.a. the text section. */
+
+static int Text_Psect;
+
+
+/*
+ * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
+ */
+static int VMS_Object_File_FD; /* File Descriptor for object file */
+static char Object_Record_Buffer[512]; /* Buffer for object file records */
+static int Object_Record_Offset;/* Offset to end of data */
+static int Current_Object_Record_Type; /* Type of record in above */
+
+/*
+ * Macros for placing data into the object record buffer
+ */
+
+#define PUT_LONG(val) \
+{ md_number_to_chars(Object_Record_Buffer + \
+ Object_Record_Offset, val, 4); \
+ Object_Record_Offset += 4; }
+
+#define PUT_SHORT(val) \
+{ md_number_to_chars(Object_Record_Buffer + \
+ Object_Record_Offset, val, 2); \
+ Object_Record_Offset += 2; }
+
+#define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val
+
+#define PUT_COUNTED_STRING(cp) {\
+ register char *p = cp; \
+ PUT_CHAR(strlen(p)); \
+ while (*p) PUT_CHAR(*p++);}
+
+/*
+ * Macro for determining if a Name has psect attributes attached
+ * to it.
+ */
+#define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"
+#define PSECT_ATTRIBUTES_STRING_LENGTH 18
+
+#define HAS_PSECT_ATTRIBUTES(Name) \
+ (strncmp((Name[0] == '_' ? Name + 1 : Name), \
+ PSECT_ATTRIBUTES_STRING, \
+ PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
+
+
+ /* in: segT out: N_TYPE bits */
+const short seg_N_TYPE[] =
+{
+ N_ABS,
+ N_TEXT,
+ N_DATA,
+ N_BSS,
+ N_UNDF, /* unknown */
+ N_UNDF, /* absent */
+ N_UNDF, /* pass1 */
+ N_UNDF, /* error */
+ N_UNDF, /* bignum/flonum */
+ N_UNDF, /* difference */
+ N_UNDF, /* debug */
+ N_UNDF, /* ntv */
+ N_UNDF, /* ptv */
+ N_REGISTER, /* register */
+};
+
+const segT N_TYPE_seg[N_TYPE + 2] =
+{ /* N_TYPE == 0x1E = 32-2 */
+ SEG_UNKNOWN, /* N_UNDF == 0 */
+ SEG_GOOF,
+ SEG_ABSOLUTE, /* N_ABS == 2 */
+ SEG_GOOF,
+ SEG_TEXT, /* N_TEXT == 4 */
+ SEG_GOOF,
+ SEG_DATA, /* N_DATA == 6 */
+ SEG_GOOF,
+ SEG_BSS, /* N_BSS == 8 */
+ SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
+ SEG_REGISTER, /* dummy N_REGISTER for regs = 30 */
+ SEG_GOOF,
+};
+
+
+/* The following code defines the special types of pseudo-ops that we
+ * use with VMS.
+ */
+
+char const_flag = 0;
+
+void
+s_const ()
+{
+ register int temp;
+
+ temp = get_absolute_expression ();
+ subseg_new (SEG_DATA, (subsegT) temp);
+ const_flag = 1;
+ demand_empty_rest_of_line ();
+}
+
+/*
+ * stab()
+ *
+ * Handle .stabX directives, which used to be open-coded.
+ * So much creeping featurism overloaded the semantics that we decided
+ * to put all .stabX thinking in one place. Here.
+ *
+ * We try to make any .stabX directive legal. Other people's AS will often
+ * do assembly-time consistency checks: eg assigning meaning to n_type bits
+ * and "protecting" you from setting them to certain values. (They also zero
+ * certain bits before emitting symbols. Tut tut.)
+ *
+ * If an expression is not absolute we either gripe or use the relocation
+ * information. Other people's assemblers silently forget information they
+ * don't need and invent information they need that you didn't supply.
+ *
+ * .stabX directives always make a symbol table entry. It may be junk if
+ * the rest of your .stabX directive is malformed.
+ */
+static void
+obj_aout_stab (what)
+ int what;
+{
+ register symbolS *symbolP = 0;
+ register char *string;
+ int saved_type = 0;
+ int length;
+ int goof; /* TRUE if we have aborted. */
+ long longint;
+
+/*
+ * Enter with input_line_pointer pointing past .stabX and any following
+ * whitespace.
+ */
+ goof = 0; /* JF who forgot this?? */
+ if (what == 's')
+ {
+ string = demand_copy_C_string (&length);
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == ',')
+ input_line_pointer++;
+ else
+ {
+ as_bad ("I need a comma after symbol's name");
+ goof = 1;
+ }
+ }
+ else
+ string = "";
+
+/*
+ * Input_line_pointer->after ','. String->symbol name.
+ */
+ if (!goof)
+ {
+ symbolP = symbol_new (string,
+ SEG_UNKNOWN,
+ 0,
+ (struct frag *) 0);
+ switch (what)
+ {
+ case 'd':
+ S_SET_NAME (symbolP, NULL); /* .stabd feature. */
+ S_SET_VALUE (symbolP, obstack_next_free (&frags) - frag_now->fr_literal);
+ symbolP->sy_frag = frag_now;
+ break;
+
+ case 'n':
+ symbolP->sy_frag = &zero_address_frag;
+ break;
+
+ case 's':
+ symbolP->sy_frag = &zero_address_frag;
+ break;
+
+ default:
+ BAD_CASE (what);
+ break;
+ }
+
+ if (get_absolute_expression_and_terminator (&longint) == ',')
+ symbolP->sy_symbol.n_type = saved_type = longint;
+ else
+ {
+ as_bad ("I want a comma after the n_type expression");
+ goof = 1;
+ input_line_pointer--; /* Backup over a non-',' char. */
+ }
+ }
+
+ if (!goof)
+ {
+ if (get_absolute_expression_and_terminator (&longint) == ',')
+ S_SET_OTHER (symbolP, longint);
+ else
+ {
+ as_bad ("I want a comma after the n_other expression");
+ goof = 1;
+ input_line_pointer--; /* Backup over a non-',' char. */
+ }
+ }
+
+ if (!goof)
+ {
+ S_SET_DESC (symbolP, get_absolute_expression ());
+ if (what == 's' || what == 'n')
+ {
+ if (*input_line_pointer != ',')
+ {
+ as_bad ("I want a comma after the n_desc expression");
+ goof = 1;
+ }
+ else
+ {
+ input_line_pointer++;
+ }
+ }
+ }
+
+ if ((!goof) && (what == 's' || what == 'n'))
+ {
+ pseudo_set (symbolP);
+ symbolP->sy_symbol.n_type = saved_type;
+ }
+
+ if (goof)
+ ignore_rest_of_line ();
+ else
+ demand_empty_rest_of_line ();
+} /* obj_aout_stab() */
+
+const pseudo_typeS obj_pseudo_table[] =
+{
+ {"stabd", obj_aout_stab, 'd'},/* stabs */
+ {"stabn", obj_aout_stab, 'n'},/* stabs */
+ {"stabs", obj_aout_stab, 's'},/* stabs */
+ {"const", s_const, 0},
+ {0, 0, 0},
+
+}; /* obj_pseudo_table */
+
+void
+obj_read_begin_hook ()
+{
+ return;
+} /* obj_read_begin_hook() */
+
+void
+obj_crawl_symbol_chain (headers)
+ object_headers *headers;
+{
+ symbolS *symbolP;
+ symbolS **symbolPP;
+ int symbol_number = 0;
+
+ /* JF deal with forward references first... */
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ if (symbolP->sy_forward)
+ {
+ S_SET_VALUE (symbolP, S_GET_VALUE (symbolP)
+ + S_GET_VALUE (symbolP->sy_forward)
+ + symbolP->sy_forward->sy_frag->fr_address);
+ symbolP->sy_forward = 0;
+ } /* if it has a forward reference */
+ } /* walk the symbol chain */
+
+ { /* crawl symbol table */
+ register int symbol_number = 0;
+
+ {
+ symbolPP = &symbol_rootP; /* -> last symbol chain link. */
+ while ((symbolP = *symbolPP) != NULL)
+ {
+ S_GET_VALUE (symbolP) += symbolP->sy_frag->fr_address;
+
+ /* OK, here is how we decide which symbols go out into the
+ brave new symtab. Symbols that do are:
+
+ * symbols with no name (stabd's?)
+ * symbols with debug info in their N_TYPE
+
+ Symbols that don't are:
+ * symbols that are registers
+ * symbols with \1 as their 3rd character (numeric labels)
+ * "local labels" as defined by S_LOCAL_NAME(name)
+ if the -L switch was passed to gas.
+
+ All other symbols are output. We complain if a deleted
+ symbol was marked external. */
+
+
+ if (!S_IS_REGISTER (symbolP))
+ {
+ symbolP->sy_name_offset = 0;
+ symbolPP = &(symbol_next (symbolP));
+ }
+ else
+ {
+ if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
+ {
+ as_bad ("Local symbol %s never defined", S_GET_NAME (symbolP));
+ } /* oops. */
+
+ } /* if this symbol should be in the output */
+ } /* for each symbol */
+ }
+ H_SET_STRING_SIZE (headers, string_byte_count);
+ H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
+ } /* crawl symbol table */
+
+} /* obj_crawl_symbol_chain() */
+
+
+ /****** VMS OBJECT FILE HACKING ROUTINES *******/
+
+
+/*
+ * Create the VMS object file
+ */
+static
+Create_VMS_Object_File ()
+{
+#if defined(eunice) || !defined(HO_VMS)
+ VMS_Object_File_FD = creat (out_file_name, 0777, "var");
+#else /* eunice */
+ VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var",
+ "mbc=16", "deq=64", "fop=tef", "shr=nil");
+#endif /* eunice */
+ /*
+ * Deal with errors
+ */
+ if (VMS_Object_File_FD < 0)
+ {
+ char Error_Line[256];
+
+ sprintf (Error_Line, "Couldn't create VMS object file \"%s\"",
+ out_file_name);
+ error (Error_Line);
+ }
+ /*
+ * Initialize object file hacking variables
+ */
+ Object_Record_Offset = 0;
+ Current_Object_Record_Type = -1;
+}
+
+
+/*
+ * Flush the object record buffer to the object file
+ */
+static
+Flush_VMS_Object_Record_Buffer ()
+{
+ int i;
+ short int zero;
+ /*
+ * If the buffer is empty, we are done
+ */
+ if (Object_Record_Offset == 0)
+ return;
+ /*
+ * Write the data to the file
+ */
+#ifndef HO_VMS /* For cross-assembly purposes. */
+ i = write (VMS_Object_File_FD, &Object_Record_Offset, 2);
+#endif /* not HO_VMS */
+ i = write (VMS_Object_File_FD,
+ Object_Record_Buffer,
+ Object_Record_Offset);
+ if (i != Object_Record_Offset)
+ error ("I/O error writing VMS object file");
+#ifndef HO_VMS /* When cross-assembling, we need to pad the record to an even
+ number of bytes. */
+ /* pad it if needed */
+ zero = 0;
+ if (Object_Record_Offset & 1 != 0)
+ write (VMS_Object_File_FD, &zero, 1);
+#endif /* not HO_VMS */
+ /*
+ * The buffer is now empty
+ */
+ Object_Record_Offset = 0;
+}
+
+
+/*
+ * Declare a particular type of object file record
+ */
+static
+Set_VMS_Object_File_Record (Type)
+ int Type;
+{
+ /*
+ * If the type matches, we are done
+ */
+ if (Type == Current_Object_Record_Type)
+ return;
+ /*
+ * Otherwise: flush the buffer
+ */
+ Flush_VMS_Object_Record_Buffer ();
+ /*
+ * Set the new type
+ */
+ Current_Object_Record_Type = Type;
+}
+
+
+
+/*
+ * Close the VMS Object file
+ */
+static
+Close_VMS_Object_File ()
+{
+ short int m_one = -1;
+#ifndef HO_VMS /* For cross-assembly purposes. */
+/* Write a 0xffff into the file, which means "End of File" */
+ write (VMS_Object_File_FD, &m_one, 2);
+#endif /* not HO_VMS */
+ close (VMS_Object_File_FD);
+}
+
+
+/*
+ * Store immediate data in current Psect
+ */
+static
+VMS_Store_Immediate_Data (Pointer, Size, Record_Type)
+ register char *Pointer;
+ int Size;
+ int Record_Type;
+{
+ register int i;
+
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * We can only store 128 bytes at a time
+ */
+ while (Size > 0)
+ {
+ /*
+ * Store a maximum of 128 bytes
+ */
+ i = (Size > 128) ? 128 : Size;
+ Size -= i;
+ /*
+ * If we cannot accommodate this record, flush the
+ * buffer.
+ */
+ if ((Object_Record_Offset + i + 1) >=
+ sizeof (Object_Record_Buffer))
+ Flush_VMS_Object_Record_Buffer ();
+ /*
+ * If the buffer is empty we must insert record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Store the count
+ */
+ PUT_CHAR (-i & 0xff);
+ /*
+ * Store the data
+ */
+ while (--i >= 0)
+ PUT_CHAR (*Pointer++);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+ }
+}
+
+/*
+ * Make a data reference
+ */
+static
+VMS_Set_Data (Psect_Index, Offset, Record_Type, Force)
+ int Psect_Index;
+ int Offset;
+ int Record_Type;
+ int Force;
+{
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * If the buffer is empty we must insert the record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Stack the Psect base + Longword Offset
+ */
+ if (Force == 1)
+ {
+ if (Psect_Index > 127)
+ {
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect_Index);
+ PUT_LONG (Offset);
+ }
+ else
+ {
+ PUT_CHAR (TIR_S_C_STA_PL);
+ PUT_CHAR (Psect_Index);
+ PUT_LONG (Offset);
+ }
+ }
+ else
+ {
+ if (Offset > 32767)
+ {
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect_Index);
+ PUT_LONG (Offset);
+ }
+ else if (Offset > 127)
+ {
+ PUT_CHAR (TIR_S_C_STA_WPW);
+ PUT_SHORT (Psect_Index);
+ PUT_SHORT (Offset);
+ }
+ else
+ {
+ PUT_CHAR (TIR_S_C_STA_WPB);
+ PUT_SHORT (Psect_Index);
+ PUT_CHAR (Offset);
+ };
+ };
+ /*
+ * Set relocation base
+ */
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+/*
+ * Make a debugger reference to a struct, union or enum.
+ */
+static
+VMS_Store_Struct (int Struct_Index)
+{
+ /*
+ * We are writing a "OBJ_S_C_DBG" record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_DBG);
+ /*
+ * If the buffer is empty we must insert the record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ PUT_CHAR (TIR_S_C_STA_UW);
+ PUT_SHORT (Struct_Index);
+ PUT_CHAR (TIR_S_C_CTL_STKDL);
+ PUT_CHAR (TIR_S_C_STO_L);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+/*
+ * Make a debugger reference to partially define a struct, union or enum.
+ */
+static
+VMS_Def_Struct (int Struct_Index)
+{
+ /*
+ * We are writing a "OBJ_S_C_DBG" record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_DBG);
+ /*
+ * If the buffer is empty we must insert the record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ PUT_CHAR (TIR_S_C_STA_UW);
+ PUT_SHORT (Struct_Index);
+ PUT_CHAR (TIR_S_C_CTL_DFLOC);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+static
+VMS_Set_Struct (int Struct_Index)
+{ /* see previous functions for comments */
+ Set_VMS_Object_File_Record (OBJ_S_C_DBG);
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ PUT_CHAR (TIR_S_C_STA_UW);
+ PUT_SHORT (Struct_Index);
+ PUT_CHAR (TIR_S_C_CTL_STLOC);
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+/*
+ * Write the Traceback Module Begin record
+ */
+static
+VMS_TBT_Module_Begin ()
+{
+ register char *cp, *cp1;
+ int Size;
+ char Module_Name[256];
+ char Local[256];
+
+ /*
+ * Get module name (the FILENAME part of the object file)
+ */
+ cp = out_file_name;
+ cp1 = Module_Name;
+ while (*cp)
+ {
+ if ((*cp == ']') || (*cp == '>') ||
+ (*cp == ':') || (*cp == '/'))
+ {
+ cp1 = Module_Name;
+ cp++;
+ continue;
+ }
+ *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++;
+ }
+ *cp1 = 0;
+ /*
+ * Limit it to 31 characters
+ */
+ while (--cp1 >= Module_Name)
+ if (*cp1 == '.')
+ *cp1 = 0;
+ if (strlen (Module_Name) > 31)
+ {
+ if (flagseen['+'])
+ printf ("%s: Module name truncated: %s\n", myname, Module_Name);
+ Module_Name[31] = 0;
+ }
+ /*
+ * Arrange to store the data locally (leave room for size byte)
+ */
+ cp = Local + 1;
+ /*
+ * Begin module
+ */
+ *cp++ = DST_S_C_MODBEG;
+ /*
+ * Unused
+ */
+ *cp++ = 0;
+ /*
+ * Language type == "C"
+ */
+ *(long *) cp = DST_S_C_C;
+ cp += sizeof (long);
+ /*
+ * Store the module name
+ */
+ *cp++ = strlen (Module_Name);
+ cp1 = Module_Name;
+ while (*cp1)
+ *cp++ = *cp1++;
+ /*
+ * Now we can store the record size
+ */
+ Size = (cp - Local);
+ Local[0] = Size - 1;
+ /*
+ * Put it into the object record
+ */
+ VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
+}
+
+
+/*
+ * Write the Traceback Module End record
+*/
+static
+VMS_TBT_Module_End ()
+{
+ char Local[2];
+
+ /*
+ * End module
+ */
+ Local[0] = 1;
+ Local[1] = DST_S_C_MODEND;
+ /*
+ * Put it into the object record
+ */
+ VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT);
+}
+
+
+/*
+ * Write the Traceback Routine Begin record
+ */
+static
+VMS_TBT_Routine_Begin (symbolP, Psect)
+ struct symbol *symbolP;
+ int Psect;
+{
+ register char *cp, *cp1;
+ char *Name;
+ int Offset;
+ int Size;
+ char Local[512];
+
+ /*
+ * Strip the leading "_" from the name
+ */
+ Name = S_GET_NAME (symbolP);
+ if (*Name == '_')
+ Name++;
+ /*
+ * Get the text psect offset
+ */
+ Offset = S_GET_VALUE (symbolP);
+ /*
+ * Calculate the record size
+ */
+ Size = 1 + 1 + 4 + 1 + strlen (Name);
+ /*
+ * Record Size
+ */
+ Local[0] = Size;
+ /*
+ * Begin Routine
+ */
+ Local[1] = DST_S_C_RTNBEG;
+ /*
+ * Uses CallS/CallG
+ */
+ Local[2] = 0;
+ /*
+ * Store the data so far
+ */
+ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
+ /*
+ * Make sure we are still generating a OBJ_S_C_TBT record
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_TBT);
+ /*
+ * Now get the symbol address
+ */
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect);
+ PUT_LONG (Offset);
+ /*
+ * Store the data reference
+ */
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /*
+ * Store the counted string as data
+ */
+ cp = Local;
+ cp1 = Name;
+ Size = strlen (cp1) + 1;
+ *cp++ = Size - 1;
+ while (*cp1)
+ *cp++ = *cp1++;
+ VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
+}
+
+
+/*
+ * Write the Traceback Routine End record
+ * We *must* search the symbol table to find the next routine, since
+ * the assember has a way of reassembling the symbol table OUT OF ORDER
+ * Thus the next routine in the symbol list is not necessarily the
+ * next one in memory. For debugging to work correctly we must know the
+ * size of the routine.
+ */
+static
+VMS_TBT_Routine_End (Max_Size, sp)
+ int Max_Size;
+ symbolS *sp;
+{
+ symbolS *symbolP;
+ int Size = 0x7fffffff;
+ char Local[16];
+
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
+ {
+ if (*S_GET_NAME (symbolP) == 'L')
+ continue;
+ if ((S_GET_VALUE (symbolP) > S_GET_VALUE (sp)) &&
+ (S_GET_VALUE (symbolP) < Size))
+ Size = S_GET_VALUE (symbolP);
+ /* check if gcc_compiled. has size of zero */
+ if ((S_GET_VALUE (symbolP) == S_GET_VALUE (sp)) &&
+ sp != symbolP &&
+ (!strcmp (S_GET_NAME (sp), "gcc_compiled.") ||
+ !strcmp (S_GET_NAME (sp), "gcc2_compiled.")))
+ Size = S_GET_VALUE (symbolP);
+
+ };
+ };
+ if (Size == 0x7fffffff)
+ Size = Max_Size;
+ Size -= S_GET_VALUE (sp); /* and get the size of the routine */
+ /*
+ * Record Size
+ */
+ Local[0] = 6;
+ /*
+ * End of Routine
+ */
+ Local[1] = DST_S_C_RTNEND;
+ /*
+ * Unused
+ */
+ Local[2] = 0;
+ /*
+ * Size of routine
+ */
+ *((long *) (Local + 3)) = Size;
+ /*
+ * Store the record
+ */
+ VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
+}
+
+/*
+ * Write the Traceback Block End record
+ */
+static
+VMS_TBT_Block_Begin (symbolP, Psect, Name)
+ struct symbol *symbolP;
+ int Psect;
+ char *Name;
+{
+ register char *cp, *cp1;
+ int Offset;
+ int Size;
+ char Local[512];
+ /*
+ * Begin block
+ */
+ Size = 1 + 1 + 4 + 1 + strlen (Name);
+ /*
+ * Record Size
+ */
+ Local[0] = Size;
+ /*
+ * Begin Block - We simulate with a phony routine
+ */
+ Local[1] = DST_S_C_BLKBEG;
+ /*
+ * Uses CallS/CallG
+ */
+ Local[2] = 0;
+ /*
+ * Store the data so far
+ */
+ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG);
+ /*
+ * Make sure we are still generating a OBJ_S_C_DBG record
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_DBG);
+ /*
+ * Now get the symbol address
+ */
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect);
+ /*
+ * Get the text psect offset
+ */
+ Offset = S_GET_VALUE (symbolP);
+ PUT_LONG (Offset);
+ /*
+ * Store the data reference
+ */
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /*
+ * Store the counted string as data
+ */
+ cp = Local;
+ cp1 = Name;
+ Size = strlen (cp1) + 1;
+ *cp++ = Size - 1;
+ while (*cp1)
+ *cp++ = *cp1++;
+ VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG);
+}
+
+
+/*
+ * Write the Traceback Block End record
+ */
+static
+VMS_TBT_Block_End (int Size)
+{
+ char Local[16];
+
+ /*
+ * End block - simulate with a phony end routine
+ */
+ Local[0] = 6;
+ Local[1] = DST_S_C_BLKEND;
+ *((long *) (Local + 3)) = Size;
+ /*
+ * Unused
+ */
+ Local[2] = 0;
+ VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG);
+}
+
+
+
+/*
+ * Write a Line number / PC correlation record
+ */
+static
+VMS_TBT_Line_PC_Correlation (Line_Number, Offset, Psect, Do_Delta)
+ int Line_Number;
+ int Offset;
+ int Psect;
+ int Do_Delta;
+{
+ register char *cp;
+ char Local[64];
+
+ /*
+* If not delta, set our PC/Line number correlation
+*/
+ if (Do_Delta == 0)
+ {
+ /*
+ * Size
+ */
+ Local[0] = 1 + 1 + 2 + 1 + 4;
+ /*
+ * Line Number/PC correlation
+ */
+ Local[1] = DST_S_C_LINE_NUM;
+ /*
+ * Set Line number
+ */
+ Local[2] = DST_S_C_SET_LINE_NUM;
+ *((unsigned short *) (Local + 3)) = Line_Number - 1;
+ /*
+ * Set PC
+ */
+ Local[5] = DST_S_C_SET_ABS_PC;
+ VMS_Store_Immediate_Data (Local, 6, OBJ_S_C_TBT);
+ /*
+ * Make sure we are still generating a OBJ_S_C_TBT record
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_TBT);
+ if (Psect < 255)
+ {
+ PUT_CHAR (TIR_S_C_STA_PL);
+ PUT_CHAR (Psect);
+ }
+ else
+ {
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect);
+ }
+ PUT_LONG (Offset);
+ PUT_CHAR (TIR_S_C_STO_PIDR);
+ /*
+ * Do a PC offset of 0 to register the line number
+ */
+ Local[0] = 2;
+ Local[1] = DST_S_C_LINE_NUM;
+ Local[2] = 0; /* Increment PC by 0 and register line # */
+ VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
+ }
+ else
+ {
+ /*
+ * If Delta is negative, terminate the line numbers
+ */
+ if (Do_Delta < 0)
+ {
+ Local[0] = 1 + 1 + 4;
+ Local[1] = DST_S_C_LINE_NUM;
+ Local[2] = DST_S_C_TERM_L;
+ *((long *) (Local + 3)) = Offset;
+ VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
+ /*
+ * Done
+ */
+ return;
+ }
+ /*
+ * Do a PC/Line delta
+ */
+ cp = Local + 1;
+ *cp++ = DST_S_C_LINE_NUM;
+ if (Line_Number > 1)
+ {
+ /*
+ * We need to increment the line number
+ */
+ if (Line_Number - 1 <= 255)
+ {
+ *cp++ = DST_S_C_INCR_LINUM;
+ *cp++ = Line_Number - 1;
+ }
+ else
+ {
+ *cp++ = DST_S_C_INCR_LINUM_W;
+ *(short *) cp = Line_Number - 1;
+ cp += sizeof (short);
+ }
+ }
+ /*
+ * Increment the PC
+ */
+ if (Offset <= 128)
+ {
+ *cp++ = -Offset;
+ }
+ else
+ {
+ if (Offset < 0x10000)
+ {
+ *cp++ = DST_S_C_DELTA_PC_W;
+ *(short *) cp = Offset;
+ cp += sizeof (short);
+ }
+ else
+ {
+ *cp++ = DST_S_C_DELTA_PC_L;
+ *(long *) cp = Offset;
+ cp += sizeof (long);
+ }
+ }
+ Local[0] = cp - (Local + 1);
+ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
+ }
+}
+
+
+/*
+ * Describe a source file to the debugger
+ */
+static
+VMS_TBT_Source_File (Filename, ID_Number)
+ char *Filename;
+ int ID_Number;
+{
+ register char *cp, *cp1;
+ int Status, i;
+ char Local[512];
+#ifndef HO_VMS /* Used for cross-assembly */
+ i = strlen (Filename);
+#else /* HO_VMS */
+ static struct FAB Fab;
+ static struct NAM Nam;
+ static struct XABDAT Date_Xab;
+ static struct XABFHC File_Header_Xab;
+ char Es_String[255], Rs_String[255];
+
+ /*
+ * Setup the Fab
+ */
+ Fab.fab$b_bid = FAB$C_BID;
+ Fab.fab$b_bln = sizeof (Fab);
+ Fab.fab$l_nam = (&Nam);
+ Fab.fab$l_xab = (char *) &Date_Xab;
+ /*
+ * Setup the Nam block so we can find out the FULL name
+ * of the source file.
+ */
+ Nam.nam$b_bid = NAM$C_BID;
+ Nam.nam$b_bln = sizeof (Nam);
+ Nam.nam$l_rsa = Rs_String;
+ Nam.nam$b_rss = sizeof (Rs_String);
+ Nam.nam$l_esa = Es_String;
+ Nam.nam$b_ess = sizeof (Es_String);
+ /*
+ * Setup the Date and File Header Xabs
+ */
+ Date_Xab.xab$b_cod = XAB$C_DAT;
+ Date_Xab.xab$b_bln = sizeof (Date_Xab);
+ Date_Xab.xab$l_nxt = (char *) &File_Header_Xab;
+ File_Header_Xab.xab$b_cod = XAB$C_FHC;
+ File_Header_Xab.xab$b_bln = sizeof (File_Header_Xab);
+ /*
+ * Get the file information
+ */
+ Fab.fab$l_fna = Filename;
+ Fab.fab$b_fns = strlen (Filename);
+ Status = sys$open (&Fab);
+ if (!(Status & 1))
+ {
+ printf ("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
+ Filename, Status);
+ return (0);
+ }
+ sys$close (&Fab);
+ /*
+ * Calculate the size of the resultant string
+ */
+ i = Nam.nam$b_rsl;
+#endif /* HO_VMS */
+ /*
+ * Size of record
+ */
+ Local[0] = 1 + 1 + 1 + 1 + 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1;
+ /*
+ * Source declaration
+ */
+ Local[1] = DST_S_C_SOURCE;
+ /*
+ * Make formfeeds count as source records
+ */
+ Local[2] = DST_S_C_SRC_FORMFEED;
+ /*
+ * Declare source file
+ */
+ Local[3] = DST_S_C_SRC_DECLFILE;
+ Local[4] = 1 + 2 + 8 + 4 + 2 + 1 + 1 + i + 1;
+ cp = Local + 5;
+ /*
+ * Flags
+ */
+ *cp++ = 0;
+ /*
+ * File ID
+ */
+ *(short *) cp = ID_Number;
+ cp += sizeof (short);
+#ifndef HO_VMS
+ /*
+ * Creation Date. Unknown, so we fill with zeroes.
+ */
+ *(long *) cp = 0;
+ cp += sizeof (long);
+ *(long *) cp = 0;
+ cp += sizeof (long);
+ /*
+ * End of file block
+ */
+ *(long *) cp = 0;
+ cp += sizeof (long);
+ /*
+ * First free byte
+ */
+ *(short *) cp = 0;
+ cp += sizeof (short);
+ /*
+ * Record format
+ */
+ *cp++ = 0;
+ /*
+ * Filename
+ */
+ *cp++ = i;
+ cp1 = Filename;
+#else /* Use this code when assembling for VMS on a VMS system */
+ /*
+ * Creation Date
+ */
+ *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[0];
+ cp += sizeof (long);
+ *(long *) cp = ((long *) &Date_Xab.xab$q_cdt)[1];
+ cp += sizeof (long);
+ /*
+ * End of file block
+ */
+ *(long *) cp = File_Header_Xab.xab$l_ebk;
+ cp += sizeof (long);
+ /*
+ * First free byte
+ */
+ *(short *) cp = File_Header_Xab.xab$w_ffb;
+ cp += sizeof (short);
+ /*
+ * Record format
+ */
+ *cp++ = File_Header_Xab.xab$b_rfo;
+ /*
+ * Filename
+ */
+ *cp++ = i;
+ cp1 = Rs_String;
+#endif /* HO_VMS */
+ while (--i >= 0)
+ *cp++ = *cp1++;
+ /*
+ * Library module name (none)
+ */
+ *cp++ = 0;
+ /*
+ * Done
+ */
+ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
+ return 1;
+}
+
+
+/*
+ * Give the number of source lines to the debugger
+ */
+static
+VMS_TBT_Source_Lines (ID_Number, Starting_Line_Number, Number_Of_Lines)
+ int ID_Number;
+ int Starting_Line_Number;
+ int Number_Of_Lines;
+{
+ char *cp, *cp1;
+ char Local[16];
+
+ /*
+ * Size of record
+ */
+ Local[0] = 1 + 1 + 2 + 1 + 4 + 1 + 2;
+ /*
+ * Source declaration
+ */
+ Local[1] = DST_S_C_SOURCE;
+ /*
+ * Set Source File
+ */
+ cp = Local + 2;
+ *cp++ = DST_S_C_SRC_SETFILE;
+ /*
+ * File ID Number
+ */
+ *(short *) cp = ID_Number;
+ cp += sizeof (short);
+ /*
+ * Set record number
+ */
+ *cp++ = DST_S_C_SRC_SETREC_L;
+ *(long *) cp = Starting_Line_Number;
+ cp += sizeof (long);
+ /*
+ * Define lines
+ */
+ *cp++ = DST_S_C_SRC_DEFLINES_W;
+ *(short *) cp = Number_Of_Lines;
+ cp += sizeof (short);
+ /*
+ * Done
+ */
+ VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
+}
+
+
+
+
+/* This routine locates a file in the list of files. If an entry does not
+ * exist, one is created. For include files, a new entry is always created
+ * such that inline functions can be properly debugged. */
+static struct input_file *
+find_file (sp)
+ symbolS *sp;
+{
+ struct input_file *same_file;
+ struct input_file *fpnt;
+ same_file = (struct input_file *) NULL;
+ for (fpnt = file_root; fpnt; fpnt = fpnt->next)
+ {
+ if (fpnt == (struct input_file *) NULL)
+ break;
+ if (fpnt->spnt == sp)
+ return fpnt;
+ };
+ for (fpnt = file_root; fpnt; fpnt = fpnt->next)
+ {
+ if (fpnt == (struct input_file *) NULL)
+ break;
+ if (strcmp (S_GET_NAME (sp), fpnt->name) == 0)
+ {
+ if (fpnt->flag == 1)
+ return fpnt;
+ same_file = fpnt;
+ break;
+ };
+ };
+ fpnt = (struct input_file *) malloc (sizeof (struct input_file));
+ if (file_root == (struct input_file *) NULL)
+ file_root = fpnt;
+ else
+ {
+ struct input_file *fpnt1;
+ for (fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next) ;
+ fpnt1->next = fpnt;
+ };
+ fpnt->next = (struct input_file *) NULL;
+ fpnt->name = S_GET_NAME (sp);
+ fpnt->min_line = 0x7fffffff;
+ fpnt->max_line = 0;
+ fpnt->offset = 0;
+ fpnt->flag = 0;
+ fpnt->file_number = 0;
+ fpnt->spnt = sp;
+ fpnt->same_file_fpnt = same_file;
+ return fpnt;
+}
+
+/*
+ * The following functions and definitions are used to generate object records
+ * that will describe program variables to the VMS debugger.
+ *
+ * This file contains many of the routines needed to output debugging info into
+ * the object file that the VMS debugger needs to understand symbols. These
+ * routines are called very late in the assembly process, and thus we can be
+ * fairly lax about changing things, since the GSD and the TIR sections have
+ * already been output.
+ */
+
+
+/* This routine converts a number string into an integer, and stops when it
+ * sees an invalid character the return value is the address of the character
+ * just past the last character read. No error is generated.
+ */
+static char *
+cvt_integer (str, rtn)
+ char *str;
+ int *rtn;
+{
+ int ival, neg;
+ neg = *str == '-' ? ++str, -1 : 1;
+ ival = 0; /* first get the number of the type for dbx */
+ while ((*str <= '9') && (*str >= '0'))
+ ival = 10 * ival + *str++ - '0';
+ *rtn = neg * ival;
+ return str;
+}
+
+/* this routine fixes the names that are generated by C++, ".this" is a good
+ * example. The period does not work for the debugger, since it looks like
+ * the syntax for a structure element, and thus it gets mightily confused
+ *
+ * We also use this to strip the PsectAttribute hack from the name before we
+ * write a debugger record */
+
+static char *
+fix_name (pnt)
+ char *pnt;
+{
+ char *pnt1;
+ /*
+ * Kill any leading "_"
+ */
+ if (*pnt == '_')
+ pnt++;
+ /*
+ * Is there a Psect Attribute to skip??
+ */
+ if (HAS_PSECT_ATTRIBUTES (pnt))
+ {
+ /*
+ * Yes: Skip it
+ */
+ pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
+ while (*pnt)
+ {
+ if ((pnt[0] == '$') && (pnt[1] == '$'))
+ {
+ pnt += 2;
+ break;
+ }
+ pnt++;
+ }
+ }
+/* Here we fix the .this -> $this conversion */
+ for (pnt1 = pnt; *pnt1 != 0; pnt1++)
+ {
+ if (*pnt1 == '.')
+ *pnt1 = '$';
+ };
+ return pnt;
+}
+
+/* When defining a structure, this routine is called to find the name of
+ * the actual structure. It is assumed that str points to the equal sign
+ * in the definition, and it moves backward until it finds the start of the
+ * name. If it finds a 0, then it knows that this structure def is in the
+ * outermost level, and thus symbol_name points to the symbol name.
+ */
+static char *
+get_struct_name (str)
+ char *str;
+{
+ char *pnt;
+ pnt = str;
+ while ((*pnt != ':') && (*pnt != '\0'))
+ pnt--;
+ if (*pnt == '\0')
+ return symbol_name;
+ *pnt-- = '\0';
+ while ((*pnt != ';') && (*pnt != '='))
+ pnt--;
+ if (*pnt == ';')
+ return pnt + 1;
+ while ((*pnt < '0') || (*pnt > '9'))
+ pnt++;
+ while ((*pnt >= '0') && (*pnt <= '9'))
+ pnt++;
+ return pnt;
+}
+
+/* search symbol list for type number dbx_type. Return a pointer to struct */
+static struct VMS_DBG_Symbol *
+find_symbol (dbx_type)
+ int dbx_type;
+{
+ struct VMS_DBG_Symbol *spnt;
+ spnt = VMS_Symbol_type_list;
+ while (spnt != (struct VMS_DBG_Symbol *) NULL)
+ {
+ if (spnt->dbx_type == dbx_type)
+ break;
+ spnt = spnt->next;
+ };
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ return 0; /*Dunno what this is*/
+ return spnt;
+}
+
+
+/* this routine puts info into either Local or Asuffix, depending on the sign
+ * of size. The reason is that it is easier to build the variable descriptor
+ * backwards, while the array descriptor is best built forwards. In the end
+ * they get put together, if there is not a struct/union/enum along the way
+ */
+static
+push (value, size)
+ int value, size;
+{
+ char *pnt;
+ int i;
+ int size1;
+ long int val;
+ val = value;
+ pnt = (char *) &val;
+ size1 = size;
+ if (size < 0)
+ {
+ size1 = -size;
+ pnt += size1 - 1;
+ };
+ if (size < 0)
+ for (i = 0; i < size1; i++)
+ {
+ Local[Lpnt--] = *pnt--;
+ if (Lpnt < 0)
+ {
+ overflow = 1;
+ Lpnt = 1;
+ };
+ }
+ else
+ for (i = 0; i < size1; i++)
+ {
+ Asuffix[Apoint++] = *pnt++;
+ if (Apoint >= MAX_DEBUG_RECORD)
+ {
+ overflow = 1;
+ Apoint = MAX_DEBUG_RECORD - 1;
+ };
+ }
+}
+
+/* this routine generates the array descriptor for a given array */
+static
+array_suffix (spnt2)
+ struct VMS_DBG_Symbol *spnt2;
+{
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_DBG_Symbol *spnt1;
+ int rank;
+ int total_size;
+ int i;
+ rank = 0;
+ spnt = spnt2;
+ while (spnt->advanced != ARRAY)
+ {
+ spnt = find_symbol (spnt->type2);
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ return;
+ };
+ spnt1 = spnt;
+ spnt1 = spnt;
+ total_size = 1;
+ while (spnt1->advanced == ARRAY)
+ {
+ rank++;
+ total_size *= (spnt1->index_max - spnt1->index_min + 1);
+ spnt1 = find_symbol (spnt1->type2);
+ };
+ total_size = total_size * spnt1->data_size;
+ push (spnt1->data_size, 2);
+ if (spnt1->VMS_type == 0xa3)
+ push (0, 1);
+ else
+ push (spnt1->VMS_type, 1);
+ push (4, 1);
+ for (i = 0; i < 6; i++)
+ push (0, 1);
+ push (0xc0, 1);
+ push (rank, 1);
+ push (total_size, 4);
+ push (0, 4);
+ spnt1 = spnt;
+ while (spnt1->advanced == ARRAY)
+ {
+ push (spnt1->index_max - spnt1->index_min + 1, 4);
+ spnt1 = find_symbol (spnt1->type2);
+ };
+ spnt1 = spnt;
+ while (spnt1->advanced == ARRAY)
+ {
+ push (spnt1->index_min, 4);
+ push (spnt1->index_max, 4);
+ spnt1 = find_symbol (spnt1->type2);
+ };
+}
+
+/* this routine generates the start of a variable descriptor based upon
+ * a struct/union/enum that has yet to be defined. We define this spot as
+ * a new location, and save four bytes for the address. When the struct is
+ * finally defined, then we can go back and plug in the correct address
+*/
+static
+new_forward_ref (dbx_type)
+ int dbx_type;
+{
+ struct forward_ref *fpnt;
+ fpnt = (struct forward_ref *) malloc (sizeof (struct forward_ref));
+ fpnt->next = f_ref_root;
+ f_ref_root = fpnt;
+ fpnt->dbx_type = dbx_type;
+ fpnt->struc_numb = ++structure_count;
+ fpnt->resolved = 'N';
+ push (3, -1);
+ total_len = 5;
+ push (total_len, -2);
+ struct_number = -fpnt->struc_numb;
+}
+
+/* this routine generates the variable descriptor used to describe non-basic
+ * variables. It calls itself recursively until it gets to the bottom of it
+ * all, and then builds the descriptor backwards. It is easiest to do it this
+ *way since we must periodically write length bytes, and it is easiest if we know
+ *the value when it is time to write it.
+ */
+static int
+gen1 (spnt, array_suffix_len)
+ struct VMS_DBG_Symbol *spnt;
+ int array_suffix_len;
+{
+ struct VMS_DBG_Symbol *spnt1;
+ int i;
+ switch (spnt->advanced)
+ {
+ case VOID:
+ push (DBG_S_C_VOID, -1);
+ total_len += 1;
+ push (total_len, -2);
+ return 0;
+ case BASIC:
+ case FUNCTION:
+ if (array_suffix_len == 0)
+ {
+ push (spnt->VMS_type, -1);
+ push (DBG_S_C_BASIC, -1);
+ total_len = 2;
+ push (total_len, -2);
+ return 1;
+ };
+ push (0, -4);
+ push (0xfa02, -2);
+ total_len = -2;
+ return 1;
+ case STRUCT:
+ case UNION:
+ case ENUM:
+ struct_number = spnt->struc_numb;
+ if (struct_number < 0)
+ {
+ new_forward_ref (spnt->dbx_type);
+ return 1;
+ }
+ push (DBG_S_C_STRUCT, -1);
+ total_len = 5;
+ push (total_len, -2);
+ return 1;
+ case POINTER:
+ spnt1 = find_symbol (spnt->type2);
+ i = 1;
+ if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
+ new_forward_ref (spnt->type2);
+ else
+ i = gen1 (spnt1, 0);
+ if (i)
+ { /* (*void) is a special case, do not put pointer suffix*/
+ push (DBG_S_C_POINTER, -1);
+ total_len += 3;
+ push (total_len, -2);
+ };
+ return 1;
+ case ARRAY:
+ spnt1 = spnt;
+ while (spnt1->advanced == ARRAY)
+ {
+ spnt1 = find_symbol (spnt1->type2);
+ if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
+ {
+ printf ("gcc-as warning(debugger output):");
+ printf ("Forward reference error, dbx type %d\n",
+ spnt->type2);
+ return;
+ }
+ };
+/* It is too late to generate forward references, so the user gets a message.
+ * This should only happen on a compiler error */
+ i = gen1 (spnt1, 1);
+ i = Apoint;
+ array_suffix (spnt);
+ array_suffix_len = Apoint - i;
+ switch (spnt1->advanced)
+ {
+ case BASIC:
+ case FUNCTION:
+ break;
+ default:
+ push (0, -2);
+ total_len += 2;
+ push (total_len, -2);
+ push (0xfa, -1);
+ push (0x0101, -2);
+ push (DBG_S_C_COMPLEX_ARRAY, -1);
+ };
+ total_len += array_suffix_len + 8;
+ push (total_len, -2);
+ };
+}
+
+/* This generates a suffix for a variable. If it is not a defined type yet,
+ * then dbx_type contains the type we are expecting so we can generate a
+ * forward reference. This calls gen1 to build most of the descriptor, and
+ * then it puts the icing on at the end. It then dumps whatever is needed
+ * to get a complete descriptor (i.e. struct reference, array suffix ).
+ */
+static
+generate_suffix (spnt, dbx_type)
+ struct VMS_DBG_Symbol *spnt;
+ int dbx_type;
+{
+ int ilen;
+ int i;
+ char pvoid[6] =
+ {5, 0xaf, 0, 1, 0, 5};
+ struct VMS_DBG_Symbol *spnt1;
+ Apoint = 0;
+ Lpnt = MAX_DEBUG_RECORD - 1;
+ total_len = 0;
+ struct_number = 0;
+ overflow = 0;
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ new_forward_ref (dbx_type);
+ else
+ {
+ if (spnt->VMS_type != 0xa3)
+ return 0; /* no suffix needed */
+ gen1 (spnt, 0);
+ };
+ push (0x00af, -2);
+ total_len += 4;
+ push (total_len, -1);
+/* if the variable descriptor overflows the record, output a descriptor for
+ * a pointer to void.
+ */
+ if ((total_len >= MAX_DEBUG_RECORD) || overflow)
+ {
+ printf (" Variable descriptor %d too complicated. Defined as *void ", spnt->dbx_type);
+ VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG);
+ return;
+ };
+ i = 0;
+ while (Lpnt < MAX_DEBUG_RECORD - 1)
+ Local[i++] = Local[++Lpnt];
+ Lpnt = i;
+/* we use this for a reference to a structure that has already been defined */
+ if (struct_number > 0)
+ {
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+ VMS_Store_Struct (struct_number);
+ };
+/* we use this for a forward reference to a structure that has yet to be
+*defined. We store four bytes of zero to make room for the actual address once
+* it is known
+*/
+ if (struct_number < 0)
+ {
+ struct_number = -struct_number;
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+ VMS_Def_Struct (struct_number);
+ for (i = 0; i < 4; i++)
+ Local[Lpnt++] = 0;
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+ };
+ i = 0;
+ while (i < Apoint)
+ Local[Lpnt++] = Asuffix[i++];
+ if (Lpnt != 0)
+ VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
+ Lpnt = 0;
+}
+
+/* This routine generates a symbol definition for a C sybmol for the debugger.
+ * It takes a psect and offset for global symbols - if psect < 0, then this is
+ * a local variable and the offset is relative to FP. In this case it can
+ * be either a variable (Offset < 0) or a parameter (Offset > 0).
+ */
+static
+VMS_DBG_record (spnt, Psect, Offset, Name)
+ struct VMS_DBG_Symbol *spnt;
+ int Psect;
+ int Offset;
+ char *Name;
+{
+ char *pnt;
+ char *Name_pnt;
+ int j;
+ int maxlen;
+ int i = 0;
+ Name_pnt = fix_name (Name); /* if there are bad characters in name, convert them */
+ if (Psect < 0)
+ { /* this is a local variable, referenced to SP */
+ maxlen = 7 + strlen (Name_pnt);
+ Local[i++] = maxlen;
+ Local[i++] = spnt->VMS_type;
+ if (Offset > 0)
+ Local[i++] = DBG_S_C_FUNCTION_PARAMETER;
+ else
+ Local[i++] = DBG_S_C_LOCAL_SYM;
+ pnt = (char *) &Offset;
+ for (j = 0; j < 4; j++)
+ Local[i++] = *pnt++; /* copy the offset */
+ }
+ else
+ {
+ maxlen = 7 + strlen (Name_pnt); /* symbols fixed in memory */
+ Local[i++] = 7 + strlen (Name_pnt);
+ Local[i++] = spnt->VMS_type;
+ Local[i++] = 1;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0);
+ }
+ Local[i++] = strlen (Name_pnt);
+ while (*Name_pnt != '\0')
+ Local[i++] = *Name_pnt++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
+ generate_suffix (spnt, 0);
+}
+
+
+/* This routine parses the stabs entries in order to make the definition
+ * for the debugger of local symbols and function parameters
+ */
+static int
+VMS_local_stab_Parse (sp)
+ symbolS *sp;
+{
+ char *pnt;
+ char *pnt1;
+ char *str;
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_Symbol *vsp;
+ int dbx_type;
+ int VMS_type;
+ dbx_type = 0;
+ str = S_GET_NAME (sp);
+ pnt = (char *) strchr (str, ':');
+ if (pnt == (char *) NULL)
+ return; /* no colon present */
+ pnt1 = pnt++; /* save this for later, and skip colon */
+ if (*pnt == 'c')
+ return 0; /* ignore static constants */
+/* there is one little catch that we must be aware of. Sometimes function
+ * parameters are optimized into registers, and the compiler, in its infiite
+ * wisdom outputs stabs records for *both*. In general we want to use the
+ * register if it is present, so we must search the rest of the symbols for
+ * this function to see if this parameter is assigned to a register.
+ */
+ {
+ char *str1;
+ char *pnt2;
+ symbolS *sp1;
+ if (*pnt == 'p')
+ {
+ for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
+ {
+ if (!S_IS_DEBUG (sp1))
+ continue;
+ if (S_GET_RAW_TYPE (sp1) == N_FUN)
+ {
+ char * pnt3=(char*) strchr (S_GET_NAME (sp1), ':') + 1;
+ if (*pnt3 == 'F' || *pnt3 == 'f') break;
+ };
+ if (S_GET_RAW_TYPE (sp1) != N_RSYM)
+ continue;
+ str1 = S_GET_NAME (sp1); /* and get the name */
+ pnt2 = str;
+ while (*pnt2 != ':')
+ {
+ if (*pnt2 != *str1)
+ break;
+ pnt2++;
+ str1++;
+ };
+ if ((*str1 != ':') || (*pnt2 != ':'))
+ continue;
+ return; /* they are the same! lets skip this one */
+ }; /* for */
+/* first find the dbx symbol type from list, and then find VMS type */
+ pnt++; /* skip p in case no register */
+ }; /* if */
+ }; /* p block */
+ pnt = cvt_integer (pnt, &dbx_type);
+ spnt = find_symbol (dbx_type);
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ return 0; /*Dunno what this is*/
+ *pnt1 = '\0';
+ VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str);
+ *pnt1 = ':'; /* and restore the string */
+ return 1;
+}
+
+/* This routine parses a stabs entry to find the information required to define
+ * a variable. It is used for global and static variables.
+ * Basically we need to know the address of the symbol. With older versions
+ * of the compiler, const symbols are
+ * treated differently, in that if they are global they are written into the
+ * text psect. The global symbol entry for such a const is actually written
+ * as a program entry point (Yuk!!), so if we cannot find a symbol in the list
+ * of psects, we must search the entry points as well. static consts are even
+ * harder, since they are never assigned a memory address. The compiler passes
+ * a stab to tell us the value, but I am not sure what to do with it.
+ */
+
+static
+VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect)
+ symbolS *sp;
+ char expected_type;
+ int type1, type2, Text_Psect;
+{
+ char *pnt;
+ char *pnt1;
+ char *str;
+ symbolS *sp1;
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_Symbol *vsp;
+ int dbx_type;
+ int VMS_type;
+ dbx_type = 0;
+ str = S_GET_NAME (sp);
+ pnt = (char *) strchr (str, ':');
+ if (pnt == (char *) NULL)
+ return; /* no colon present */
+ pnt1 = pnt; /* save this for later*/
+ pnt++;
+ if (*pnt == expected_type)
+ {
+ pnt = cvt_integer (pnt + 1, &dbx_type);
+ spnt = find_symbol (dbx_type);
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ return 0; /*Dunno what this is*/
+/* now we need to search the symbol table to find the psect and offset for
+ * this variable.
+ */
+ *pnt1 = '\0';
+ vsp = VMS_Symbols;
+ while (vsp != (struct VMS_Symbol *) NULL)
+ {
+ pnt = S_GET_NAME (vsp->Symbol);
+ if (pnt != (char *) NULL)
+ if (*pnt++ == '_')
+/* make sure name is the same, and make sure correct symbol type */
+ if ((strlen (pnt) == strlen (str)) && (strcmp (pnt, str) == 0)
+ && ((S_GET_RAW_TYPE (vsp->Symbol) == type1) ||
+ (S_GET_RAW_TYPE (vsp->Symbol) == type2)))
+ break;
+ vsp = vsp->Next;
+ };
+ if (vsp != (struct VMS_Symbol *) NULL)
+ {
+ VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
+ *pnt1 = ':'; /* and restore the string */
+ return 1;
+ };
+/* the symbol was not in the symbol list, but it may be an "entry point"
+ if it was a constant */
+ for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT))
+ continue;
+ pnt = S_GET_NAME (sp1);
+ if (*pnt == '_')
+ pnt++;
+ if (strcmp (pnt, str) == 0)
+ {
+ if (!gave_compiler_message && expected_type == 'G')
+ {
+ printf ("***Warning - the assembly code generated by the compiler has placed\n");
+ printf ("global constant(s) in the text psect. These will not be available to\n");
+ printf ("other modules, since this is not the correct way to handle this. You\n");
+ printf ("have two options: 1) get a patched compiler that does not put global\n");
+ printf ("constants in the text psect, or 2) remove the 'const' keyword from\n");
+ printf ("definitions of global variables in your source module(s). Don't say\n");
+ printf ("I didn't warn you!");
+ gave_compiler_message = 1;
+ };
+ VMS_DBG_record (spnt,
+ Text_Psect,
+ S_GET_VALUE (sp1),
+ str);
+ *pnt1 = ':';
+ *S_GET_NAME (sp1) = 'L';
+ /* fool assembler to not output this
+ * as a routine in the TBT */
+ return 1;
+ };
+ };
+ };
+ *pnt1 = ':'; /* and restore the string */
+ return 0;
+}
+
+static
+VMS_GSYM_Parse (sp, Text_Psect)
+ symbolS *sp;
+ int Text_Psect;
+{ /* Global variables */
+ VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect);
+}
+
+
+static
+VMS_LCSYM_Parse (sp, Text_Psect)
+ symbolS *sp;
+ int Text_Psect;
+{ /* Static symbols - uninitialized */
+ VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect);
+}
+
+static
+VMS_STSYM_Parse (sp, Text_Psect)
+ symbolS *sp;
+ int Text_Psect;
+{ /* Static symbols - initialized */
+ VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect);
+}
+
+
+/* for register symbols, we must figure out what range of addresses within the
+ * psect are valid. We will use the brackets in the stab directives to give us
+ * guidance as to the PC range that this variable is in scope. I am still not
+ * completely comfortable with this but as I learn more, I seem to get a better
+ * handle on what is going on.
+ * Caveat Emptor.
+ */
+static
+VMS_RSYM_Parse (sp, Current_Routine, Text_Psect)
+ symbolS *sp, *Current_Routine;
+ int Text_Psect;
+{
+ char *pnt;
+ char *pnt1;
+ char *str;
+ int dbx_type;
+ struct VMS_DBG_Symbol *spnt;
+ int j;
+ int maxlen;
+ int i = 0;
+ int bcnt = 0;
+ int Min_Offset = -1; /* min PC of validity */
+ int Max_Offset = 0; /* max PC of validity */
+ symbolS *symbolP;
+ for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (symbolP))
+ {
+ case N_LBRAC:
+ if (bcnt++ == 0)
+ Min_Offset = S_GET_VALUE (symbolP);
+ break;
+ case N_RBRAC:
+ if (--bcnt == 0)
+ Max_Offset =
+ S_GET_VALUE (symbolP) - 1;
+ break;
+ }
+ if ((Min_Offset != -1) && (bcnt == 0))
+ break;
+ if (S_GET_RAW_TYPE (symbolP) == N_FUN)
+ {
+ pnt=(char*) strchr (S_GET_NAME (symbolP), ':') + 1;
+ if (*pnt == 'F' || *pnt == 'f') break;
+ };
+ }
+/* check to see that the addresses were defined. If not, then there were no
+ * brackets in the function, and we must try to search for the next function
+ * Since functions can be in any order, we should search all of the symbol list
+ * to find the correct ending address. */
+ if (Min_Offset == -1)
+ {
+ int Max_Source_Offset;
+ int This_Offset;
+ Min_Offset = S_GET_VALUE (sp);
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ This_Offset = S_GET_VALUE (symbolP);
+ switch (S_GET_RAW_TYPE (symbolP))
+ {
+ case N_TEXT | N_EXT:
+ if ((This_Offset > Min_Offset) && (This_Offset < Max_Offset))
+ Max_Offset = This_Offset;
+ break;
+ case N_SLINE:
+ if (This_Offset > Max_Source_Offset)
+ Max_Source_Offset = This_Offset;
+ }
+ }
+/* if this is the last routine, then we use the PC of the last source line
+ * as a marker of the max PC for which this reg is valid */
+ if (Max_Offset == 0x7fffffff)
+ Max_Offset = Max_Source_Offset;
+ };
+ dbx_type = 0;
+ str = S_GET_NAME (sp);
+ pnt = (char *) strchr (str, ':');
+ if (pnt == (char *) NULL)
+ return; /* no colon present */
+ pnt1 = pnt; /* save this for later*/
+ pnt++;
+ if (*pnt != 'r')
+ return 0;
+ pnt = cvt_integer (pnt + 1, &dbx_type);
+ spnt = find_symbol (dbx_type);
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ return 0; /*Dunno what this is yet*/
+ *pnt1 = '\0';
+ pnt = fix_name (S_GET_NAME (sp)); /* if there are bad characters in name, convert them */
+ maxlen = 25 + strlen (pnt);
+ Local[i++] = maxlen;
+ Local[i++] = spnt->VMS_type;
+ Local[i++] = 0xfb;
+ Local[i++] = strlen (pnt) + 1;
+ Local[i++] = 0x00;
+ Local[i++] = 0x00;
+ Local[i++] = 0x00;
+ Local[i++] = strlen (pnt);
+ while (*pnt != '\0')
+ Local[i++] = *pnt++;
+ Local[i++] = 0xfd;
+ Local[i++] = 0x0f;
+ Local[i++] = 0x00;
+ Local[i++] = 0x03;
+ Local[i++] = 0x01;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1);
+ VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1);
+ Local[i++] = 0x03;
+ Local[i++] = S_GET_VALUE (sp);
+ Local[i++] = 0x00;
+ Local[i++] = 0x00;
+ Local[i++] = 0x00;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ *pnt1 = ':';
+ if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
+ generate_suffix (spnt, 0);
+}
+
+/* this function examines a structure definition, checking all of the elements
+ * to make sure that all of them are fully defined. The only thing that we
+ * kick out are arrays of undefined structs, since we do not know how big
+ * they are. All others we can handle with a normal forward reference.
+ */
+static int
+forward_reference (pnt)
+ char *pnt;
+{
+ int i;
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_DBG_Symbol *spnt1;
+ pnt = cvt_integer (pnt + 1, &i);
+ if (*pnt == ';')
+ return 0; /* no forward references */
+ do
+ {
+ pnt = (char *) strchr (pnt, ':');
+ pnt = cvt_integer (pnt + 1, &i);
+ spnt = find_symbol (i);
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ return 0;
+ while ((spnt->advanced == POINTER) || (spnt->advanced == ARRAY))
+ {
+ i = spnt->type2;
+ spnt1 = find_symbol (spnt->type2);
+ if ((spnt->advanced == ARRAY) &&
+ (spnt1 == (struct VMS_DBG_Symbol *) NULL))
+ return 1;
+ if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
+ break;
+ spnt = spnt1;
+ };
+ pnt = cvt_integer (pnt + 1, &i);
+ pnt = cvt_integer (pnt + 1, &i);
+ } while (*++pnt != ';');
+ return 0; /* no forward refences found */
+}
+
+/* This routine parses the stabs directives to find any definitions of dbx type
+ * numbers. It makes a note of all of them, creating a structure element
+ * of VMS_DBG_Symbol that describes it. This also generates the info for the
+ * debugger that describes the struct/union/enum, so that further references
+ * to these data types will be by number
+ * We have to process pointers right away, since there can be references
+ * to them later in the same stabs directive. We cannot have forward
+ * references to pointers, (but we can have a forward reference to a pointer to
+ * a structure/enum/union) and this is why we process them immediately.
+ * After we process the pointer, then we search for defs that are nested even
+ * deeper.
+ */
+static int
+VMS_typedef_parse (str)
+ char *str;
+{
+ char *pnt;
+ char *pnt1;
+ char *pnt2;
+ int i;
+ int dtype;
+ struct forward_ref *fpnt;
+ int i1, i2, i3;
+ int convert_integer;
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_DBG_Symbol *spnt1;
+/* check for any nested def's */
+ pnt = (char *) strchr (str + 1, '=');
+ if ((pnt != (char *) NULL) && (*(str + 1) != '*'))
+ if (VMS_typedef_parse (pnt) == 1)
+ return 1;
+/* now find dbx_type of entry */
+ pnt = str - 1;
+ if (*pnt == 'c')
+ { /* check for static constants */
+ *str = '\0'; /* for now we ignore them */
+ return 0;
+ };
+ while ((*pnt <= '9') && (*pnt >= '0'))
+ pnt--;
+ pnt++; /* and get back to the number */
+ cvt_integer (pnt, &i1);
+ spnt = find_symbol (i1);
+/* first we see if this has been defined already, due to a forward reference*/
+ if (spnt == (struct VMS_DBG_Symbol *) NULL)
+ {
+ if (VMS_Symbol_type_list == (struct VMS_DBG_Symbol *) NULL)
+ {
+ spnt = (struct VMS_DBG_Symbol *) malloc (sizeof (struct VMS_DBG_Symbol));
+ spnt->next = (struct VMS_DBG_Symbol *) NULL;
+ VMS_Symbol_type_list = spnt;
+ }
+ else
+ {
+ spnt = (struct VMS_DBG_Symbol *) malloc (sizeof (struct VMS_DBG_Symbol));
+ spnt->next = VMS_Symbol_type_list;
+ VMS_Symbol_type_list = spnt;
+ };
+ spnt->dbx_type = i1; /* and save the type */
+ };
+/* for structs and unions, do a partial parse, otherwise we sometimes get
+ * circular definitions that are impossible to resolve. We read enough info
+ * so that any reference to this type has enough info to be resolved
+ */
+ pnt = str + 1; /* point to character past equal sign */
+ if ((*pnt == 'u') || (*pnt == 's'))
+ {
+ };
+ if ((*pnt <= '9') && (*pnt >= '0'))
+ {
+ if (type_check ("void"))
+ { /* this is the void symbol */
+ *str = '\0';
+ spnt->advanced = VOID;
+ return 0;
+ };
+ if (type_check ("unknown type"))
+ { /* this is the void symbol */
+ *str = '\0';
+ spnt->advanced = UNKNOWN;
+ return 0;
+ };
+ printf ("gcc-as warning(debugger output):");
+ printf (" %d is an unknown untyped variable.\n", spnt->dbx_type);
+ return 1; /* do not know what this is */
+ };
+/* now define this module*/
+ pnt = str + 1; /* point to character past equal sign */
+ switch (*pnt)
+ {
+ case 'r':
+ spnt->advanced = BASIC;
+ if (type_check ("int"))
+ {
+ spnt->VMS_type = DBG_S_C_SLINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("long int"))
+ {
+ spnt->VMS_type = DBG_S_C_SLINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("unsigned int"))
+ {
+ spnt->VMS_type = DBG_S_C_ULINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("long unsigned int"))
+ {
+ spnt->VMS_type = DBG_S_C_ULINT;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("short int"))
+ {
+ spnt->VMS_type = DBG_S_C_SSINT;
+ spnt->data_size = 2;
+ }
+ else if (type_check ("short unsigned int"))
+ {
+ spnt->VMS_type = DBG_S_C_USINT;
+ spnt->data_size = 2;
+ }
+ else if (type_check ("char"))
+ {
+ spnt->VMS_type = DBG_S_C_SCHAR;
+ spnt->data_size = 1;
+ }
+ else if (type_check ("signed char"))
+ {
+ spnt->VMS_type = DBG_S_C_SCHAR;
+ spnt->data_size = 1;
+ }
+ else if (type_check ("unsigned char"))
+ {
+ spnt->VMS_type = DBG_S_C_UCHAR;
+ spnt->data_size = 1;
+ }
+ else if (type_check ("float"))
+ {
+ spnt->VMS_type = DBG_S_C_REAL4;
+ spnt->data_size = 4;
+ }
+ else if (type_check ("double"))
+ {
+ spnt->VMS_type = DBG_S_C_REAL8;
+ spnt->data_size = 8;
+ }
+ pnt1 = (char *) strchr (str, ';') + 1;
+ break;
+ case 's':
+ case 'u':
+ if (*pnt == 's')
+ spnt->advanced = STRUCT;
+ else
+ spnt->advanced = UNION;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ pnt1 = cvt_integer (pnt + 1, &spnt->data_size);
+ if (forward_reference (pnt))
+ {
+ spnt->struc_numb = -1;
+ return 1;
+ }
+ spnt->struc_numb = ++structure_count;
+ pnt1--;
+ pnt = get_struct_name (str);
+ VMS_Def_Struct (spnt->struc_numb);
+ fpnt = f_ref_root;
+ while (fpnt != (struct forward_ref *) NULL)
+ {
+ if (fpnt->dbx_type == spnt->dbx_type)
+ {
+ fpnt->resolved = 'Y';
+ VMS_Set_Struct (fpnt->struc_numb);
+ VMS_Store_Struct (spnt->struc_numb);
+ };
+ fpnt = fpnt->next;
+ };
+ VMS_Set_Struct (spnt->struc_numb);
+ i = 0;
+ Local[i++] = 11 + strlen (pnt);
+ Local[i++] = DBG_S_C_STRUCT_START;
+ Local[i++] = 0x80;
+ for (i1 = 0; i1 < 4; i1++)
+ Local[i++] = 0x00;
+ Local[i++] = strlen (pnt);
+ pnt2 = pnt;
+ while (*pnt2 != '\0')
+ Local[i++] = *pnt2++;
+ i2 = spnt->data_size * 8; /* number of bits */
+ pnt2 = (char *) &i2;
+ for (i1 = 0; i1 < 4; i1++)
+ Local[i++] = *pnt2++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ if (pnt != symbol_name)
+ {
+ pnt += strlen (pnt);
+ *pnt = ':';
+ }; /* replace colon for later */
+ while (*++pnt1 != ';')
+ {
+ pnt = (char *) strchr (pnt1, ':');
+ *pnt = '\0';
+ pnt2 = pnt1;
+ pnt1 = cvt_integer (pnt + 1, &dtype);
+ pnt1 = cvt_integer (pnt1 + 1, &i2);
+ pnt1 = cvt_integer (pnt1 + 1, &i3);
+ if ((dtype == 1) && (i3 != 32))
+ { /* bitfield */
+ Apoint = 0;
+ push (19 + strlen (pnt2), 1);
+ push (0xfa22, 2);
+ push (1 + strlen (pnt2), 4);
+ push (strlen (pnt2), 1);
+ while (*pnt2 != '\0')
+ push (*pnt2++, 1);
+ push (i3, 2); /* size of bitfield */
+ push (0x0d22, 2);
+ push (0x00, 4);
+ push (i2, 4); /* start position */
+ VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG);
+ Apoint = 0;
+ }
+ else
+ {
+ Local[i++] = 7 + strlen (pnt2);
+ spnt1 = find_symbol (dtype);
+ /* check if this is a forward reference */
+ if (spnt1 != (struct VMS_DBG_Symbol *) NULL)
+ Local[i++] = spnt1->VMS_type;
+ else
+ Local[i++] = DBG_S_C_ADVANCED_TYPE;
+ Local[i++] = DBG_S_C_STRUCT_ITEM;
+ pnt = (char *) &i2;
+ for (i1 = 0; i1 < 4; i1++)
+ Local[i++] = *pnt++;
+ Local[i++] = strlen (pnt2);
+ while (*pnt2 != '\0')
+ Local[i++] = *pnt2++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ if (spnt1 == (struct VMS_DBG_Symbol *) NULL)
+ generate_suffix (spnt1, dtype);
+ else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
+ generate_suffix (spnt1, 0);
+ };
+ };
+ pnt1++;
+ Local[i++] = 0x01; /* length byte */
+ Local[i++] = DBG_S_C_STRUCT_END;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ break;
+ case 'e':
+ spnt->advanced = ENUM;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ spnt->struc_numb = ++structure_count;
+ spnt->data_size = 4;
+ VMS_Def_Struct (spnt->struc_numb);
+ fpnt = f_ref_root;
+ while (fpnt != (struct forward_ref *) NULL)
+ {
+ if (fpnt->dbx_type == spnt->dbx_type)
+ {
+ fpnt->resolved = 'Y';
+ VMS_Set_Struct (fpnt->struc_numb);
+ VMS_Store_Struct (spnt->struc_numb);
+ };
+ fpnt = fpnt->next;
+ };
+ VMS_Set_Struct (spnt->struc_numb);
+ i = 0;
+ Local[i++] = 3 + strlen (symbol_name);
+ Local[i++] = DBG_S_C_ENUM_START;
+ Local[i++] = 0x20;
+ Local[i++] = strlen (symbol_name);
+ pnt2 = symbol_name;
+ while (*pnt2 != '\0')
+ Local[i++] = *pnt2++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ while (*++pnt != ';')
+ {
+ pnt1 = (char *) strchr (pnt, ':');
+ *pnt1++ = '\0';
+ pnt1 = cvt_integer (pnt1, &i1);
+ Local[i++] = 7 + strlen (pnt);
+ Local[i++] = DBG_S_C_ENUM_ITEM;
+ Local[i++] = 0x00;
+ pnt2 = (char *) &i1;
+ for (i2 = 0; i2 < 4; i2++)
+ Local[i++] = *pnt2++;
+ Local[i++] = strlen (pnt);
+ pnt2 = pnt;
+ while (*pnt != '\0')
+ Local[i++] = *pnt++;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ pnt = pnt1; /* Skip final semicolon */
+ };
+ Local[i++] = 0x01; /* len byte */
+ Local[i++] = DBG_S_C_ENUM_END;
+ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
+ i = 0;
+ pnt1 = pnt + 1;
+ break;
+ case 'a':
+ spnt->advanced = ARRAY;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ pnt = (char *) strchr (pnt, ';');
+ if (pnt == (char *) NULL)
+ return 1;
+ pnt1 = cvt_integer (pnt + 1, &spnt->index_min);
+ pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max);
+ pnt1 = cvt_integer (pnt1 + 1, &spnt->type2);
+ break;
+ case 'f':
+ spnt->advanced = FUNCTION;
+ spnt->VMS_type = DBG_S_C_FUNCTION_ADDR;
+ /* this masquerades as a basic type*/
+ spnt->data_size = 4;
+ pnt1 = cvt_integer (pnt + 1, &spnt->type2);
+ break;
+ case '*':
+ spnt->advanced = POINTER;
+ spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
+ spnt->data_size = 4;
+ pnt1 = cvt_integer (pnt + 1, &spnt->type2);
+ pnt = (char *) strchr (str + 1, '=');
+ if ((pnt != (char *) NULL))
+ if (VMS_typedef_parse (pnt) == 1)
+ return 1;
+ break;
+ default:
+ spnt->advanced = UNKNOWN;
+ spnt->VMS_type = 0;
+ printf ("gcc-as warning(debugger output):");
+ printf (" %d is an unknown type of variable.\n", spnt->dbx_type);
+ return 1; /* unable to decipher */
+ };
+/* this removes the evidence of the definition so that the outer levels of
+parsing do not have to worry about it */
+ pnt = str;
+ while (*pnt1 != '\0')
+ *pnt++ = *pnt1++;
+ *pnt = '\0';
+ return 0;
+}
+
+
+/*
+ * This is the root routine that parses the stabs entries for definitions.
+ * it calls VMS_typedef_parse, which can in turn call itself.
+ * We need to be careful, since sometimes there are forward references to
+ * other symbol types, and these cannot be resolved until we have completed
+ * the parse.
+ */
+static int
+VMS_LSYM_Parse ()
+{
+ char *pnt;
+ char *pnt1;
+ char *pnt2;
+ char *str;
+ char fixit[10];
+ int incomplete, i, pass, incom1;
+ struct VMS_DBG_Symbol *spnt;
+ struct VMS_Symbol *vsp;
+ struct forward_ref *fpnt;
+ symbolS *sp;
+ pass = 0;
+ incomplete = 0;
+ do
+ {
+ incom1 = incomplete;
+ incomplete = 0;
+ for (sp = symbol_rootP; sp; sp = symbol_next (sp))
+ {
+ /*
+ * Deal with STAB symbols
+ */
+ if (S_IS_DEBUG (sp))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (sp))
+ {
+ case N_GSYM:
+ case N_LCSYM:
+ case N_STSYM:
+ case N_PSYM:
+ case N_RSYM:
+ case N_LSYM:
+ case N_FUN: /*sometimes these contain typedefs*/
+ str = S_GET_NAME (sp);
+ symbol_name = str;
+ pnt = (char *) strchr (str, ':');
+ if (pnt == (char *) NULL)
+ break;
+ *pnt = '\0';
+ pnt1 = pnt + 1;
+ pnt2 = (char *) strchr (pnt1, '=');
+ if (pnt2 == (char *) NULL)
+ {
+ *pnt = ':'; /* replace colon */
+ break;
+ }; /* no symbol here */
+ incomplete += VMS_typedef_parse (pnt2);
+ *pnt = ':'; /* put back colon so variable def code finds dbx_type*/
+ break;
+ } /*switch*/
+ } /* if */
+ } /*for*/
+ pass++;
+ } while ((incomplete != 0) && (incomplete != incom1));
+ /* repeat until all refs resolved if possible */
+/* if (pass > 1) printf(" Required %d passes\n",pass);*/
+ if (incomplete != 0)
+ {
+ printf ("gcc-as warning(debugger output):");
+ printf ("Unable to resolve %d circular references.\n", incomplete);
+ };
+ fpnt = f_ref_root;
+ symbol_name = "\0";
+ while (fpnt != (struct forward_ref *) NULL)
+ {
+ if (fpnt->resolved != 'Y')
+ {
+ if (find_symbol (fpnt->dbx_type) !=
+ (struct VMS_DBG_Symbol *) NULL)
+ {
+ printf ("gcc-as warning(debugger output):");
+ printf ("Forward reference error, dbx type %d\n",
+ fpnt->dbx_type);
+ break;
+ };
+ fixit[0] = 0;
+ sprintf (&fixit[1], "%d=s4;", fpnt->dbx_type);
+ pnt2 = (char *) strchr (&fixit[1], '=');
+ VMS_typedef_parse (pnt2);
+ };
+ fpnt = fpnt->next;
+ };
+}
+
+static
+Define_Local_Symbols (s1, s2)
+ symbolS *s1, *s2;
+{
+ symbolS *symbolP1;
+ for (symbolP1 = symbol_next (s1); symbolP1 != s2; symbolP1 = symbol_next (symbolP1))
+ {
+ if (symbolP1 == (symbolS *) NULL)
+ return;
+ if (S_GET_RAW_TYPE (symbolP1) == N_FUN)
+ {
+ char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1;
+ if (*pnt == 'F' || *pnt == 'f') break;
+ };
+ /*
+ * Deal with STAB symbols
+ */
+ if (S_IS_DEBUG (symbolP1))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (symbolP1))
+ {
+ case N_LSYM:
+ case N_PSYM:
+ VMS_local_stab_Parse (symbolP1);
+ break;
+ case N_RSYM:
+ VMS_RSYM_Parse (symbolP1, Current_Routine, Text_Psect);
+ break;
+ } /*switch*/
+ } /* if */
+ } /* for */
+}
+
+
+/* This function crawls the symbol chain searching for local symbols that need
+ * to be described to the debugger. When we enter a new scope with a "{", it
+ * creates a new "block", which helps the debugger keep track of which scope
+ * we are currently in.
+ */
+
+static symbolS *
+Define_Routine (symbolP, Level)
+ symbolS *symbolP;
+ int Level;
+{
+ symbolS *sstart;
+ symbolS *symbolP1;
+ char str[10];
+ int rcount = 0;
+ int Offset;
+ sstart = symbolP;
+ for (symbolP1 = symbol_next (symbolP); symbolP1; symbolP1 = symbol_next (symbolP1))
+ {
+ if (S_GET_RAW_TYPE (symbolP1) == N_FUN)
+ {
+ char * pnt=(char*) strchr (S_GET_NAME (symbolP1), ':') + 1;
+ if (*pnt == 'F' || *pnt == 'f') break;
+ };
+ /*
+ * Deal with STAB symbols
+ */
+ if (S_IS_DEBUG (symbolP1))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch (S_GET_RAW_TYPE (symbolP1))
+ {
+ case N_LBRAC:
+ if (Level != 0)
+ {
+ sprintf (str, "$%d", rcount++);
+ VMS_TBT_Block_Begin (symbolP1, Text_Psect, str);
+ };
+ Offset = S_GET_VALUE (symbolP1);
+ Define_Local_Symbols (sstart, symbolP1);
+ symbolP1 =
+ Define_Routine (symbolP1, Level + 1);
+ if (Level != 0)
+ VMS_TBT_Block_End (S_GET_VALUE (symbolP1) -
+ Offset);
+ sstart = symbolP1;
+ break;
+ case N_RBRAC:
+ return symbolP1;
+ } /*switch*/
+ } /* if */
+ } /* for */
+ /* we end up here if there were no brackets in this function. Define
+everything */
+ Define_Local_Symbols (sstart, (symbolS *) 0);
+ return symbolP1;
+}
+
+
+static
+VMS_DBG_Define_Routine (symbolP, Curr_Routine, Txt_Psect)
+ symbolS *symbolP;
+ symbolS *Curr_Routine;
+ int Txt_Psect;
+{
+ Current_Routine = Curr_Routine;
+ Text_Psect = Txt_Psect;
+ Define_Routine (symbolP, 0);
+}
+
+
+
+
+#ifndef HO_VMS
+#include <sys/types.h>
+#include <time.h>
+
+/* Manufacure a VMS like time on a unix based system. */
+get_VMS_time_on_unix (char *Now)
+{
+ char *pnt;
+ time_t timeb;
+ time (&timeb);
+ pnt = ctime (&timeb);
+ pnt[3] = 0;
+ pnt[7] = 0;
+ pnt[10] = 0;
+ pnt[16] = 0;
+ pnt[24] = 0;
+ sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11);
+}
+
+#endif /* not HO_VMS */
+/*
+ * Write the MHD (Module Header) records
+ */
+static
+Write_VMS_MHD_Records ()
+{
+ register char *cp, *cp1;
+ register int i;
+ struct
+ {
+ int Size;
+ char *Ptr;
+ } Descriptor;
+ char Module_Name[256];
+ char Now[18];
+
+ /*
+ * We are writing a module header record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_HDR);
+ /*
+ * ***************************
+ * *MAIN MODULE HEADER RECORD*
+ * ***************************
+ *
+ * Store record type and header type
+ */
+ PUT_CHAR (OBJ_S_C_HDR);
+ PUT_CHAR (MHD_S_C_MHD);
+ /*
+ * Structure level is 0
+ */
+ PUT_CHAR (OBJ_S_C_STRLVL);
+ /*
+ * Maximum record size is size of the object record buffer
+ */
+ PUT_SHORT (sizeof (Object_Record_Buffer));
+ /*
+ * Get module name (the FILENAME part of the object file)
+ */
+ cp = out_file_name;
+ cp1 = Module_Name;
+ while (*cp)
+ {
+ if ((*cp == ']') || (*cp == '>') ||
+ (*cp == ':') || (*cp == '/'))
+ {
+ cp1 = Module_Name;
+ cp++;
+ continue;
+ }
+ *cp1++ = islower (*cp) ? toupper (*cp++) : *cp++;
+ }
+ *cp1 = 0;
+ /*
+ * Limit it to 31 characters and store in the object record
+ */
+ while (--cp1 >= Module_Name)
+ if (*cp1 == '.')
+ *cp1 = 0;
+ if (strlen (Module_Name) > 31)
+ {
+ if (flagseen['+'])
+ printf ("%s: Module name truncated: %s\n", myname, Module_Name);
+ Module_Name[31] = 0;
+ }
+ PUT_COUNTED_STRING (Module_Name);
+ /*
+ * Module Version is "V1.0"
+ */
+ PUT_COUNTED_STRING ("V1.0");
+ /*
+ * Creation time is "now" (17 chars of time string)
+ */
+#ifndef HO_VMS
+ get_VMS_time_on_unix (&Now[0]);
+#else /* HO_VMS */
+ Descriptor.Size = 17;
+ Descriptor.Ptr = Now;
+ sys$asctim (0, &Descriptor, 0, 0);
+#endif /* HO_VMS */
+ for (i = 0; i < 17; i++)
+ PUT_CHAR (Now[i]);
+ /*
+ * Patch time is "never" (17 zeros)
+ */
+ for (i = 0; i < 17; i++)
+ PUT_CHAR (0);
+ /*
+ * Flush the record
+ */
+ Flush_VMS_Object_Record_Buffer ();
+ /*
+ * *************************
+ * *LANGUAGE PROCESSOR NAME*
+ * *************************
+ *
+ * Store record type and header type
+ */
+ PUT_CHAR (OBJ_S_C_HDR);
+ PUT_CHAR (MHD_S_C_LNM);
+ /*
+ * Store language processor name and version
+ * (not a counted string!)
+ */
+ cp = compiler_version_string;
+ if (cp == 0)
+ {
+ cp = "GNU AS V";
+ while (*cp)
+ PUT_CHAR (*cp++);
+ cp = strchr (&version_string, '.');
+ while (*cp != ' ')
+ cp--;
+ cp++;
+ };
+ while (*cp >= 32)
+ PUT_CHAR (*cp++);
+ /*
+ * Flush the record
+ */
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Write the EOM (End Of Module) record
+ */
+static
+Write_VMS_EOM_Record (Psect, Offset)
+ int Psect;
+ int Offset;
+{
+ /*
+ * We are writing an end-of-module record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_EOM);
+ /*
+ * Store record Type
+ */
+ PUT_CHAR (OBJ_S_C_EOM);
+ /*
+ * Store the error severity (0)
+ */
+ PUT_CHAR (0);
+ /*
+ * Store the entry point, if it exists
+ */
+ if (Psect >= 0)
+ {
+ /*
+ * Store the entry point Psect
+ */
+ PUT_CHAR (Psect);
+ /*
+ * Store the entry point Psect offset
+ */
+ PUT_LONG (Offset);
+ }
+ /*
+ * Flush the record
+ */
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
+
+static int
+hash_string (ptr)
+ unsigned char *ptr;
+{
+ register unsigned char *p = ptr;
+ register unsigned char *end = p + strlen (ptr);
+ register unsigned char c;
+ register int hash = 0;
+
+ while (p != end)
+ {
+ c = *p++;
+ hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
+ }
+ return hash;
+}
+
+/*
+ * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
+ */
+static
+VMS_Case_Hack_Symbol (In, Out)
+ register char *In;
+ register char *Out;
+{
+ long int init = 0;
+ long int result;
+ char *pnt;
+ char *new_name;
+ char *old_name;
+ register int i;
+ int destructor = 0; /*hack to allow for case sens in a destructor*/
+ int truncate = 0;
+ int Case_Hack_Bits = 0;
+ int Saw_Dollar = 0;
+ static char Hex_Table[16] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ /*
+ * Kill any leading "_"
+ */
+ if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0')))
+ In++;
+
+ new_name = Out; /* save this for later*/
+
+#if barfoo /* Dead code */
+ if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_'))
+ destructor = 1;
+#endif
+
+ /* We may need to truncate the symbol, save the hash for later*/
+ if (strlen (In) > 23)
+ result = hash_string (In);
+ /*
+ * Is there a Psect Attribute to skip??
+ */
+ if (HAS_PSECT_ATTRIBUTES (In))
+ {
+ /*
+ * Yes: Skip it
+ */
+ In += PSECT_ATTRIBUTES_STRING_LENGTH;
+ while (*In)
+ {
+ if ((In[0] == '$') && (In[1] == '$'))
+ {
+ In += 2;
+ break;
+ }
+ In++;
+ }
+ }
+
+ old_name = In;
+/* if (strlen(In) > 31 && flagseen['+'])
+ printf("%s: Symbol name truncated: %s\n",myname,In);*/
+ /*
+ * Do the case conversion
+ */
+ i = 23; /* Maximum of 23 chars */
+ while (*In && (--i >= 0))
+ {
+ Case_Hack_Bits <<= 1;
+ if (*In == '$')
+ Saw_Dollar = 1;
+ if ((destructor == 1) && (i == 21))
+ Saw_Dollar = 0;
+ switch (vms_name_mapping)
+ {
+ case 0:
+ if (isupper(*In)) {
+ *Out++ = *In++;
+ Case_Hack_Bits |= 1;
+ } else {
+ *Out++ = islower(*In) ? toupper(*In++) : *In++;
+ }
+ break;
+ case 3: *Out++ = *In++;
+ break;
+ case 2:
+ if (islower(*In)) {
+ *Out++ = *In++;
+ } else {
+ *Out++ = isupper(*In) ? tolower(*In++) : *In++;
+ }
+ break;
+ };
+ }
+ /*
+ * If we saw a dollar sign, we don't do case hacking
+ */
+ if (flagseen['h'] || Saw_Dollar)
+ Case_Hack_Bits = 0;
+
+ /*
+ * If we have more than 23 characters and everything is lowercase
+ * we can insert the full 31 characters
+ */
+ if (*In)
+ {
+ /*
+ * We have more than 23 characters
+ * If we must add the case hack, then we have truncated the str
+ */
+ pnt = Out;
+ truncate = 1;
+ if (Case_Hack_Bits == 0)
+ {
+ /*
+ * And so far they are all lower case:
+ * Check up to 8 more characters
+ * and ensure that they are lowercase
+ */
+ for (i = 0; (In[i] != 0) && (i < 8); i++)
+ if (isupper(In[i]) && !Saw_Dollar && !flagseen['h'])
+ break;
+
+ if (In[i] == 0)
+ truncate = 0;
+
+ if ((i == 8) || (In[i] == 0))
+ {
+ /*
+ * They are: Copy up to 31 characters
+ * to the output string
+ */
+ i = 8;
+ while ((--i >= 0) && (*In))
+ switch (vms_name_mapping){
+ case 0: *Out++ = islower(*In) ?
+ toupper (*In++) :
+ *In++;
+ break;
+ case 3: *Out++ = *In++;
+ break;
+ case 2: *Out++ = isupper(*In) ?
+ tolower(*In++) :
+ *In++;
+ break;
+ };
+ }
+ }
+ }
+ /*
+ * If there were any uppercase characters in the name we
+ * take on the case hacking string
+ */
+
+ /* Old behavior for regular GNU-C compiler */
+ if (!flagseen['+'])
+ truncate = 0;
+ if ((Case_Hack_Bits != 0) || (truncate == 1))
+ {
+ if (truncate == 0)
+ {
+ *Out++ = '_';
+ for (i = 0; i < 6; i++)
+ {
+ *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
+ Case_Hack_Bits >>= 4;
+ }
+ *Out++ = 'X';
+ }
+ else
+ {
+ Out = pnt; /*Cut back to 23 characters maximum */
+ *Out++ = '_';
+ for (i = 0; i < 7; i++)
+ {
+ init = result & 0x01f;
+ if (init < 10)
+ *Out++ = '0' + init;
+ else
+ *Out++ = 'A' + init - 10;
+ result = result >> 5;
+ }
+ }
+ } /*Case Hack */
+ /*
+ * Done
+ */
+ *Out = 0;
+ if (truncate == 1 && flagseen['+'] && flagseen['H'])
+ printf ("%s: Symbol %s replaced by %s\n", myname, old_name, new_name);
+}
+
+
+/*
+ * Scan a symbol name for a psect attribute specification
+ */
+#define GLOBALSYMBOL_BIT 0x10000
+#define GLOBALVALUE_BIT 0x20000
+
+
+static
+VMS_Modify_Psect_Attributes (Name, Attribute_Pointer)
+ char *Name;
+ int *Attribute_Pointer;
+{
+ register int i;
+ register char *cp;
+ int Negate;
+ static struct
+ {
+ char *Name;
+ int Value;
+ } Attributes[] =
+ {
+ {"PIC", GPS_S_M_PIC},
+ {"LIB", GPS_S_M_LIB},
+ {"OVR", GPS_S_M_OVR},
+ {"REL", GPS_S_M_REL},
+ {"GBL", GPS_S_M_GBL},
+ {"SHR", GPS_S_M_SHR},
+ {"EXE", GPS_S_M_EXE},
+ {"RD", GPS_S_M_RD},
+ {"WRT", GPS_S_M_WRT},
+ {"VEC", GPS_S_M_VEC},
+ {"GLOBALSYMBOL", GLOBALSYMBOL_BIT},
+ {"GLOBALVALUE", GLOBALVALUE_BIT},
+ {0, 0}
+ };
+
+ /*
+ * Kill leading "_"
+ */
+ if (*Name == '_')
+ Name++;
+ /*
+ * Check for a PSECT attribute list
+ */
+ if (!HAS_PSECT_ATTRIBUTES (Name))
+ return; /* If not, return */
+ /*
+ * Skip the attribute list indicator
+ */
+ Name += PSECT_ATTRIBUTES_STRING_LENGTH;
+ /*
+ * Process the attributes ("_" separated, "$" terminated)
+ */
+ while (*Name != '$')
+ {
+ /*
+ * Assume not negating
+ */
+ Negate = 0;
+ /*
+ * Check for "NO"
+ */
+ if ((Name[0] == 'N') && (Name[1] == 'O'))
+ {
+ /*
+ * We are negating (and skip the NO)
+ */
+ Negate = 1;
+ Name += 2;
+ }
+ /*
+ * Find the token delimiter
+ */
+ cp = Name;
+ while (*cp && (*cp != '_') && (*cp != '$'))
+ cp++;
+ /*
+ * Look for the token in the attribute list
+ */
+ for (i = 0; Attributes[i].Name; i++)
+ {
+ /*
+ * If the strings match, set/clear the attr.
+ */
+ if (strncmp (Name, Attributes[i].Name, cp - Name) == 0)
+ {
+ /*
+ * Set or clear
+ */
+ if (Negate)
+ *Attribute_Pointer &=
+ ~Attributes[i].Value;
+ else
+ *Attribute_Pointer |=
+ Attributes[i].Value;
+ /*
+ * Done
+ */
+ break;
+ }
+ }
+ /*
+ * Now skip the attribute
+ */
+ Name = cp;
+ if (*Name == '_')
+ Name++;
+ }
+ /*
+ * Done
+ */
+ return;
+}
+
+
+/*
+ * Define a global symbol
+ */
+static
+VMS_Global_Symbol_Spec (Name, Psect_Number, Psect_Offset, Defined)
+ char *Name;
+ int Psect_Number;
+ int Psect_Offset;
+{
+ char Local[32];
+
+ /*
+ * We are writing a GSD record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_GSD);
+ /*
+ * If the buffer is empty we must insert the GSD record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_GSD);
+ /*
+ * We are writing a Global symbol definition subrecord
+ */
+ if (Psect_Number <= 255)
+ {
+ PUT_CHAR (GSD_S_C_SYM);
+ }
+ else
+ {
+ PUT_CHAR (GSD_S_C_SYMW);
+ }
+ /*
+ * Data type is undefined
+ */
+ PUT_CHAR (0);
+ /*
+ * Switch on Definition/Reference
+ */
+ if ((Defined & 1) != 0)
+ {
+ /*
+ * Definition:
+ * Flags = "RELOCATABLE" and "DEFINED" for regular symbol
+ * = "DEFINED" for globalvalue (Defined & 2 == 1)
+ */
+ if ((Defined & 2) == 0)
+ {
+ PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
+ }
+ else
+ {
+ PUT_SHORT (GSY_S_M_DEF);
+ };
+ /*
+ * Psect Number
+ */
+ if (Psect_Number <= 255)
+ {
+ PUT_CHAR (Psect_Number);
+ }
+ else
+ {
+ PUT_SHORT (Psect_Number);
+ }
+ /*
+ * Offset
+ */
+ PUT_LONG (Psect_Offset);
+ }
+ else
+ {
+ /*
+ * Reference:
+ * Flags = "RELOCATABLE" for regular symbol,
+ * = "" for globalvalue (Defined & 2 == 1)
+ */
+ if ((Defined & 2) == 0)
+ {
+ PUT_SHORT (GSY_S_M_REL);
+ }
+ else
+ {
+ PUT_SHORT (0);
+ };
+ }
+ /*
+ * Finally, the global symbol name
+ */
+ VMS_Case_Hack_Symbol (Name, Local);
+ PUT_COUNTED_STRING (Local);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Define a psect
+ */
+static int
+VMS_Psect_Spec (Name, Size, Type, vsp)
+ char *Name;
+ int Size;
+ char *Type;
+ struct VMS_Symbol *vsp;
+{
+ char Local[32];
+ int Psect_Attributes;
+
+ /*
+ * Generate the appropriate PSECT flags given the PSECT type
+ */
+ if (strcmp (Type, "COMMON") == 0)
+ {
+ /*
+ * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
+ */
+ Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL |
+ GPS_S_M_SHR | GPS_S_M_RD | GPS_S_M_WRT);
+ }
+ else if (strcmp (Type, "CONST") == 0)
+ {
+ /*
+ * Common block psects are: PIC,OVR,REL,GBL,SHR,RD
+ */
+ Psect_Attributes = (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL |
+ GPS_S_M_SHR | GPS_S_M_RD);
+ }
+ else if (strcmp (Type, "DATA") == 0)
+ {
+ /*
+ * The Data psects are PIC,REL,RD,WRT
+ */
+ Psect_Attributes =
+ (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT);
+ }
+ else if (strcmp (Type, "TEXT") == 0)
+ {
+ /*
+ * The Text psects are PIC,REL,SHR,EXE,RD
+ */
+ Psect_Attributes =
+ (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR |
+ GPS_S_M_EXE | GPS_S_M_RD);
+ }
+ else
+ {
+ /*
+ * Error: Unknown psect type
+ */
+ error ("Unknown VMS psect type");
+ }
+ /*
+ * Modify the psect attributes according to any attribute string
+ */
+ if (HAS_PSECT_ATTRIBUTES (Name))
+ VMS_Modify_Psect_Attributes (Name, &Psect_Attributes);
+ /*
+ * Check for globalref/def/val.
+ */
+ if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
+ {
+ /*
+ * globalvalue symbols were generated before. This code
+ * prevents unsightly psect buildup, and makes sure that
+ * fixup references are emitted correctly.
+ */
+ vsp->Psect_Index = -1; /* to catch errors */
+ S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF; /* make refs work */
+ return 1; /* decrement psect counter */
+ };
+
+ if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0)
+ {
+ switch (S_GET_RAW_TYPE (vsp->Symbol))
+ {
+ case N_UNDF | N_EXT:
+ VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
+ vsp->Psect_Offset, 0);
+ vsp->Psect_Index = -1;
+ S_GET_RAW_TYPE (vsp->Symbol) = N_UNDF;
+ return 1; /* return and indicate no psect */
+ case N_DATA | N_EXT:
+ VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
+ vsp->Psect_Offset, 1);
+ /* In this case we still generate the psect */
+ break;
+ default:
+ {
+ char Error_Line[256];
+ sprintf (Error_Line, "Globalsymbol attribute for"
+ " symbol %s was unexpected.\n", Name);
+ error (Error_Line);
+ break;
+ };
+ }; /* switch */
+ };
+
+ Psect_Attributes &= 0xffff; /* clear out the globalref/def stuff */
+ /*
+ * We are writing a GSD record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_GSD);
+ /*
+ * If the buffer is empty we must insert the GSD record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_GSD);
+ /*
+ * We are writing a PSECT definition subrecord
+ */
+ PUT_CHAR (GSD_S_C_PSC);
+ /*
+ * Psects are always LONGWORD aligned
+ */
+ PUT_CHAR (2);
+ /*
+ * Specify the psect attributes
+ */
+ PUT_SHORT (Psect_Attributes);
+ /*
+ * Specify the allocation
+ */
+ PUT_LONG (Size);
+ /*
+ * Finally, the psect name
+ */
+ VMS_Case_Hack_Symbol (Name, Local);
+ PUT_COUNTED_STRING (Local);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+ return 0;
+}
+
+
+/*
+ * Given the pointer to a symbol we calculate how big the data at the
+ * symbol is. We do this by looking for the next symbol (local or
+ * global) which will indicate the start of another datum.
+ */
+static int
+VMS_Initialized_Data_Size (sp, End_Of_Data)
+ register struct symbol *sp;
+ int End_Of_Data;
+{
+ register struct symbol *sp1, *Next_Symbol;
+
+ /*
+ * Find the next symbol
+ * it delimits this datum
+ */
+ Next_Symbol = 0;
+ for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
+ {
+ /*
+ * The data type must match
+ */
+ if (S_GET_TYPE (sp1) != N_DATA)
+ continue;
+ /*
+ * The symbol must be AFTER this symbol
+ */
+ if (S_GET_VALUE (sp1) <= S_GET_VALUE (sp))
+ continue;
+ /*
+ * We ignore THIS symbol
+ */
+ if (sp1 == sp)
+ continue;
+ /*
+ * If there is already a candidate selected for the
+ * next symbol, see if we are a better candidate
+ */
+ if (Next_Symbol)
+ {
+ /*
+ * We are a better candidate if we are "closer"
+ * to the symbol
+ */
+ if (S_GET_VALUE (sp1) >
+ S_GET_VALUE (Next_Symbol))
+ continue;
+ /*
+ * Win: Make this the candidate
+ */
+ Next_Symbol = sp1;
+ }
+ else
+ {
+ /*
+ * This is the 1st candidate
+ */
+ Next_Symbol = sp1;
+ }
+ }
+ /*
+ * Calculate its size
+ */
+ return (Next_Symbol ?
+ (S_GET_VALUE (Next_Symbol) -
+ S_GET_VALUE (sp)) :
+ (End_Of_Data - S_GET_VALUE (sp)));
+}
+
+/*
+ * Check symbol names for the Psect hack with a globalvalue, and then
+ * generate globalvalues for those that have it.
+ */
+static
+VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment)
+ unsigned text_siz;
+ unsigned data_siz;
+ char *Data_Segment;
+{
+ register symbolS *sp;
+ char *stripped_name, *Name;
+ int Size;
+ int Psect_Attributes;
+ int globalvalue;
+
+ /*
+ * Scan the symbol table for globalvalues, and emit def/ref when
+ * required. These will be caught again later and converted to
+ * N_UNDF
+ */
+ for (sp = symbol_rootP; sp; sp = sp->sy_next)
+ {
+ /*
+ * See if this is something we want to look at.
+ */
+ if ((S_GET_RAW_TYPE (sp) != (N_DATA | N_EXT)) &&
+ (S_GET_RAW_TYPE (sp) != (N_UNDF | N_EXT)))
+ continue;
+ /*
+ * See if this has globalvalue specification.
+ */
+ Name = S_GET_NAME (sp);
+
+ if (!HAS_PSECT_ATTRIBUTES (Name))
+ continue;
+
+ stripped_name = (char *) malloc (strlen (Name) + 1);
+ strcpy (stripped_name, Name);
+ Psect_Attributes = 0;
+ VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes);
+
+ if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
+ {
+ switch (S_GET_RAW_TYPE (sp))
+ {
+ case N_UNDF | N_EXT:
+ VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2);
+ break;
+ case N_DATA | N_EXT:
+ Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
+ if (Size > 4)
+ error ("Invalid data type for globalvalue");
+ globalvalue = 0;
+
+ memcpy (&globalvalue, Data_Segment + S_GET_VALUE (sp) -
+ text_siz, Size);
+ /* Three times for good luck. The linker seems to get confused
+ if there are fewer than three */
+ VMS_Global_Symbol_Spec (stripped_name, 0, 0, 2);
+ VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3);
+ VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue, 3);
+ break;
+ default:
+ printf (" Invalid globalvalue of %s\n", stripped_name);
+ break;
+ }; /* switch */
+ }; /* if */
+ free (stripped_name); /* clean up */
+ }; /* for */
+
+}
+
+
+/*
+ * Define a procedure entry pt/mask
+ */
+static
+VMS_Procedure_Entry_Pt (Name, Psect_Number, Psect_Offset, Entry_Mask)
+ char *Name;
+ int Psect_Number;
+ int Psect_Offset;
+ int Entry_Mask;
+{
+ char Local[32];
+
+ /*
+ * We are writing a GSD record
+ */
+ Set_VMS_Object_File_Record (OBJ_S_C_GSD);
+ /*
+ * If the buffer is empty we must insert the GSD record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (OBJ_S_C_GSD);
+ /*
+ * We are writing a Procedure Entry Pt/Mask subrecord
+ */
+ if (Psect_Number <= 255)
+ {
+ PUT_CHAR (GSD_S_C_EPM);
+ }
+ else
+ {
+ PUT_CHAR (GSD_S_C_EPMW);
+ }
+ /*
+ * Data type is undefined
+ */
+ PUT_CHAR (0);
+ /*
+ * Flags = "RELOCATABLE" and "DEFINED"
+ */
+ PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
+ /*
+ * Psect Number
+ */
+ if (Psect_Number <= 255)
+ {
+ PUT_CHAR (Psect_Number);
+ }
+ else
+ {
+ PUT_SHORT (Psect_Number);
+ }
+ /*
+ * Offset
+ */
+ PUT_LONG (Psect_Offset);
+ /*
+ * Entry mask
+ */
+ PUT_SHORT (Entry_Mask);
+ /*
+ * Finally, the global symbol name
+ */
+ VMS_Case_Hack_Symbol (Name, Local);
+ PUT_COUNTED_STRING (Local);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Set the current location counter to a particular Psect and Offset
+ */
+static
+VMS_Set_Psect (Psect_Index, Offset, Record_Type)
+ int Psect_Index;
+ int Offset;
+ int Record_Type;
+{
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * If the buffer is empty we must insert the record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Stack the Psect base + Longword Offset
+ */
+ if (Psect_Index < 255)
+ {
+ PUT_CHAR (TIR_S_C_STA_PL);
+ PUT_CHAR (Psect_Index);
+ }
+ else
+ {
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (Psect_Index);
+ }
+ PUT_LONG (Offset);
+ /*
+ * Set relocation base
+ */
+ PUT_CHAR (TIR_S_C_CTL_SETRB);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Store repeated immediate data in current Psect
+ */
+static
+VMS_Store_Repeated_Data (Repeat_Count, Pointer, Size, Record_Type)
+ int Repeat_Count;
+ register char *Pointer;
+ int Size;
+ int Record_Type;
+{
+
+ /*
+ * Ignore zero bytes/words/longwords
+ */
+ if ((Size == sizeof (char)) && (*Pointer == 0))
+ return;
+ if ((Size == sizeof (short)) && (*(short *) Pointer == 0))
+ return;
+ if ((Size == sizeof (long)) && (*(long *) Pointer == 0))
+ return;
+ /*
+ * If the data is too big for a TIR_S_C_STO_RIVB sub-record
+ * then we do it manually
+ */
+ if (Size > 255)
+ {
+ while (--Repeat_Count >= 0)
+ VMS_Store_Immediate_Data (Pointer, Size, Record_Type);
+ return;
+ }
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * If the buffer is empty we must insert record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Stack the repeat count
+ */
+ PUT_CHAR (TIR_S_C_STA_LW);
+ PUT_LONG (Repeat_Count);
+ /*
+ * And now the command and its data
+ */
+ PUT_CHAR (TIR_S_C_STO_RIVB);
+ PUT_CHAR (Size);
+ while (--Size >= 0)
+ PUT_CHAR (*Pointer++);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Store a Position Independent Reference
+ */
+static
+VMS_Store_PIC_Symbol_Reference (Symbol, Offset, PC_Relative,
+ Psect, Psect_Offset, Record_Type)
+ struct symbol *Symbol;
+ int Offset;
+ int PC_Relative;
+ int Psect;
+ int Psect_Offset;
+ int Record_Type;
+{
+ register struct VMS_Symbol *vsp =
+ (struct VMS_Symbol *) (Symbol->sy_number);
+ char Local[32];
+
+ /*
+ * We are writing a "Record_Type" record
+ */
+ Set_VMS_Object_File_Record (Record_Type);
+ /*
+ * If the buffer is empty we must insert record type
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Set to the appropriate offset in the Psect
+ */
+ if (PC_Relative)
+ {
+ /*
+ * For a Code reference we need to fix the operand
+ * specifier as well (so back up 1 byte)
+ */
+ VMS_Set_Psect (Psect, Psect_Offset - 1, Record_Type);
+ }
+ else
+ {
+ /*
+ * For a Data reference we just store HERE
+ */
+ VMS_Set_Psect (Psect, Psect_Offset, Record_Type);
+ }
+ /*
+ * Make sure we are still generating a "Record Type" record
+ */
+ if (Object_Record_Offset == 0)
+ PUT_CHAR (Record_Type);
+ /*
+ * Dispatch on symbol type (so we can stack its value)
+ */
+ switch (S_GET_RAW_TYPE (Symbol))
+ {
+ /*
+ * Global symbol
+ */
+#ifdef NOT_VAX_11_C_COMPATIBLE
+ case N_UNDF | N_EXT:
+ case N_DATA | N_EXT:
+#endif /* NOT_VAX_11_C_COMPATIBLE */
+ case N_UNDF:
+ case N_TEXT | N_EXT:
+ /*
+ * Get the symbol name (case hacked)
+ */
+ VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local);
+ /*
+ * Stack the global symbol value
+ */
+ PUT_CHAR (TIR_S_C_STA_GBL);
+ PUT_COUNTED_STRING (Local);
+ if (Offset)
+ {
+ /*
+ * Stack the longword offset
+ */
+ PUT_CHAR (TIR_S_C_STA_LW);
+ PUT_LONG (Offset);
+ /*
+ * Add the two, leaving the result on the stack
+ */
+ PUT_CHAR (TIR_S_C_OPR_ADD);
+ }
+ break;
+ /*
+ * Uninitialized local data
+ */
+ case N_BSS:
+ /*
+ * Stack the Psect (+offset)
+ */
+ if (vsp->Psect_Index < 255)
+ {
+ PUT_CHAR (TIR_S_C_STA_PL);
+ PUT_CHAR (vsp->Psect_Index);
+ }
+ else
+ {
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (vsp->Psect_Index);
+ }
+ PUT_LONG (vsp->Psect_Offset + Offset);
+ break;
+ /*
+ * Local text
+ */
+ case N_TEXT:
+ /*
+ * Stack the Psect (+offset)
+ */
+ if (vsp->Psect_Index < 255)
+ {
+ PUT_CHAR (TIR_S_C_STA_PL);
+ PUT_CHAR (vsp->Psect_Index);
+ }
+ else
+ {
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (vsp->Psect_Index);
+ }
+ PUT_LONG (S_GET_VALUE (Symbol) + Offset);
+ break;
+ /*
+ * Initialized local or global data
+ */
+ case N_DATA:
+#ifndef NOT_VAX_11_C_COMPATIBLE
+ case N_UNDF | N_EXT:
+ case N_DATA | N_EXT:
+#endif /* NOT_VAX_11_C_COMPATIBLE */
+ /*
+ * Stack the Psect (+offset)
+ */
+ if (vsp->Psect_Index < 255)
+ {
+ PUT_CHAR (TIR_S_C_STA_PL);
+ PUT_CHAR (vsp->Psect_Index);
+ }
+ else
+ {
+ PUT_CHAR (TIR_S_C_STA_WPL);
+ PUT_SHORT (vsp->Psect_Index);
+ }
+ PUT_LONG (vsp->Psect_Offset + Offset);
+ break;
+ }
+ /*
+ * Store either a code or data reference
+ */
+ PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR);
+ /*
+ * Flush the buffer if it is more than 75% full
+ */
+ if (Object_Record_Offset >
+ (sizeof (Object_Record_Buffer) * 3 / 4))
+ Flush_VMS_Object_Record_Buffer ();
+}
+
+
+/*
+ * Check in the text area for an indirect pc-relative reference
+ * and fix it up with addressing mode 0xff [PC indirect]
+ *
+ * THIS SHOULD BE REPLACED BY THE USE OF TIR_S_C_STO_PIRR IN THE
+ * PIC CODE GENERATING FIXUP ROUTINE.
+ */
+static
+VMS_Fix_Indirect_Reference (Text_Psect, Offset, fragP, text_frag_root)
+ int Text_Psect;
+ int Offset;
+ register fragS *fragP;
+ struct frag *text_frag_root;
+{
+ /*
+ * The addressing mode byte is 1 byte before the address
+ */
+ Offset--;
+ /*
+ * Is it in THIS frag??
+ */
+ if ((Offset < fragP->fr_address) ||
+ (Offset >= (fragP->fr_address + fragP->fr_fix)))
+ {
+ /*
+ * We need to search for the fragment containing this
+ * Offset
+ */
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ if ((Offset >= fragP->fr_address) &&
+ (Offset < (fragP->fr_address + fragP->fr_fix)))
+ break;
+ }
+ /*
+ * If we couldn't find the frag, things are BAD!!
+ */
+ if (fragP == 0)
+ error ("Couldn't find fixup fragment when checking for indirect reference");
+ }
+ /*
+ * Check for indirect PC relative addressing mode
+ */
+ if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff)
+ {
+ static char Address_Mode = 0xff;
+
+ /*
+ * Yes: Store the indirect mode back into the image
+ * to fix up the damage done by STO_PICR
+ */
+ VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR);
+ VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR);
+ }
+}
+
+
+
+/*
+ * This is a hacked _doprnt() for VAX-11 "C". It understands that
+ * it is ONLY called by as_fatal(Format, Args) with a pointer to the
+ * "Args" argument. From this we can make it all work right!
+ */
+#if !defined(eunice) && defined(HO_VMS)
+_doprnt (Format, a, f)
+ char *Format;
+ FILE *f;
+ char **a;
+{
+ int Nargs = ((int *) a)[-2]; /* This understands as_fatal() */
+
+ switch (Nargs)
+ {
+ default:
+ fprintf (f, "_doprnt error on \"%s\"!!", Format);
+ break;
+ case 1:
+ fprintf (f, Format);
+ break;
+ case 2:
+ fprintf (f, Format, a[0]);
+ break;
+ case 3:
+ fprintf (f, Format, a[0], a[1]);
+ break;
+ case 4:
+ fprintf (f, Format, a[0], a[1], a[2]);
+ break;
+ case 5:
+ fprintf (f, Format, a[0], a[1], a[2], a[3]);
+ break;
+ case 6:
+ fprintf (f, Format, a[0], a[1], a[2], a[3], a[4]);
+ break;
+ case 7:
+ fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5]);
+ break;
+ case 8:
+ fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5], a[6]);
+ break;
+ case 9:
+ fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
+ break;
+ case 10:
+ fprintf (f, Format, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
+ break;
+ }
+}
+
+#endif /* eunice */
+
+
+/*
+ * If the procedure "main()" exists we have to add the instruction
+ * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
+ */
+VMS_Check_For_Main ()
+{
+ register symbolS *symbolP;
+#ifdef HACK_DEC_C_STARTUP /* JF */
+ register struct frchain *frchainP;
+ register fragS *fragP;
+ register fragS **prev_fragPP;
+ register struct fix *fixP;
+ register fragS *New_Frag;
+ int i;
+#endif /* HACK_DEC_C_STARTUP */
+
+ symbolP = (struct symbol *) symbol_find ("_main");
+ if (symbolP && !S_IS_DEBUG (symbolP) &&
+ S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
+ {
+#ifdef HACK_DEC_C_STARTUP
+ if (!flagseen['+'])
+ {
+#endif
+ /*
+ * Remember the entry point symbol
+ */
+ Entry_Point_Symbol = symbolP;
+#ifdef HACK_DEC_C_STARTUP
+ }
+ else
+ {
+ /*
+ * Scan all the fragment chains for the one with "_main"
+ * (Actually we know the fragment from the symbol, but we need
+ * the previous fragment so we can change its pointer)
+ */
+ frchainP = frchain_root;
+ while (frchainP)
+ {
+ /*
+ * Scan all the fragments in this chain, remembering
+ * the "previous fragment"
+ */
+ prev_fragPP = &frchainP->frch_root;
+ fragP = frchainP->frch_root;
+ while (fragP && (fragP != frchainP->frch_last))
+ {
+ /*
+ * Is this the fragment?
+ */
+ if (fragP == symbolP->sy_frag)
+ {
+ /*
+ * Yes: Modify the fragment by replacing
+ * it with a new fragment.
+ */
+ New_Frag = (fragS *)
+ xmalloc (sizeof (*New_Frag) +
+ fragP->fr_fix +
+ fragP->fr_var +
+ 5);
+ /*
+ * The fragments are the same except
+ * that the "fixed" area is larger
+ */
+ *New_Frag = *fragP;
+ New_Frag->fr_fix += 6;
+ /*
+ * Copy the literal data opening a hole
+ * 2 bytes after "_main" (i.e. just after
+ * the entry mask). Into which we place
+ * the JSB instruction.
+ */
+ New_Frag->fr_literal[0] = fragP->fr_literal[0];
+ New_Frag->fr_literal[1] = fragP->fr_literal[1];
+ New_Frag->fr_literal[2] = 0x16; /* Jsb */
+ New_Frag->fr_literal[3] = 0xef;
+ New_Frag->fr_literal[4] = 0;
+ New_Frag->fr_literal[5] = 0;
+ New_Frag->fr_literal[6] = 0;
+ New_Frag->fr_literal[7] = 0;
+ for (i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
+ New_Frag->fr_literal[i + 6] =
+ fragP->fr_literal[i];
+ /*
+ * Now replace the old fragment with the
+ * newly generated one.
+ */
+ *prev_fragPP = New_Frag;
+ /*
+ * Remember the entry point symbol
+ */
+ Entry_Point_Symbol = symbolP;
+ /*
+ * Scan the text area fixup structures
+ * as offsets in the fragment may have
+ * changed
+ */
+ for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
+ {
+ /*
+ * Look for references to this
+ * fragment.
+ */
+ if (fixP->fx_frag == fragP)
+ {
+ /*
+ * Change the fragment
+ * pointer
+ */
+ fixP->fx_frag = New_Frag;
+ /*
+ * If the offset is after
+ * the entry mask we need
+ * to account for the JSB
+ * instruction we just
+ * inserted.
+ */
+ if (fixP->fx_where >= 2)
+ fixP->fx_where += 6;
+ }
+ }
+ /*
+ * Scan the symbols as offsets in the
+ * fragment may have changed
+ */
+ for (symbolP = symbol_rootP;
+ symbolP;
+ symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Look for references to this
+ * fragment.
+ */
+ if (symbolP->sy_frag == fragP)
+ {
+ /*
+ * Change the fragment
+ * pointer
+ */
+ symbolP->sy_frag = New_Frag;
+ /*
+ * If the offset is after
+ * the entry mask we need
+ * to account for the JSB
+ * instruction we just
+ * inserted.
+ */
+ if (S_GET_VALUE (symbolP) >= 2)
+ S_GET_VALUE (symbolP) += 6;
+ }
+ }
+ /*
+ * Make a symbol reference to
+ * "_c$main_args" so we can get
+ * its address inserted into the
+ * JSB instruction.
+ */
+ symbolP = (symbolS *) xmalloc (sizeof (*symbolP));
+ S_GET_NAME (symbolP) = "_c$main_args";
+ S_SET_TYPE (symbolP, N_UNDF);
+ S_GET_OTHER (symbolP) = 0;
+ S_GET_DESC (symbolP) = 0;
+ S_GET_VALUE (symbolP) = 0;
+ symbolP->sy_name_offset = 0;
+ symbolP->sy_number = 0;
+ symbolP->sy_frag = New_Frag;
+ symbolP->sy_forward = 0;
+ /* this actually inserts at the beginning of the list */
+ symbol_append (symbol_rootP, symbolP, &symbol_rootP, &symbol_lastP);
+
+ symbol_rootP = symbolP;
+ /*
+ * Generate a text fixup structure
+ * to get "_c$main_args" stored into the
+ * JSB instruction.
+ */
+ fixP = (struct fix *) xmalloc (sizeof (*fixP));
+ fixP->fx_frag = New_Frag;
+ fixP->fx_where = 4;
+ fixP->fx_addsy = symbolP;
+ fixP->fx_subsy = 0;
+ fixP->fx_offset = 0;
+ fixP->fx_size = sizeof (long);
+ fixP->fx_pcrel = 1;
+ fixP->fx_next = text_fix_root;
+ text_fix_root = fixP;
+ /*
+ * Now make sure we exit from the loop
+ */
+ frchainP = 0;
+ break;
+ }
+ /*
+ * Try the next fragment
+ */
+ prev_fragPP = &fragP->fr_next;
+ fragP = fragP->fr_next;
+ }
+ /*
+ * Try the next fragment chain
+ */
+ if (frchainP)
+ frchainP = frchainP->frch_next;
+ }
+ }
+#endif /* HACK_DEC_C_STARTUP */
+ }
+}
+
+/*
+ * Write a VAX/VMS object file (everything else has been done!)
+ */
+VMS_write_object_file (text_siz, data_siz, text_frag_root, data_frag_root)
+ unsigned text_siz;
+ unsigned data_siz;
+ struct frag *text_frag_root;
+ struct frag *data_frag_root;
+{
+ register fragS *fragP;
+ register symbolS *symbolP;
+ register symbolS *sp;
+ register struct fix *fixP;
+ register struct VMS_Symbol *vsp;
+ char *Data_Segment;
+ int Local_Initialized_Data_Size = 0;
+ int Globalref;
+ int Psect_Number = 0; /* Psect Index Number */
+ int Text_Psect = -1; /* Text Psect Index */
+ int Data_Psect = -2; /* Data Psect Index JF: Was -1 */
+ int Bss_Psect = -3; /* Bss Psect Index JF: Was -1 */
+
+ /*
+ * Create the VMS object file
+ */
+ Create_VMS_Object_File ();
+ /*
+ * Write the module header records
+ */
+ Write_VMS_MHD_Records ();
+
+ /*
+ * Store the Data segment:
+ *
+ * Since this is REALLY hard to do any other way,
+ * we actually manufacture the data segment and
+ * the store the appropriate values out of it.
+ * We need to generate this early, so that globalvalues
+ * can be properly emitted.
+ */
+ if (data_siz > 0)
+ {
+ /*
+ * Allocate the data segment
+ */
+ Data_Segment = (char *) xmalloc (data_siz);
+ /*
+ * Run through the data fragments, filling in the segment
+ */
+ for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ register long int count;
+ register char *fill_literal;
+ register long int fill_size;
+ int i;
+
+ i = fragP->fr_address - text_siz;
+ if (fragP->fr_fix)
+ memcpy (Data_Segment + i,
+ fragP->fr_literal,
+ fragP->fr_fix);
+ i += fragP->fr_fix;
+
+ fill_literal = fragP->fr_literal + fragP->fr_fix;
+ fill_size = fragP->fr_var;
+ for (count = fragP->fr_offset; count; count--)
+ {
+ if (fill_size)
+ memcpy (Data_Segment + i, fill_literal, fill_size);
+ i += fill_size;
+ }
+ }
+ }
+
+
+ /*
+ * Generate the VMS object file records
+ * 1st GSD then TIR records
+ */
+
+ /******* Global Symbol Dictionary *******/
+ /*
+ * Emit globalvalues now. We must do this before the text psect
+ * is defined, or we will get linker warnings about multiply defined
+ * symbols. All of the globalvalues "reference" psect 0, although
+ * it really does not have anything to do with it.
+ */
+ VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
+ /*
+ * Define the Text Psect
+ */
+ Text_Psect = Psect_Number++;
+ VMS_Psect_Spec ("$code", text_siz, "TEXT", 0);
+ /*
+ * Define the BSS Psect
+ */
+ if (local_bss_counter > 0)
+ {
+ Bss_Psect = Psect_Number++;
+ VMS_Psect_Spec ("$uninitialized_data", local_bss_counter, "DATA",
+ 0);
+ }
+#ifndef gxx_bug_fixed
+ /*
+ * The g++ compiler does not write out external references to vtables
+ * correctly. Check for this and holler if we see it happening.
+ * If that compiler bug is ever fixed we can remove this.
+ */
+ for (sp = symbol_rootP; sp; sp = symbol_next (sp))
+ {
+ /*
+ * Dispatch on symbol type
+ */
+ switch (S_GET_RAW_TYPE (sp)) {
+ /*
+ * Global Reference
+ */
+ case N_UNDF:
+ /*
+ * Make a GSD global symbol reference
+ * record.
+ */
+ if (strncmp (S_GET_NAME (sp),"__vt.",5) == 0)
+ {
+ S_GET_RAW_TYPE (sp) = N_UNDF | N_EXT;
+ as_warn("g++ wrote an extern reference to %s as a routine.",
+ S_GET_NAME (sp));
+ as_warn("I will fix it, but I hope that it was not really a routine");
+ };
+ break;
+ default:
+ break;
+ }
+ }
+#endif /* gxx_bug_fixed */
+ /*
+ * Now scan the symbols and emit the appropriate GSD records
+ */
+ for (sp = symbol_rootP; sp; sp = symbol_next (sp))
+ {
+ /*
+ * Dispatch on symbol type
+ */
+ switch (S_GET_RAW_TYPE (sp))
+ {
+ /*
+ * Global uninitialized data
+ */
+ case N_UNDF | N_EXT:
+ /*
+ * Make a VMS data symbol entry
+ */
+ vsp = (struct VMS_Symbol *)
+ xmalloc (sizeof (*vsp));
+ vsp->Symbol = sp;
+ vsp->Size = S_GET_VALUE (sp);
+ vsp->Psect_Index = Psect_Number++;
+ vsp->Psect_Offset = 0;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_number = (int) vsp;
+ /*
+ * Make the psect for this data
+ */
+ if (S_GET_OTHER (sp))
+ Globalref = VMS_Psect_Spec (
+ S_GET_NAME (sp),
+ vsp->Size,
+ "CONST",
+ vsp);
+ else
+ Globalref = VMS_Psect_Spec (
+ S_GET_NAME (sp),
+ vsp->Size,
+ "COMMON",
+ vsp);
+ if (Globalref)
+ Psect_Number--;
+#ifdef NOT_VAX_11_C_COMPATIBLE
+ /*
+ * Place a global symbol at the
+ * beginning of the Psect
+ */
+ VMS_Global_Symbol_Spec (S_GET_NAME (sp),
+ vsp->Psect_Index,
+ 0,
+ 1);
+#endif /* NOT_VAX_11_C_COMPATIBLE */
+ break;
+ /*
+ * Local uninitialized data
+ */
+ case N_BSS:
+ /*
+ * Make a VMS data symbol entry
+ */
+ vsp = (struct VMS_Symbol *)
+ xmalloc (sizeof (*vsp));
+ vsp->Symbol = sp;
+ vsp->Size = 0;
+ vsp->Psect_Index = Bss_Psect;
+ vsp->Psect_Offset =
+ S_GET_VALUE (sp) -
+ bss_address_frag.fr_address;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_number = (int) vsp;
+ break;
+ /*
+ * Global initialized data
+ */
+ case N_DATA | N_EXT:
+ /*
+ * Make a VMS data symbol entry
+ */
+ vsp = (struct VMS_Symbol *)
+ xmalloc (sizeof (*vsp));
+ vsp->Symbol = sp;
+ vsp->Size = VMS_Initialized_Data_Size (sp,
+ text_siz + data_siz);
+ vsp->Psect_Index = Psect_Number++;
+ vsp->Psect_Offset = 0;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_number = (int) vsp;
+ /*
+ * Make its psect
+ */
+ if (S_GET_OTHER (sp))
+ Globalref = VMS_Psect_Spec (
+ S_GET_NAME (sp),
+ vsp->Size,
+ "CONST",
+ vsp);
+ else
+ Globalref = VMS_Psect_Spec (
+ S_GET_NAME (sp),
+ vsp->Size,
+ "COMMON",
+ vsp);
+ if (Globalref)
+ Psect_Number--;
+#ifdef NOT_VAX_11_C_COMPATIBLE
+ /*
+ * Place a global symbol at the
+ * beginning of the Psect
+ */
+ VMS_Global_Symbol_Spec (S_GET_NAME (sp),
+ vsp->Psect_Index,
+ 0,
+ 1);
+#endif /* NOT_VAX_11_C_COMPATIBLE */
+ break;
+ /*
+ * Local initialized data
+ */
+ case N_DATA:
+ /*
+ * Make a VMS data symbol entry
+ */
+ vsp = (struct VMS_Symbol *)
+ xmalloc (sizeof (*vsp));
+ vsp->Symbol = sp;
+ vsp->Size =
+ VMS_Initialized_Data_Size (sp,
+ text_siz + data_siz);
+ vsp->Psect_Index = Data_Psect;
+ vsp->Psect_Offset =
+ Local_Initialized_Data_Size;
+ Local_Initialized_Data_Size += vsp->Size;
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_number = (int) vsp;
+ break;
+ /*
+ * Global Text definition
+ */
+ case N_TEXT | N_EXT:
+ {
+ unsigned short Entry_Mask;
+
+ /*
+ * Get the entry mask
+ */
+ fragP = sp->sy_frag;
+ Entry_Mask = (fragP->fr_literal[0] & 0xff) +
+ ((fragP->fr_literal[1] & 0xff)
+ << 8);
+ /*
+ * Define the Procedure entry pt.
+ */
+ VMS_Procedure_Entry_Pt (S_GET_NAME (sp),
+ Text_Psect,
+ S_GET_VALUE (sp),
+ Entry_Mask);
+ break;
+ }
+ /*
+ * Local Text definition
+ */
+ case N_TEXT:
+ /*
+ * Make a VMS data symbol entry
+ */
+ if (Text_Psect != -1)
+ {
+ vsp = (struct VMS_Symbol *)
+ xmalloc (sizeof (*vsp));
+ vsp->Symbol = sp;
+ vsp->Size = 0;
+ vsp->Psect_Index = Text_Psect;
+ vsp->Psect_Offset = S_GET_VALUE (sp);
+ vsp->Next = VMS_Symbols;
+ VMS_Symbols = vsp;
+ sp->sy_number = (int) vsp;
+ }
+ break;
+ /*
+ * Global Reference
+ */
+ case N_UNDF:
+ /*
+ * Make a GSD global symbol reference
+ * record.
+ */
+ VMS_Global_Symbol_Spec (S_GET_NAME (sp),
+ 0,
+ 0,
+ 0);
+ break;
+ /*
+ * Anything else
+ */
+ default:
+ /*
+ * Ignore STAB symbols
+ * Including .stabs emitted by g++
+ */
+ if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22))
+ break;
+ /*
+ * Error
+ */
+ if (S_GET_TYPE (sp) != 22)
+ printf (" ERROR, unknown type (%d)\n",
+ S_GET_TYPE (sp));
+ break;
+ }
+ }
+ /*
+ * Define the Data Psect
+ */
+ if ((data_siz > 0) && (Local_Initialized_Data_Size > 0))
+ {
+ /*
+ * Do it
+ */
+ Data_Psect = Psect_Number++;
+ VMS_Psect_Spec ("$data",
+ Local_Initialized_Data_Size,
+ "DATA", 0);
+ /*
+ * Scan the VMS symbols and fill in the data psect
+ */
+ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+ {
+ /*
+ * Only look for undefined psects
+ */
+ if (vsp->Psect_Index < 0)
+ {
+ /*
+ * And only initialized data
+ */
+ if ((S_GET_TYPE (vsp->Symbol) == N_DATA) && !S_IS_EXTERNAL (vsp->Symbol))
+ vsp->Psect_Index = Data_Psect;
+ }
+ }
+ }
+
+ /******* Text Information and Relocation Records *******/
+ /*
+ * Write the text segment data
+ */
+ if (text_siz > 0)
+ {
+ /*
+ * Scan the text fragments
+ */
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
+ {
+ /*
+ * Stop if we get to the data fragments
+ */
+ if (fragP == data_frag_root)
+ break;
+ /*
+ * Ignore fragments with no data
+ */
+ if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
+ continue;
+ /*
+ * Go the the appropriate offset in the
+ * Text Psect.
+ */
+ VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
+ /*
+ * Store the "fixed" part
+ */
+ if (fragP->fr_fix)
+ VMS_Store_Immediate_Data (fragP->fr_literal,
+ fragP->fr_fix,
+ OBJ_S_C_TIR);
+ /*
+ * Store the "variable" part
+ */
+ if (fragP->fr_var && fragP->fr_offset)
+ VMS_Store_Repeated_Data (fragP->fr_offset,
+ fragP->fr_literal +
+ fragP->fr_fix,
+ fragP->fr_var,
+ OBJ_S_C_TIR);
+ }
+ /*
+ * Now we go through the text segment fixups and
+ * generate TIR records to fix up addresses within
+ * the Text Psect
+ */
+ for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
+ {
+ /*
+ * We DO handle the case of "Symbol - Symbol" as
+ * long as it is in the same segment.
+ */
+ if (fixP->fx_subsy && fixP->fx_addsy)
+ {
+ int i;
+
+ /*
+ * They need to be in the same segment
+ */
+ if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
+ S_GET_RAW_TYPE (fixP->fx_addsy))
+ error ("Fixup data addsy and subsy didn't have the same type");
+ /*
+ * And they need to be in one that we
+ * can check the psect on
+ */
+ if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
+ (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
+ error ("Fixup data addsy and subsy didn't have an appropriate type");
+ /*
+ * This had better not be PC relative!
+ */
+ if (fixP->fx_pcrel)
+ error ("Fixup data was erroneously \"pcrel\"");
+ /*
+ * Subtract their values to get the
+ * difference.
+ */
+ i = S_GET_VALUE (fixP->fx_addsy) -
+ S_GET_VALUE (fixP->fx_subsy);
+ /*
+ * Now generate the fixup object records
+ * Set the psect and store the data
+ */
+ VMS_Set_Psect (Text_Psect,
+ fixP->fx_where +
+ fixP->fx_frag->fr_address,
+ OBJ_S_C_TIR);
+ VMS_Store_Immediate_Data (&i,
+ fixP->fx_size,
+ OBJ_S_C_TIR);
+ /*
+ * Done
+ */
+ continue;
+ }
+ /*
+ * Size will HAVE to be "long"
+ */
+ if (fixP->fx_size != sizeof (long))
+ error ("Fixup datum was not a longword");
+ /*
+ * Symbol must be "added" (if it is ever
+ * subtracted we can
+ * fix this assumption)
+ */
+ if (fixP->fx_addsy == 0)
+ error ("Fixup datum was not \"fixP->fx_addsy\"");
+ /*
+ * Store the symbol value in a PIC fashion
+ */
+ VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
+ fixP->fx_offset,
+ fixP->fx_pcrel,
+ Text_Psect,
+ fixP->fx_where +
+ fixP->fx_frag->fr_address,
+ OBJ_S_C_TIR);
+ /*
+ * Check for indirect address reference,
+ * which has to be fixed up (as the linker
+ * will screw it up with TIR_S_C_STO_PICR).
+ */
+ if (fixP->fx_pcrel)
+ VMS_Fix_Indirect_Reference (Text_Psect,
+ fixP->fx_where +
+ fixP->fx_frag->fr_address,
+ fixP->fx_frag,
+ text_frag_root);
+ }
+ }
+ /*
+ * Store the Data segment:
+ *
+ * Since this is REALLY hard to do any other way,
+ * we actually manufacture the data segment and
+ * the store the appropriate values out of it.
+ * The segment was manufactured before, now we just
+ * dump it into the appropriate psects.
+ */
+ if (data_siz > 0)
+ {
+
+ /*
+ * Now we can run through all the data symbols
+ * and store the data
+ */
+ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+ {
+ /*
+ * Ignore anything other than data symbols
+ */
+ if (S_GET_TYPE (vsp->Symbol) != N_DATA)
+ continue;
+ /*
+ * Set the Psect + Offset
+ */
+ VMS_Set_Psect (vsp->Psect_Index,
+ vsp->Psect_Offset,
+ OBJ_S_C_TIR);
+ /*
+ * Store the data
+ */
+ VMS_Store_Immediate_Data (Data_Segment +
+ S_GET_VALUE (vsp->Symbol) -
+ text_siz,
+ vsp->Size,
+ OBJ_S_C_TIR);
+ }
+ /*
+ * Now we go through the data segment fixups and
+ * generate TIR records to fix up addresses within
+ * the Data Psects
+ */
+ for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
+ {
+ /*
+ * Find the symbol for the containing datum
+ */
+ for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
+ {
+ /*
+ * Only bother with Data symbols
+ */
+ sp = vsp->Symbol;
+ if (S_GET_TYPE (sp) != N_DATA)
+ continue;
+ /*
+ * Ignore symbol if After fixup
+ */
+ if (S_GET_VALUE (sp) >
+ (fixP->fx_where +
+ fixP->fx_frag->fr_address))
+ continue;
+ /*
+ * See if the datum is here
+ */
+ if ((S_GET_VALUE (sp) + vsp->Size) <=
+ (fixP->fx_where +
+ fixP->fx_frag->fr_address))
+ continue;
+ /*
+ * We DO handle the case of "Symbol - Symbol" as
+ * long as it is in the same segment.
+ */
+ if (fixP->fx_subsy && fixP->fx_addsy)
+ {
+ int i;
+
+ /*
+ * They need to be in the same segment
+ */
+ if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
+ S_GET_RAW_TYPE (fixP->fx_addsy))
+ error ("Fixup data addsy and subsy didn't have the same type");
+ /*
+ * And they need to be in one that we
+ * can check the psect on
+ */
+ if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
+ (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
+ error ("Fixup data addsy and subsy didn't have an appropriate type");
+ /*
+ * This had better not be PC relative!
+ */
+ if (fixP->fx_pcrel)
+ error ("Fixup data was erroneously \"pcrel\"");
+ /*
+ * Subtract their values to get the
+ * difference.
+ */
+ i = S_GET_VALUE (fixP->fx_addsy) -
+ S_GET_VALUE (fixP->fx_subsy);
+ /*
+ * Now generate the fixup object records
+ * Set the psect and store the data
+ */
+ VMS_Set_Psect (vsp->Psect_Index,
+ fixP->fx_frag->fr_address +
+ fixP->fx_where -
+ S_GET_VALUE (vsp->Symbol) +
+ vsp->Psect_Offset,
+ OBJ_S_C_TIR);
+ VMS_Store_Immediate_Data (&i,
+ fixP->fx_size,
+ OBJ_S_C_TIR);
+ /*
+ * Done
+ */
+ break;
+ }
+ /*
+ * Size will HAVE to be "long"
+ */
+ if (fixP->fx_size != sizeof (long))
+ error ("Fixup datum was not a longword");
+ /*
+ * Symbol must be "added" (if it is ever
+ * subtracted we can
+ * fix this assumption)
+ */
+ if (fixP->fx_addsy == 0)
+ error ("Fixup datum was not \"fixP->fx_addsy\"");
+ /*
+ * Store the symbol value in a PIC fashion
+ */
+ VMS_Store_PIC_Symbol_Reference (
+ fixP->fx_addsy,
+ fixP->fx_offset,
+ fixP->fx_pcrel,
+ vsp->Psect_Index,
+ fixP->fx_frag->fr_address +
+ fixP->fx_where -
+ S_GET_VALUE (vsp->Symbol) +
+ vsp->Psect_Offset,
+ OBJ_S_C_TIR);
+ /*
+ * Done
+ */
+ break;
+ }
+
+ }
+ }
+
+ /*
+ * Write the Traceback Begin Module record
+ */
+ VMS_TBT_Module_Begin ();
+ /*
+ * Scan the symbols and write out the routines
+ * (this makes the assumption that symbols are in
+ * order of ascending text segment offset)
+ */
+ {
+ struct symbol *Current_Routine = 0;
+ int Current_Line_Number = 0;
+ int Current_Offset = -1;
+ struct input_file *Current_File;
+
+/* Output debugging info for global variables and static variables that are not
+ * specific to one routine. We also need to examine all stabs directives, to
+ * find the definitions to all of the advanced data types, and this is done by
+ * VMS_LSYM_Parse. This needs to be done before any definitions are output to
+ * the object file, since there can be forward references in the stabs
+ * directives. When through with parsing, the text of the stabs directive
+ * is altered, with the definitions removed, so that later passes will see
+ * directives as they would be written if the type were already defined.
+ *
+ * We also look for files and include files, and make a list of them. We
+ * examine the source file numbers to establish the actual lines that code was
+ * generated from, and then generate offsets.
+ */
+ VMS_LSYM_Parse ();
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Deal with STAB symbols
+ */
+ if (S_IS_DEBUG (symbolP))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
+ {
+ case N_SLINE:
+ if (S_GET_DESC (symbolP) > Current_File->max_line)
+ Current_File->max_line = S_GET_DESC (symbolP);
+ if (S_GET_DESC (symbolP) < Current_File->min_line)
+ Current_File->min_line = S_GET_DESC (symbolP);
+ break;
+ case N_SO:
+ Current_File = find_file (symbolP);
+ Current_File->flag = 1;
+ Current_File->min_line = 1;
+ break;
+ case N_SOL:
+ Current_File = find_file (symbolP);
+ break;
+ case N_GSYM:
+ VMS_GSYM_Parse (symbolP, Text_Psect);
+ break;
+ case N_LCSYM:
+ VMS_LCSYM_Parse (symbolP, Text_Psect);
+ break;
+ case N_FUN: /* For static constant symbols */
+ case N_STSYM:
+ VMS_STSYM_Parse (symbolP, Text_Psect);
+ break;
+ }
+ }
+ }
+
+ /* now we take a quick sweep through the files and assign offsets
+ to each one. This will essentially be the starting line number to the
+ debugger for each file. Output the info for the debugger to specify the
+ files, and then tell it how many lines to use */
+ {
+ int File_Number = 0;
+ int Debugger_Offset = 0;
+ int file_available;
+ Current_File = file_root;
+ for (Current_File = file_root; Current_File; Current_File = Current_File->next)
+ {
+ if (Current_File == (struct input_file *) NULL)
+ break;
+ if (Current_File->max_line == 0)
+ continue;
+ if ((strncmp (Current_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
+ !flagseen['D'])
+ continue;
+ if ((strncmp (Current_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
+ !flagseen['D'])
+ continue;
+/* show a few extra lines at the start of the region selected */
+ if (Current_File->min_line > 2)
+ Current_File->min_line -= 2;
+ Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
+ Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
+ if (Current_File->same_file_fpnt != (struct input_file *) NULL)
+ Current_File->file_number = Current_File->same_file_fpnt->file_number;
+ else
+ {
+ Current_File->file_number = ++File_Number;
+ file_available = VMS_TBT_Source_File (Current_File->name,
+ Current_File->file_number);
+ if (!file_available)
+ {
+ Current_File->file_number = 0;
+ File_Number--;
+ continue;
+ };
+ };
+ VMS_TBT_Source_Lines (Current_File->file_number,
+ Current_File->min_line,
+ Current_File->max_line - Current_File->min_line + 1);
+ }; /* for */
+ }; /* scope */
+ Current_File = (struct input_file *) NULL;
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
+ {
+ /*
+ * Deal with text symbols
+ */
+ if (!S_IS_DEBUG (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
+ {
+ /*
+ * Ignore symbols starting with "L",
+ * as they are local symbols
+ */
+ if (*S_GET_NAME (symbolP) == 'L')
+ continue;
+ /*
+ * If there is a routine start defined,
+ * terminate it.
+ */
+ if (Current_Routine)
+ {
+ /*
+ * End the routine
+ */
+ VMS_TBT_Routine_End (text_siz, Current_Routine);
+ }
+ /*
+ * Store the routine begin traceback info
+ */
+ if (Text_Psect != -1)
+ {
+ VMS_TBT_Routine_Begin (symbolP, Text_Psect);
+ Current_Routine = symbolP;
+ }
+/* Output local symbols, i.e. all symbols that are associated with a specific
+ * routine. We output them now so the debugger recognizes them as local to
+ * this routine.
+ */
+ {
+ symbolS *symbolP1;
+ char *pnt;
+ char *pnt1;
+ for (symbolP1 = Current_Routine; symbolP1; symbolP1 = symbol_next (symbolP1))
+ {
+ if (!S_IS_DEBUG (symbolP1))
+ continue;
+ if (S_GET_RAW_TYPE (symbolP1) != N_FUN)
+ continue;
+ pnt = S_GET_NAME (symbolP);
+ pnt1 = S_GET_NAME (symbolP1);
+ if (*pnt++ != '_')
+ continue;
+ while (*pnt++ == *pnt1++)
+ {
+ };
+ if (*pnt1 != 'F' && *pnt1 != 'f') continue;
+ if ((*(--pnt) == '\0') && (*(--pnt1) == ':'))
+ break;
+ };
+ if (symbolP1 != (symbolS *) NULL)
+ VMS_DBG_Define_Routine (symbolP1, Current_Routine, Text_Psect);
+ } /* local symbol block */
+ /*
+ * Done
+ */
+ continue;
+ }
+ /*
+ * Deal with STAB symbols
+ */
+ if (S_IS_DEBUG (symbolP))
+ {
+ /*
+ * Dispatch on STAB type
+ */
+ switch ((unsigned char) S_GET_RAW_TYPE (symbolP))
+ {
+ /*
+ * Line number
+ */
+ case N_SLINE:
+ /* Offset the line into the correct portion
+ * of the file */
+ if (Current_File->file_number == 0)
+ break;
+ /* Sometimes the same offset gets several source
+ * lines assigned to it.
+ * We should be selective about which lines
+ * we allow, we should prefer lines that are
+ * in the main source file when debugging
+ * inline functions. */
+ if ((Current_File->file_number != 1) &&
+ S_GET_VALUE (symbolP) ==
+ Current_Offset)
+ break;
+ /* calculate actual debugger source line */
+ S_GET_DESC (symbolP)
+ += Current_File->offset;
+ /*
+ * If this is the 1st N_SLINE, setup
+ * PC/Line correlation. Otherwise
+ * do the delta PC/Line. If the offset
+ * for the line number is not +ve we need
+ * to do another PC/Line correlation
+ * setup
+ */
+ if (Current_Offset == -1)
+ {
+ VMS_TBT_Line_PC_Correlation (
+ S_GET_DESC (symbolP),
+ S_GET_VALUE (symbolP),
+ Text_Psect,
+ 0);
+ }
+ else
+ {
+ if ((S_GET_DESC (symbolP) -
+ Current_Line_Number) <= 0)
+ {
+ /*
+ * Line delta is not +ve, we
+ * need to close the line and
+ * start a new PC/Line
+ * correlation.
+ */
+ VMS_TBT_Line_PC_Correlation (0,
+ S_GET_VALUE (symbolP) -
+ Current_Offset,
+ 0,
+ -1);
+ VMS_TBT_Line_PC_Correlation (
+ S_GET_DESC (symbolP),
+ S_GET_VALUE (symbolP),
+ Text_Psect,
+ 0);
+ }
+ else
+ {
+ /*
+ * Line delta is +ve, all is well
+ */
+ VMS_TBT_Line_PC_Correlation (
+ S_GET_DESC (symbolP) -
+ Current_Line_Number,
+ S_GET_VALUE (symbolP) -
+ Current_Offset,
+ 0,
+ 1);
+ }
+ }
+ /*
+ * Update the current line/PC
+ */
+ Current_Line_Number = S_GET_DESC (symbolP);
+ Current_Offset = S_GET_VALUE (symbolP);
+ /*
+ * Done
+ */
+ break;
+ /*
+ * Source file
+ */
+ case N_SO:
+ /*
+ * Remember that we had a source file
+ * and emit the source file debugger
+ * record
+ */
+ Current_File =
+ find_file (symbolP);
+ break;
+/* We need to make sure that we are really in the actual source file when
+ * we compute the maximum line number. Otherwise the debugger gets really
+ * confused */
+ case N_SOL:
+ Current_File =
+ find_file (symbolP);
+ break;
+ }
+ }
+ }
+ /*
+ * If there is a routine start defined,
+ * terminate it (and the line numbers)
+ */
+ if (Current_Routine)
+ {
+ /*
+ * Terminate the line numbers
+ */
+ VMS_TBT_Line_PC_Correlation (0,
+ text_siz - S_GET_VALUE (Current_Routine),
+ 0,
+ -1);
+ /*
+ * Terminate the routine
+ */
+ VMS_TBT_Routine_End (text_siz, Current_Routine);
+ }
+ }
+ /*
+ * Write the Traceback End Module TBT record
+ */
+ VMS_TBT_Module_End ();
+
+ /*
+ * Write the End Of Module record
+ */
+ if (Entry_Point_Symbol == 0)
+ Write_VMS_EOM_Record (-1, 0);
+ else
+ Write_VMS_EOM_Record (Text_Psect,
+ S_GET_VALUE (Entry_Point_Symbol));
+
+ /*
+ * All done, close the object file
+ */
+ Close_VMS_Object_File ();
+}
+
+/* end of obj-vms.c */
diff --git a/gnu/usr.bin/as/config/obj-vms.h b/gnu/usr.bin/as/config/obj-vms.h
new file mode 100644
index 0000000..f997535
--- /dev/null
+++ b/gnu/usr.bin/as/config/obj-vms.h
@@ -0,0 +1,474 @@
+/* VMS object file format
+ Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2,
+or (at your option) any later version.
+
+GAS is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public
+License along with GAS; see the file COPYING. If not, write
+to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Tag to validate a.out object file format processing */
+#define OBJ_VMS 1
+
+#include "targ-cpu.h"
+
+/* This flag is used to remember whether we are in the const or the
+ data section. By and large they are identical, but we set a no-write
+ bit for psects in the const section. */
+
+extern char const_flag;
+
+
+/* These are defined in obj-vms.c. */
+extern const short seg_N_TYPE[];
+extern const segT N_TYPE_seg[];
+
+enum reloc_type {
+ NO_RELOC, RELOC_32
+};
+
+#define N_BADMAG(x) (0)
+#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 )
+
+/* We use this copy of the exec header for VMS. We do not actually use it, but
+ what we actually do is let gas fill in the relevant slots, and when we get
+ around to writing an obj file, we just pick out what we need. */
+
+struct exec
+{
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned long a_trsize; /* length of relocation info for text, in bytes */
+ unsigned long a_drsize; /* length of relocation info for data, in bytes */
+ unsigned long a_entry; /* start address */
+ unsigned long a_syms; /* length of symbol table data in file, in bytes */
+};
+
+typedef struct {
+ struct exec header; /* a.out header */
+ long string_table_size; /* names + '\0' + sizeof(int) */
+} object_headers;
+
+/* 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 */
+
+#define N_GSYM 0x20 /* global symbol: name,,0,type,0 */
+#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,0 */
+#define N_FUN 0x24 /* procedure: name,,0,linenumber,address */
+#define N_STSYM 0x26 /* static symbol: name,,0,type,address */
+#define N_LCSYM 0x28 /* .lcomm symbol: name,,0,type,address */
+#define N_RSYM 0x40 /* register sym: name,,0,type,register */
+#define N_SLINE 0x44 /* src line: 0,,0,linenumber,address */
+#define N_CATCH 0x54 /* */
+#define N_SSYM 0x60 /* structure elt: name,,0,type,struct_offset */
+#define N_SO 0x64 /* source file name: name,,0,0,address */
+#define N_LSYM 0x80 /* local sym: name,,0,type,offset */
+#define N_SOL 0x84 /* #included file name: name,,0,0,address */
+#define N_PSYM 0xa0 /* parameter: name,,0,type,offset */
+#define N_ENTRY 0xa4 /* alternate entry: name,linenumber,address */
+#define N_LBRAC 0xc0 /* left bracket: 0,,0,nesting level,address */
+#define N_RBRAC 0xe0 /* right bracket: 0,,0,nesting level,address */
+#define N_BCOMM 0xe2 /* begin common: name,, */
+#define N_ECOMM 0xe4 /* end common: name,, */
+#define N_ECOML 0xe8 /* end common (local name): ,,address */
+#define N_LENG 0xfe /* second stab entry with length information */
+
+/* SYMBOL TABLE */
+/* Symbol table entry data type */
+
+typedef struct nlist obj_symbol_type; /* Symbol table entry */
+
+/* Symbol table macros and constants */
+
+/*
+ * Macros to extract information from a symbol table entry.
+ * This syntaxic indirection allows independence regarding a.out or coff.
+ * The argument (s) of all these macros is a pointer to a symbol table entry.
+ */
+
+/* True if the symbol is external */
+#define S_IS_EXTERNAL(s) ((s)->sy_symbol.n_type & N_EXT)
+
+/* True if symbol has been defined, ie is in N_{TEXT,DATA,BSS,ABS} or N_EXT */
+#define S_IS_DEFINED(s) (S_GET_TYPE(s) != N_UNDF)
+
+#define S_IS_REGISTER(s) ((s)->sy_symbol.n_type == N_REGISTER)
+
+/* True if a debug special symbol entry */
+#define S_IS_DEBUG(s) ((s)->sy_symbol.n_type & N_STAB)
+/* True if a symbol is local symbol name */
+/* A symbol name whose name begin with ^A is a gas internal pseudo symbol
+ nameless symbols come from .stab directives. */
+#define S_IS_LOCAL(s) (S_GET_NAME(s) && \
+ !S_IS_DEBUG(s) && \
+ (S_GET_NAME(s)[0] == '\001' || \
+ (S_LOCAL_NAME(s) && !flagseen['L'])))
+/* True if a symbol is not defined in this file */
+#define S_IS_EXTERN(s) ((s)->sy_symbol.n_type & N_EXT)
+/* True if the symbol has been generated because of a .stabd directive */
+#define S_IS_STABD(s) (S_GET_NAME(s) == (char *)0)
+
+/* Accessors */
+/* The value of the symbol */
+#define S_GET_VALUE(s) (((s)->sy_symbol.n_value))
+/* The name of the symbol */
+#define S_GET_NAME(s) ((s)->sy_symbol.n_un.n_name)
+/* The pointer to the string table */
+#define S_GET_OFFSET(s) ((s)->sy_symbol.n_un.n_strx)
+/* The raw type of the symbol */
+#define S_GET_RAW_TYPE(s) ((s)->sy_symbol.n_type)
+/* The type of the symbol */
+#define S_GET_TYPE(s) ((s)->sy_symbol.n_type & N_TYPE)
+/* The numeric value of the segment */
+#define S_GET_SEGMENT(s) (N_TYPE_seg[S_GET_TYPE(s)])
+/* The n_other expression value */
+#define S_GET_OTHER(s) ((s)->sy_symbol.n_other)
+/* The n_desc expression value */
+#define S_GET_DESC(s) ((s)->sy_symbol.n_desc)
+
+/* Modifiers */
+/* Set the value of the symbol */
+#define S_SET_VALUE(s,v) ((s)->sy_symbol.n_value = (unsigned long) (v))
+/* Assume that a symbol cannot be simultaneously in more than on segment */
+ /* set segment */
+#define S_SET_SEGMENT(s,seg) ((s)->sy_symbol.n_type &= ~N_TYPE,(s)->sy_symbol.n_type|=SEGMENT_TO_SYMBOL_TYPE(seg))
+/* The symbol is external */
+#define S_SET_EXTERNAL(s) ((s)->sy_symbol.n_type |= N_EXT)
+/* The symbol is not external */
+#define S_CLEAR_EXTERNAL(s) ((s)->sy_symbol.n_type &= ~N_EXT)
+/* Set the name of the symbol */
+#define S_SET_NAME(s,v) ((s)->sy_symbol.n_un.n_name = (v))
+/* Set the offset in the string table */
+#define S_SET_OFFSET(s,v) ((s)->sy_symbol.n_un.n_strx = (v))
+/* Set the n_other expression value */
+#define S_SET_OTHER(s,v) ((s)->sy_symbol.n_other = (v))
+/* Set the n_desc expression value */
+#define S_SET_DESC(s,v) ((s)->sy_symbol.n_desc = (v))
+
+
+/* File header macro and type definition */
+
+#define H_GET_TEXT_SIZE(h) ((h)->header.a_text)
+#define H_GET_DATA_SIZE(h) ((h)->header.a_data)
+#define H_GET_BSS_SIZE(h) ((h)->header.a_bss)
+
+#define H_SET_TEXT_SIZE(h,v) ((h)->header.a_text = md_section_align(SEG_TEXT, (v)))
+#define H_SET_DATA_SIZE(h,v) ((h)->header.a_data = md_section_align(SEG_DATA, (v)))
+#define H_SET_BSS_SIZE(h,v) ((h)->header.a_bss = md_section_align(SEG_BSS, (v)))
+
+#define H_SET_STRING_SIZE(h,v) ((h)->string_table_size = (v))
+#define H_SET_SYMBOL_TABLE_SIZE(h,v) ((h)->header.a_syms = (v) * \
+ sizeof(struct nlist))
+
+/*
+ * Current means for getting the name of a segment.
+ * This will change for infinite-segments support (e.g. COFF).
+ */
+#define segment_name(seg) ( seg_name[(int)(seg)] )
+extern char *const seg_name[];
+
+
+/* line numbering stuff. */
+#define OBJ_EMIT_LINENO(a, b, c) {;}
+
+#define obj_symbol_new_hook(s) {;}
+
+#ifdef __STDC__
+struct fix;
+void tc_aout_fix_to_chars(char *where, struct fix *fixP, relax_addressT segment_address);
+#else
+void tc_aout_fix_to_chars();
+#endif /* __STDC__ */
+
+/* The rest of this file contains definitions for constants used within the actual
+ VMS object file. We do not use a $ in the symbols (as per usual VMS
+ convention) since System V gags on it. */
+
+#define OBJ_S_C_HDR 0
+#define OBJ_S_C_HDR_MHD 0
+#define OBJ_S_C_HDR_LNM 1
+#define OBJ_S_C_HDR_SRC 2
+#define OBJ_S_C_HDR_TTL 3
+#define OBJ_S_C_HDR_CPR 4
+#define OBJ_S_C_HDR_MTC 5
+#define OBJ_S_C_HDR_GTX 6
+#define OBJ_S_C_GSD 1
+#define OBJ_S_C_GSD_PSC 0
+#define OBJ_S_C_GSD_SYM 1
+#define OBJ_S_C_GSD_EPM 2
+#define OBJ_S_C_GSD_PRO 3
+#define OBJ_S_C_GSD_SYMW 4
+#define OBJ_S_C_GSD_EPMW 5
+#define OBJ_S_C_GSD_PROW 6
+#define OBJ_S_C_GSD_IDC 7
+#define OBJ_S_C_GSD_ENV 8
+#define OBJ_S_C_GSD_LSY 9
+#define OBJ_S_C_GSD_LEPM 10
+#define OBJ_S_C_GSD_LPRO 11
+#define OBJ_S_C_GSD_SPSC 12
+#define OBJ_S_C_TIR 2
+#define OBJ_S_C_EOM 3
+#define OBJ_S_C_DBG 4
+#define OBJ_S_C_TBT 5
+#define OBJ_S_C_LNK 6
+#define OBJ_S_C_EOMW 7
+#define OBJ_S_C_MAXRECTYP 7
+#define OBJ_S_K_SUBTYP 1
+#define OBJ_S_C_SUBTYP 1
+#define OBJ_S_C_MAXRECSIZ 2048
+#define OBJ_S_C_STRLVL 0
+#define OBJ_S_C_SYMSIZ 31
+#define OBJ_S_C_STOREPLIM -1
+#define OBJ_S_C_PSCALILIM 9
+
+#define MHD_S_C_MHD 0
+#define MHD_S_C_LNM 1
+#define MHD_S_C_SRC 2
+#define MHD_S_C_TTL 3
+#define MHD_S_C_CPR 4
+#define MHD_S_C_MTC 5
+#define MHD_S_C_GTX 6
+#define MHD_S_C_MAXHDRTYP 6
+
+#define GSD_S_K_ENTRIES 1
+#define GSD_S_C_ENTRIES 1
+#define GSD_S_C_PSC 0
+#define GSD_S_C_SYM 1
+#define GSD_S_C_EPM 2
+#define GSD_S_C_PRO 3
+#define GSD_S_C_SYMW 4
+#define GSD_S_C_EPMW 5
+#define GSD_S_C_PROW 6
+#define GSD_S_C_IDC 7
+#define GSD_S_C_ENV 8
+#define GSD_S_C_LSY 9
+#define GSD_S_C_LEPM 10
+#define GSD_S_C_LPRO 11
+#define GSD_S_C_SPSC 12
+#define GSD_S_C_SYMV 13
+#define GSD_S_C_EPMV 14
+#define GSD_S_C_PROV 15
+#define GSD_S_C_MAXRECTYP 15
+
+#define GSY_S_M_WEAK 1
+#define GSY_S_M_DEF 2
+#define GSY_S_M_UNI 4
+#define GSY_S_M_REL 8
+
+#define GPS_S_M_PIC 1
+#define GPS_S_M_LIB 2
+#define GPS_S_M_OVR 4
+#define GPS_S_M_REL 8
+#define GPS_S_M_GBL 16
+#define GPS_S_M_SHR 32
+#define GPS_S_M_EXE 64
+#define GPS_S_M_RD 128
+#define GPS_S_M_WRT 256
+#define GPS_S_M_VEC 512
+#define GPS_S_K_NAME 9
+#define GPS_S_C_NAME 9
+
+#define TIR_S_C_STA_GBL 0
+#define TIR_S_C_STA_SB 1
+#define TIR_S_C_STA_SW 2
+#define TIR_S_C_STA_LW 3
+#define TIR_S_C_STA_PB 4
+#define TIR_S_C_STA_PW 5
+#define TIR_S_C_STA_PL 6
+#define TIR_S_C_STA_UB 7
+#define TIR_S_C_STA_UW 8
+#define TIR_S_C_STA_BFI 9
+#define TIR_S_C_STA_WFI 10
+#define TIR_S_C_STA_LFI 11
+#define TIR_S_C_STA_EPM 12
+#define TIR_S_C_STA_CKARG 13
+#define TIR_S_C_STA_WPB 14
+#define TIR_S_C_STA_WPW 15
+#define TIR_S_C_STA_WPL 16
+#define TIR_S_C_STA_LSY 17
+#define TIR_S_C_STA_LIT 18
+#define TIR_S_C_STA_LEPM 19
+#define TIR_S_C_MAXSTACOD 19
+#define TIR_S_C_MINSTOCOD 20
+#define TIR_S_C_STO_SB 20
+#define TIR_S_C_STO_SW 21
+#define TIR_S_C_STO_L 22
+#define TIR_S_C_STO_BD 23
+#define TIR_S_C_STO_WD 24
+#define TIR_S_C_STO_LD 25
+#define TIR_S_C_STO_LI 26
+#define TIR_S_C_STO_PIDR 27
+#define TIR_S_C_STO_PICR 28
+#define TIR_S_C_STO_RSB 29
+#define TIR_S_C_STO_RSW 30
+#define TIR_S_C_STO_RL 31
+#define TIR_S_C_STO_VPS 32
+#define TIR_S_C_STO_USB 33
+#define TIR_S_C_STO_USW 34
+#define TIR_S_C_STO_RUB 35
+#define TIR_S_C_STO_RUW 36
+#define TIR_S_C_STO_B 37
+#define TIR_S_C_STO_W 38
+#define TIR_S_C_STO_RB 39
+#define TIR_S_C_STO_RW 40
+#define TIR_S_C_STO_RIVB 41
+#define TIR_S_C_STO_PIRR 42
+#define TIR_S_C_MAXSTOCOD 42
+#define TIR_S_C_MINOPRCOD 50
+#define TIR_S_C_OPR_NOP 50
+#define TIR_S_C_OPR_ADD 51
+#define TIR_S_C_OPR_SUB 52
+#define TIR_S_C_OPR_MUL 53
+#define TIR_S_C_OPR_DIV 54
+#define TIR_S_C_OPR_AND 55
+#define TIR_S_C_OPR_IOR 56
+#define TIR_S_C_OPR_EOR 57
+#define TIR_S_C_OPR_NEG 58
+#define TIR_S_C_OPR_COM 59
+#define TIR_S_C_OPR_INSV 60
+#define TIR_S_C_OPR_ASH 61
+#define TIR_S_C_OPR_USH 62
+#define TIR_S_C_OPR_ROT 63
+#define TIR_S_C_OPR_SEL 64
+#define TIR_S_C_OPR_REDEF 65
+#define TIR_S_C_OPR_DFLIT 66
+#define TIR_S_C_MAXOPRCOD 66
+#define TIR_S_C_MINCTLCOD 80
+#define TIR_S_C_CTL_SETRB 80
+#define TIR_S_C_CTL_AUGRB 81
+#define TIR_S_C_CTL_DFLOC 82
+#define TIR_S_C_CTL_STLOC 83
+#define TIR_S_C_CTL_STKDL 84
+#define TIR_S_C_MAXCTLCOD 84
+
+/*
+ * Debugger symbol definitions: These are done by hand, as no
+ * machine-readable version seems
+ * to be available.
+ */
+#define DST_S_C_C 7 /* Language == "C" */
+#define DST_S_C_VERSION 153
+#define DST_S_C_SOURCE 155 /* Source file */
+#define DST_S_C_PROLOG 162
+#define DST_S_C_BLKBEG 176 /* Beginning of block */
+#define DST_S_C_BLKEND 177 /* End of block */
+#define DST_S_C_ENTRY 181
+#define DST_S_C_PSECT 184
+#define DST_S_C_LINE_NUM 185 /* Line Number */
+#define DST_S_C_LBLORLIT 186
+#define DST_S_C_LABEL 187
+#define DST_S_C_MODBEG 188 /* Beginning of module */
+#define DST_S_C_MODEND 189 /* End of module */
+#define DST_S_C_RTNBEG 190 /* Beginning of routine */
+#define DST_S_C_RTNEND 191 /* End of routine */
+#define DST_S_C_DELTA_PC_W 1 /* Incr PC */
+#define DST_S_C_INCR_LINUM 2 /* Incr Line # */
+#define DST_S_C_INCR_LINUM_W 3 /* Incr Line # */
+#define DST_S_C_SET_LINUM_INCR 4
+#define DST_S_C_SET_LINUM_INCR_W 5
+#define DST_S_C_RESET_LINUM_INCR 6
+#define DST_S_C_BEG_STMT_MODE 7
+#define DST_S_C_END_STMT_MODE 8
+#define DST_S_C_SET_LINE_NUM 9 /* Set Line # */
+#define DST_S_C_SET_PC 10
+#define DST_S_C_SET_PC_W 11
+#define DST_S_C_SET_PC_L 12
+#define DST_S_C_SET_STMTNUM 13
+#define DST_S_C_TERM 14 /* End of lines */
+#define DST_S_C_TERM_W 15 /* End of lines */
+#define DST_S_C_SET_ABS_PC 16 /* Set PC */
+#define DST_S_C_DELTA_PC_L 17 /* Incr PC */
+#define DST_S_C_INCR_LINUM_L 18 /* Incr Line # */
+#define DST_S_C_SET_LINUM_B 19 /* Set Line # */
+#define DST_S_C_SET_LINUM_L 20 /* Set Line # */
+#define DST_S_C_TERM_L 21 /* End of lines */
+/* these are used with DST_S_C_SOURCE */
+#define DST_S_C_SRC_FORMFEED 16 /* ^L counts */
+#define DST_S_C_SRC_DECLFILE 1 /* Declare file */
+#define DST_S_C_SRC_SETFILE 2 /* Set file */
+#define DST_S_C_SRC_SETREC_L 3 /* Set record */
+#define DST_S_C_SRC_DEFLINES_W 10 /* # of line */
+/* the following are the codes for the various data types. Anything not on
+ * the list is included under 'advanced_type'
+ */
+#define DBG_S_C_UCHAR 0x02
+#define DBG_S_C_USINT 0x03
+#define DBG_S_C_ULINT 0x04
+#define DBG_S_C_SCHAR 0x06
+#define DBG_S_C_SSINT 0x07
+#define DBG_S_C_SLINT 0x08
+#define DBG_S_C_REAL4 0x0a
+#define DBG_S_C_REAL8 0x0b
+#define DBG_S_C_FUNCTION_ADDR 0x17
+#define DBG_S_C_ADVANCED_TYPE 0xa3
+/* These are the codes that are used to generate the definitions of struct
+ * union and enum records
+ */
+#define DBG_S_C_ENUM_ITEM 0xa4
+#define DBG_S_C_ENUM_START 0xa5
+#define DBG_S_C_ENUM_END 0xa6
+#define DBG_S_C_STRUCT_START 0xab
+#define DBG_S_C_STRUCT_ITEM 0xff
+#define DBG_S_C_STRUCT_END 0xac
+/* These are the codes that are used in the suffix records to determine the
+ * actual data type
+ */
+#define DBG_S_C_BASIC 0x01
+#define DBG_S_C_BASIC_ARRAY 0x02
+#define DBG_S_C_STRUCT 0x03
+#define DBG_S_C_POINTER 0x04
+#define DBG_S_C_VOID 0x05
+#define DBG_S_C_COMPLEX_ARRAY 0x07
+/* These codes are used in the generation of the symbol definition records
+ */
+#define DBG_S_C_FUNCTION_PARAMETER 0xc9
+#define DBG_S_C_LOCAL_SYM 0xd9
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj-vms.h */
diff --git a/gnu/usr.bin/as/config/tc-a29k.c b/gnu/usr.bin/as/config/tc-a29k.c
new file mode 100644
index 0000000..c32c2b3
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-a29k.c
@@ -0,0 +1,1113 @@
+/* tc-a29k.c -- Assemble for the AMD 29000.
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* John Gilmore has reorganized this module somewhat, to make it easier
+ to convert it to new machines' assemblers as desired. There was too
+ much bloody rewriting required before. There still probably is. */
+
+#include "as.h"
+
+#include "opcode/a29k.h"
+
+/* Make it easier to clone this machine desc into another one. */
+#define machine_opcode a29k_opcode
+#define machine_opcodes a29k_opcodes
+#define machine_ip a29k_ip
+#define machine_it a29k_it
+
+const relax_typeS md_relax_table[] = { 0 };
+
+#define IMMEDIATE_BIT 0x01000000 /* Turns RB into Immediate */
+#define ABSOLUTE_BIT 0x01000000 /* Turns PC-relative to Absolute */
+#define CE_BIT 0x00800000 /* Coprocessor enable in LOAD */
+#define UI_BIT 0x00000080 /* Unsigned integer in CONVERT */
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash = NULL;
+
+struct machine_it {
+ char *error;
+ unsigned long opcode;
+ struct nlist *nlistp;
+ expressionS exp;
+ int pcrel;
+ int reloc_offset; /* Offset of reloc within insn */
+ enum reloc_type reloc;
+} the_insn;
+
+#if __STDC__ == 1
+
+/* static int getExpression(char *str); */
+static void machine_ip(char *str);
+/* static void print_insn(struct machine_it *insn); */
+static void s_data1(void);
+static void s_use(void);
+
+#else /* not __STDC__ */
+
+/* static int getExpression(); */
+static void machine_ip();
+/* static void print_insn(); */
+static void s_data1();
+static void s_use();
+
+#endif /* not __STDC__ */
+
+const pseudo_typeS
+ md_pseudo_table[] = {
+ { "align", s_align_bytes, 4 },
+ { "block", s_space, 0 },
+ { "cputype", s_ignore, 0 }, /* CPU as 29000 or 29050 */
+ { "reg", s_lsym, 0 }, /* Register equate, same as equ */
+ { "space", s_ignore, 0 }, /* Listing control */
+ { "sect", s_ignore, 0 }, /* Creation of coff sections */
+ { "use", s_use, 0 },
+ { "word", cons, 4 },
+ { NULL, 0, 0 },
+ };
+
+int md_short_jump_size = 4;
+int md_long_jump_size = 4;
+#if defined(BFD_HEADERS)
+#ifdef RELSZ
+const int md_reloc_size = RELSZ; /* Coff headers */
+#else
+const int md_reloc_size = 12; /* something else headers */
+#endif
+#else
+const int md_reloc_size = 12; /* Not bfdized*/
+#endif
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+char comment_chars[] = ";";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments like this one will always work */
+char line_comment_chars[] = "#";
+
+/* We needed an unused char for line separation to work around the
+ lack of macros, using sed and such. */
+char line_separator_chars[] = "@";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ */
+
+static unsigned char octal[256];
+#define isoctal(c) octal[c]
+ static unsigned char toHex[256];
+
+/*
+ * anull bit - causes the branch delay slot instructions to not be executed
+ */
+#define ANNUL (1 << 29)
+
+static void
+ s_use()
+{
+
+ if (strncmp(input_line_pointer, ".text", 5) == 0) {
+ input_line_pointer += 5;
+ s_text();
+ return;
+ }
+ if (strncmp(input_line_pointer, ".data", 5) == 0) {
+ input_line_pointer += 5;
+ s_data();
+ return;
+ }
+ if (strncmp(input_line_pointer, ".data1", 6) == 0) {
+ input_line_pointer += 6;
+ s_data1();
+ return;
+ }
+ /* Literals can't go in the text segment because you can't read
+ from instruction memory on some 29k's. So, into initialized data. */
+ if (strncmp(input_line_pointer, ".lit", 4) == 0) {
+ input_line_pointer += 4;
+ subseg_new(SEG_DATA, 200);
+ demand_empty_rest_of_line();
+ return;
+ }
+
+ as_bad("Unknown segment type");
+ demand_empty_rest_of_line();
+ return;
+}
+
+static void
+ s_data1()
+{
+ subseg_new(SEG_DATA, 1);
+ demand_empty_rest_of_line();
+ return;
+}
+
+/* Install symbol definition that maps REGNAME to REGNO.
+ FIXME-SOON: These are not recognized in mixed case. */
+
+static void
+ insert_sreg (regname, regnum)
+char *regname;
+int regnum;
+{
+ /* FIXME-SOON, put something in these syms so they won't be output to the symbol
+ table of the resulting object file. */
+
+ /* Must be large enough to hold the names of the special registers. */
+ char buf[80];
+ int i;
+
+ symbol_table_insert(symbol_new(regname, SEG_REGISTER, regnum, &zero_address_frag));
+ for (i = 0; regname[i]; i++)
+ buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i];
+ buf[i] = '\0';
+
+ symbol_table_insert(symbol_new(buf, SEG_REGISTER, regnum, &zero_address_frag));
+} /* insert_sreg() */
+
+/* Install symbol definitions for assorted special registers.
+ See ASM29K Ref page 2-9. */
+
+void define_some_regs() {
+#define SREG 256
+
+ /* Protected special-purpose register names */
+ insert_sreg ("vab", SREG+0);
+ insert_sreg ("ops", SREG+1);
+ insert_sreg ("cps", SREG+2);
+ insert_sreg ("cfg", SREG+3);
+ insert_sreg ("cha", SREG+4);
+ insert_sreg ("chd", SREG+5);
+ insert_sreg ("chc", SREG+6);
+ insert_sreg ("rbp", SREG+7);
+ insert_sreg ("tmc", SREG+8);
+ insert_sreg ("tmr", SREG+9);
+ insert_sreg ("pc0", SREG+10);
+ insert_sreg ("pc1", SREG+11);
+ insert_sreg ("pc2", SREG+12);
+ insert_sreg ("mmu", SREG+13);
+ insert_sreg ("lru", SREG+14);
+
+ /* Unprotected special-purpose register names */
+ insert_sreg ("ipc", SREG+128);
+ insert_sreg ("ipa", SREG+129);
+ insert_sreg ("ipb", SREG+130);
+ insert_sreg ("q", SREG+131);
+ insert_sreg ("alu", SREG+132);
+ insert_sreg ("bp", SREG+133);
+ insert_sreg ("fc", SREG+134);
+ insert_sreg ("cr", SREG+135);
+ insert_sreg ("fpe", SREG+160);
+ insert_sreg ("inte",SREG+161);
+ insert_sreg ("fps", SREG+162);
+ /* "", SREG+163); Reserved */
+ insert_sreg ("exop",SREG+164);
+} /* define_some_regs() */
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need. */
+void
+ md_begin()
+{
+ register char *retval = NULL;
+ int lose = 0;
+ register int skipnext = 0;
+ register unsigned int i;
+ register char *strend, *strend2;
+
+ /* Hash up all the opcodes for fast use later. */
+
+ op_hash = hash_new();
+ if (op_hash == NULL)
+ as_fatal("Virtual memory exhausted");
+
+ for (i = 0; i < num_opcodes; i++)
+ {
+ const char *name = machine_opcodes[i].name;
+
+ if (skipnext) {
+ skipnext = 0;
+ continue;
+ }
+
+ /* Hack to avoid multiple opcode entries. We pre-locate all the
+ variations (b/i field and P/A field) and handle them. */
+
+ if (!strcmp (name, machine_opcodes[i+1].name)) {
+ if ((machine_opcodes[i].opcode ^ machine_opcodes[i+1].opcode)
+ != 0x01000000)
+ goto bad_table;
+ strend = machine_opcodes[i ].args+strlen(machine_opcodes[i ].args)-1;
+ strend2 = machine_opcodes[i+1].args+strlen(machine_opcodes[i+1].args)-1;
+ switch (*strend) {
+ case 'b':
+ if (*strend2 != 'i') goto bad_table;
+ break;
+ case 'i':
+ if (*strend2 != 'b') goto bad_table;
+ break;
+ case 'P':
+ if (*strend2 != 'A') goto bad_table;
+ break;
+ case 'A':
+ if (*strend2 != 'P') goto bad_table;
+ break;
+ default:
+ bad_table:
+ fprintf (stderr, "internal error: can't handle opcode %s\n", name);
+ lose = 1;
+ }
+
+ /* OK, this is an i/b or A/P pair. We skip the higher-valued one,
+ and let the code for operand checking handle OR-ing in the bit. */
+ if (machine_opcodes[i].opcode & 1)
+ continue;
+ else
+ skipnext = 1;
+ }
+
+ retval = hash_insert (op_hash, name, &machine_opcodes[i]);
+ if (retval != NULL && *retval != '\0')
+ {
+ fprintf (stderr, "internal error: can't hash `%s': %s\n",
+ machine_opcodes[i].name, retval);
+ lose = 1;
+ }
+ }
+
+ if (lose)
+ as_fatal("Broken assembler. No assembly attempted.");
+
+ for (i = '0'; i < '8'; ++i)
+ octal[i] = 1;
+ for (i = '0'; i <= '9'; ++i)
+ toHex[i] = i - '0';
+ for (i = 'a'; i <= 'f'; ++i)
+ toHex[i] = i + 10 - 'a';
+ for (i = 'A'; i <= 'F'; ++i)
+ toHex[i] = i + 10 - 'A';
+
+ define_some_regs ();
+}
+
+void md_end() {
+ return;
+}
+
+/* Assemble a single instruction. Its label has already been handled
+ by the generic front end. We just parse opcode and operands, and
+ produce the bytes of data and relocation. */
+
+void md_assemble(str)
+char *str;
+{
+ char *toP;
+ /* !!!! int rsd; */
+
+ know(str);
+ machine_ip(str);
+ toP = frag_more(4);
+ /* put out the opcode */
+ md_number_to_chars(toP, the_insn.opcode, 4);
+
+ /* put out the symbol-dependent stuff */
+ if (the_insn.reloc != NO_RELOC) {
+ fix_new(
+ frag_now, /* which frag */
+ (toP - frag_now->fr_literal + the_insn.reloc_offset), /* where */
+ 4, /* size */
+ the_insn.exp.X_add_symbol,
+ the_insn.exp.X_subtract_symbol,
+ the_insn.exp.X_add_number,
+ the_insn.pcrel,
+ the_insn.reloc
+ );
+ }
+}
+
+char *
+ parse_operand (s, operandp)
+char *s;
+expressionS *operandp;
+{
+ char *save = input_line_pointer;
+ char *new;
+ segT seg;
+
+ input_line_pointer = s;
+ seg = expr (0, operandp);
+ new = input_line_pointer;
+ input_line_pointer = save;
+
+ switch (seg) {
+ case SEG_ABSOLUTE:
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ case SEG_BIG:
+ case SEG_REGISTER:
+ return new;
+
+ case SEG_ABSENT:
+ as_bad("Missing operand");
+ return new;
+
+ default:
+ as_bad("Don't understand operand of type %s", segment_name (seg));
+ return new;
+ }
+}
+
+/* Instruction parsing. Takes a string containing the opcode.
+ Operands are at input_line_pointer. Output is in the_insn.
+ Warnings or errors are generated. */
+
+static void
+ machine_ip(str)
+char *str;
+{
+ char *s;
+ const char *args;
+ /* !!!! char c; */
+ /* !!!! unsigned long i; */
+ struct machine_opcode *insn;
+ char *argsStart;
+ unsigned long opcode;
+ /* !!!! unsigned int mask; */
+ expressionS the_operand;
+ expressionS *operand = &the_operand;
+ unsigned int reg;
+
+ /* Must handle `div0' opcode. */
+ s = str;
+ if (isalpha(*s))
+ for (; isalnum(*s); ++s)
+ if (isupper (*s))
+ *s = tolower (*s);
+
+ switch (*s) {
+ case '\0':
+ break;
+
+ case ' ': /* FIXME-SOMEDAY more whitespace */
+ *s++ = '\0';
+ break;
+
+ default:
+ as_bad("Unknown opcode: `%s'", str);
+ return;
+ }
+ if ((insn = (struct machine_opcode *) hash_find(op_hash, str)) == NULL) {
+ as_bad("Unknown opcode `%s'.", str);
+ return;
+ }
+ argsStart = s;
+ opcode = insn->opcode;
+ memset(&the_insn, '\0', sizeof(the_insn));
+ the_insn.reloc = NO_RELOC;
+
+ /*
+ * Build the opcode, checking as we go to make
+ * sure that the operands match.
+ *
+ * If an operand matches, we modify the_insn or opcode appropriately,
+ * and do a "continue". If an operand fails to match, we "break".
+ */
+ if (insn->args[0] != '\0')
+ s = parse_operand (s, operand); /* Prime the pump */
+
+ for (args = insn->args; ; ++args) {
+ switch (*args) {
+
+ case '\0': /* end of args */
+ if (*s == '\0') {
+ /* We are truly done. */
+ the_insn.opcode = opcode;
+ return;
+ }
+ as_bad("Too many operands: %s", s);
+ break;
+
+ case ',': /* Must match a comma */
+ if (*s++ == ',') {
+ s = parse_operand (s, operand); /* Parse next opnd */
+ continue;
+ }
+ break;
+
+ case 'v': /* Trap numbers (immediate field) */
+ if (operand->X_seg == SEG_ABSOLUTE) {
+ if (operand->X_add_number < 256) {
+ opcode |= (operand->X_add_number << 16);
+ continue;
+ } else {
+ as_bad("Immediate value of %d is too large",
+ operand->X_add_number);
+ continue;
+ }
+ }
+ the_insn.reloc = RELOC_8;
+ the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */
+ the_insn.exp = *operand;
+ continue;
+
+ case 'b': /* A general register or 8-bit immediate */
+ case 'i':
+ /* We treat the two cases identically since we mashed
+ them together in the opcode table. */
+ if (operand->X_seg == SEG_REGISTER)
+ goto general_reg;
+
+ opcode |= IMMEDIATE_BIT;
+ if (operand->X_seg == SEG_ABSOLUTE) {
+ if (operand->X_add_number < 256) {
+ opcode |= operand->X_add_number;
+ continue;
+ } else {
+ as_bad("Immediate value of %d is too large",
+ operand->X_add_number);
+ continue;
+ }
+ }
+ the_insn.reloc = RELOC_8;
+ the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */
+ the_insn.exp = *operand;
+ continue;
+
+ case 'a': /* next operand must be a register */
+ case 'c':
+ general_reg:
+ /* lrNNN or grNNN or %%expr or a user-def register name */
+ if (operand->X_seg != SEG_REGISTER)
+ break; /* Only registers */
+ know (operand->X_add_symbol == 0);
+ know (operand->X_subtract_symbol == 0);
+ reg = operand->X_add_number;
+ if (reg >= SREG)
+ break; /* No special registers */
+
+ /*
+ * Got the register, now figure out where
+ * it goes in the opcode.
+ */
+ switch (*args) {
+ case 'a':
+ opcode |= reg << 8;
+ continue;
+
+ case 'b':
+ case 'i':
+ opcode |= reg;
+ continue;
+
+ case 'c':
+ opcode |= reg << 16;
+ continue;
+ }
+ as_fatal("failed sanity check.");
+ break;
+
+ case 'x': /* 16 bit constant, zero-extended */
+ case 'X': /* 16 bit constant, one-extended */
+ if (operand->X_seg == SEG_ABSOLUTE) {
+ opcode |= (operand->X_add_number & 0xFF) << 0 |
+ ((operand->X_add_number & 0xFF00) << 8);
+ continue;
+ }
+ the_insn.reloc = RELOC_CONST;
+ the_insn.exp = *operand;
+ continue;
+
+ case 'h':
+ if (operand->X_seg == SEG_ABSOLUTE) {
+ opcode |= (operand->X_add_number & 0x00FF0000) >> 16 |
+ (((unsigned long)operand->X_add_number
+ /* avoid sign ext */ & 0xFF000000) >> 8);
+ continue;
+ }
+ the_insn.reloc = RELOC_CONSTH;
+ the_insn.exp = *operand;
+ continue;
+
+ case 'P': /* PC-relative jump address */
+ case 'A': /* Absolute jump address */
+ /* These two are treated together since we folded the
+ opcode table entries together. */
+ if (operand->X_seg == SEG_ABSOLUTE) {
+ opcode |= ABSOLUTE_BIT |
+ (operand->X_add_number & 0x0003FC00) << 6 |
+ ((operand->X_add_number & 0x000003FC) >> 2);
+ continue;
+ }
+ the_insn.reloc = RELOC_JUMPTARG;
+ the_insn.exp = *operand;
+ the_insn.pcrel = 1; /* Assume PC-relative jump */
+ /* FIXME-SOON, Do we figure out whether abs later, after know sym val? */
+ continue;
+
+ case 'e': /* Coprocessor enable bit for LOAD/STORE insn */
+ if (operand->X_seg == SEG_ABSOLUTE) {
+ if (operand->X_add_number == 0)
+ continue;
+ if (operand->X_add_number == 1) {
+ opcode |= CE_BIT;
+ continue;
+ }
+ }
+ break;
+
+ case 'n': /* Control bits for LOAD/STORE instructions */
+ if (operand->X_seg == SEG_ABSOLUTE &&
+ operand->X_add_number < 128) {
+ opcode |= (operand->X_add_number << 16);
+ continue;
+ }
+ break;
+
+ case 's': /* Special register number */
+ if (operand->X_seg != SEG_REGISTER)
+ break; /* Only registers */
+ if (operand->X_add_number < SREG)
+ break; /* Not a special register */
+ opcode |= (operand->X_add_number & 0xFF) << 8;
+ continue;
+
+ case 'u': /* UI bit of CONVERT */
+ if (operand->X_seg == SEG_ABSOLUTE) {
+ if (operand->X_add_number == 0)
+ continue;
+ if (operand->X_add_number == 1) {
+ opcode |= UI_BIT;
+ continue;
+ }
+ }
+ break;
+
+ case 'r': /* RND bits of CONVERT */
+ if (operand->X_seg == SEG_ABSOLUTE &&
+ operand->X_add_number < 8) {
+ opcode |= operand->X_add_number << 4;
+ continue;
+ }
+ break;
+
+ case 'd': /* FD bits of CONVERT */
+ if (operand->X_seg == SEG_ABSOLUTE &&
+ operand->X_add_number < 4) {
+ opcode |= operand->X_add_number << 2;
+ continue;
+ }
+ break;
+
+
+ case 'f': /* FS bits of CONVERT */
+ if (operand->X_seg == SEG_ABSOLUTE &&
+ operand->X_add_number < 4) {
+ opcode |= operand->X_add_number << 0;
+ continue;
+ }
+ break;
+
+ case 'C':
+ if (operand->X_seg == SEG_ABSOLUTE &&
+ operand->X_add_number < 4) {
+ opcode |= operand->X_add_number << 16;
+ continue;
+ }
+ break;
+
+ case 'F':
+ if (operand->X_seg == SEG_ABSOLUTE &&
+ operand->X_add_number < 16) {
+ opcode |= operand->X_add_number << 18;
+ continue;
+ }
+ break;
+
+ default:
+ BAD_CASE (*args);
+ }
+ /* Types or values of args don't match. */
+ as_bad("Invalid operands");
+ return;
+ }
+}
+
+/*
+ This is identical to the md_atof in m68k.c. I think this is right,
+ but I'm not sure.
+
+ Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+ md_atof(type,litP,sizeP)
+char type;
+char *litP;
+int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type) {
+
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to MD_ATOF()";
+ }
+ t=atof_ieee(input_line_pointer,type,words);
+ if (t)
+ input_line_pointer=t;
+ *sizeP=prec * sizeof(LITTLENUM_TYPE);
+ for (wordP=words;prec--;) {
+ md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
+ litP+=sizeof(LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+/*
+ * Write out big-endian.
+ */
+void
+ md_number_to_chars(buf, val, n)
+char *buf;
+long val;
+int n;
+{
+
+ switch (n) {
+
+ case 4:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ case 2:
+ *buf++ = val >> 8;
+ case 1:
+ *buf = val;
+ break;
+
+ default:
+ as_fatal("failed sanity check.");
+ }
+ return;
+}
+
+void md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+
+
+ know(fixP->fx_size == 4);
+ know(fixP->fx_r_type < NO_RELOC);
+
+ /*
+ * This is a hack. There should be a better way to
+ * handle this.
+ */
+ if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {
+ val += fixP->fx_where + fixP->fx_frag->fr_address;
+ }
+
+ switch (fixP->fx_r_type) {
+
+ case RELOC_32:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_8:
+ buf[0] = val;
+ break;
+
+ case RELOC_WDISP30:
+ val = (val >>= 2) + 1;
+ buf[0] |= (val >> 24) & 0x3f;
+ buf[1]= (val >> 16);
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_HI22:
+ buf[1] |= (val >> 26) & 0x3f;
+ buf[2] = val >> 18;
+ buf[3] = val >> 10;
+ break;
+
+ case RELOC_LO10:
+ buf[2] |= (val >> 8) & 0x03;
+ buf[3] = val;
+ break;
+
+ case RELOC_BASE13:
+ buf[2] |= (val >> 8) & 0x1f;
+ buf[3] = val;
+ break;
+
+ case RELOC_WDISP22:
+ val = (val >>= 2) + 1;
+ /* FALLTHROUGH */
+ case RELOC_BASE22:
+ buf[1] |= (val >> 16) & 0x3f;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+#if 0
+ case RELOC_PC10:
+ case RELOC_PC22:
+ case RELOC_JMP_TBL:
+ case RELOC_SEGOFF16:
+ case RELOC_GLOB_DAT:
+ case RELOC_JMP_SLOT:
+ case RELOC_RELATIVE:
+#endif
+ case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */
+ buf[1] = val >> 10; /* Holds bits 0003FFFC of address */
+ buf[3] = val >> 2;
+ break;
+
+ case RELOC_CONST: /* 00XX00XX pattern in a word */
+ buf[1] = val >> 8; /* Holds bits 0000XXXX */
+ buf[3] = val;
+ break;
+
+ case RELOC_CONSTH: /* 00XX00XX pattern in a word */
+ buf[1] = val >> 24; /* Holds bits XXXX0000 */
+ buf[3] = val >> 16;
+ break;
+
+ case NO_RELOC:
+ default:
+ as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
+ break;
+ }
+ return;
+}
+
+#ifdef OBJ_COFF
+short tc_coff_fix2rtype(fixP)
+fixS *fixP;
+{
+
+ /* FIXME-NOW: relocation type handling is not yet written for
+ a29k. */
+
+
+ switch (fixP->fx_r_type) {
+ case RELOC_32: return(R_WORD);
+ case RELOC_8: return(R_BYTE);
+ case RELOC_CONST: return (R_ILOHALF);
+ case RELOC_CONSTH: return (R_IHIHALF);
+ case RELOC_JUMPTARG: return (R_IREL);
+ default: printf("need %o3\n", fixP->fx_r_type);
+ abort(0);
+ } /* switch on type */
+
+ return(0);
+} /* tc_coff_fix2rtype() */
+#endif /* OBJ_COFF */
+
+/* should never be called for sparc */
+void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("a29k_create_short_jmp\n");
+}
+
+/* should never be called for 29k */
+void md_convert_frag(headers, fragP)
+object_headers *headers;
+register fragS *fragP;
+{
+ as_fatal("sparc_convert_frag\n");
+}
+
+/* should never be called for 29k */
+void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr;
+long to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("sparc_create_long_jump\n");
+}
+
+/* should never be called for a29k */
+int md_estimate_size_before_relax(fragP, segtype)
+register fragS *fragP;
+segT segtype;
+{
+ as_fatal("sparc_estimate_size_before_relax\n");
+ return(0);
+}
+
+#if 0
+/* for debugging only */
+static void
+ print_insn(insn)
+struct machine_it *insn;
+{
+ char *Reloc[] = {
+ "RELOC_8",
+ "RELOC_16",
+ "RELOC_32",
+ "RELOC_DISP8",
+ "RELOC_DISP16",
+ "RELOC_DISP32",
+ "RELOC_WDISP30",
+ "RELOC_WDISP22",
+ "RELOC_HI22",
+ "RELOC_22",
+ "RELOC_13",
+ "RELOC_LO10",
+ "RELOC_SFA_BASE",
+ "RELOC_SFA_OFF13",
+ "RELOC_BASE10",
+ "RELOC_BASE13",
+ "RELOC_BASE22",
+ "RELOC_PC10",
+ "RELOC_PC22",
+ "RELOC_JMP_TBL",
+ "RELOC_SEGOFF16",
+ "RELOC_GLOB_DAT",
+ "RELOC_JMP_SLOT",
+ "RELOC_RELATIVE",
+ "NO_RELOC"
+ };
+
+ if (insn->error) {
+ fprintf(stderr, "ERROR: %s\n");
+ }
+ fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
+ fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
+ fprintf(stderr, "exp = {\n");
+ fprintf(stderr, "\t\tX_add_symbol = %s\n",
+ insn->exp.X_add_symbol ?
+ (S_GET_NAME(insn->exp.X_add_symbol) ?
+ S_GET_NAME(insn->exp.X_add_symbol) : "???") : "0");
+ fprintf(stderr, "\t\tX_sub_symbol = %s\n",
+ insn->exp.X_subtract_symbol ?
+ (S_GET_NAME(insn->exp.X_subtract_symbol) ?
+ S_GET_NAME(insn->exp.X_subtract_symbol) : "???") : "0");
+ fprintf(stderr, "\t\tX_add_number = %d\n",
+ insn->exp.X_add_number);
+ fprintf(stderr, "}\n");
+ return;
+}
+#endif
+
+/* Translate internal representation of relocation info to target format.
+
+ On sparc/29k: first 4 bytes are normal unsigned long address, next three
+ bytes are index, most sig. byte first. Byte 7 is broken up with
+ bit 7 as external, bits 6 & 5 unused, and the lower
+ five bits as relocation type. Next 4 bytes are long addend. */
+/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
+
+#ifdef OBJ_AOUT
+
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ long r_symbolnum;
+
+ know(fixP->fx_r_type < NO_RELOC);
+ know(fixP->fx_addsy != NULL);
+
+ md_number_to_chars(where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy)
+ ? S_GET_TYPE(fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[4] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[6] = r_symbolnum & 0x0ff;
+ where[7] = (((!S_IS_DEFINED(fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
+ /* Also easy */
+ md_number_to_chars(&where[8], fixP->fx_addnumber, 4);
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+#endif /* OBJ_AOUT */
+
+int
+ md_parse_option(argP,cntP,vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ return(0);
+}
+
+
+/* Default the values of symbols known that should be "predefined". We
+ don't bother to predefine them unless you actually use one, since there
+ are a lot of them. */
+
+symbolS *md_undefined_symbol (name)
+char *name;
+{
+ long regnum;
+ char testbuf[5+ /*SLOP*/ 5];
+
+ if (name[0] == 'g' || name[0] == 'G' || name[0] == 'l' || name[0] == 'L')
+ {
+ /* Perhaps a global or local register name */
+ if (name[1] == 'r' || name[1] == 'R')
+ {
+ /* Parse the number, make sure it has no extra zeroes or trailing
+ chars */
+ regnum = atol(&name[2]);
+ if (regnum > 127)
+ return 0;
+ sprintf(testbuf, "%ld", regnum);
+ if (strcmp (testbuf, &name[2]) != 0)
+ return 0; /* gr007 or lr7foo or whatever */
+
+ /* We have a wiener! Define and return a new symbol for it. */
+ if (name[0] == 'l' || name[0] == 'L')
+ regnum += 128;
+ return(symbol_new(name, SEG_REGISTER, regnum, &zero_address_frag));
+ }
+ }
+
+ return 0;
+}
+
+/* Parse an operand that is machine-specific. */
+
+void md_operand(expressionP)
+expressionS *expressionP;
+{
+
+ if (input_line_pointer[0] == '%' && input_line_pointer[1] == '%')
+ {
+ /* We have a numeric register expression. No biggy. */
+ input_line_pointer += 2; /* Skip %% */
+ (void)expression (expressionP);
+ if (expressionP->X_seg != SEG_ABSOLUTE
+ || expressionP->X_add_number > 255)
+ as_bad("Invalid expression after %%%%\n");
+ expressionP->X_seg = SEG_REGISTER;
+ }
+ else if (input_line_pointer[0] == '&')
+ {
+ /* We are taking the 'address' of a register...this one is not
+ in the manual, but it *is* in traps/fpsymbol.h! What they
+ seem to want is the register number, as an absolute number. */
+ input_line_pointer++; /* Skip & */
+ (void)expression (expressionP);
+ if (expressionP->X_seg != SEG_REGISTER)
+ as_bad("Invalid register in & expression");
+ else
+ expressionP->X_seg = SEG_ABSOLUTE;
+ }
+}
+
+/* Round up a section size to the appropriate boundary. */
+long
+ md_section_align (segment, size)
+segT segment;
+long size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the 29000, they're relative to the address of the instruction,
+ which we have set up as the address of the fixup too. */
+long md_pcrel_from (fixP)
+fixS *fixP;
+{
+ return fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * End:
+ */
+
+/* end of tc-a29k.c */
diff --git a/gnu/usr.bin/as/config/tc-a29k.h b/gnu/usr.bin/as/config/tc-a29k.h
new file mode 100644
index 0000000..a362595
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-a29k.h
@@ -0,0 +1,40 @@
+/* tc-a29k.h -- Assemble for the AMD 29000.
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TC_A29K
+
+#define NO_LISTING
+
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+#define tc_coff_symbol_emit_hook(a) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+
+#define AOUT_MACHTYPE 101
+#define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype(fix_ptr)
+#define BFD_ARCH bfd_arch_a29k
+#define COFF_MAGIC SIPFBOMAGIC
+
+/* Should the reloc be output ?
+ on the 29k, this is true only if there is a symbol attatched.
+ on the h8, this is allways true, since no fixup is done
+ */
+#define TC_COUNT_RELOC(x) (x->fx_addsy)
+
+/* end of tc-a29k.h */
diff --git a/gnu/usr.bin/as/config/tc-generic.c b/gnu/usr.bin/as/config/tc-generic.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-generic.c
diff --git a/gnu/usr.bin/as/config/tc-generic.h b/gnu/usr.bin/as/config/tc-generic.h
new file mode 100644
index 0000000..7a16dd0
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-generic.h
@@ -0,0 +1,37 @@
+/* This file is tc-generic.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file is tc-generic.h and is intended to be a template for target cpu
+ * specific header files. It is my intent that this file compile. It is also
+ * my intent that this file grow into something that can be used as both a
+ * template for porting, and a stub for testing. xoxorich.
+ */
+
+#define TC_GENERIC 1
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-generic.h */
diff --git a/gnu/usr.bin/as/config/tc-h8300.c b/gnu/usr.bin/as/config/tc-h8300.c
new file mode 100644
index 0000000..4657d1e
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-h8300.c
@@ -0,0 +1,1295 @@
+/* tc-h8300.c -- Assemble code for the Hitachi H8/300
+ Copyright (C) 1991, 1992 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+ Written By Steve Chamberlain
+ sac@cygnus.com
+ */
+
+#include <stdio.h>
+#include "as.h"
+#include "bfd.h"
+#include "opcode/h8300.h"
+#include <ctype.h>
+#include "listing.h"
+
+char comment_chars[] = { ';',0 };
+char line_separator_chars[] = { '$' ,0};
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+
+void cons();
+
+const pseudo_typeS md_pseudo_table[] = {
+ { "int", cons, 2 },
+ { 0,0,0 }
+};
+
+const int md_reloc_size ;
+
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+
+const relax_typeS md_relax_table[1];
+
+
+static struct hash_control *opcode_hash_control; /* Opcode mnemonics */
+
+
+/*
+ This function is called once, at assembler startup time. This should
+ set up all the tables, etc that the MD part of the assembler needs
+ */
+#if 0
+/* encode the size and number into the number field
+ xxnnnn
+ 00 8 bit
+ 01 16 bit
+ 10 ccr
+ nnnnreg number
+ */
+#define WORD_REG 0x10
+#define BYTE_REG 0x00
+#define CCR_REG 0x20
+struct reg_entry
+{
+ char *name;
+ char number;
+};
+
+struct reg_entry reg_list[] = {
+ "r0",WORD_REG +0,
+ "r1",WORD_REG +1,
+ "r2",WORD_REG +2,
+ "r3",WORD_REG +3,
+ "r4",WORD_REG +4,
+ "r5",WORD_REG +5,
+ "r6",WORD_REG +6,
+ "r7",WORD_REG +7,
+ "fp",WORD_REG +6,
+ "sp",WORD_REG +7,
+ "r0h",BYTE_REG + 0,
+ "r0l",BYTE_REG + 1,
+ "r1h",BYTE_REG + 2,
+ "r1l",BYTE_REG + 3,
+ "r2h",BYTE_REG + 4,
+ "r2l",BYTE_REG + 5,
+ "r3h",BYTE_REG + 6,
+ "r3l",BYTE_REG + 7,
+ "r4h",BYTE_REG + 8,
+ "r4l",BYTE_REG + 9,
+ "r5h",BYTE_REG + 10,
+ "r5l",BYTE_REG + 11,
+ "r6h",BYTE_REG + 12,
+ "r6l",BYTE_REG + 13,
+ "r7h",BYTE_REG + 14,
+ "r7l",BYTE_REG + 15,
+ "ccr",CCR_REG,
+ 0,0
+ }
+;
+
+
+#endif
+
+
+void md_begin ()
+{
+ struct h8_opcode *opcode;
+ const struct reg_entry *reg;
+ char prev_buffer[100];
+ int idx = 0;
+
+ opcode_hash_control = hash_new();
+ prev_buffer[0] = 0;
+
+ for (opcode = h8_opcodes; opcode->name; opcode++)
+ {
+ /* Strip off any . part when inserting the opcode and only enter
+ unique codes into the hash table
+ */
+ char *src= opcode->name;
+ unsigned int len = strlen(src);
+ char *dst = malloc(len+1);
+ char *buffer = dst;
+ opcode->size = 0;
+ while (*src) {
+ if (*src == '.') {
+ *dst++ = 0;
+ src++;
+ opcode->size = *src;
+ break;
+ }
+ *dst++ = *src++;
+ }
+ if (strcmp(buffer, prev_buffer))
+ {
+ hash_insert(opcode_hash_control, buffer, (char *)opcode);
+ strcpy(prev_buffer, buffer);
+ idx++;
+ }
+ opcode->idx = idx;
+
+
+ /* Find the number of operands */
+ opcode->noperands = 0;
+ while (opcode->args.nib[opcode->noperands] != E)
+ opcode->noperands ++;
+ /* Find the length of the opcode in bytes */
+ opcode->length =0;
+ while (opcode->data.nib[opcode->length*2] != E)
+ opcode->length++;
+ }
+
+}
+
+
+struct h8_exp {
+ char *e_beg;
+ char *e_end;
+ expressionS e_exp;
+};
+struct h8_op
+{
+ unsigned int dispreg;
+ op_type mode;
+ unsigned reg;
+ expressionS exp;
+};
+
+
+
+/*
+ parse operands
+ WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
+ r0l,r0h,..r7l,r7h
+ @WREG
+ @WREG+
+ @-WREG
+ #const
+
+ */
+
+op_type r8_sord[] = {RS8, RD8};
+op_type r16_sord[] = {RS16, RD16};
+op_type rind_sord[] = {RSIND, RDIND};
+op_type abs_sord[2] = {ABS16SRC, ABS16DST};
+op_type disp_sord[] = {DISPSRC, DISPDST};
+
+/* try and parse a reg name, returns number of chars consumed */
+int
+ DEFUN(parse_reg,(src, mode, reg, dst),
+ char *src AND
+ op_type *mode AND
+ unsigned int *reg AND
+ int dst)
+{
+ if (src[0] == 's' && src[1] == 'p')
+ {
+ *mode = r16_sord[dst];
+ *reg = 7;
+ return 2;
+ }
+ if (src[0] == 'c' && src[1] == 'c' && src[2] == 'r')
+ {
+ *mode = CCR;
+ *reg = 0;
+ return 3;
+ }
+ if (src[0] == 'f' && src[1] == 'p')
+ {
+ *mode = r16_sord[dst];
+ *reg = 6;
+ return 2;
+ }
+ if (src[0] == 'r')
+ {
+ if (src[1] >= '0' && src[1] <= '7')
+ {
+ if (src[2] == 'l')
+ {
+ *mode = r8_sord[dst];
+ *reg = (src[1] - '0') + 8;
+ return 3;
+ }
+ if (src[2] == 'h')
+ {
+ *mode = r8_sord[dst];
+ *reg = (src[1] - '0') ;
+ return 3;
+ }
+ *mode = r16_sord[dst];
+ *reg = (src[1] - '0');
+ return 2;
+ }
+ }
+ return 0;
+}
+
+char *
+ DEFUN(parse_exp,(s, op),
+ char *s AND
+ expressionS *op)
+{
+ char *save = input_line_pointer;
+ char *new;
+ segT seg;
+ input_line_pointer = s;
+ seg = expr(0,op);
+ new = input_line_pointer;
+ input_line_pointer = save;
+ if (SEG_NORMAL(seg))
+ return new;
+ switch (seg) {
+ case SEG_ABSOLUTE:
+ case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ case SEG_BIG:
+ case SEG_REGISTER:
+ return new;
+ case SEG_ABSENT:
+ as_bad("Missing operand");
+ return new;
+ default:
+ as_bad("Don't understand operand of type %s", segment_name (seg));
+ return new;
+ }
+}
+
+static char *
+ DEFUN(skip_colonthing,(ptr),
+ char *ptr)
+{
+ if (*ptr == ':') {
+ ptr++;
+ while (isdigit(*ptr))
+ ptr++;
+
+ }
+ return ptr;
+}
+
+/* The many forms of operand:
+
+ Rn Register direct
+ @Rn Register indirect
+ @(exp[:16], Rn) Register indirect with displacement
+ @Rn+
+ @-Rn
+ @aa:8 absolute 8 bit
+ @aa:16 absolute 16 bit
+ @aa absolute 16 bit
+
+ #xx[:size] immediate data
+ @(exp:[8], pc) pc rel
+ @@aa[:8] memory indirect
+
+ */
+
+static void
+ DEFUN(get_operand,(ptr, op, dst),
+ char **ptr AND
+ struct h8_op *op AND
+ unsigned int dst)
+{
+ char *src = *ptr;
+ op_type mode;
+ unsigned int num;
+ unsigned int len;
+ unsigned int size;
+ op->mode = E;
+
+ len = parse_reg(src, &op->mode, &op->reg, dst);
+ if (len) {
+ *ptr = src + len;
+ return ;
+ }
+
+ if (*src == '@')
+ {
+ src++;
+ if (*src == '@')
+ {
+ src++;
+ src = parse_exp(src,&op->exp);
+ src = skip_colonthing(src);
+
+ *ptr = src;
+
+ op->mode = MEMIND;
+ return;
+
+ }
+
+
+ if (*src == '-')
+ {
+ src++;
+ len = parse_reg(src, &mode, &num, dst);
+ if (len == 0)
+ {
+ /* Oops, not a reg after all, must be ordinary exp */
+ src--;
+ /* must be a symbol */
+ op->mode = abs_sord[dst];
+ *ptr = skip_colonthing(parse_exp(src, &op->exp));
+
+ return;
+
+
+ }
+
+ if (mode != r16_sord[dst])
+ {
+ as_bad("@- needs word register");
+ }
+ op->mode = RDDEC;
+ op->reg = num;
+ *ptr = src + len;
+ return;
+ }
+ if (*src == '(' && ')')
+ {
+ /* Disp */
+ src++;
+ src = parse_exp(src, &op->exp);
+
+ if (*src == ')')
+ {
+ src++;
+ op->mode = abs_sord[dst];
+ *ptr = src;
+ return;
+ }
+ src = skip_colonthing(src);
+
+ if (*src != ',')
+ {
+ as_bad("expected @(exp, reg16)");
+ }
+ src++;
+ len = parse_reg(src, &mode, &op->reg, dst);
+ if (len == 0 || mode != r16_sord[dst])
+ {
+ as_bad("expected @(exp, reg16)");
+ }
+ op->mode = disp_sord[dst];
+ src += len;
+ src = skip_colonthing(src);
+
+ if (*src != ')' && '(')
+ {
+ as_bad("expected @(exp, reg16)");
+
+ }
+ *ptr = src +1;
+
+ return;
+ }
+ len = parse_reg(src, &mode, &num, dst);
+
+ if (len) {
+ src += len;
+ if (*src == '+')
+ {
+ src++;
+ if (mode != RS16)
+ {
+ as_bad("@Rn+ needs src word register");
+ }
+ op->mode = RSINC;
+ op->reg = num;
+ *ptr = src;
+ return;
+ }
+ if (mode != r16_sord[dst])
+ {
+ as_bad("@Rn needs word register");
+ }
+ op->mode =rind_sord[dst];
+ op->reg = num;
+ *ptr = src;
+ return;
+ }
+ else
+ {
+ /* must be a symbol */
+ op->mode = abs_sord[dst];
+ *ptr = skip_colonthing(parse_exp(src, &op->exp));
+
+ return;
+ }
+ }
+
+
+ if (*src == '#') {
+ src++;
+ op->mode = IMM16;
+ src = parse_exp(src, &op->exp);
+ *ptr= skip_colonthing(src);
+
+ return;
+ }
+ else {
+ *ptr = parse_exp(src, &op->exp);
+ op->mode = DISP8;
+ }
+}
+
+
+static
+ char *
+ DEFUN(get_operands,(noperands,op_end, operand),
+ unsigned int noperands AND
+ char *op_end AND
+ struct h8_op *operand)
+{
+ char *ptr = op_end;
+ switch (noperands)
+ {
+ case 0:
+ operand[0].mode = 0;
+ operand[1].mode = 0;
+ break;
+
+ case 1:
+ ptr++;
+ get_operand(& ptr, operand +0,0);
+ operand[1].mode =0;
+ break;
+
+ case 2:
+ ptr++;
+ get_operand(& ptr, operand +0,0);
+ if (*ptr == ',') ptr++;
+ get_operand(& ptr, operand +1, 1);
+ break;
+
+ default:
+ abort();
+ }
+
+
+ return ptr;
+}
+
+/* Passed a pointer to a list of opcodes which use different
+ addressing modes, return the opcode which matches the opcodes
+ provided
+ */
+static
+ struct h8_opcode *
+ DEFUN(get_specific,(opcode, operands),
+ struct h8_opcode *opcode AND
+ struct h8_op *operands)
+
+{
+ struct h8_opcode *this_try = opcode ;
+ int found = 0;
+ unsigned int noperands = opcode->noperands;
+
+ unsigned int dispreg;
+ unsigned int this_index = opcode->idx;
+ while (this_index == opcode->idx && !found)
+ {
+ unsigned int i;
+
+ this_try = opcode ++;
+ for (i = 0; i < noperands; i++)
+ {
+ op_type op = (this_try->args.nib[i]) & ~(B30|B31);
+ switch (op)
+ {
+ case Hex0:
+ case Hex1:
+ case Hex2:
+ case Hex3:
+ case Hex4:
+ case Hex5:
+ case Hex6:
+ case Hex7:
+ case Hex8:
+ case Hex9:
+ case HexA:
+ case HexB:
+ case HexC:
+ case HexD:
+ case HexE:
+ case HexF:
+ break;
+ case DISPSRC:
+ case DISPDST:
+ operands[0].dispreg = operands[i].reg;
+ case RD8:
+ case RS8:
+ case RDIND:
+ case RSIND:
+ case RD16:
+ case RS16:
+ case CCR:
+ case RSINC:
+ case RDDEC:
+ if (operands[i].mode != op) goto fail;
+ break;
+ case KBIT:
+ case IMM16:
+ case IMM3:
+ case IMM8:
+ if (operands[i].mode != IMM16) goto fail;
+ break;
+ case MEMIND:
+ if (operands[i].mode != MEMIND) goto fail;
+ break;
+ case ABS16SRC:
+ case ABS8SRC:
+ case ABS16OR8SRC:
+ case ABS16ORREL8SRC:
+
+ if (operands[i].mode != ABS16SRC) goto fail;
+ break;
+ case ABS16OR8DST:
+ case ABS16DST:
+ case ABS8DST:
+ if (operands[i].mode != ABS16DST) goto fail;
+ break;
+ }
+ }
+ found =1;
+ fail: ;
+ }
+ if (found)
+ return this_try;
+ else
+ return 0;
+}
+
+static void
+ DEFUN(check_operand,(operand, width, string),
+ struct h8_op *operand AND
+ unsigned int width AND
+ char *string)
+{
+ if (operand->exp.X_add_symbol == 0
+ && operand->exp.X_subtract_symbol == 0)
+ {
+
+ /* No symbol involved, let's look at offset, it's dangerous if any of
+ the high bits are not 0 or ff's, find out by oring or anding with
+ the width and seeing if the answer is 0 or all fs*/
+ if ((operand->exp.X_add_number | width) != ~0 &&
+ (operand->exp.X_add_number & ~width) != 0)
+ {
+ as_warn("operand %s0x%x out of range.", string, operand->exp.X_add_number);
+ }
+ }
+
+}
+
+/* Now we know what sort of opcodes it is, lets build the bytes -
+ */
+static void
+ DEFUN (build_bytes,(this_try, operand),
+ struct h8_opcode *this_try AND
+ struct h8_op *operand)
+
+{
+ unsigned int i;
+
+ char *output = frag_more(this_try->length);
+ char *output_ptr = output;
+ op_type *nibble_ptr = this_try->data.nib;
+ char part;
+ op_type c;
+ char high;
+ int nib;
+ top: ;
+ while (*nibble_ptr != E)
+ {
+ int nibble;
+ for (nibble = 0; nibble <2; nibble++)
+ {
+ c = *nibble_ptr & ~(B30|B31);
+ switch (c)
+ {
+ default:
+ abort();
+ case KBIT:
+ switch (operand[0].exp.X_add_number)
+ {
+ case 1:
+ nib = 0;
+ break;
+ case 2:
+ nib = 8;
+ break;
+ default:
+ as_bad("Need #1 or #2 here");
+ break;
+ }
+ /* stop it making a fix */
+ operand[0].mode = 0;
+ break;
+ 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:
+ nib = c;
+ break;
+ case DISPREG:
+ nib = operand[0].dispreg;
+ break;
+ case IMM8:
+ operand[0].mode = IMM8;
+ nib = 0;
+ break;
+
+ case DISPDST:
+ nib = 0;
+ break;
+ case IMM3:
+ if (operand[0].exp.X_add_symbol == 0) {
+ operand[0].mode = 0; /* stop it making a fix */
+ nib = (operand[0].exp.X_add_number);
+ }
+ else as_bad("can't have symbol for bit number");
+ if (nib < 0 || nib > 7)
+ {
+ as_bad("Bit number out of range %d", nib);
+ }
+
+ break;
+
+ case ABS16DST:
+ nib = 0;
+ break;
+ case ABS8DST:
+ operand[1].mode = ABS8DST;
+ nib = 0;
+ break;
+ case ABS8SRC:
+ operand[0].mode = ABS8SRC;
+ nib = 0;
+ break;
+ case ABS16OR8DST:
+ operand[1].mode = c;
+
+ nib = 0;
+
+ break;
+
+ case ABS16ORREL8SRC:
+ operand[0].mode = c;
+ nib=0;
+ break;
+
+ case ABS16OR8SRC:
+ operand[0].mode = ABS16OR8SRC;
+ nib = 0;
+ break;
+ case DISPSRC:
+ operand[0].mode = ABS16SRC;
+ nib = 0;
+ break;
+
+ case DISP8:
+ operand[0].mode = DISP8;
+ nib = 0;
+ break;
+
+ case ABS16SRC:
+ case IMM16:
+ case IGNORE:
+ case MEMIND:
+
+ nib=0;
+ break;
+ case RS8:
+ case RS16:
+ case RSIND:
+ case RSINC:
+ nib = operand[0].reg;
+ break;
+
+ case RD8:
+ case RD16:
+ case RDDEC:
+ case RDIND:
+ nib = operand[1].reg;
+ break;
+
+ case E:
+ abort();
+ break;
+ }
+ if (*nibble_ptr & B31) {
+ nib |=0x8;
+ }
+
+ if (nibble == 0) {
+ *output_ptr = nib << 4;
+ }
+ else {
+ *output_ptr |= nib;
+ output_ptr++;
+ }
+ nibble_ptr++;
+ }
+
+ }
+
+ /* output any fixes */
+ for (i = 0; i < 2; i++)
+ {
+ switch (operand[i].mode) {
+ case 0:
+ break;
+
+ case DISP8:
+ check_operand(operand+i, 0x7f,"@");
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number -1,
+ 1,
+ R_PCRBYTE);
+ break;
+ case IMM8:
+ check_operand(operand+i, 0xff,"#");
+ /* If there is nothing else going on we can safely
+ reloc in place */
+ if (operand[i].exp.X_add_symbol == 0)
+ {
+ output[1] = operand[i].exp.X_add_number;
+ }
+ else
+ {
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELBYTE);
+ }
+
+ break;
+ case MEMIND:
+ check_operand(operand+i, 0xff,"@@");
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELBYTE);
+ break;
+ case ABS8DST:
+ case ABS8SRC:
+ check_operand(operand+i, 0xff,"@");
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 1,
+ 1,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELBYTE);
+ break;
+
+ case ABS16OR8SRC:
+ case ABS16OR8DST:
+ check_operand(operand+i, 0xffff,"@");
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 2,
+ 2,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_MOVB1);
+ break;
+
+ case ABS16ORREL8SRC:
+ check_operand(operand+i, 0xffff,"@");
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 2,
+ 2,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_JMP1);
+ break;
+
+
+ case ABS16SRC:
+ case ABS16DST:
+ case IMM16:
+ case DISPSRC:
+ case DISPDST:
+ check_operand(operand+i, 0xffff,"@");
+ if (operand[i].exp.X_add_symbol == 0)
+ {
+ /* This should be done with bfd */
+ output[3] = operand[i].exp.X_add_number & 0xff;
+ output[2] = operand[i].exp.X_add_number >> 8;
+
+ }
+ else
+ {
+
+ fix_new(frag_now,
+ output - frag_now->fr_literal + 2,
+ 2,
+ operand[i].exp.X_add_symbol,
+ operand[i].exp.X_subtract_symbol,
+ operand[i].exp.X_add_number,
+ 0,
+ R_RELWORD);
+ }
+
+ break;
+ case RS8:
+ case RD8:
+ case RS16:
+ case RD16:
+ case RDDEC:
+ case KBIT:
+ case RSINC:
+ case RDIND:
+ case RSIND:
+ case CCR:
+
+ break;
+ default:
+ abort();
+ }
+ }
+
+}
+/*
+ try and give an intelligent error message for common and simple to
+ detect errors
+ */
+
+static void
+ DEFUN(clever_message, (opcode, operand),
+ struct h8_opcode *opcode AND
+ struct h8_op *operand)
+{
+ struct h8_opcode *scan = opcode;
+
+ /* Find out if there was more than one possible opccode */
+
+ if ((opcode+1)->idx != opcode->idx)
+ {
+ unsigned int argn;
+
+ /* Only one opcode of this flavour, try and guess which operand
+ didn't match */
+ for (argn = 0; argn < opcode->noperands; argn++)
+ {
+ switch (opcode->args.nib[argn])
+ {
+ case RD16:
+ if (operand[argn].mode != RD16)
+ {
+ as_bad("destination operand must be 16 bit register");
+ }
+ return;
+ case RS8:
+
+ if (operand[argn].mode != RS8)
+ {
+ as_bad("source operand must be 8 bit register");
+ }
+ return;
+ case ABS16DST:
+ if (operand[argn].mode != ABS16DST)
+ {
+ as_bad("destination operand must be 16bit absolute address");
+ return;
+ }
+
+ case RD8:
+ if (operand[argn].mode != RD8)
+ {
+ as_bad("destination operand must be 8 bit register");
+ }
+ return;
+
+ case ABS16SRC:
+ if (operand[argn].mode != ABS16SRC)
+ {
+ as_bad("source operand must be 16bit absolute address");
+ return;
+ }
+ }
+ }
+ }
+ as_bad("invalid operands");
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This funciton is supposed to emit
+ the frags/bytes it assembles to.
+ */
+
+
+
+void
+ DEFUN(md_assemble,(str),
+ char *str)
+{
+ char *op_start;
+ char *op_end;
+ unsigned int i;
+ struct h8_op operand[2];
+ struct h8_opcode * opcode;
+ struct h8_opcode * prev_opcode;
+
+ char *dot = 0;
+ char c;
+ /* Drop leading whitespace */
+ while (*str == ' ')
+ str++;
+
+ /* find the op code end */
+ for (op_start = op_end = str;
+ *op_end != 0 && *op_end != ' ';
+ op_end ++)
+ {
+ if (*op_end == '.') {
+ dot = op_end+1;
+ *op_end = 0;
+ op_end+=2;
+ break;
+ }
+ }
+
+ ;
+
+ if (op_end == op_start)
+ {
+ as_bad("can't find opcode ");
+ }
+ c = *op_end;
+
+ *op_end = 0;
+
+ opcode = (struct h8_opcode *) hash_find(opcode_hash_control,
+ op_start);
+
+ if (opcode == NULL)
+ {
+ as_bad("unknown opcode");
+ return;
+ }
+
+
+ input_line_pointer = get_operands(opcode->noperands, op_end,
+ operand);
+ *op_end = c;
+ prev_opcode = opcode;
+
+ opcode = get_specific(opcode, operand);
+
+ if (opcode == 0)
+ {
+ /* Couldn't find an opcode which matched the operands */
+ char *where =frag_more(2);
+ where[0] = 0x0;
+ where[1] = 0x0;
+ clever_message(prev_opcode, operand);
+
+ return;
+ }
+ if (opcode->size && dot)
+ {
+ if (opcode->size != *dot)
+ {
+ as_warn("mismatch between opcode size and operand size");
+ }
+ }
+
+ build_bytes(opcode, operand);
+
+}
+
+void
+ DEFUN(tc_crawl_symbol_chain, (headers),
+ object_headers *headers)
+{
+ printf("call to tc_crawl_symbol_chain \n");
+}
+
+symbolS *DEFUN(md_undefined_symbol,(name),
+ char *name)
+{
+ return 0;
+}
+
+void
+ DEFUN(tc_headers_hook,(headers),
+ object_headers *headers)
+{
+ printf("call to tc_headers_hook \n");
+}
+void
+ DEFUN_VOID(md_end)
+{
+}
+
+/* Various routines to kill one day */
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+char *
+ md_atof(type,litP,sizeP)
+char type;
+char *litP;
+int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee();
+
+ switch (type) {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to MD_ATOF()";
+ }
+ t=atof_ieee(input_line_pointer,type,words);
+ if (t)
+ input_line_pointer=t;
+
+ *sizeP=prec * sizeof(LITTLENUM_TYPE);
+ for (wordP=words;prec--;) {
+ md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
+ litP+=sizeof(LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+int
+ md_parse_option(argP, cntP, vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+
+{
+ return 0;
+
+}
+
+int md_short_jump_size;
+
+void tc_aout_fix_to_chars () { printf("call to tc_aout_fix_to_chars \n");
+ abort(); }
+void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr;
+long to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("failed sanity check.");
+}
+
+void
+ md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("failed sanity check.");
+}
+
+void
+ md_convert_frag(headers, fragP)
+object_headers *headers;
+fragS * fragP;
+
+{ printf("call to md_convert_frag \n"); abort(); }
+
+long
+ DEFUN(md_section_align,(seg, size),
+ segT seg AND
+ long size)
+{
+ return((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));
+
+}
+
+void
+ md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ switch (fixP->fx_size) {
+ case 1:
+ *buf++=val;
+ break;
+ case 2:
+ *buf++=(val>>8);
+ *buf++=val;
+ break;
+ case 4:
+ *buf++=(val>>24);
+ *buf++=(val>>16);
+ *buf++=(val>>8);
+ *buf++=val;
+ break;
+ default:
+ abort();
+
+ }
+}
+
+void DEFUN(md_operand, (expressionP),expressionS *expressionP)
+{ }
+
+int md_long_jump_size;
+int
+ md_estimate_size_before_relax(fragP, segment_type)
+register fragS *fragP;
+register segT segment_type;
+{
+ printf("call tomd_estimate_size_before_relax \n"); abort(); }
+/* Put number into target byte order */
+
+void DEFUN(md_number_to_chars,(ptr, use, nbytes),
+ char *ptr AND
+ long use AND
+ int nbytes)
+{
+ switch (nbytes) {
+ case 4: *ptr++ = (use >> 24) & 0xff;
+ case 3: *ptr++ = (use >> 16) & 0xff;
+ case 2: *ptr++ = (use >> 8) & 0xff;
+ case 1: *ptr++ = (use >> 0) & 0xff;
+ break;
+ default:
+ abort();
+ }
+}
+long md_pcrel_from(fixP)
+fixS *fixP; { abort(); }
+
+void tc_coff_symbol_emit_hook() { }
+
+
+void tc_reloc_mangle(fix_ptr, intr, base)
+fixS *fix_ptr;
+struct internal_reloc *intr;
+bfd_vma base;
+
+{
+ symbolS *symbol_ptr;
+
+ symbol_ptr = fix_ptr->fx_addsy;
+
+ /* If this relocation is attached to a symbol then it's ok
+ to output it */
+ if (fix_ptr->fx_r_type == RELOC_32) {
+ /* cons likes to create reloc32's whatever the size of the reloc..
+ */
+ switch (fix_ptr->fx_size)
+ {
+
+ case 2:
+ intr->r_type = R_RELWORD;
+ break;
+ case 1:
+ intr->r_type = R_RELBYTE;
+ break;
+ default:
+ abort();
+
+ }
+
+ }
+ else {
+ intr->r_type = fix_ptr->fx_r_type;
+ }
+
+ intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where +base;
+ intr->r_offset = fix_ptr->fx_offset;
+
+ if (symbol_ptr)
+ intr->r_symndx = symbol_ptr->sy_number;
+ else
+ intr->r_symndx = -1;
+
+
+}
+
+/* end of tc-h8300.c */
diff --git a/gnu/usr.bin/as/config/tc-h8300.h b/gnu/usr.bin/as/config/tc-h8300.h
new file mode 100644
index 0000000..dc01f6c
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-h8300.h
@@ -0,0 +1,38 @@
+/* This file is tc-h8300.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#define TC_H8300
+
+/* This macro translates between an internal fix and an coff reloc type */
+#define TC_COFF_FIX2RTYPE(fixP) abort();
+
+#define BFD_ARCH bfd_arch_h8300
+#define COFF_MAGIC 0x8300
+#define TC_COUNT_RELOC(x) (1)
+
+
+#define TC_RELOC_MANGLE(a,b,c) tc_reloc_mangle(a,b,c)
+
+#define DO_NOT_STRIP 1
+#define DO_STRIP 0
+#define LISTING_HEADER "Hitachi H8/300 GAS "
+
+/* end of tc-h8300.h */
diff --git a/gnu/usr.bin/as/config/tc-i386.c b/gnu/usr.bin/as/config/tc-i386.c
new file mode 100644
index 0000000..133c07a
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-i386.c
@@ -0,0 +1,2345 @@
+/* i386.c -- Assemble code for the Intel 80386
+ Copyright (C) 1989, 1991, 1992 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ Intel 80386 machine specific gas.
+ Written by Eliot Dresselhaus (eliot@mgm.mit.edu).
+ Bugs & suggestions are completely welcome. This is free software.
+ Please help us make it better.
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+
+#include "obstack.h"
+#include "opcode/i386.h"
+
+/* 'md_assemble ()' gathers together information and puts it into a
+ i386_insn. */
+
+typedef struct {
+ /* TM holds the template for the insn were currently assembling. */
+ template tm;
+ /* SUFFIX holds the opcode suffix (e.g. 'l' for 'movl') if given. */
+ char suffix;
+ /* Operands are coded with OPERANDS, TYPES, DISPS, IMMS, and REGS. */
+
+ /* OPERANDS gives the number of given operands. */
+ unsigned int operands;
+
+ /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number of
+ given register, displacement, memory operands and immediate operands. */
+ unsigned int reg_operands, disp_operands, mem_operands, imm_operands;
+
+ /* TYPES [i] is the type (see above #defines) which tells us how to
+ search through DISPS [i] & IMMS [i] & REGS [i] for the required
+ operand. */
+ unsigned int types[MAX_OPERANDS];
+
+ /* Displacements (if given) for each operand. */
+ expressionS *disps[MAX_OPERANDS];
+
+#ifdef PIC
+ /* Relocation type for operand */
+ enum reloc_type disp_reloc[MAX_OPERANDS];
+#endif
+
+ /* Immediate operands (if given) for each operand. */
+ expressionS *imms[MAX_OPERANDS];
+
+ /* Register operands (if given) for each operand. */
+ reg_entry *regs[MAX_OPERANDS];
+
+ /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
+ the base index byte below. */
+ reg_entry *base_reg;
+ reg_entry *index_reg;
+ unsigned int log2_scale_factor;
+
+ /* SEG gives the seg_entry of this insn. It is equal to zero unless
+ an explicit segment override is given. */
+ const seg_entry *seg; /* segment for memory operands (if given) */
+
+ /* PREFIX holds all the given prefix opcodes (usually null).
+ PREFIXES is the size of PREFIX. */
+ /* richfix: really unsigned? */
+ unsigned char prefix[MAX_PREFIXES];
+ unsigned int prefixes;
+
+ /* RM and IB are the modrm byte and the base index byte where the addressing
+ modes of this insn are encoded. */
+
+ modrm_byte rm;
+ base_index_byte bi;
+
+} i386_insn;
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "#";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments started like this one will always work if
+ '/' isn't otherwise defined. */
+const char line_comment_chars[] = "#/"; /* removed '#' xoxorich. */
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "fFdDxX";
+
+/* tables for lexical analysis */
+static char opcode_chars[256];
+static char register_chars[256];
+static char operand_chars[256];
+static char space_chars[256];
+static char identifier_chars[256];
+static char digit_chars[256];
+
+/* lexical macros */
+#define is_opcode_char(x) (opcode_chars[(unsigned char) x])
+#define is_operand_char(x) (operand_chars[(unsigned char) x])
+#define is_register_char(x) (register_chars[(unsigned char) x])
+#define is_space_char(x) (space_chars[(unsigned char) x])
+#define is_identifier_char(x) (identifier_chars[(unsigned char) x])
+#define is_digit_char(x) (digit_chars[(unsigned char) x])
+
+/* put here all non-digit non-letter charcters that may occur in an operand */
+static char operand_special_chars[] = "%$-+(,)*._~/<>|&^!:";
+
+static char *ordinal_names[] = { "first", "second", "third" }; /* for printfs */
+
+/* md_assemble() always leaves the strings it's passed unaltered. To
+ effect this we maintain a stack of saved characters that we've smashed
+ with '\0's (indicating end of strings for various sub-fields of the
+ assembler instruction). */
+static char save_stack[32];
+static char *save_stack_p; /* stack pointer */
+#define END_STRING_AND_SAVE(s) *save_stack_p++ = *s; *s = '\0'
+#define RESTORE_END_STRING(s) *s = *--save_stack_p
+
+ /* The instruction we're assembling. */
+ static i386_insn i;
+
+/* Per instruction expressionS buffers: 2 displacements & 2 immediate max. */
+static expressionS disp_expressions[2], im_expressions[2];
+
+/* pointers to ebp & esp entries in reg_hash hash table */
+static reg_entry *ebp, *esp;
+
+static int this_operand; /* current operand we are working on */
+
+/*
+ Interface to relax_segment.
+ There are 2 relax states for 386 jump insns: one for conditional & one
+ for unconditional jumps. This is because the these two types of jumps
+ add different sizes to frags when we're figuring out what sort of jump
+ to choose to reach a given label. */
+
+/* types */
+#define COND_JUMP 1 /* conditional jump */
+#define UNCOND_JUMP 2 /* unconditional jump */
+/* sizes */
+#define BYTE 0
+#define WORD 1
+#define DWORD 2
+#define UNKNOWN_SIZE 3
+
+#define ENCODE_RELAX_STATE(type,size) ((type<<2) | (size))
+#define SIZE_FROM_RELAX_STATE(s) \
+ ( (((s) & 0x3) == BYTE ? 1 : (((s) & 0x3) == WORD ? 2 : 4)) )
+
+const relax_typeS md_relax_table[] = {
+ /*
+ The fields are:
+ 1) most positive reach of this state,
+ 2) most negative reach of this state,
+ 3) how many bytes this mode will add to the size of the current frag
+ 4) which index into the table to try if we can't fit into this one.
+ */
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 1, 0, 0},
+
+ /* For now we don't use word displacement jumps: they may be
+ untrustworthy. */
+ {127+1, -128+1, 0, ENCODE_RELAX_STATE(COND_JUMP,DWORD) },
+ /* word conditionals add 3 bytes to frag:
+ 2 opcode prefix; 1 displacement bytes */
+ {32767+2, -32768+2, 3, ENCODE_RELAX_STATE(COND_JUMP,DWORD) },
+ /* dword conditionals adds 4 bytes to frag:
+ 1 opcode prefix; 3 displacement bytes */
+ {0, 0, 4, 0},
+ {1, 1, 0, 0},
+
+ {127+1, -128+1, 0, ENCODE_RELAX_STATE(UNCOND_JUMP,DWORD) },
+ /* word jmp adds 2 bytes to frag:
+ 1 opcode prefix; 1 displacement bytes */
+ {32767+2, -32768+2, 2, ENCODE_RELAX_STATE(UNCOND_JUMP,DWORD) },
+ /* dword jmp adds 3 bytes to frag:
+ 0 opcode prefix; 3 displacement bytes */
+ {0, 0, 3, 0},
+ {1, 1, 0, 0},
+
+};
+
+#if __STDC__ == 1
+
+static char *output_invalid(int c);
+static int fits_in_signed_byte(long num);
+static int fits_in_signed_word(long num);
+static int fits_in_unsigned_byte(long num);
+static int fits_in_unsigned_word(long num);
+static int i386_operand(char *operand_string);
+static int smallest_imm_type(long num);
+static reg_entry *parse_register(char *reg_string);
+static unsigned long mode_from_disp_size(unsigned long t);
+static unsigned long opcode_suffix_to_type(unsigned long s);
+static void s_bss(void);
+
+#else /* not __STDC__ */
+
+static char *output_invalid();
+static int fits_in_signed_byte();
+static int fits_in_signed_word();
+static int fits_in_unsigned_byte();
+static int fits_in_unsigned_word();
+static int i386_operand();
+static int smallest_imm_type();
+static reg_entry *parse_register();
+static unsigned long mode_from_disp_size();
+static unsigned long opcode_suffix_to_type();
+static void s_bss();
+
+#endif /* not __STDC__ */
+
+
+/* Ignore certain directives generated by gcc. This probably should
+ not be here. */
+void dummy ()
+{
+ while (*input_line_pointer && *input_line_pointer != '\n')
+ input_line_pointer++;
+}
+
+const pseudo_typeS md_pseudo_table[] = {
+ { "bss", s_bss, 0 },
+
+#ifndef OLD_GAS
+ { "align", s_align_bytes, 0 },
+#else /* OLD_GAS */
+ { "align", s_align_ptwo, 0 },
+#endif /* OLD_GAS */
+
+ { "ffloat", float_cons, 'f' },
+ { "dfloat", float_cons, 'd' },
+ { "tfloat", float_cons, 'x' },
+ { "value", cons, 2 },
+ { 0, 0, 0 }
+};
+
+/* for interface with expression () */
+extern char * input_line_pointer;
+
+/* obstack for constructing various things in md_begin */
+struct obstack o;
+
+/* hash table for opcode lookup */
+static struct hash_control *op_hash = (struct hash_control *) 0;
+/* hash table for register lookup */
+static struct hash_control *reg_hash = (struct hash_control *) 0;
+/* hash table for prefix lookup */
+static struct hash_control *prefix_hash = (struct hash_control *) 0;
+
+
+void md_begin ()
+{
+ char * hash_err;
+
+ obstack_begin (&o,4096);
+
+ /* initialize op_hash hash table */
+ op_hash = hash_new(); /* xmalloc handles error */
+
+ {
+ register const template *optab;
+ register templates *core_optab;
+ char *prev_name;
+
+ optab = i386_optab; /* setup for loop */
+ prev_name = optab->name;
+ obstack_grow (&o, optab, sizeof(template));
+ core_optab = (templates *) xmalloc (sizeof (templates));
+
+ for (optab++; optab < i386_optab_end; optab++) {
+ if (! strcmp (optab->name, prev_name)) {
+ /* same name as before --> append to current template list */
+ obstack_grow (&o, optab, sizeof(template));
+ } else {
+ /* different name --> ship out current template list;
+ add to hash table; & begin anew */
+ /* Note: end must be set before start! since obstack_next_free changes
+ upon opstack_finish */
+ core_optab->end = (template *) obstack_next_free(&o);
+ core_optab->start = (template *) obstack_finish(&o);
+ hash_err = hash_insert (op_hash, prev_name, (char *) core_optab);
+ if (hash_err && *hash_err) {
+ hash_error:
+ as_fatal("Internal Error: Can't hash %s: %s", prev_name, hash_err);
+ }
+ prev_name = optab->name;
+ core_optab = (templates *) xmalloc (sizeof(templates));
+ obstack_grow (&o, optab, sizeof(template));
+ }
+ }
+ }
+
+ /* initialize reg_hash hash table */
+ reg_hash = hash_new();
+ {
+ register const reg_entry *regtab;
+
+ for (regtab = i386_regtab; regtab < i386_regtab_end; regtab++) {
+ hash_err = hash_insert (reg_hash, regtab->reg_name, regtab);
+ if (hash_err && *hash_err) goto hash_error;
+ }
+ }
+
+ esp = (reg_entry *) hash_find (reg_hash, "esp");
+ ebp = (reg_entry *) hash_find (reg_hash, "ebp");
+
+ /* initialize reg_hash hash table */
+ prefix_hash = hash_new();
+ {
+ register const prefix_entry *prefixtab;
+
+ for (prefixtab = i386_prefixtab;
+ prefixtab < i386_prefixtab_end; prefixtab++) {
+ hash_err = hash_insert (prefix_hash, prefixtab->prefix_name, prefixtab);
+ if (hash_err && *hash_err) goto hash_error;
+ }
+ }
+
+ /* fill in lexical tables: opcode_chars, operand_chars, space_chars */
+ {
+ register unsigned int c;
+
+ memset(opcode_chars, '\0', sizeof(opcode_chars));
+ memset(operand_chars, '\0', sizeof(operand_chars));
+ memset(space_chars, '\0', sizeof(space_chars));
+ memset(identifier_chars, '\0', sizeof(identifier_chars));
+ memset(digit_chars, '\0', sizeof(digit_chars));
+
+ for (c = 0; c < 256; c++) {
+ if (islower(c) || isdigit(c)) {
+ opcode_chars[c] = c;
+ register_chars[c] = c;
+ } else if (isupper(c)) {
+ opcode_chars[c] = tolower(c);
+ register_chars[c] = opcode_chars[c];
+ } else if (c == PREFIX_SEPERATOR) {
+ opcode_chars[c] = c;
+ } else if (c == ')' || c == '(') {
+ register_chars[c] = c;
+ }
+
+ if (isupper(c) || islower(c) || isdigit(c))
+ operand_chars[c] = c;
+ else if (c && strchr(operand_special_chars, c))
+ operand_chars[c] = c;
+
+ if (isdigit(c) || c == '-') digit_chars[c] = c;
+
+ if (isalpha(c) || c == '_' || c == '.' || isdigit(c))
+ identifier_chars[c] = c;
+
+ if (c == ' ' || c == '\t') space_chars[c] = c;
+ }
+ }
+}
+
+void md_end() {} /* not much to do here. */
+
+
+#define DEBUG386
+#ifdef DEBUG386
+
+/* debugging routines for md_assemble */
+static void pi (), pte (), pt (), pe (), ps ();
+
+static void pi (line, x)
+char * line;
+i386_insn *x;
+{
+ register template *p;
+ int i;
+
+ fprintf (stdout, "%s: template ", line);
+ pte (&x->tm);
+ fprintf (stdout, " modrm: mode %x reg %x reg/mem %x",
+ x->rm.mode, x->rm.reg, x->rm.regmem);
+ fprintf (stdout, " base %x index %x scale %x\n",
+ x->bi.base, x->bi.index, x->bi.scale);
+ for (i = 0; i < x->operands; i++) {
+ fprintf (stdout, " #%d: ", i+1);
+ pt (x->types[i]);
+ fprintf (stdout, "\n");
+ if (x->types[i] & Reg) fprintf (stdout, "%s\n", x->regs[i]->reg_name);
+ if (x->types[i] & Imm) pe (x->imms[i]);
+ if (x->types[i] & (Disp|Abs)) pe (x->disps[i]);
+ }
+}
+
+static void pte (t)
+template *t;
+{
+ int i;
+ fprintf (stdout, " %d operands ", t->operands);
+ fprintf (stdout, "opcode %x ",
+ t->base_opcode);
+ if (t->extension_opcode != None)
+ fprintf (stdout, "ext %x ", t->extension_opcode);
+ if (t->opcode_modifier&D)
+ fprintf (stdout, "D");
+ if (t->opcode_modifier&W)
+ fprintf (stdout, "W");
+ fprintf (stdout, "\n");
+ for (i = 0; i < t->operands; i++) {
+ fprintf (stdout, " #%d type ", i+1);
+ pt (t->operand_types[i]);
+ fprintf (stdout, "\n");
+ }
+}
+
+static void pe (e)
+expressionS *e;
+{
+ fprintf (stdout, " segment %s\n", segment_name (e->X_seg));
+ fprintf (stdout, " add_number %ld (%lx)\n",
+ e->X_add_number, e->X_add_number);
+ if (e->X_add_symbol) {
+ fprintf (stdout, " add_symbol ");
+ ps (e->X_add_symbol);
+ fprintf (stdout, "\n");
+ }
+ if (e->X_subtract_symbol) {
+ fprintf (stdout, " sub_symbol ");
+ ps (e->X_subtract_symbol);
+ fprintf (stdout, "\n");
+ }
+}
+
+static void ps (s)
+symbolS *s;
+{
+ fprintf (stdout, "%s type %s%s",
+ S_GET_NAME(s),
+ S_IS_EXTERNAL(s) ? "EXTERNAL " : "",
+ segment_name(S_GET_SEGMENT(s)));
+}
+
+struct type_name {
+ unsigned int mask;
+ char *tname;
+} type_names[] = {
+ { Reg8, "r8" }, { Reg16, "r16" }, { Reg32, "r32" }, { Imm8, "i8" },
+ { Imm8S, "i8s" },
+ { Imm16, "i16" }, { Imm32, "i32" }, { Mem8, "Mem8"}, { Mem16, "Mem16"},
+ { Mem32, "Mem32"}, { BaseIndex, "BaseIndex" },
+ { Abs8, "Abs8" }, { Abs16, "Abs16" }, { Abs32, "Abs32" },
+ { Disp8, "d8" }, { Disp16, "d16" },
+ { Disp32, "d32" }, { SReg2, "SReg2" }, { SReg3, "SReg3" }, { Acc, "Acc" },
+ { InOutPortReg, "InOutPortReg" }, { ShiftCount, "ShiftCount" },
+ { Imm1, "i1" }, { Control, "control reg" }, {Test, "test reg"},
+ { FloatReg, "FReg"}, {FloatAcc, "FAcc"},
+ { JumpAbsolute, "Jump Absolute"},
+ { 0, "" }
+};
+
+static void pt (t)
+unsigned int t;
+{
+ register struct type_name *ty;
+
+ if (t == Unknown) {
+ fprintf (stdout, "Unknown");
+ } else {
+ for (ty = type_names; ty->mask; ty++)
+ if (t & ty->mask) fprintf (stdout, "%s, ", ty->tname);
+ }
+ fflush (stdout);
+}
+
+#endif /* DEBUG386 */
+
+/*
+ This is the guts of the machine-dependent assembler. LINE points to a
+ machine dependent instruction. This funciton is supposed to emit
+ the frags/bytes it assembles to.
+ */
+void md_assemble (line)
+char *line;
+{
+ /* Holds temlate once we've found it. */
+ register template *t;
+
+ /* Possible templates for current insn */
+ templates *current_templates = (templates *) 0;
+
+ /* Initialize globals. */
+ memset(&i, '\0', sizeof(i));
+ memset(disp_expressions, '\0', sizeof(disp_expressions));
+ memset(im_expressions, '\0', sizeof(im_expressions));
+ save_stack_p = save_stack; /* reset stack pointer */
+
+ /* Fist parse an opcode & call i386_operand for the operands.
+ We assume that the scrubber has arranged it so that line[0] is the valid
+ start of a (possibly prefixed) opcode. */
+ {
+ register char *l = line; /* Fast place to put LINE. */
+
+ /* 1 if operand is pending after ','. */
+ unsigned int expecting_operand = 0;
+ /* 1 if we found a prefix only acceptable with string insns. */
+ unsigned int expecting_string_instruction = 0;
+ /* Non-zero if operand parens not balenced. */
+ unsigned int paren_not_balenced;
+ char * token_start = l;
+
+ while (! is_space_char(*l) && *l != END_OF_INSN) {
+ if (! is_opcode_char(*l)) {
+ as_bad("invalid character %s in opcode", output_invalid(*l));
+ return;
+ } else if (*l != PREFIX_SEPERATOR) {
+ *l = opcode_chars[(unsigned char) *l]; /* fold case of opcodes */
+ l++;
+ } else { /* this opcode's got a prefix */
+ register unsigned int q;
+ register prefix_entry * prefix;
+
+ if (l == token_start) {
+ as_bad("expecting prefix; got nothing");
+ return;
+ }
+ END_STRING_AND_SAVE (l);
+ prefix = (prefix_entry *) hash_find (prefix_hash, token_start);
+ if (! prefix) {
+ as_bad("no such opcode prefix ('%s')", token_start);
+ return;
+ }
+ RESTORE_END_STRING (l);
+ /* check for repeated prefix */
+ for (q = 0; q < i.prefixes; q++)
+ if (i.prefix[q] == prefix->prefix_code) {
+ as_bad("same prefix used twice; you don't really want this!");
+ return;
+ }
+ if (i.prefixes == MAX_PREFIXES) {
+ as_bad("too many opcode prefixes");
+ return;
+ }
+ i.prefix[i.prefixes++] = prefix->prefix_code;
+ if (prefix->prefix_code == REPE || prefix->prefix_code == REPNE)
+ expecting_string_instruction = 1;
+ /* skip past PREFIX_SEPERATOR and reset token_start */
+ token_start = ++l;
+ }
+ }
+ END_STRING_AND_SAVE (l);
+ if (token_start == l) {
+ as_bad("expecting opcode; got nothing");
+ return;
+ }
+
+ /* Lookup insn in hash; try intel & att naming conventions if appropriate;
+ that is: we only use the opcode suffix 'b' 'w' or 'l' if we need to. */
+ current_templates = (templates *) hash_find (op_hash, token_start);
+ if (! current_templates) {
+ int last_index = strlen(token_start) - 1;
+ char last_char = token_start[last_index];
+ switch (last_char) {
+ case DWORD_OPCODE_SUFFIX:
+ case WORD_OPCODE_SUFFIX:
+ case BYTE_OPCODE_SUFFIX:
+ token_start[last_index] = '\0';
+ current_templates = (templates *) hash_find (op_hash, token_start);
+ token_start[last_index] = last_char;
+ i.suffix = last_char;
+ }
+ if (!current_templates) {
+ as_bad("no such 386 instruction: `%s'", token_start); return;
+ }
+ }
+ RESTORE_END_STRING (l);
+
+ /* check for rep/repne without a string instruction */
+ if (expecting_string_instruction &&
+ ! IS_STRING_INSTRUCTION (current_templates->
+ start->base_opcode)) {
+ as_bad("expecting string instruction after rep/repne");
+ return;
+ }
+
+ /* There may be operands to parse. */
+ if (*l != END_OF_INSN &&
+ /* For string instructions, we ignore any operands if given. This
+ kludges, for example, 'rep/movsb %ds:(%esi), %es:(%edi)' where
+ the operands are always going to be the same, and are not really
+ encoded in machine code. */
+ ! IS_STRING_INSTRUCTION (current_templates->
+ start->base_opcode)) {
+ /* parse operands */
+ do {
+ /* skip optional white space before operand */
+ while (! is_operand_char(*l) && *l != END_OF_INSN) {
+ if (! is_space_char(*l)) {
+ as_bad("invalid character %s before %s operand",
+ output_invalid(*l),
+ ordinal_names[i.operands]);
+ return;
+ }
+ l++;
+ }
+ token_start = l; /* after white space */
+ paren_not_balenced = 0;
+ while (paren_not_balenced || *l != ',') {
+ if (*l == END_OF_INSN) {
+ if (paren_not_balenced) {
+ as_bad("unbalenced parenthesis in %s operand.",
+ ordinal_names[i.operands]);
+ return;
+ } else break; /* we are done */
+ } else if (! is_operand_char(*l) && ! is_space_char(*l)) {
+ as_bad("invalid character %s in %s operand",
+ output_invalid(*l),
+ ordinal_names[i.operands]);
+ return;
+ }
+ if (*l == '(') ++paren_not_balenced;
+ if (*l == ')') --paren_not_balenced;
+ l++;
+ }
+ if (l != token_start) { /* yes, we've read in another operand */
+ unsigned int operand_ok;
+ this_operand = i.operands++;
+ if (i.operands > MAX_OPERANDS) {
+ as_bad("spurious operands; (%d operands/instruction max)",
+ MAX_OPERANDS);
+ return;
+ }
+ /* now parse operand adding info to 'i' as we go along */
+ END_STRING_AND_SAVE (l);
+ operand_ok = i386_operand (token_start);
+ RESTORE_END_STRING (l); /* restore old contents */
+ if (!operand_ok) return;
+ } else {
+ if (expecting_operand) {
+ expecting_operand_after_comma:
+ as_bad("expecting operand after ','; got nothing");
+ return;
+ }
+ if (*l == ',') {
+ as_bad("expecting operand before ','; got nothing");
+ return;
+ }
+ }
+
+ /* now *l must be either ',' or END_OF_INSN */
+ if (*l == ',') {
+ if (*++l == END_OF_INSN) { /* just skip it, if it's \n complain */
+ goto expecting_operand_after_comma;
+ }
+ expecting_operand = 1;
+ }
+ } while (*l != END_OF_INSN); /* until we get end of insn */
+ }
+ }
+
+ /* Now we've parsed the opcode into a set of templates, and have the
+ operands at hand.
+ Next, we find a template that matches the given insn,
+ making sure the overlap of the given operands types is consistent
+ with the template operand types. */
+
+#define MATCH(overlap,given_type) \
+ (overlap && \
+ (overlap & (JumpAbsolute|BaseIndex|Mem8)) \
+ == (given_type & (JumpAbsolute|BaseIndex|Mem8)))
+
+ /* If m0 and m1 are register matches they must be consistent
+ with the expected operand types t0 and t1.
+ That is, if both m0 & m1 are register matches
+ i.e. ( ((m0 & (Reg)) && (m1 & (Reg)) ) ?
+ then, either 1. or 2. must be true:
+ 1. the expected operand type register overlap is null:
+ (t0 & t1 & Reg) == 0
+ AND
+ the given register overlap is null:
+ (m0 & m1 & Reg) == 0
+ 2. the expected operand type register overlap == the given
+ operand type overlap: (t0 & t1 & m0 & m1 & Reg).
+ */
+#define CONSISTENT_REGISTER_MATCH(m0, m1, t0, t1) \
+ ( ((m0 & (Reg)) && (m1 & (Reg))) ? \
+ ( ((t0 & t1 & (Reg)) == 0 && (m0 & m1 & (Reg)) == 0) || \
+ ((t0 & t1) & (m0 & m1) & (Reg)) \
+ ) : 1)
+ {
+ register unsigned int overlap0, overlap1;
+ expressionS * exp;
+ unsigned int overlap2;
+ unsigned int found_reverse_match;
+
+ overlap0 = overlap1 = overlap2 = found_reverse_match = 0;
+ for (t = current_templates->start;
+ t < current_templates->end;
+ t++) {
+
+ /* must have right number of operands */
+ if (i.operands != t->operands) continue;
+ else if (!t->operands) break; /* 0 operands always matches */
+
+ overlap0 = i.types[0] & t->operand_types[0];
+ switch (t->operands) {
+ case 1:
+ if (! MATCH (overlap0,i.types[0])) continue;
+ break;
+ case 2: case 3:
+ overlap1 = i.types[1] & t->operand_types[1];
+ if (! MATCH (overlap0,i.types[0]) ||
+ ! MATCH (overlap1,i.types[1]) ||
+ ! CONSISTENT_REGISTER_MATCH(overlap0, overlap1,
+ t->operand_types[0],
+ t->operand_types[1])) {
+
+ /* check if other direction is valid ... */
+ if (! (t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS))
+ continue;
+
+ /* try reversing direction of operands */
+ overlap0 = i.types[0] & t->operand_types[1];
+ overlap1 = i.types[1] & t->operand_types[0];
+ if (! MATCH (overlap0,i.types[0]) ||
+ ! MATCH (overlap1,i.types[1]) ||
+ ! CONSISTENT_REGISTER_MATCH (overlap0, overlap1,
+ t->operand_types[0],
+ t->operand_types[1])) {
+ /* does not match either direction */
+ continue;
+ }
+ /* found a reverse match here -- slip through */
+ /* found_reverse_match holds which of D or FloatD we've found */
+ found_reverse_match = t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS;
+ } /* endif: not forward match */
+ /* found either forward/reverse 2 operand match here */
+ if (t->operands == 3) {
+ overlap2 = i.types[2] & t->operand_types[2];
+ if (! MATCH (overlap2,i.types[2]) ||
+ ! CONSISTENT_REGISTER_MATCH (overlap0, overlap2,
+ t->operand_types[0],
+ t->operand_types[2]) ||
+ ! CONSISTENT_REGISTER_MATCH (overlap1, overlap2,
+ t->operand_types[1],
+ t->operand_types[2]))
+ continue;
+ }
+ /* found either forward/reverse 2 or 3 operand match here:
+ slip through to break */
+ }
+ break; /* we've found a match; break out of loop */
+ } /* for (t = ... */
+ if (t == current_templates->end) { /* we found no match */
+ as_bad("operands given don't match any known 386 instruction");
+ return;
+ }
+
+ /* Copy the template we found (we may change it!). */
+ memcpy(&i.tm, t, sizeof(template));
+ t = &i.tm; /* alter new copy of template */
+
+ /* If there's no opcode suffix we try to invent one based on register
+ operands. */
+ if (! i.suffix && i.reg_operands) {
+ /* We take i.suffix from the LAST register operand specified. This
+ assumes that the last register operands is the destination register
+ operand. */
+ int o;
+ for (o = 0; o < MAX_OPERANDS; o++)
+ if (i.types[o] & Reg) {
+ i.suffix = (i.types[o] == Reg8) ? BYTE_OPCODE_SUFFIX :
+ (i.types[o] == Reg16) ? WORD_OPCODE_SUFFIX :
+ DWORD_OPCODE_SUFFIX;
+ }
+ }
+
+ /* Make still unresolved immediate matches conform to size of immediate
+ given in i.suffix. Note: overlap2 cannot be an immediate!
+ We assume this. */
+ if ((overlap0 & (Imm8|Imm8S|Imm16|Imm32))
+ && overlap0 != Imm8 && overlap0 != Imm8S
+ && overlap0 != Imm16 && overlap0 != Imm32) {
+ if (! i.suffix) {
+ as_bad("no opcode suffix given; can't determine immediate size");
+ return;
+ }
+ overlap0 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8|Imm8S) :
+ (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32));
+ }
+ if ((overlap1 & (Imm8|Imm8S|Imm16|Imm32))
+ && overlap1 != Imm8 && overlap1 != Imm8S
+ && overlap1 != Imm16 && overlap1 != Imm32) {
+ if (! i.suffix) {
+ as_bad("no opcode suffix given; can't determine immediate size");
+ return;
+ }
+ overlap1 &= (i.suffix == BYTE_OPCODE_SUFFIX ? (Imm8|Imm8S) :
+ (i.suffix == WORD_OPCODE_SUFFIX ? Imm16 : Imm32));
+ }
+
+ i.types[0] = overlap0;
+ i.types[1] = overlap1;
+ i.types[2] = overlap2;
+
+ if (overlap0 & ImplicitRegister) i.reg_operands--;
+ if (overlap1 & ImplicitRegister) i.reg_operands--;
+ if (overlap2 & ImplicitRegister) i.reg_operands--;
+ if (overlap0 & Imm1) i.imm_operands = 0; /* kludge for shift insns */
+
+ if (found_reverse_match) {
+ unsigned int save;
+ save = t->operand_types[0];
+ t->operand_types[0] = t->operand_types[1];
+ t->operand_types[1] = save;
+ }
+
+ /* Finalize opcode. First, we change the opcode based on the operand
+ size given by i.suffix: we never have to change things for byte insns,
+ or when no opcode suffix is need to size the operands. */
+
+ if (! i.suffix && (t->opcode_modifier & W)) {
+ as_bad("no opcode suffix given and no register operands; can't size instruction");
+ return;
+ }
+
+ if (i.suffix && i.suffix != BYTE_OPCODE_SUFFIX) {
+ /* Select between byte and word/dword operations. */
+ if (t->opcode_modifier & W)
+ t->base_opcode |= W;
+ /* Now select between word & dword operations via the
+ operand size prefix. */
+ if (i.suffix == WORD_OPCODE_SUFFIX) {
+ if (i.prefixes == MAX_PREFIXES) {
+ as_bad("%d prefixes given and 'w' opcode suffix gives too many prefixes",
+ MAX_PREFIXES);
+ return;
+ }
+ i.prefix[i.prefixes++] = WORD_PREFIX_OPCODE;
+ }
+ }
+
+ /* For insns with operands there are more diddles to do to the opcode. */
+ if (i.operands) {
+ /* If we found a reverse match we must alter the opcode direction bit
+ found_reverse_match holds bit to set (different for int &
+ float insns). */
+
+ if (found_reverse_match) {
+ t->base_opcode |= found_reverse_match;
+ }
+
+ /*
+ The imul $imm, %reg instruction is converted into
+ imul $imm, %reg, %reg. */
+ if (t->opcode_modifier & imulKludge) {
+ i.regs[2] = i.regs[1]; /* Pretend we saw the 3 operand case. */
+ i.reg_operands = 2;
+ }
+
+ /* Certain instructions expect the destination to be in the i.rm.reg
+ field. This is by far the exceptional case. For these instructions,
+ if the source operand is a register, we must reverse the i.rm.reg
+ and i.rm.regmem fields. We accomplish this by faking that the
+ two register operands were given in the reverse order. */
+ if ((t->opcode_modifier & ReverseRegRegmem) && i.reg_operands == 2) {
+ unsigned int first_reg_operand = (i.types[0] & Reg) ? 0 : 1;
+ unsigned int second_reg_operand = first_reg_operand + 1;
+ reg_entry *tmp = i.regs[first_reg_operand];
+ i.regs[first_reg_operand] = i.regs[second_reg_operand];
+ i.regs[second_reg_operand] = tmp;
+ }
+
+ if (t->opcode_modifier & ShortForm) {
+ /* The register or float register operand is in operand 0 or 1. */
+ unsigned int o = (i.types[0] & (Reg|FloatReg)) ? 0 : 1;
+ /* Register goes in low 3 bits of opcode. */
+ t->base_opcode |= i.regs[o]->reg_num;
+ } else if (t->opcode_modifier & ShortFormW) {
+ /* Short form with 0x8 width bit. Register is always dest. operand */
+ t->base_opcode |= i.regs[1]->reg_num;
+ if (i.suffix == WORD_OPCODE_SUFFIX ||
+ i.suffix == DWORD_OPCODE_SUFFIX)
+ t->base_opcode |= 0x8;
+ } else if (t->opcode_modifier & Seg2ShortForm) {
+ if (t->base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1) {
+ as_bad("you can't 'pop cs' on the 386.");
+ return;
+ }
+ t->base_opcode |= (i.regs[0]->reg_num << 3);
+ } else if (t->opcode_modifier & Seg3ShortForm) {
+ /* 'push %fs' is 0x0fa0; 'pop %fs' is 0x0fa1.
+ 'push %gs' is 0x0fa8; 'pop %fs' is 0x0fa9.
+ So, only if i.regs[0]->reg_num == 5 (%gs) do we need
+ to change the opcode. */
+ if (i.regs[0]->reg_num == 5)
+ t->base_opcode |= 0x08;
+ } else if (t->opcode_modifier & Modrm) {
+ /* The opcode is completed (modulo t->extension_opcode which must
+ be put into the modrm byte.
+ Now, we make the modrm & index base bytes based on all the info
+ we've collected. */
+
+ /* i.reg_operands MUST be the number of real register operands;
+ implicit registers do not count. */
+ if (i.reg_operands == 2) {
+ unsigned int source, dest;
+ source = (i.types[0] & (Reg|SReg2|SReg3|Control|Debug|Test)) ? 0 : 1;
+ dest = source + 1;
+ i.rm.mode = 3;
+ /* We must be careful to make sure that all segment/control/test/
+ debug registers go into the i.rm.reg field (despite the whether
+ they are source or destination operands). */
+ if (i.regs[dest]->reg_type & (SReg2|SReg3|Control|Debug|Test)) {
+ i.rm.reg = i.regs[dest]->reg_num;
+ i.rm.regmem = i.regs[source]->reg_num;
+ } else {
+ i.rm.reg = i.regs[source]->reg_num;
+ i.rm.regmem = i.regs[dest]->reg_num;
+ }
+ } else { /* if it's not 2 reg operands... */
+ if (i.mem_operands) {
+ unsigned int fake_zero_displacement = 0;
+ unsigned int o = (i.types[0] & Mem) ? 0 : ((i.types[1] & Mem) ? 1 : 2);
+
+ /* Encode memory operand into modrm byte and base index byte. */
+
+ if (i.base_reg == esp && ! i.index_reg) {
+ /* <disp>(%esp) becomes two byte modrm with no index register. */
+ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
+ i.rm.mode = mode_from_disp_size(i.types[o]);
+ i.bi.base = ESP_REG_NUM;
+ i.bi.index = NO_INDEX_REGISTER;
+ i.bi.scale = 0; /* Must be zero! */
+ } else if (i.base_reg == ebp && !i.index_reg) {
+ if (! (i.types[o] & Disp)) {
+ /* Must fake a zero byte displacement.
+ There is no direct way to code '(%ebp)' directly. */
+ fake_zero_displacement = 1;
+ /* fake_zero_displacement code does not set this. */
+ i.types[o] |= Disp8;
+ }
+ i.rm.mode = mode_from_disp_size(i.types[o]);
+ i.rm.regmem = EBP_REG_NUM;
+ } else if (! i.base_reg && (i.types[o] & BaseIndex)) {
+ /* There are three cases here.
+ Case 1: '<32bit disp>(,1)' -- indirect absolute.
+ (Same as cases 2 & 3 with NO index register)
+ Case 2: <32bit disp> (,<index>) -- no base register with disp
+ Case 3: (, <index>) --- no base register;
+ no disp (must add 32bit 0 disp). */
+ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
+ i.rm.mode = 0; /* 32bit mode */
+ i.bi.base = NO_BASE_REGISTER;
+ i.types[o] &= ~Disp;
+ i.types[o] |= Disp32; /* Must be 32bit! */
+ if (i.index_reg) { /* case 2 or case 3 */
+ i.bi.index = i.index_reg->reg_num;
+ i.bi.scale = i.log2_scale_factor;
+ if (i.disp_operands == 0)
+ fake_zero_displacement = 1; /* case 3 */
+ } else {
+ i.bi.index = NO_INDEX_REGISTER;
+ i.bi.scale = 0;
+ }
+ } else if (i.disp_operands && !i.base_reg && !i.index_reg) {
+ /* Operand is just <32bit disp> */
+ i.rm.regmem = EBP_REG_NUM;
+ i.rm.mode = 0;
+ i.types[o] &= ~Disp;
+ i.types[o] |= Disp32;
+ } else {
+ /* It's not a special case; rev'em up. */
+ i.rm.regmem = i.base_reg->reg_num;
+ i.rm.mode = mode_from_disp_size(i.types[o]);
+ if (i.index_reg) {
+ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING;
+ i.bi.base = i.base_reg->reg_num;
+ i.bi.index = i.index_reg->reg_num;
+ i.bi.scale = i.log2_scale_factor;
+ if (i.base_reg == ebp && i.disp_operands == 0) { /* pace */
+ fake_zero_displacement = 1;
+ i.types[o] |= Disp8;
+ i.rm.mode = mode_from_disp_size(i.types[o]);
+ }
+ }
+ }
+ if (fake_zero_displacement) {
+ /* Fakes a zero displacement assuming that i.types[o] holds
+ the correct displacement size. */
+ exp = &disp_expressions[i.disp_operands++];
+ i.disps[o] = exp;
+ exp->X_seg = SEG_ABSOLUTE;
+ exp->X_add_number = 0;
+ exp->X_add_symbol = (symbolS *) 0;
+ exp->X_subtract_symbol = (symbolS *) 0;
+ }
+
+ /* Select the correct segment for the memory operand. */
+ if (i.seg) {
+ unsigned int seg_index;
+ const seg_entry *default_seg;
+
+ if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING) {
+ seg_index = (i.rm.mode<<3) | i.bi.base;
+ default_seg = two_byte_segment_defaults[seg_index];
+ } else {
+ seg_index = (i.rm.mode<<3) | i.rm.regmem;
+ default_seg = one_byte_segment_defaults[seg_index];
+ }
+ /* If the specified segment is not the default, use an
+ opcode prefix to select it */
+ if (i.seg != default_seg) {
+ if (i.prefixes == MAX_PREFIXES) {
+ as_bad("%d prefixes given and %s segment override gives too many prefixes",
+ MAX_PREFIXES, i.seg->seg_name);
+ return;
+ }
+ i.prefix[i.prefixes++] = i.seg->seg_prefix;
+ }
+ }
+ }
+
+ /* Fill in i.rm.reg or i.rm.regmem field with register operand
+ (if any) based on t->extension_opcode. Again, we must be careful
+ to make sure that segment/control/debug/test registers are coded
+ into the i.rm.reg field. */
+ if (i.reg_operands) {
+ unsigned int o =
+ (i.types[0] & (Reg|SReg2|SReg3|Control|Debug|Test)) ? 0 :
+ (i.types[1] & (Reg|SReg2|SReg3|Control|Debug|Test)) ? 1 : 2;
+ /* If there is an extension opcode to put here, the register number
+ must be put into the regmem field. */
+ if (t->extension_opcode != None)
+ i.rm.regmem = i.regs[o]->reg_num;
+ else i.rm.reg = i.regs[o]->reg_num;
+
+ /* Now, if no memory operand has set i.rm.mode = 0, 1, 2
+ we must set it to 3 to indicate this is a register operand
+ int the regmem field */
+ if (! i.mem_operands) i.rm.mode = 3;
+ }
+
+ /* Fill in i.rm.reg field with extension opcode (if any). */
+ if (t->extension_opcode != None)
+ i.rm.reg = t->extension_opcode;
+ }
+ }
+ }
+ }
+
+ /* Handle conversion of 'int $3' --> special int3 insn. */
+ if (t->base_opcode == INT_OPCODE && i.imms[0]->X_add_number == 3) {
+ t->base_opcode = INT3_OPCODE;
+ i.imm_operands = 0;
+ }
+
+ /* We are ready to output the insn. */
+ {
+ register char * p;
+
+ /* Output jumps. */
+ if (t->opcode_modifier & Jump) {
+ int n = i.disps[0]->X_add_number;
+
+ switch (i.disps[0]->X_seg) {
+ case SEG_ABSOLUTE:
+ if (fits_in_signed_byte(n)) {
+ p = frag_more (2);
+ p[0] = t->base_opcode;
+ p[1] = n;
+#if 0 /* leave out 16 bit jumps - pace */
+ } else if (fits_in_signed_word(n)) {
+ p = frag_more (4);
+ p[0] = WORD_PREFIX_OPCODE;
+ p[1] = t->base_opcode;
+ md_number_to_chars (&p[2], n, 2);
+#endif
+ } else { /* It's an absolute dword displacement. */
+ if (t->base_opcode == JUMP_PC_RELATIVE) { /* pace */
+ /* unconditional jump */
+ p = frag_more (5);
+ p[0] = 0xe9;
+ md_number_to_chars (&p[1], n, 4);
+ } else {
+ /* conditional jump */
+ p = frag_more (6);
+ p[0] = TWO_BYTE_OPCODE_ESCAPE;
+ p[1] = t->base_opcode + 0x10;
+ md_number_to_chars (&p[2], n, 4);
+ }
+ }
+ break;
+ default:
+ /* It's a symbol; end frag & setup for relax.
+ Make sure there are 6 chars left in the current frag; if not
+ we'll have to start a new one. */
+ /* I caught it failing with obstack_room == 6,
+ so I changed to <= pace */
+ if (obstack_room (&frags) <= 6) {
+ frag_wane(frag_now);
+ frag_new (0);
+ }
+ p = frag_more (1);
+ p[0] = t->base_opcode;
+ frag_var (rs_machine_dependent,
+ 6, /* 2 opcode/prefix + 4 displacement */
+ 1,
+ ((unsigned char) *p == JUMP_PC_RELATIVE
+ ? ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE)
+ : ENCODE_RELAX_STATE (COND_JUMP, BYTE)),
+ i.disps[0]->X_add_symbol,
+ n, p);
+/*
+ * XXX - what do we do about jmp x@PLT ??
+ * kludged in md_estimate_size_before_relax() below
+ */
+ break;
+ }
+ } else if (t->opcode_modifier & (JumpByte|JumpDword)) {
+ int size = (t->opcode_modifier & JumpByte) ? 1 : 4;
+ int n = i.disps[0]->X_add_number;
+
+ if (fits_in_unsigned_byte(t->base_opcode)) {
+ FRAG_APPEND_1_CHAR (t->base_opcode);
+ } else {
+ p = frag_more (2); /* opcode can be at most two bytes */
+ /* put out high byte first: can't use md_number_to_chars! */
+ *p++ = (t->base_opcode >> 8) & 0xff;
+ *p = t->base_opcode & 0xff;
+ }
+
+ p = frag_more (size);
+ switch (i.disps[0]->X_seg) {
+ case SEG_ABSOLUTE:
+ md_number_to_chars (p, n, size);
+ if (size == 1 && ! fits_in_signed_byte(n)) {
+ as_bad("loop/jecx only takes byte displacement; %d shortened to %d",
+ n, *p);
+ }
+ break;
+ default:
+ fix_new (frag_now, p - frag_now->fr_literal, size,
+ i.disps[0]->X_add_symbol, i.disps[0]->X_subtract_symbol,
+ i.disps[0]->X_add_number, 1, i.disp_reloc[0], i.disps[0]->X_got_symbol);
+ break;
+ }
+ } else if (t->opcode_modifier & JumpInterSegment) {
+ p = frag_more (1 + 2 + 4); /* 1 opcode; 2 segment; 4 offset */
+ p[0] = t->base_opcode;
+ if (i.imms[1]->X_seg == SEG_ABSOLUTE)
+ md_number_to_chars (p + 1, i.imms[1]->X_add_number, 4);
+ else
+ fix_new (frag_now, p + 1 - frag_now->fr_literal, 4,
+ i.imms[1]->X_add_symbol,
+ i.imms[1]->X_subtract_symbol,
+ i.imms[1]->X_add_number, 0, NO_RELOC, i.imms[1]->X_got_symbol);
+ if (i.imms[0]->X_seg != SEG_ABSOLUTE)
+ as_bad("can't handle non absolute segment in long call/jmp");
+ md_number_to_chars (p + 5, i.imms[0]->X_add_number, 2);
+ } else {
+ /* Output normal instructions here. */
+ unsigned char *q;
+#ifdef PIC
+ /*
+ * Remember # of opcode bytes to put in pcrel_adjust
+ * for use in _GLOBAL_OFFSET_TABLE_ expressions.
+ */
+ int nopbytes = 0;
+#endif
+
+ /* First the prefix bytes. */
+ for (q = i.prefix; q < i.prefix + i.prefixes; q++) {
+ p = frag_more (1);
+ nopbytes += 1;
+ md_number_to_chars (p, (unsigned int) *q, 1);
+ }
+
+ /* Now the opcode; be careful about word order here! */
+ if (fits_in_unsigned_byte(t->base_opcode)) {
+ nopbytes += 1;
+ FRAG_APPEND_1_CHAR (t->base_opcode);
+ } else if (fits_in_unsigned_word(t->base_opcode)) {
+ p = frag_more (2);
+ nopbytes += 2;
+ /* put out high byte first: can't use md_number_to_chars! */
+ *p++ = (t->base_opcode >> 8) & 0xff;
+ *p = t->base_opcode & 0xff;
+ } else { /* opcode is either 3 or 4 bytes */
+ if (t->base_opcode & 0xff000000) {
+ p = frag_more (4);
+ nopbytes += 4;
+ *p++ = (t->base_opcode >> 24) & 0xff;
+ } else {
+ p = frag_more (3);
+ nopbytes += 3;
+ }
+ *p++ = (t->base_opcode >> 16) & 0xff;
+ *p++ = (t->base_opcode >> 8) & 0xff;
+ *p = (t->base_opcode ) & 0xff;
+ }
+
+ /* Now the modrm byte and base index byte (if present). */
+ if (t->opcode_modifier & Modrm) {
+ p = frag_more (1);
+ nopbytes += 1;
+ /* md_number_to_chars (p, i.rm, 1); */
+ md_number_to_chars (p, (i.rm.regmem<<0 | i.rm.reg<<3 | i.rm.mode<<6), 1);
+ /* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode)
+ ==> need second modrm byte. */
+ if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING && i.rm.mode != 3) {
+ p = frag_more (1);
+ nopbytes += 1;
+ /* md_number_to_chars (p, i.bi, 1); */
+ md_number_to_chars (p,(i.bi.base<<0 | i.bi.index<<3 | i.bi.scale<<6), 1);
+ }
+ }
+
+ if (i.disp_operands) {
+ register unsigned int n;
+
+ for (n = 0; n < i.operands; n++) {
+ if (i.disps[n]) {
+ if (i.disps[n]->X_seg == SEG_ABSOLUTE) {
+ if (i.types[n] & (Disp8|Abs8)) {
+ p = frag_more (1);
+ md_number_to_chars (p, i.disps[n]->X_add_number, 1);
+ } else if (i.types[n] & (Disp16|Abs16)) {
+ p = frag_more (2);
+ md_number_to_chars (p, i.disps[n]->X_add_number, 2);
+ } else { /* Disp32|Abs32 */
+ p = frag_more (4);
+ md_number_to_chars (p, i.disps[n]->X_add_number, 4);
+ }
+ } else { /* not SEG_ABSOLUTE */
+ /* need a 32-bit fixup (don't support 8bit non-absolute disps) */
+
+ fixS *fixP;
+ p = frag_more (4);
+ fixP = fix_new (frag_now, p - frag_now->fr_literal, 4,
+ i.disps[n]->X_add_symbol, i.disps[n]->X_subtract_symbol,
+ i.disps[n]->X_add_number, 0, i.disp_reloc[n], i.disps[n]->X_got_symbol);
+#ifdef PIC
+ if (i.disps[n]->X_got_symbol) {
+ fixP->fx_pcrel_adjust = nopbytes;
+ }
+#endif
+ }
+ }
+ }
+ } /* end displacement output */
+
+ /* output immediate */
+ if (i.imm_operands) {
+ register unsigned int n;
+
+ for (n = 0; n < i.operands; n++) {
+ if (i.imms[n]) {
+ if (i.imms[n]->X_seg == SEG_ABSOLUTE) {
+ if (i.types[n] & (Imm8|Imm8S)) {
+ p = frag_more (1);
+ md_number_to_chars (p, i.imms[n]->X_add_number, 1);
+ } else if (i.types[n] & Imm16) {
+ p = frag_more (2);
+ md_number_to_chars (p, i.imms[n]->X_add_number, 2);
+ } else {
+ p = frag_more (4);
+ md_number_to_chars (p, i.imms[n]->X_add_number, 4);
+ }
+ } else { /* not SEG_ABSOLUTE */
+ /* need a 32-bit fixup (don't support 8bit non-absolute ims) */
+ /* try to support other sizes ... */
+ fixS *fixP;
+ int size;
+ if (i.types[n] & (Imm8|Imm8S))
+ size = 1;
+ else if (i.types[n] & Imm16)
+ size = 2;
+ else
+ size = 4;
+ p = frag_more (size);
+ fixP = fix_new (frag_now, p - frag_now->fr_literal, size,
+ i.imms[n]->X_add_symbol, i.imms[n]->X_subtract_symbol,
+ i.imms[n]->X_add_number, 0, NO_RELOC, i.imms[n]->X_got_symbol);
+#ifdef PIC
+ if (i.imms[n]->X_got_symbol) {
+ fixP->fx_pcrel_adjust = nopbytes;
+ }
+#endif
+ }
+ }
+ }
+ } /* end immediate output */
+ }
+
+#ifdef DEBUG386
+ if (flagseen['D']) {
+ pi (line, &i);
+ }
+#endif /* DEBUG386 */
+
+ }
+ return;
+}
+
+/* Parse OPERAND_STRING into the i386_insn structure I. Returns non-zero
+ on error. */
+
+static int i386_operand (operand_string)
+char *operand_string;
+{
+ register char *op_string = operand_string;
+
+ /* Address of '\0' at end of operand_string. */
+ char * end_of_operand_string = operand_string + strlen(operand_string);
+
+ /* Start and end of displacement string expression (if found). */
+ char *displacement_string_start = NULL;
+ char *displacement_string_end = NULL;
+
+ /* We check for an absolute prefix (differentiating,
+ for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */
+ if (*op_string == ABSOLUTE_PREFIX) {
+ op_string++;
+ i.types[this_operand] |= JumpAbsolute;
+ }
+
+ /* Check if operand is a register. */
+ if (*op_string == REGISTER_PREFIX) {
+ register reg_entry *r;
+ if (!(r = parse_register (op_string))) {
+ as_bad("bad register name ('%s')", op_string);
+ return 0;
+ }
+ /* Check for segment override, rather than segment register by
+ searching for ':' after %<x>s where <x> = s, c, d, e, f, g. */
+ if ((r->reg_type & (SReg2|SReg3)) && op_string[3] == ':') {
+ switch (r->reg_num) {
+ case 0:
+ i.seg = (seg_entry *) &es; break;
+ case 1:
+ i.seg = (seg_entry *) &cs; break;
+ case 2:
+ i.seg = (seg_entry *) &ss; break;
+ case 3:
+ i.seg = (seg_entry *) &ds; break;
+ case 4:
+ i.seg = (seg_entry *) &fs; break;
+ case 5:
+ i.seg = (seg_entry *) &gs; break;
+ }
+ op_string += 4; /* skip % <x> s : */
+ operand_string = op_string; /* Pretend given string starts here. */
+ if (!is_digit_char(*op_string) && !is_identifier_char(*op_string)
+ && *op_string != '(' && *op_string != ABSOLUTE_PREFIX) {
+ as_bad("bad memory operand after segment override");
+ return 0;
+ }
+ /* Handle case of %es:*foo. */
+ if (*op_string == ABSOLUTE_PREFIX) {
+ op_string++;
+ i.types[this_operand] |= JumpAbsolute;
+ }
+ goto do_memory_reference;
+ }
+ i.types[this_operand] |= r->reg_type;
+ i.regs[this_operand] = r;
+ i.reg_operands++;
+ } else if (*op_string == IMMEDIATE_PREFIX) { /* ... or an immediate */
+ char *save_input_line_pointer;
+ segT exp_seg = SEG_GOOF;
+ expressionS *exp;
+
+ if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) {
+ as_bad("only 1 or 2 immediate operands are allowed");
+ return 0;
+ }
+
+ exp = &im_expressions[i.imm_operands++];
+ i.imms[this_operand] = exp;
+ save_input_line_pointer = input_line_pointer;
+ /* must advance op_string! */
+ input_line_pointer = ++op_string;
+ SKIP_WHITESPACE ();
+
+ exp_seg = expression(exp);
+ input_line_pointer = save_input_line_pointer;
+
+ switch (exp_seg) {
+ case SEG_ABSENT: /* missing or bad expr becomes absolute 0 */
+ as_bad("missing or invalid immediate expression '%s' taken as 0",
+ operand_string);
+ exp->X_seg = SEG_ABSOLUTE;
+ exp->X_add_number = 0;
+ exp->X_add_symbol = (symbolS *) 0;
+ exp->X_subtract_symbol = (symbolS *) 0;
+ i.types[this_operand] |= Imm;
+ break;
+ case SEG_ABSOLUTE:
+ i.types[this_operand] |= smallest_imm_type(exp->X_add_number);
+ break;
+ case SEG_TEXT: case SEG_DATA: case SEG_BSS: case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ i.types[this_operand] |= Imm32; /* this is an address ==> 32bit */
+ break;
+ default:
+ seg_unimplemented:
+ as_bad("Unimplemented segment type %d in parse_operand", exp_seg);
+ return 0;
+ }
+ /* shorten this type of this operand if the instruction wants
+ * fewer bits than are present in the immediate. The bit field
+ * code can put out 'andb $0xffffff, %al', for example. pace
+ * also 'movw $foo,(%eax)'
+ */
+ switch (i.suffix) {
+ case WORD_OPCODE_SUFFIX:
+ i.types[this_operand] |= Imm16;
+ break;
+ case BYTE_OPCODE_SUFFIX:
+ i.types[this_operand] |= Imm16 | Imm8 | Imm8S;
+ break;
+ }
+ } else if (is_digit_char(*op_string) || is_identifier_char(*op_string)
+ || *op_string == '(') {
+ /* This is a memory reference of some sort. */
+ register char * base_string;
+ unsigned int found_base_index_form;
+
+ do_memory_reference:
+ if (i.mem_operands == MAX_MEMORY_OPERANDS) {
+ as_bad("more than 1 memory reference in instruction");
+ return 0;
+ }
+ i.mem_operands++;
+
+ /* Determine type of memory operand from opcode_suffix;
+ no opcode suffix implies general memory references. */
+ switch (i.suffix) {
+ case BYTE_OPCODE_SUFFIX:
+ i.types[this_operand] |= Mem8;
+ break;
+ case WORD_OPCODE_SUFFIX:
+ i.types[this_operand] |= Mem16;
+ break;
+ case DWORD_OPCODE_SUFFIX:
+ default:
+ i.types[this_operand] |= Mem32;
+ }
+
+ /* Check for base index form. We detect the base index form by
+ looking for an ')' at the end of the operand, searching
+ for the '(' matching it, and finding a REGISTER_PREFIX or ','
+ after it. */
+ base_string = end_of_operand_string - 1;
+ found_base_index_form = 0;
+ if (*base_string == ')') {
+ unsigned int parens_balenced = 1;
+ /* We've already checked that the number of left & right ()'s are equal,
+ so this loop will not be infinite. */
+ do {
+ base_string--;
+ if (*base_string == ')') parens_balenced++;
+ if (*base_string == '(') parens_balenced--;
+ } while (parens_balenced);
+ base_string++; /* Skip past '('. */
+ if (*base_string == REGISTER_PREFIX || *base_string == ',')
+ found_base_index_form = 1;
+ }
+
+ /* If we can't parse a base index register expression, we've found
+ a pure displacement expression. We set up displacement_string_start
+ and displacement_string_end for the code below. */
+ if (! found_base_index_form) {
+ displacement_string_start = op_string;
+ displacement_string_end = end_of_operand_string;
+ } else {
+ char *base_reg_name, *index_reg_name, *num_string;
+ int num;
+
+ i.types[this_operand] |= BaseIndex;
+
+ /* If there is a displacement set-up for it to be parsed later. */
+ if (base_string != op_string + 1) {
+ displacement_string_start = op_string;
+ displacement_string_end = base_string - 1;
+ }
+
+ /* Find base register (if any). */
+ if (*base_string != ',') {
+ base_reg_name = base_string++;
+ /* skip past register name & parse it */
+ while (isalpha(*base_string)) base_string++;
+ if (base_string == base_reg_name+1) {
+ as_bad("can't find base register name after '(%c'",
+ REGISTER_PREFIX);
+ return 0;
+ }
+ END_STRING_AND_SAVE (base_string);
+ if (! (i.base_reg = parse_register (base_reg_name))) {
+ as_bad("bad base register name ('%s')", base_reg_name);
+ return 0;
+ }
+ RESTORE_END_STRING (base_string);
+ }
+
+ /* Now check seperator; must be ',' ==> index reg
+ OR num ==> no index reg. just scale factor
+ OR ')' ==> end. (scale factor = 1) */
+ if (*base_string != ',' && *base_string != ')') {
+ as_bad("expecting ',' or ')' after base register in `%s'",
+ operand_string);
+ return 0;
+ }
+
+ /* There may index reg here; and there may be a scale factor. */
+ if (*base_string == ',' && *(base_string+1) == REGISTER_PREFIX) {
+ index_reg_name = ++base_string;
+ while (isalpha(*++base_string));
+ END_STRING_AND_SAVE (base_string);
+ if (! (i.index_reg = parse_register(index_reg_name))) {
+ as_bad("bad index register name ('%s')", index_reg_name);
+ return 0;
+ }
+ RESTORE_END_STRING (base_string);
+ }
+
+ /* Check for scale factor. */
+ if (*base_string == ',' && isdigit(*(base_string+1))) {
+ num_string = ++base_string;
+ while (is_digit_char(*base_string)) base_string++;
+ if (base_string == num_string) {
+ as_bad("can't find a scale factor after ','");
+ return 0;
+ }
+ END_STRING_AND_SAVE (base_string);
+ /* We've got a scale factor. */
+ if (! sscanf (num_string, "%d", &num)) {
+ as_bad("can't parse scale factor from '%s'", num_string);
+ return 0;
+ }
+ RESTORE_END_STRING (base_string);
+ switch (num) { /* must be 1 digit scale */
+ case 1: i.log2_scale_factor = 0; break;
+ case 2: i.log2_scale_factor = 1; break;
+ case 4: i.log2_scale_factor = 2; break;
+ case 8: i.log2_scale_factor = 3; break;
+ default:
+ as_bad("expecting scale factor of 1, 2, 4, 8; got %d", num);
+ return 0;
+ }
+ } else {
+ if (! i.index_reg && *base_string == ',') {
+ as_bad("expecting index register or scale factor after ','; got '%c'",
+ *(base_string+1));
+ return 0;
+ }
+ }
+ }
+
+ /* If there's an expression begining the operand, parse it,
+ assuming displacement_string_start and displacement_string_end
+ are meaningful. */
+ if (displacement_string_start) {
+ register expressionS *exp;
+ segT exp_seg = SEG_GOOF;
+ char *save_input_line_pointer;
+ exp = &disp_expressions[i.disp_operands];
+ i.disps[this_operand] = exp;
+ i.disp_reloc[this_operand] = NO_RELOC;
+ i.disp_operands++;
+ save_input_line_pointer = input_line_pointer;
+ input_line_pointer = displacement_string_start;
+ END_STRING_AND_SAVE (displacement_string_end);
+#ifdef PIC
+ {
+ /*
+ * We can have operands of the form
+ * <symbol>@GOTOFF+<nnn>
+ * Take the easy way out here and copy everything
+ * into a temporary buffer...
+ */
+ register char *cp;
+ if (picmode &&
+ (cp = strchr(input_line_pointer,'@'))) {
+ char tmpbuf[BUFSIZ];
+
+ if (strncmp(cp+1, "PLT", 3) == 0) {
+ i.disp_reloc[this_operand] = RELOC_JMP_TBL;
+ *cp = '\0';
+ strcpy(tmpbuf, input_line_pointer);
+ strcat(tmpbuf, cp+1+3);
+ *cp = '@';
+ } else if (strncmp(cp+1, "GOTOFF", 6) == 0) {
+ i.disp_reloc[this_operand] = RELOC_GOTOFF;
+ *cp = '\0';
+ strcpy(tmpbuf, input_line_pointer);
+ strcat(tmpbuf, cp+1+6);
+ *cp = '@';
+ } else if (strncmp(cp+1, "GOT", 3) == 0) {
+ i.disp_reloc[this_operand] = RELOC_GOT;
+ *cp = '\0';
+ strcpy(tmpbuf, input_line_pointer);
+ strcat(tmpbuf, cp+1+3);
+ *cp = '@';
+ } else
+ as_bad("Bad reloc specifier '%s' in expression", cp+1);
+ input_line_pointer = tmpbuf;
+ }
+ }
+#endif
+ exp_seg = expression(exp);
+#ifdef PIC
+ if (i.disp_reloc[this_operand] == RELOC_GOTOFF)
+ exp->X_add_symbol->sy_forceout = 1;
+#endif
+ if (*input_line_pointer)
+ as_bad("Ignoring junk '%s' after expression",input_line_pointer);
+ RESTORE_END_STRING (displacement_string_end);
+ input_line_pointer = save_input_line_pointer;
+ switch (exp_seg) {
+ case SEG_ABSENT:
+ /* missing expr becomes absolute 0 */
+ as_bad("missing or invalid displacement '%s' taken as 0",
+ operand_string);
+ if (i.disp_reloc[this_operand] != NO_RELOC || !found_base_index_form || !i.base_reg) {
+ i.types[this_operand] |= (Disp|Abs);
+ exp->X_seg = SEG_ABSOLUTE;
+ exp->X_add_number = 0;
+ exp->X_add_symbol = (symbolS *) 0;
+ exp->X_subtract_symbol = (symbolS *) 0;
+ } else {
+#ifdef DEBUGxxx
+ printf("displacement removed in operand `%s'\n", operand_string);
+#endif
+ i.disp_operands--;
+ i.disps[this_operand] = 0;
+ }
+ break;
+ case SEG_ABSOLUTE:
+ if (i.disp_reloc[this_operand] != NO_RELOC || !found_base_index_form || !i.base_reg || exp->X_add_symbol || exp->X_subtract_symbol || exp->X_add_number != 0)
+ i.types[this_operand] |= SMALLEST_DISP_TYPE (exp->X_add_number);
+ else {
+#ifdef DEBUGxxx
+ printf("displacement removed in operand `%s'\n", operand_string);
+#endif
+ i.disp_operands--;
+ i.disps[this_operand] = 0;
+ }
+ break;
+ case SEG_TEXT: case SEG_DATA: case SEG_BSS:
+ case SEG_UNKNOWN: /* must be 32 bit displacement (i.e. address) */
+ if (i.disp_reloc[this_operand] != NO_RELOC || !found_base_index_form || !i.base_reg || exp->X_add_symbol || exp->X_subtract_symbol || exp->X_add_number != 0)
+ i.types[this_operand] |= Disp32;
+ else {
+#ifdef DEBUGxxx
+ printf("displacement removed in operand `%s'\n", operand_string);
+#endif
+ i.disp_operands--;
+ i.disps[this_operand] = 0;
+ }
+ break;
+ default:
+ goto seg_unimplemented;
+ }
+ }
+
+ /* Make sure the memory operand we've been dealt is valid. */
+ if (i.base_reg && i.index_reg &&
+ ! (i.base_reg->reg_type & i.index_reg->reg_type & Reg)) {
+ as_bad("register size mismatch in (base,index,scale) expression");
+ return 0;
+ }
+ /*
+ * special case for (%dx) while doing input/output op
+ */
+ if ((i.base_reg &&
+ (i.base_reg->reg_type == (Reg16|InOutPortReg)) &&
+ (i.index_reg == 0)))
+ return 1;
+ if ((i.base_reg && (i.base_reg->reg_type & Reg32) == 0) ||
+ (i.index_reg && (i.index_reg->reg_type & Reg32) == 0)) {
+ as_bad("base/index register must be 32 bit register");
+ return 0;
+ }
+ if (i.index_reg && i.index_reg == esp) {
+ as_bad("%s may not be used as an index register", esp->reg_name);
+ return 0;
+ }
+ } else { /* it's not a memory operand; argh! */
+ as_bad("invalid char %s begining %s operand '%s'",
+ output_invalid(*op_string), ordinal_names[this_operand],
+ op_string);
+ return 0;
+ }
+ return 1; /* normal return */
+}
+
+/*
+ * md_estimate_size_before_relax()
+ *
+ * Called just before relax().
+ * Any symbol that is now undefined will not become defined.
+ * Return the correct fr_subtype in the frag.
+ * Return the initial "guess for fr_var" to caller.
+ * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ * Although it may not be explicit in the frag, pretend fr_var starts with a
+ * 0 value.
+ */
+int
+ md_estimate_size_before_relax (fragP, segment)
+register fragS * fragP;
+register segT segment;
+{
+ register unsigned char * opcode;
+ register int old_fr_fix;
+
+ old_fr_fix = fragP->fr_fix;
+ opcode = (unsigned char *) fragP->fr_opcode;
+ /* We've already got fragP->fr_subtype right; all we have to do is check
+ for un-relaxable symbols. */
+ if (S_GET_SEGMENT(fragP->fr_symbol) != segment) {
+ /* symbol is undefined in this segment */
+ switch (opcode[0]) {
+ case JUMP_PC_RELATIVE: /* make jmp (0xeb) a dword displacement jump */
+ opcode[0] = 0xe9; /* dword disp jmp */
+ fragP->fr_fix += 4;
+ fix_new (fragP, old_fr_fix, 4,
+ fragP->fr_symbol,
+ (symbolS *) 0,
+ fragP->fr_offset, 1,
+#ifdef PIC
+/* XXX - oops, the JMP_TBL relocation info should have percolated through
+ * here, define a field in frag to this?
+ */
+ (picmode && S_GET_SEGMENT(fragP->fr_symbol) == SEG_UNKNOWN)?
+ RELOC_JMP_TBL :
+#endif
+ NO_RELOC, (symbolS *)0);
+ break;
+
+ default:
+ /* This changes the byte-displacement jump 0x7N -->
+ the dword-displacement jump 0x0f8N */
+ opcode[1] = opcode[0] + 0x10;
+ opcode[0] = TWO_BYTE_OPCODE_ESCAPE; /* two-byte escape */
+ fragP->fr_fix += 1 + 4; /* we've added an opcode byte */
+ fix_new (fragP, old_fr_fix + 1, 4,
+ fragP->fr_symbol,
+ (symbolS *) 0,
+ fragP->fr_offset, 1,
+#ifdef PIC
+/*XXX*/ (picmode && S_GET_SEGMENT(fragP->fr_symbol) == SEG_UNKNOWN)?
+ RELOC_JMP_TBL :
+#endif
+ NO_RELOC, (symbolS *)0);
+ break;
+ }
+ frag_wane (fragP);
+ }
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+} /* md_estimate_size_before_relax() */
+
+/*
+ * md_convert_frag();
+ *
+ * Called after relax() is finished.
+ * In: Address of frag.
+ * fr_type == rs_machine_dependent.
+ * fr_subtype is what the address relaxed to.
+ *
+ * Out: Any fixSs and constants are set up.
+ * Caller will turn frag into a ".space 0".
+ */
+void
+ md_convert_frag (headers, fragP)
+object_headers *headers;
+register fragS * fragP;
+{
+ register unsigned char *opcode;
+ unsigned char *where_to_put_displacement = NULL;
+ unsigned int target_address;
+ unsigned int opcode_address;
+ unsigned int extension = 0;
+ int displacement_from_opcode_start;
+
+ opcode = (unsigned char *) fragP->fr_opcode;
+
+ /* Address we want to reach in file space. */
+ target_address = S_GET_VALUE(fragP->fr_symbol) + fragP->fr_offset;
+
+ /* Address opcode resides at in file space. */
+ opcode_address = fragP->fr_address + fragP->fr_fix;
+
+ /* Displacement from opcode start to fill into instruction. */
+ displacement_from_opcode_start = target_address - opcode_address;
+
+ switch (fragP->fr_subtype) {
+ case ENCODE_RELAX_STATE (COND_JUMP, BYTE):
+ case ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE):
+ /* don't have to change opcode */
+ extension = 1; /* 1 opcode + 1 displacement */
+ where_to_put_displacement = &opcode[1];
+ break;
+
+ case ENCODE_RELAX_STATE (COND_JUMP, WORD):
+ opcode[1] = TWO_BYTE_OPCODE_ESCAPE;
+ opcode[2] = opcode[0] + 0x10;
+ opcode[0] = WORD_PREFIX_OPCODE;
+ extension = 4; /* 3 opcode + 2 displacement */
+ where_to_put_displacement = &opcode[3];
+ break;
+
+ case ENCODE_RELAX_STATE (UNCOND_JUMP, WORD):
+ opcode[1] = 0xe9;
+ opcode[0] = WORD_PREFIX_OPCODE;
+ extension = 3; /* 2 opcode + 2 displacement */
+ where_to_put_displacement = &opcode[2];
+ break;
+
+ case ENCODE_RELAX_STATE (COND_JUMP, DWORD):
+ opcode[1] = opcode[0] + 0x10;
+ opcode[0] = TWO_BYTE_OPCODE_ESCAPE;
+ extension = 5; /* 2 opcode + 4 displacement */
+ where_to_put_displacement = &opcode[2];
+ break;
+
+ case ENCODE_RELAX_STATE (UNCOND_JUMP, DWORD):
+ opcode[0] = 0xe9;
+ extension = 4; /* 1 opcode + 4 displacement */
+ where_to_put_displacement = &opcode[1];
+ break;
+
+ default:
+ BAD_CASE(fragP->fr_subtype);
+ break;
+}
+ /* now put displacement after opcode */
+ md_number_to_chars ((char *) where_to_put_displacement,
+ displacement_from_opcode_start - extension,
+ SIZE_FROM_RELAX_STATE (fragP->fr_subtype));
+ fragP->fr_fix += extension;
+}
+
+
+int md_short_jump_size = 2; /* size of byte displacement jmp */
+int md_long_jump_size = 5; /* size of dword displacement jmp */
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - (from_addr + 2);
+ md_number_to_chars (ptr, (long) 0xeb, 1); /* opcode for byte-disp jump */
+ md_number_to_chars (ptr + 1, offset, 1);
+}
+
+void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ if (flagseen['m']) {
+ offset = to_addr - S_GET_VALUE(to_symbol);
+ md_number_to_chars (ptr, 0xe9, 1); /* opcode for long jmp */
+ md_number_to_chars (ptr + 1, offset, 4);
+ fix_new (frag, (ptr+1) - frag->fr_literal, 4,
+ to_symbol, (symbolS *) 0, (long) 0, 0, NO_RELOC, (symbolS *)0);
+ } else {
+ offset = to_addr - (from_addr + 5);
+ md_number_to_chars(ptr, (long) 0xe9, 1);
+ md_number_to_chars(ptr + 1, offset, 4);
+ }
+}
+
+int
+ md_parse_option(argP,cntP,vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ switch (**argP) {
+#ifdef PIC
+ case 'k':
+ case 'K':
+#if 00
+ char *tmp = xmalloc(3+1+strlen(operand_special_chars));
+ strcpy(tmp, operand_special_chars);
+ strcat(tmp, "@[]");
+ operand_special_chars = tmp;
+#endif
+ /* Allow `[', `]' in expressions and `@' in operands */
+ operand_chars['@'] = '@';
+ operand_chars['['] = '[';
+ operand_chars[']'] = ']';
+
+ /* Disallow `[' as a name beginner */
+ lex_type['['] = 0;
+
+ /* Predefine GOT symbol */
+ GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+ /* write out in little endian. */
+void /* Knows about order of bytes in address. */
+ md_number_to_chars(con, value, nbytes)
+char con[]; /* Return 'nbytes' of chars here. */
+long value; /* The value of the bits. */
+int nbytes; /* Number of bytes in the output. */
+{
+ register char * p = con;
+
+ switch (nbytes) {
+ case 1:
+ p[0] = value & 0xff;
+ break;
+ case 2:
+ p[0] = value & 0xff;
+ p[1] = (value >> 8) & 0xff;
+ break;
+ case 4:
+ p[0] = value & 0xff;
+ p[1] = (value>>8) & 0xff;
+ p[2] = (value>>16) & 0xff;
+ p[3] = (value>>24) & 0xff;
+ break;
+ default:
+ BAD_CASE (nbytes);
+ }
+}
+
+
+/* Apply a fixup (fixS) to segment data, once it has been determined
+ by our caller that we have all the info we need to fix it up.
+
+ On the 386, immediates, displacements, and data pointers are all in
+ the same (little-endian) format, so we don't need to care about which
+ we are handling. */
+
+void
+ md_apply_fix (fixP, value)
+fixS * fixP; /* The fix we're to put in */
+long value; /* The value of the bits. */
+{
+ register char * p = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ switch (fixP->fx_size) {
+ case 1:
+ *p = value;
+ break;
+ case 2:
+ *p++ = value;
+ *p = (value>>8);
+ break;
+ case 4:
+ *p++ = value;
+ *p++ = (value>>8);
+ *p++ = (value>>16);
+ *p = (value>>24);
+ break;
+ default:
+ BAD_CASE (fixP->fx_size);
+ }
+}
+
+long /* Knows about the byte order in a word. */
+ md_chars_to_number (con, nbytes)
+unsigned char con[]; /* Low order byte 1st. */
+int nbytes; /* Number of bytes in the input. */
+{
+ long retval;
+ for (retval=0, con+=nbytes-1; nbytes--; con--)
+ {
+ retval <<= BITS_PER_CHAR;
+ retval |= *con;
+ }
+ return retval;
+}
+
+/* Not needed for coff since relocation structure does not
+ contain bitfields. */
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+#ifdef comment
+/* Output relocation information in the target's format. */
+void
+ md_ri_to_chars(the_bytes, ri)
+char *the_bytes;
+struct reloc_info_generic *ri;
+{
+ /* this is easy */
+ md_number_to_chars(the_bytes, ri->r_address, 4);
+ /* now the fun stuff */
+ the_bytes[6] = (ri->r_symbolnum >> 16) & 0x0ff;
+ the_bytes[5] = (ri->r_symbolnum >> 8) & 0x0ff;
+ the_bytes[4] = ri->r_symbolnum & 0x0ff;
+ the_bytes[7] = (((ri->r_extern << 3) & 0x08) | ((ri->r_length << 1) & 0x06) |
+ ((ri->r_pcrel << 0) & 0x01)) & 0x0F;
+}
+#endif /* comment */
+
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };
+ long r_symbolnum;
+
+ know(fixP->fx_addsy != NULL);
+
+ md_number_to_chars(where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy)
+ ? S_GET_TYPE(fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+#ifdef PIC
+ {
+ int extra_bits = 0;
+ int extrn_bit = !S_IS_DEFINED(fixP->fx_addsy);
+
+ switch (fixP->fx_r_type) {
+ case NO_RELOC:
+ break;
+ case RELOC_32:
+ if (!picmode || !S_IS_EXTERNAL(fixP->fx_addsy))
+ break;
+ r_symbolnum = fixP->fx_addsy->sy_number;
+ extrn_bit = 1;
+ break;
+ case RELOC_GOT:
+ extra_bits = (1 << 4) & 0x10; /* r_baserel */
+ r_symbolnum = fixP->fx_addsy->sy_number;
+ if (!extrn_bit && !S_IS_EXTERNAL(fixP->fx_addsy))
+ as_warn("GOT relocation burb: `%s' should be global",
+ S_GET_NAME(fixP->fx_addsy));
+ S_SET_EXTERNAL(fixP->fx_addsy);
+ extrn_bit = 1;
+ break;
+ case RELOC_GOTOFF:
+ extra_bits = (1 << 4) & 0x10; /* r_baserel */
+ r_symbolnum = fixP->fx_addsy->sy_number;
+ if (extrn_bit || S_IS_EXTERNAL(fixP->fx_addsy))
+ as_warn("GOT relocation burb: `%s' should be static",
+ S_GET_NAME(fixP->fx_addsy));
+ break;
+ case RELOC_JMP_TBL:
+ extra_bits = (1 << 5) & 0x20; /* r_jmptable */
+ break;
+ case RELOC_RELATIVE:
+ /* consider using this bit (together with r_baserel) for
+ * GOTOFFs, so ld can check
+ */
+ as_fatal("relocation botch");
+ extra_bits = (1 << 6) & 0x40; /* r_relative */
+ break;
+ }
+ where[6] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[4] = r_symbolnum & 0x0ff;
+ where[7] = ( ((extrn_bit << 3) & 0x08)
+ | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
+ | ((fixP->fx_pcrel << 0) & 0x01)
+ | (extra_bits)
+ );
+ }
+#else
+ where[6] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[4] = r_symbolnum & 0x0ff;
+ where[7] = ((((!S_IS_DEFINED(fixP->fx_addsy)) << 3) & 0x08)
+ | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
+ | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));
+#endif
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+
+#define MAX_LITTLENUMS 6
+
+/* Turn the string pointed to by litP into a floating point constant of type
+ type, and emit the appropriate bytes. The number of LITTLENUMS emitted
+ is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+char *
+ md_atof(type,litP,sizeP)
+char type;
+char *litP;
+int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+
+ switch (type) {
+ case 'f':
+ case 'F':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 5;
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to md_atof ()";
+ }
+ t = atof_ieee (input_line_pointer,type,words);
+ if (t)
+ input_line_pointer=t;
+
+ *sizeP = prec * sizeof(LITTLENUM_TYPE);
+ /* this loops outputs the LITTLENUMs in REVERSE order; in accord with
+ the bigendian 386 */
+ for (wordP = words + prec - 1;prec--;) {
+ md_number_to_chars (litP, (long) (*wordP--), sizeof(LITTLENUM_TYPE));
+ litP += sizeof(LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+char output_invalid_buf[8];
+
+static char * output_invalid (c)
+char c;
+{
+ if (isprint(c)) sprintf (output_invalid_buf, "'%c'", c);
+ else sprintf (output_invalid_buf, "(0x%x)", (unsigned) c);
+ return output_invalid_buf;
+}
+
+static reg_entry *parse_register (reg_string)
+char *reg_string; /* reg_string starts *before* REGISTER_PREFIX */
+{
+ register char *s = reg_string;
+ register char *p;
+ char reg_name_given[MAX_REG_NAME_SIZE];
+
+ s++; /* skip REGISTER_PREFIX */
+ for (p = reg_name_given; is_register_char (*s); p++, s++) {
+ *p = register_chars[*s];
+ if (p >= reg_name_given + MAX_REG_NAME_SIZE)
+ return (reg_entry *) 0;
+ }
+ *p = '\0';
+ return (reg_entry *) hash_find (reg_hash, reg_name_given);
+}
+
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+ md_undefined_symbol (name)
+char *name;
+{
+#ifdef PIC
+ /* HACK:
+ * Sun's ld expects __GLOBAL_OFFSET_TABLE_,
+ * gcc generates _GLOBAL_OFFSET_TABLE_
+ * should probably fix ld - new SVR4 style??
+ */
+ if (*name == '_' && *(name+1) == 'G' &&
+ strcmp(name, "_GLOBAL_OFFSET_TABLE_") == 0)
+ return symbol_find("__GLOBAL_OFFSET_TABLE_");
+#endif
+ return 0;
+}
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void
+ md_operand (expressionP)
+expressionS *expressionP;
+{
+}
+
+/* Round up a section size to the appropriate boundary. */
+long
+ md_section_align (segment, size)
+segT segment;
+long size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the i386, they're relative to the address of the offset, plus
+ its size. (??? Is this right? FIXME-SOON!) */
+long
+ md_pcrel_from (fixP)
+fixS *fixP;
+{
+#ifdef PIC
+ /*
+ * _GLOBAL_OFFSET_TABLE_ refs are relative to the offset of the
+ * current instruction. fx_pcrel_adjust has been setup to account
+ * for the number of opcode bytes preceding the fixup location,
+ * it is zero for eg. .long pseudo-ops.
+ */
+ if (fixP->fx_gotsy)
+ return fixP->fx_where + fixP->fx_frag->fr_address - fixP->fx_pcrel_adjust;
+ else
+#endif
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+ /* these were macros, but I don't trust macros that eval their
+ arguments more than once. Besides, gcc can static inline them.
+ xoxorich. */
+
+static unsigned long mode_from_disp_size(t)
+unsigned long t;
+{
+ return((t & (Disp8))
+ ? 1
+ : ((t & (Disp32)) ? 2 : 0));
+} /* mode_from_disp_size() */
+
+/* convert opcode suffix ('b' 'w' 'l' typically) into type specifyer */
+
+static unsigned long opcode_suffix_to_type(s)
+unsigned long s;
+{
+ return(s == BYTE_OPCODE_SUFFIX
+ ? Byte : (s == WORD_OPCODE_SUFFIX
+ ? Word : DWord));
+} /* opcode_suffix_to_type() */
+
+static int fits_in_signed_byte(num)
+long num;
+{
+ return((num >= -128) && (num <= 127));
+} /* fits_in_signed_byte() */
+
+static int fits_in_unsigned_byte(num)
+long num;
+{
+ return((num & 0xff) == num);
+} /* fits_in_unsigned_byte() */
+
+static int fits_in_unsigned_word(num)
+long num;
+{
+ return((num & 0xffff) == num);
+} /* fits_in_unsigned_word() */
+
+static int fits_in_signed_word(num)
+long num;
+{
+ return((-32768 <= num) && (num <= 32767));
+} /* fits_in_signed_word() */
+
+static int smallest_imm_type(num)
+long num;
+{
+ return((num == 1)
+ ? (Imm1|Imm8|Imm8S|Imm16|Imm32)
+ : (fits_in_signed_byte(num)
+ ? (Imm8S|Imm8|Imm16|Imm32)
+ : (fits_in_unsigned_byte(num)
+ ? (Imm8|Imm16|Imm32)
+ : ((fits_in_signed_word(num) || fits_in_unsigned_word(num))
+ ? (Imm16|Imm32)
+ : (Imm32)))));
+} /* smallest_imm_type() */
+
+static void s_bss()
+{
+ register int temp;
+
+ temp = get_absolute_expression ();
+ subseg_new (SEG_BSS, (subsegT)temp);
+ demand_empty_rest_of_line();
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * End:
+ */
+
+/* end of tc-i386.c */
diff --git a/gnu/usr.bin/as/config/tc-i386.h b/gnu/usr.bin/as/config/tc-i386.h
new file mode 100644
index 0000000..a227895
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-i386.h
@@ -0,0 +1,251 @@
+/* tc-i386.h -- Header file for tc-i386.c
+ Copyright (C) 1989, 1992 Free Software Foundation.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+#ifndef TC_I386
+#define TC_I386 1
+
+#define AOUT_MACHTYPE 134
+
+#define REVERSE_SORT_RELOCS
+
+#define LOCAL_LABELS_FB
+
+#define tc_coff_symbol_emit_hook(a) ; /* not used */
+
+ /* Local labels starts with .L */
+ /* fixme-now: this is for testing against old gas */
+/* #define LOCAL_LABEL(name) ((name)[0] == '.' && (name)[1] == 'L') */
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+
+#define MAX_OPERANDS 3 /* max operands per insn */
+#define MAX_PREFIXES 4 /* max prefixes per opcode */
+#define MAX_IMMEDIATE_OPERANDS 2 /* max immediates per insn */
+#define MAX_MEMORY_OPERANDS 2 /* max memory ref per insn
+ * lcall uses 2
+ */
+/* we define the syntax here (modulo base,index,scale syntax) */
+#define REGISTER_PREFIX '%'
+#define IMMEDIATE_PREFIX '$'
+#define ABSOLUTE_PREFIX '*'
+#define PREFIX_SEPERATOR '/'
+
+#define TWO_BYTE_OPCODE_ESCAPE 0x0f
+
+#ifndef OLD_GAS
+#define NOP_OPCODE 0x90
+#else /* OLD_GAS */
+#define NOP_OPCODE 0x00
+#endif /* OLD_GAS */
+
+/* register numbers */
+#define EBP_REG_NUM 5
+#define ESP_REG_NUM 4
+
+/* modrm_byte.regmem for twobyte escape */
+#define ESCAPE_TO_TWO_BYTE_ADDRESSING ESP_REG_NUM
+/* index_base_byte.index for no index register addressing */
+#define NO_INDEX_REGISTER ESP_REG_NUM
+/* index_base_byte.base for no base register addressing */
+#define NO_BASE_REGISTER EBP_REG_NUM
+
+ /* these are the att as opcode suffixes, making movl --> mov, for example */
+#define DWORD_OPCODE_SUFFIX 'l'
+#define WORD_OPCODE_SUFFIX 'w'
+#define BYTE_OPCODE_SUFFIX 'b'
+
+ /* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */
+#define REGMEM_FIELD_HAS_REG 0x3 /* always = 0x3 */
+#define REGMEM_FIELD_HAS_MEM (~REGMEM_FIELD_HAS_REG)
+
+#define END_OF_INSN '\0'
+
+/*
+ When an operand is read in it is classified by its type. This type includes
+ all the possible ways an operand can be used. Thus, '%eax' is both 'register
+ # 0' and 'The Accumulator'. In our language this is expressed by OR'ing
+ 'Reg32' (any 32 bit register) and 'Acc' (the accumulator).
+ Operands are classified so that we can match given operand types with
+ the opcode table in i386-opcode.h.
+ */
+#define Unknown 0x0
+/* register */
+#define Reg8 0x1 /* 8 bit reg */
+#define Reg16 0x2 /* 16 bit reg */
+#define Reg32 0x4 /* 32 bit reg */
+#define Reg (Reg8|Reg16|Reg32) /* gen'l register */
+#define WordReg (Reg16|Reg32) /* for push/pop operands */
+/* immediate */
+#define Imm8 0x8 /* 8 bit immediate */
+#define Imm8S 0x10 /* 8 bit immediate sign extended */
+#define Imm16 0x20 /* 16 bit immediate */
+#define Imm32 0x40 /* 32 bit immediate */
+#define Imm1 0x80 /* 1 bit immediate */
+#define ImmUnknown Imm32 /* for unknown expressions */
+#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */
+/* memory */
+#define Disp8 0x200 /* 8 bit displacement (for jumps) */
+#define Disp16 0x400 /* 16 bit displacement */
+#define Disp32 0x800 /* 32 bit displacement */
+#define Disp (Disp8|Disp16|Disp32) /* General displacement */
+#define DispUnknown Disp32 /* for unknown size displacements */
+#define Mem8 0x1000
+#define Mem16 0x2000
+#define Mem32 0x4000
+#define BaseIndex 0x8000
+#define Mem (Disp|Mem8|Mem16|Mem32|BaseIndex) /* General memory */
+#define WordMem (Mem16|Mem32|Disp|BaseIndex)
+#define ByteMem (Mem8|Disp|BaseIndex)
+/* specials */
+#define InOutPortReg 0x10000 /* register to hold in/out port addr = dx */
+#define ShiftCount 0x20000 /* register to hold shift cound = cl */
+#define Control 0x40000 /* Control register */
+#define Debug 0x80000 /* Debug register */
+#define Test 0x100000 /* Test register */
+#define FloatReg 0x200000 /* Float register */
+#define FloatAcc 0x400000 /* Float stack top %st(0) */
+#define SReg2 0x800000 /* 2 bit segment register */
+#define SReg3 0x1000000 /* 3 bit segment register */
+#define Acc 0x2000000 /* Accumulator %al or %ax or %eax */
+#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc)
+#define JumpAbsolute 0x4000000
+#define Abs8 0x08000000
+#define Abs16 0x10000000
+#define Abs32 0x20000000
+#define Abs (Abs8|Abs16|Abs32)
+
+#define Byte (Reg8|Imm8|Imm8S)
+#define Word (Reg16|Imm16)
+#define DWord (Reg32|Imm32)
+
+#define SMALLEST_DISP_TYPE(num) \
+ fits_in_signed_byte(num) ? (Disp8|Disp32|Abs8|Abs32) : (Disp32|Abs32)
+
+typedef struct {
+ /* instruction name sans width suffix ("mov" for movl insns) */
+ char *name;
+
+ /* how many operands */
+ unsigned int operands;
+
+ /* base_opcode is the fundamental opcode byte with a optional prefix(es). */
+ unsigned int base_opcode;
+
+ /* extension_opcode is the 3 bit extension for group <n> insns.
+ If this template has no extension opcode (the usual case) use None */
+ unsigned char extension_opcode;
+#define None 0xff /* If no extension_opcode is possible. */
+
+ /* the bits in opcode_modifier are used to generate the final opcode from
+ the base_opcode. These bits also are used to detect alternate forms of
+ the same instruction */
+ unsigned int opcode_modifier;
+
+ /* opcode_modifier bits: */
+#define W 0x1 /* set if operands are words or dwords */
+#define D 0x2 /* D = 0 if Reg --> Regmem; D = 1 if Regmem --> Reg */
+ /* direction flag for floating insns: MUST BE 0x400 */
+#define FloatD 0x400
+ /* shorthand */
+#define DW (D|W)
+#define ShortForm 0x10 /* register is in low 3 bits of opcode */
+#define ShortFormW 0x20 /* ShortForm and W bit is 0x8 */
+#define Seg2ShortForm 0x40 /* encoding of load segment reg insns */
+#define Seg3ShortForm 0x80 /* fs/gs segment register insns. */
+#define Jump 0x100 /* special case for jump insns. */
+#define JumpInterSegment 0x200 /* special case for intersegment leaps/calls */
+ /* 0x400 CANNOT BE USED since it's already used by FloatD above */
+#define DONT_USE 0x400
+#define NoModrm 0x800
+#define Modrm 0x1000
+#define imulKludge 0x2000
+#define JumpByte 0x4000
+#define JumpDword 0x8000
+#define ReverseRegRegmem 0x10000
+
+ /* (opcode_modifier & COMES_IN_ALL_SIZES) is true if the
+ instuction comes in byte, word, and dword sizes and is encoded into
+ machine code in the canonical way. */
+#define COMES_IN_ALL_SIZES (W)
+
+ /* (opcode_modifier & COMES_IN_BOTH_DIRECTIONS) indicates that the
+ source and destination operands can be reversed by setting either
+ the D (for integer insns) or the FloatD (for floating insns) bit
+ in base_opcode. */
+#define COMES_IN_BOTH_DIRECTIONS (D|FloatD)
+
+ /* operand_types[i] describes the type of operand i. This is made
+ by OR'ing together all of the possible type masks. (e.g.
+ 'operand_types[i] = Reg|Imm' specifies that operand i can be
+ either a register or an immediate operand */
+ unsigned int operand_types[3];
+} template;
+
+/*
+ 'templates' is for grouping together 'template' structures for opcodes
+ of the same name. This is only used for storing the insns in the grand
+ ole hash table of insns.
+ The templates themselves start at START and range up to (but not including)
+ END.
+ */
+typedef struct {
+ template *start;
+ template *end;
+} templates;
+
+/* these are for register name --> number & type hash lookup */
+typedef struct {
+ char *reg_name;
+ unsigned int reg_type;
+ unsigned int reg_num;
+} reg_entry;
+
+typedef struct {
+ char *seg_name;
+ unsigned int seg_prefix;
+} seg_entry;
+
+/* these are for prefix name --> prefix code hash lookup */
+typedef struct {
+ char *prefix_name;
+ unsigned char prefix_code;
+} prefix_entry;
+
+/* 386 operand encoding bytes: see 386 book for details of this. */
+typedef struct {
+ unsigned regmem:3; /* codes register or memory operand */
+ unsigned reg:3; /* codes register operand (or extended opcode) */
+ unsigned mode:2; /* how to interpret regmem & reg */
+} modrm_byte;
+
+/* 386 opcode byte to code indirect addressing. */
+typedef struct {
+ unsigned base:3;
+ unsigned index:3;
+ unsigned scale:2;
+} base_index_byte;
+
+#endif /* TC_I386 */
+
+/* end of tc-i386.h */
diff --git a/gnu/usr.bin/as/config/tc-i860.c b/gnu/usr.bin/as/config/tc-i860.c
new file mode 100644
index 0000000..be2690d
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-i860.c
@@ -0,0 +1,1295 @@
+/* tc-i860.c -- Assemble for the I860
+ Copyright (C) 1989, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "as.h"
+
+#include "opcode/i860.h"
+
+void md_begin();
+void md_end();
+void md_number_to_chars();
+void md_assemble();
+char *md_atof();
+void md_convert_frag();
+void md_create_short_jump();
+void md_create_long_jump();
+int md_estimate_size_before_relax();
+void md_number_to_imm();
+void md_number_to_disp();
+void md_number_to_field();
+void md_ri_to_chars();
+static void i860_ip();
+
+const relax_typeS md_relax_table[] = { 0 };
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash = NULL;
+
+static void s_dual(), s_enddual();
+static void s_atmp();
+
+const pseudo_typeS
+ md_pseudo_table[] = {
+ { "dual", s_dual, 4 },
+ { "enddual", s_enddual, 4 },
+ { "atmp", s_atmp, 4 },
+ { NULL, 0, 0 },
+ };
+
+int md_short_jump_size = 4;
+int md_long_jump_size = 4;
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+char comment_chars[] = "!/"; /* JF removed '|' from comment_chars */
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments like this one will always work. */
+char line_comment_chars[] = "#/";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ */
+int size_reloc_info = sizeof(struct relocation_info);
+
+static unsigned char octal[256];
+#define isoctal(c) octal[c]
+ static unsigned char toHex[256];
+
+struct i860_it {
+ char *error;
+ unsigned long opcode;
+ struct nlist *nlistp;
+ expressionS exp;
+ int pcrel;
+ enum expand_type expand;
+ enum highlow_type highlow;
+ enum reloc_type reloc;
+} the_insn;
+
+#if __STDC__ == 1
+
+#ifdef comment
+static void print_insn(struct i860_it *insn);
+#endif /* comment */
+
+static int getExpression(char *str);
+
+#else /* not __STDC__ */
+
+#ifdef comment
+static void print_insn();
+#endif /* comment */
+
+static int getExpression();
+
+#endif /* not __STDC__ */
+
+static char *expr_end;
+static char last_expand; /* error if expansion after branch */
+
+enum dual
+{
+ DUAL_OFF = 0, DUAL_ON, DUAL_DDOT, DUAL_ONDDOT,
+};
+static enum dual dual_mode = DUAL_OFF; /* dual-instruction mode */
+
+static void
+ s_dual() /* floating point instructions have dual set */
+{
+ dual_mode = DUAL_ON;
+}
+
+static void
+ s_enddual() /* floating point instructions have dual set */
+{
+ dual_mode = DUAL_OFF;
+}
+
+static int atmp = 31; /* temporary register for pseudo's */
+
+static void
+ s_atmp()
+{
+ register int temp;
+ if (strncmp(input_line_pointer, "sp", 2) == 0) {
+ input_line_pointer += 2;
+ atmp = 2;
+ }
+ else if (strncmp(input_line_pointer, "fp", 2) == 0) {
+ input_line_pointer += 2;
+ atmp = 3;
+ }
+ else if (strncmp(input_line_pointer, "r", 1) == 0) {
+ input_line_pointer += 1;
+ temp = get_absolute_expression();
+ if (temp >= 0 && temp <= 31)
+ atmp = temp;
+ else
+ as_bad("Unknown temporary pseudo register");
+ }
+ else {
+ as_bad("Unknown temporary pseudo register");
+ }
+ demand_empty_rest_of_line();
+ return;
+}
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need. */
+void
+ md_begin()
+{
+ register char *retval = NULL;
+ int lose = 0;
+ register unsigned int i = 0;
+
+ op_hash = hash_new();
+ if (op_hash == NULL)
+ as_fatal("Virtual memory exhausted");
+
+ while (i < NUMOPCODES)
+ {
+ const char *name = i860_opcodes[i].name;
+ retval = hash_insert(op_hash, name, &i860_opcodes[i]);
+ if (retval != NULL && *retval != '\0')
+ {
+ fprintf (stderr, "internal error: can't hash `%s': %s\n",
+ i860_opcodes[i].name, retval);
+ lose = 1;
+ }
+ do
+ {
+ if (i860_opcodes[i].match & i860_opcodes[i].lose)
+ {
+ fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
+ i860_opcodes[i].name, i860_opcodes[i].args);
+ lose = 1;
+ }
+ ++i;
+ } while (i < NUMOPCODES
+ && !strcmp(i860_opcodes[i].name, name));
+ }
+
+ if (lose)
+ as_fatal("Broken assembler. No assembly attempted.");
+
+ for (i = '0'; i < '8'; ++i)
+ octal[i] = 1;
+ for (i = '0'; i <= '9'; ++i)
+ toHex[i] = i - '0';
+ for (i = 'a'; i <= 'f'; ++i)
+ toHex[i] = i + 10 - 'a';
+ for (i = 'A'; i <= 'F'; ++i)
+ toHex[i] = i + 10 - 'A';
+}
+
+void
+ md_end()
+{
+ return;
+}
+
+void
+ md_assemble(str)
+char *str;
+{
+ char *toP;
+/* int rsd; FIXME: remove this line. */
+ int no_opcodes = 1;
+ int i;
+ struct i860_it pseudo[3];
+
+ assert(str);
+ i860_ip(str);
+
+ /* check for expandable flag to produce pseudo-instructions */
+ if (the_insn.expand != 0 && the_insn.highlow == NO_SPEC) {
+ for (i = 0; i < 3; i++)
+ pseudo[i] = the_insn;
+
+ switch (the_insn.expand) {
+
+ case E_DELAY:
+ no_opcodes = 1;
+ break;
+
+ case E_MOV:
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_subtract_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 15) &&
+ the_insn.exp.X_add_number >= -(1 << 15)))
+ break;
+ /* or l%const,r0,ireg_dest */
+ pseudo[0].opcode = (the_insn.opcode & 0x001f0000) | 0xe4000000;
+ pseudo[0].highlow = PAIR;
+ /* orh h%const,ireg_dest,ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & 0x03ffffff) | 0xec000000 |
+ ((the_insn.opcode & 0x001f0000) << 5);
+ pseudo[1].highlow = HIGH;
+ no_opcodes = 2;
+ break;
+
+ case E_ADDR:
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_subtract_symbol == NULL)
+ break;
+ /* orh ha%addr_expr,r0,r31 */
+ pseudo[0].opcode = 0xec000000 | (atmp<<16);
+ pseudo[0].highlow = HIGHADJ;
+ pseudo[0].reloc = LOW0; /* must overwrite */
+ /* l%addr_expr(r31),ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & ~0x003e0000) | (atmp << 21);
+ pseudo[1].highlow = PAIR;
+ no_opcodes = 2;
+ break;
+
+ case E_U32: /* 2nd version emulates Intel as, not doc. */
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_subtract_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 16) &&
+ the_insn.exp.X_add_number >= 0))
+ break;
+ /* $(opcode)h h%const,ireg_src2,ireg_dest
+ pseudo[0].opcode = (the_insn.opcode & 0xf3ffffff) | 0x0c000000; */
+ /* $(opcode)h h%const,ireg_src2,r31 */
+ pseudo[0].opcode = (the_insn.opcode & 0xf3e0ffff) | 0x0c000000 |
+ (atmp << 16);
+ pseudo[0].highlow = HIGH;
+ /* $(opcode) l%const,ireg_dest,ireg_dest
+ pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 |
+ ((the_insn.opcode & 0x001f0000) << 5); */
+ /* $(opcode) l%const,r31,ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 |
+ (atmp << 21);
+ pseudo[1].highlow = PAIR;
+ no_opcodes = 2;
+ break;
+
+ case E_AND: /* 2nd version emulates Intel as, not doc. */
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_subtract_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 16) &&
+ the_insn.exp.X_add_number >= 0))
+ break;
+ /* andnot h%const,ireg_src2,ireg_dest
+ pseudo[0].opcode = (the_insn.opcode & 0x03ffffff) | 0xd4000000; */
+ /* andnot h%const,ireg_src2,r31 */
+ pseudo[0].opcode = (the_insn.opcode & 0x03e0ffff) | 0xd4000000 |
+ (atmp << 16);
+ pseudo[0].highlow = HIGH;
+ pseudo[0].exp.X_add_number = -1 - the_insn.exp.X_add_number;
+ /* andnot l%const,ireg_dest,ireg_dest
+ pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 |
+ ((the_insn.opcode & 0x001f0000) << 5); */
+ /* andnot l%const,r31,ireg_dest */
+ pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 |
+ (atmp << 21);
+ pseudo[1].highlow = PAIR;
+ pseudo[1].exp.X_add_number = -1 - the_insn.exp.X_add_number;
+ no_opcodes = 2;
+ break;
+
+ case E_S32:
+ if (the_insn.exp.X_add_symbol == NULL &&
+ the_insn.exp.X_subtract_symbol == NULL &&
+ (the_insn.exp.X_add_number < (1 << 15) &&
+ the_insn.exp.X_add_number >= -(1 << 15)))
+ break;
+ /* orh h%const,r0,r31 */
+ pseudo[0].opcode = 0xec000000 | (atmp << 16);
+ pseudo[0].highlow = HIGH;
+ /* or l%const,r31,r31 */
+ pseudo[1].opcode = 0xe4000000 | (atmp << 21) | (atmp << 16);
+ pseudo[1].highlow = PAIR;
+ /* r31,ireg_src2,ireg_dest */
+ pseudo[2].opcode = (the_insn.opcode & ~0x0400ffff) | (atmp << 11);
+ pseudo[2].reloc = NO_RELOC;
+ no_opcodes = 3;
+ break;
+
+ default:
+ as_fatal("failed sanity check.");
+ }
+
+ the_insn = pseudo[0];
+ /* check for expanded opcode after branch or in dual */
+ if (no_opcodes > 1 && last_expand == 1)
+ as_warn("Expanded opcode after delayed branch: `%s'", str);
+ if (no_opcodes > 1 && dual_mode != DUAL_OFF)
+ as_warn("Expanded opcode in dual mode: `%s'", str);
+ }
+
+ i = 0;
+ do { /* always produce at least one opcode */
+ toP = frag_more(4);
+ /* put out the opcode */
+ md_number_to_chars(toP, the_insn.opcode, 4);
+
+ /* check for expanded opcode after branch or in dual */
+ last_expand = the_insn.pcrel;
+
+ /* put out the symbol-dependent stuff */
+ if (the_insn.reloc != NO_RELOC) {
+ fix_new(frag_now, /* which frag */
+ (toP - frag_now->fr_literal), /* where */
+ 4, /* size */
+ the_insn.exp.X_add_symbol,
+ the_insn.exp.X_subtract_symbol,
+ the_insn.exp.X_add_number,
+ the_insn.pcrel,
+ /* merge bit fields into one argument */
+ (int)(((the_insn.highlow & 0x3) << 4) | (the_insn.reloc & 0xf)));
+ }
+ the_insn = pseudo[++i];
+ } while (--no_opcodes > 0);
+
+}
+
+static void
+ i860_ip(str)
+char *str;
+{
+ char *s;
+ const char *args;
+ char c;
+/* unsigned long i; FIXME: remove this line. */
+ struct i860_opcode *insn;
+ char *argsStart;
+ unsigned long opcode;
+ unsigned int mask;
+ int match = 0;
+ int comma = 0;
+
+
+ for (s = str; islower(*s) || *s == '.' || *s == '3'; ++s)
+ ;
+ switch (*s) {
+
+ case '\0':
+ break;
+
+ case ',':
+ comma = 1;
+
+ /*FALLTHROUGH*/
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ default:
+ as_bad("Unknown opcode: `%s'", str);
+ exit(1);
+ }
+
+ if (strncmp(str, "d.", 2) == 0) { /* check for d. opcode prefix */
+ if (dual_mode == DUAL_ON)
+ dual_mode = DUAL_ONDDOT;
+ else
+ dual_mode = DUAL_DDOT;
+ str += 2;
+ }
+
+ if ((insn = (struct i860_opcode *) hash_find(op_hash, str)) == NULL) {
+ if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT)
+ str -= 2;
+ as_bad("Unknown opcode: `%s'", str);
+ return;
+ }
+ if (comma) {
+ *--s = ',';
+ }
+ argsStart = s;
+ for (;;) {
+ opcode = insn->match;
+ memset(&the_insn, '\0', sizeof(the_insn));
+ the_insn.reloc = NO_RELOC;
+
+ /*
+ * Build the opcode, checking as we go to make
+ * sure that the operands match
+ */
+ for (args = insn->args; ; ++args) {
+ switch (*args) {
+
+ case '\0': /* end of args */
+ if (*s == '\0') {
+ match = 1;
+ }
+ break;
+
+ case '+':
+ case '(': /* these must match exactly */
+ case ')':
+ case ',':
+ case ' ':
+ if (*s++ == *args)
+ continue;
+ break;
+
+ case '#': /* must be at least one digit */
+ if (isdigit(*s++)) {
+ while (isdigit(*s)) {
+ ++s;
+ }
+ continue;
+ }
+ break;
+
+ case '1': /* next operand must be a register */
+ case '2':
+ case 'd':
+ switch (*s) {
+
+ case 'f': /* frame pointer */
+ s++;
+ if (*s++ == 'p') {
+ mask = 0x3;
+ break;
+ }
+ goto error;
+
+ case 's': /* stack pointer */
+ s++;
+ if (*s++ == 'p') {
+ mask= 0x2;
+ break;
+ }
+ goto error;
+
+ case 'r': /* any register */
+ s++;
+ if (!isdigit(c = *s++)) {
+ goto error;
+ }
+ if (isdigit(*s)) {
+ if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
+ goto error;
+ }
+ } else {
+ c -= '0';
+ }
+ mask= c;
+ break;
+
+ default: /* not this opcode */
+ goto error;
+ }
+ /*
+ * Got the register, now figure out where
+ * it goes in the opcode.
+ */
+ switch (*args) {
+
+ case '1':
+ opcode |= mask << 11;
+ continue;
+
+ case '2':
+ opcode |= mask << 21;
+ continue;
+
+ case 'd':
+ opcode |= mask << 16;
+ continue;
+
+ }
+ break;
+
+ case 'e': /* next operand is a floating point register */
+ case 'f':
+ case 'g':
+ if (*s++ == 'f' && isdigit(*s)) {
+ mask = *s++;
+ if (isdigit(*s)) {
+ mask = 10 * (mask - '0') + (*s++ - '0');
+ if (mask >= 32) {
+ break;
+ }
+ } else {
+ mask -= '0';
+ }
+ switch (*args) {
+
+ case 'e':
+ opcode |= mask << 11;
+ continue;
+
+ case 'f':
+ opcode |= mask << 21;
+ continue;
+
+ case 'g':
+ opcode |= mask << 16;
+ if (dual_mode != DUAL_OFF)
+ opcode |= (1 << 9); /* dual mode instruction */
+ if (dual_mode == DUAL_DDOT)
+ dual_mode = DUAL_OFF;
+ if (dual_mode == DUAL_ONDDOT)
+ dual_mode = DUAL_ON;
+ if ((opcode & (1 << 10)) && (mask == ((opcode >> 11) & 0x1f)))
+ as_warn("Fsr1 equals fdest with Pipelining");
+ continue;
+ }
+ }
+ break;
+
+ case 'c': /* next operand must be a control register */
+ if (strncmp(s, "fir", 3) == 0) {
+ opcode |= 0x0 << 21;
+ s += 3;
+ continue;
+ }
+ if (strncmp(s, "psr", 3) == 0) {
+ opcode |= 0x1 << 21;
+ s += 3;
+ continue;
+ }
+ if (strncmp(s, "dirbase", 7) == 0) {
+ opcode |= 0x2 << 21;
+ s += 7;
+ continue;
+ }
+ if (strncmp(s, "db", 2) == 0) {
+ opcode |= 0x3 << 21;
+ s += 2;
+ continue;
+ }
+ if (strncmp(s, "fsr", 3) == 0) {
+ opcode |= 0x4 << 21;
+ s += 3;
+ continue;
+ }
+ if (strncmp(s, "epsr", 4) == 0) {
+ opcode |= 0x5 << 21;
+ s += 4;
+ continue;
+ }
+ break;
+
+ case '5': /* 5 bit immediate in src1 */
+ memset(&the_insn, '\0', sizeof(the_insn));
+ if ( !getExpression(s)) {
+ s = expr_end;
+ if (the_insn.exp.X_add_number & ~0x1f)
+ as_bad("5-bit immediate too large");
+ opcode |= (the_insn.exp.X_add_number & 0x1f) << 11;
+ memset(&the_insn, '\0', sizeof(the_insn));
+ the_insn.reloc = NO_RELOC;
+ continue;
+ }
+ break;
+
+ case 'l': /* 26 bit immediate, relative branch */
+ the_insn.reloc = BRADDR;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 's': /* 16 bit immediate, split relative branch */
+ /* upper 5 bits of offset in dest field */
+ the_insn.pcrel = 1;
+ the_insn.reloc = SPLIT0;
+ goto immediate;
+
+ case 'S': /* 16 bit immediate, split (st), aligned */
+ if (opcode & (1 << 28))
+ if (opcode & 0x1)
+ the_insn.reloc = SPLIT2;
+ else
+ the_insn.reloc = SPLIT1;
+ else
+ the_insn.reloc = SPLIT0;
+ goto immediate;
+
+ case 'I': /* 16 bit immediate, aligned */
+ if (opcode & (1 << 28))
+ if (opcode & 0x1)
+ the_insn.reloc = LOW2;
+ else
+ the_insn.reloc = LOW1;
+ else
+ the_insn.reloc = LOW0;
+ goto immediate;
+
+ case 'i': /* 16 bit immediate */
+ the_insn.reloc = LOW0;
+
+ /*FALLTHROUGH*/
+
+ immediate:
+ if (*s == ' ')
+ s++;
+ if (strncmp(s, "ha%", 3) == 0) {
+ the_insn.highlow = HIGHADJ;
+ s += 3;
+ } else if (strncmp(s, "h%", 2) == 0) {
+ the_insn.highlow = HIGH;
+ s += 2;
+ } else if (strncmp(s, "l%", 2) == 0) {
+ the_insn.highlow = PAIR;
+ s += 2;
+ }
+ the_insn.expand = insn->expand;
+
+ /* Note that if the getExpression() fails, we will still have
+ created U entries in the symbol table for the 'symbols'
+ in the input string. Try not to create U symbols for
+ registers, etc. */
+
+ if ( !getExpression(s)) {
+ s = expr_end;
+ continue;
+ }
+ break;
+
+ default:
+ as_fatal("failed sanity check.");
+ }
+ break;
+ }
+ error:
+ if (match == 0)
+ {
+ /* Args don't match. */
+ if (&insn[1] - i860_opcodes < NUMOPCODES
+ && !strcmp(insn->name, insn[1].name))
+ {
+ ++insn;
+ s = argsStart;
+ continue;
+ }
+ else
+ {
+ as_bad("Illegal operands");
+ return;
+ }
+ }
+ break;
+ }
+
+ the_insn.opcode = opcode;
+ return;
+}
+
+static int
+ getExpression(str)
+char *str;
+{
+ char *save_in;
+ segT seg;
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ switch (seg = expression(&the_insn.exp)) {
+
+ case SEG_ABSOLUTE:
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ case SEG_BIG:
+ case SEG_ABSENT:
+ break;
+
+ default:
+ the_insn.error = "bad segment";
+ expr_end = input_line_pointer;
+ input_line_pointer=save_in;
+ return 1;
+ }
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+}
+
+
+/*
+ This is identical to the md_atof in m68k.c. I think this is right,
+ but I'm not sure.
+
+ Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *
+ md_atof(type,litP,sizeP)
+char type;
+char *litP;
+int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee();
+
+ switch (type) {
+
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to MD_ATOF()";
+ }
+ t=atof_ieee(input_line_pointer,type,words);
+ if (t)
+ input_line_pointer=t;
+ *sizeP=prec * sizeof(LITTLENUM_TYPE);
+ for (wordP=words;prec--;) {
+ md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
+ litP+=sizeof(LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+/*
+ * Write out big-endian.
+ */
+void
+ md_number_to_chars(buf, val, n)
+char *buf;
+long val;
+int n;
+{
+ switch (n) {
+
+ case 4:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ case 2:
+ *buf++ = val >> 8;
+ case 1:
+ *buf = val;
+ break;
+
+ default:
+ as_fatal("failed sanity check.");
+ }
+ return;
+}
+
+void md_number_to_imm(buf, val, n, fixP)
+char *buf;
+long val;
+int n;
+fixS *fixP;
+{
+ enum reloc_type reloc = fixP->fx_r_type & 0xf;
+ enum highlow_type highlow = (fixP->fx_r_type >> 4) & 0x3;
+
+ assert(buf);
+ assert(n == 4); /* always on i860 */
+
+ switch (highlow) {
+
+ case HIGHADJ: /* adjusts the high-order 16-bits */
+ if (val & (1 << 15))
+ val += (1 << 16);
+
+ /*FALLTHROUGH*/
+
+ case HIGH: /* selects the high-order 16-bits */
+ val >>= 16;
+ break;
+
+ case PAIR: /* selects the low-order 16-bits */
+ val = val & 0xffff;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (reloc) {
+
+ case BRADDR: /* br, call, bc, bc.t, bnc, bnc.t w/26-bit immediate */
+ if (fixP->fx_pcrel != 1)
+ as_bad("26-bit branch w/o pc relative set: 0x%08x", val);
+ val >>= 2; /* align pcrel offset, see manual */
+
+ if (val >= (1 << 25) || val < -(1 << 25)) /* check for overflow */
+ as_bad("26-bit branch offset overflow: 0x%08x", val);
+ buf[0] = (buf[0] & 0xfc) | ((val >> 24) & 0x3);
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case SPLIT2: /* 16 bit immediate, 4-byte aligned */
+ if (val & 0x3)
+ as_bad("16-bit immediate 4-byte alignment error: 0x%08x", val);
+ val &= ~0x3; /* 4-byte align value */
+ /*FALLTHROUGH*/
+ case SPLIT1: /* 16 bit immediate, 2-byte aligned */
+ if (val & 0x1)
+ as_bad("16-bit immediate 2-byte alignment error: 0x%08x", val);
+ val &= ~0x1; /* 2-byte align value */
+ /*FALLTHROUGH*/
+ case SPLIT0: /* st,bla,bte,btne w/16-bit immediate */
+ if (fixP->fx_pcrel == 1)
+ val >>= 2; /* align pcrel offset, see manual */
+ /* check for bounds */
+ if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15)))
+ as_bad("16-bit branch offset overflow: 0x%08x", val);
+ buf[1] = (buf[1] & ~0x1f) | ((val >> 11) & 0x1f);
+ buf[2] = (buf[2] & ~0x7) | ((val >> 8) & 0x7);
+ buf[3] |= val; /* perserve bottom opcode bits */
+ break;
+
+ case LOW4: /* fld,pfld,pst,flush 16-byte aligned */
+ if (val & 0xf)
+ as_bad("16-bit immediate 16-byte alignment error: 0x%08x", val);
+ val &= ~0xf; /* 16-byte align value */
+ /*FALLTHROUGH*/
+ case LOW3: /* fld,pfld,pst,flush 8-byte aligned */
+ if (val & 0x7)
+ as_bad("16-bit immediate 8-byte alignment error: 0x%08x", val);
+ val &= ~0x7; /* 8-byte align value */
+ /*FALLTHROUGH*/
+ case LOW2: /* 16 bit immediate, 4-byte aligned */
+ if (val & 0x3)
+ as_bad("16-bit immediate 4-byte alignment error: 0x%08x", val);
+ val &= ~0x3; /* 4-byte align value */
+ /*FALLTHROUGH*/
+ case LOW1: /* 16 bit immediate, 2-byte aligned */
+ if (val & 0x1)
+ as_bad("16-bit immediate 2-byte alignment error: 0x%08x", val);
+ val &= ~0x1; /* 2-byte align value */
+ /*FALLTHROUGH*/
+ case LOW0: /* 16 bit immediate, byte aligned */
+ /* check for bounds */
+ if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15)))
+ as_bad("16-bit immediate overflow: 0x%08x", val);
+ buf[2] = val >> 8;
+ buf[3] |= val; /* perserve bottom opcode bits */
+ break;
+
+ case RELOC_32:
+ md_number_to_chars(buf, val, 4);
+ break;
+
+ case NO_RELOC:
+ default:
+ as_bad("bad relocation type: 0x%02x", reloc);
+ break;
+ }
+ return;
+}
+
+/* should never be called for i860 */
+void
+ md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("i860_create_short_jmp\n");
+}
+
+/* should never be called for i860 */
+void
+ md_number_to_disp(buf, val, n)
+char *buf;
+long val;
+int n;
+{
+ as_fatal("md_number_to_disp\n");
+}
+
+/* should never be called for i860 */
+void
+ md_number_to_field(buf,val,fix)
+char *buf;
+long val;
+void *fix;
+{
+ as_fatal("i860_number_to_field\n");
+}
+
+/* the bit-field entries in the relocation_info struct plays hell
+ with the byte-order problems of cross-assembly. So as a hack,
+ I added this mach. dependent ri twiddler. Ugly, but it gets
+ you there. -KWK */
+/* on i860: first 4 bytes are normal unsigned long address, next three
+ bytes are index, most sig. byte first. Byte 7 is broken up with
+ bit 7 as pcrel, bit 6 as extern, and the lower six bits as
+ relocation type (highlow 5-4). Next 4 bytes are long addend. */
+/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
+void
+ md_ri_to_chars(ri_p, ri)
+struct relocation_info *ri_p, ri;
+{
+#if 0
+ unsigned char the_bytes[sizeof(*ri_p)];
+
+ /* this is easy */
+ md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address));
+ /* now the fun stuff */
+ the_bytes[4] = (ri.r_index >> 16) & 0x0ff;
+ the_bytes[5] = (ri.r_index >> 8) & 0x0ff;
+ the_bytes[6] = ri.r_index & 0x0ff;
+ the_bytes[7] = ((ri.r_extern << 7) & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F);
+ /* Also easy */
+ md_number_to_chars(&the_bytes[8], ri.r_addend, sizeof(ri.r_addend));
+ /* now put it back where you found it, Junior... */
+ memcpy((char *) ri_p, the_bytes, sizeof(*ri_p));
+#endif
+}
+
+/* should never be called for i860 */
+void
+ md_convert_frag(headers, fragP)
+object_headers *headers;
+register fragS *fragP;
+{
+ as_fatal("i860_convert_frag\n");
+}
+
+/* should never be called for i860 */
+void
+ md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr,
+ to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("i860_create_long_jump\n");
+}
+
+/* should never be called for i860 */
+int
+ md_estimate_size_before_relax(fragP, segtype)
+register fragS *fragP;
+segT segtype;
+{
+ as_fatal("i860_estimate_size_before_relax\n");
+ return(0);
+}
+
+#ifdef comment
+/* for debugging only, must match enum reloc_type */
+static char *Reloc[] = {
+ "NO_RELOC",
+ "BRADDR",
+ "LOW0",
+ "LOW1",
+ "LOW2",
+ "LOW3",
+ "LOW4",
+ "SPLIT0",
+ "SPLIT1",
+ "SPLIT2",
+ "RELOC_32",
+};
+static char *Highlow[] = {
+ "NO_SPEC",
+ "PAIR",
+ "HIGH",
+ "HIGHADJ",
+};
+
+static void
+ print_insn(insn)
+struct i860_it *insn;
+{
+ if (insn->error) {
+ fprintf(stderr, "ERROR: %s\n", insn->error);
+ }
+ fprintf(stderr, "opcode=0x%08x\t", insn->opcode);
+ fprintf(stderr, "expand=0x%08x\t", insn->expand);
+ fprintf(stderr, "reloc = %s\t", Reloc[insn->reloc]);
+ fprintf(stderr, "highlow = %s\n", Highlow[insn->highlow]);
+ fprintf(stderr, "exp = {\n");
+ fprintf(stderr, "\t\tX_add_symbol = %s\n",
+ insn->exp.X_add_symbol ?
+ (S_GET_NAME(insn->exp.X_add_symbol) ?
+ S_GET_NAME(insn->exp.X_add_symbol) : "???") : "0");
+ fprintf(stderr, "\t\tX_sub_symbol = %s\n",
+ insn->exp.X_subtract_symbol ?
+ (S_GET_NAME(insn->exp.X_subtract_symbol) ?
+ S_GET_NAME(insn->exp.X_subtract_symbol) : "???") : "0");
+ fprintf(stderr, "\t\tX_add_number = %d\n",
+ insn->exp.X_add_number);
+ fprintf(stderr, "}\n");
+ return;
+}
+#endif /* comment */
+
+int
+ md_parse_option(argP,cntP,vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ return 0;
+}
+
+#ifdef comment
+/*
+ * I860 relocations are completely different, so it needs
+ * this machine dependent routine to emit them.
+ */
+void
+ emit_machine_reloc(fixP, segment_address_in_file)
+register fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ struct reloc_info_i860 ri;
+ register symbolS *symbolP;
+ extern char *next_object_file_charP;
+ long add_number;
+
+ memset((char *) &ri, '\0', sizeof(ri));
+ for (; fixP; fixP = fixP->fx_next) {
+
+ if (fixP->fx_r_type & ~0x3f) {
+ as_fatal("fixP->fx_r_type = %d\n", fixP->fx_r_type);
+ }
+ ri.r_pcrel = fixP->fx_pcrel;
+ ri.r_type = fixP->fx_r_type;
+
+ if ((symbolP = fixP->fx_addsy) != NULL) {
+ ri.r_address = fixP->fx_frag->fr_address +
+ fixP->fx_where - segment_address_in_file;
+ if (!S_IS_DEFINED(symbolP)) {
+ ri.r_extern = 1;
+ ri.r_symbolnum = symbolP->sy_number;
+ } else {
+ ri.r_extern = 0;
+ ri.r_symbolnum = S_GET_TYPE(symbolP);
+ }
+ if (symbolP && symbolP->sy_frag) {
+ ri.r_addend = symbolP->sy_frag->fr_address;
+ }
+ ri.r_type = fixP->fx_r_type;
+ if (fixP->fx_pcrel) {
+ /* preserve actual offset vs. pc + 4 */
+ ri.r_addend -= (ri.r_address + 4);
+ } else {
+ ri.r_addend = fixP->fx_addnumber;
+ }
+
+ md_ri_to_chars((char *) &ri, ri);
+ append(&next_object_file_charP, (char *)& ri, sizeof(ri));
+ }
+ }
+ return;
+}
+#endif /* comment */
+
+#ifdef OBJ_AOUT
+
+/* on i860: first 4 bytes are normal unsigned long address, next three
+ bytes are index, most sig. byte first. Byte 7 is broken up with
+ bit 7 as pcrel, bit 6 as extern, and the lower six bits as
+ relocation type (highlow 5-4). Next 4 bytes are long addend.
+
+ ie,
+
+ struct reloc_info_i860 {
+ unsigned long r_address;
+ unsigned int r_symbolnum : 24;
+ unsigned int r_pcrel : 1;
+ unsigned int r_extern : 1;
+ unsigned int r_type : 6;
+ long r_addend;
+ }
+
+ */
+
+const int md_reloc_size = 12;
+
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ long r_index;
+ long r_extern;
+ long r_addend = 0;
+ long r_address;
+
+ know(fixP->fx_addsy);
+ know(!(fixP->fx_r_type & ~0x3f));
+
+ if (!S_IS_DEFINED(fixP->fx_addsy)) {
+ r_extern = 1;
+ r_index = fixP->fx_addsy->sy_number;
+ } else {
+ r_extern = 0;
+ r_index = S_GET_TYPE(fixP->fx_addsy);
+ }
+
+ md_number_to_chars(where,
+ r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ where[4] = (r_index >> 16) & 0x0ff;
+ where[5] = (r_index >> 8) & 0x0ff;
+ where[6] = r_index & 0x0ff;
+ where[7] = (((fixP->fx_pcrel << 7) & 0x80)
+ | ((r_extern << 6) & 0x40)
+ | (fixP->fx_r_type & 0x3F));
+
+ if (fixP->fx_addsy->sy_frag) {
+ r_addend = fixP->fx_addsy->sy_frag->fr_address;
+ }
+
+ if (fixP->fx_pcrel) {
+ /* preserve actual offset vs. pc + 4 */
+ r_addend -= (r_address + 4);
+ } else {
+ r_addend = fixP->fx_addnumber;
+ }
+
+ md_number_to_chars(&where[8], r_addend, 4);
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+#endif /* OBJ_AOUT */
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void
+ md_operand (expressionP)
+expressionS *expressionP;
+{
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+ md_undefined_symbol (name)
+char *name;
+{
+ return 0;
+}
+
+/* Round up a section size to the appropriate boundary. */
+long
+ md_section_align (segment, size)
+segT segment;
+long size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the i860, they're relative to the address of the offset, plus
+ its size. (??? Is this right? FIXME-SOON!) */
+long
+ md_pcrel_from (fixP)
+fixS *fixP;
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+void
+ md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ /* fixme-soon: looks to me like i860 never has bit fixes. Let's see. xoxorich. */
+ know(fixP->fx_bit_fixP == NULL);
+ if (!fixP->fx_bit_fixP) {
+
+ /* fixme-soon: also looks like fx_im_disp is always 0. Let's see. xoxorich. */
+ know(fixP->fx_im_disp == 0);
+ switch (fixP->fx_im_disp) {
+ case 0:
+ fixP->fx_addnumber = val;
+ md_number_to_imm(place, val, fixP->fx_size, fixP);
+ break;
+ case 1:
+ md_number_to_disp(place,
+ fixP->fx_pcrel ? val + fixP->fx_pcrel_adjust : val,
+ fixP->fx_size);
+ break;
+ case 2: /* fix requested for .long .word etc */
+ md_number_to_chars(place, val, fixP->fx_size);
+ break;
+ default:
+ as_fatal("Internal error in md_apply_fix() in file \"%s\"", __FILE__);
+ } /* OVE: maybe one ought to put _imm _disp _chars in one md-func */
+ } else {
+ md_number_to_field(place, val, fixP->fx_bit_fixP);
+ }
+
+ return;
+} /* md_apply_fix() */
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * comment-column: 0
+ * End:
+ */
+
+/* end of tc-i860.c */
diff --git a/gnu/usr.bin/as/config/tc-i860.h b/gnu/usr.bin/as/config/tc-i860.h
new file mode 100644
index 0000000..adc0d8f
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-i860.h
@@ -0,0 +1,24 @@
+/*
+ * This file is tc-i860.h.
+ */
+
+#define TC_I860 1
+
+#define NO_LISTING
+
+#ifdef OLD_GAS
+#define REVERSE_SORT_RELOCS
+#endif /* OLD_GAS */
+
+#define tc_headers_hook(a) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-i860.h */
diff --git a/gnu/usr.bin/as/config/tc-i960.c b/gnu/usr.bin/as/config/tc-i960.c
new file mode 100644
index 0000000..5a3c8ca
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-i960.c
@@ -0,0 +1,2759 @@
+/* tc-i960.c - All the i80960-specific stuff
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* See comment on md_parse_option for 80960-specific invocation options. */
+
+/******************************************************************************
+ * i80690 NOTE!!!:
+ * Header, symbol, and relocation info will be used on the host machine
+ * only -- only executable code is actually downloaded to the i80960.
+ * Therefore, leave all such information in host byte order.
+ *
+ * (That's a slight lie -- we DO download some header information, but
+ * the downloader converts the file format and corrects the byte-ordering
+ * of the relevant fields while doing so.)
+ *
+ ***************************************************************************** */
+
+/* There are 4 different lengths of (potentially) symbol-based displacements
+ * in the 80960 instruction set, each of which could require address fix-ups
+ * and (in the case of external symbols) emission of relocation directives:
+ *
+ * 32-bit (MEMB)
+ * This is a standard length for the base assembler and requires no
+ * special action.
+ *
+ * 13-bit (COBR)
+ * This is a non-standard length, but the base assembler has a hook for
+ * bit field address fixups: the fixS structure can point to a descriptor
+ * of the field, in which case our md_number_to_field() routine gets called
+ * to process it.
+ *
+ * I made the hook a little cleaner by having fix_new() (in the base
+ * assembler) return a pointer to the fixS in question. And I made it a
+ * little simpler by storing the field size (in this case 13) instead of
+ * of a pointer to another structure: 80960 displacements are ALWAYS
+ * stored in the low-order bits of a 4-byte word.
+ *
+ * Since the target of a COBR cannot be external, no relocation directives
+ * for this size displacement have to be generated. But the base assembler
+ * had to be modified to issue error messages if the symbol did turn out
+ * to be external.
+ *
+ * 24-bit (CTRL)
+ * Fixups are handled as for the 13-bit case (except that 24 is stored
+ * in the fixS).
+ *
+ * The relocation directive generated is the same as that for the 32-bit
+ * displacement, except that it's PC-relative (the 32-bit displacement
+ * never is). The i80960 version of the linker needs a mod to
+ * distinguish and handle the 24-bit case.
+ *
+ * 12-bit (MEMA)
+ * MEMA formats are always promoted to MEMB (32-bit) if the displacement
+ * is based on a symbol, because it could be relocated at link time.
+ * The only time we use the 12-bit format is if an absolute value of
+ * less than 4096 is specified, in which case we need neither a fixup nor
+ * a relocation directive.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "as.h"
+
+#include "obstack.h"
+
+#include "opcode/i960.h"
+
+extern char *input_line_pointer;
+extern struct hash_control *po_hash;
+extern char *next_object_file_charP;
+
+#ifdef OBJ_COFF
+const int md_reloc_size = sizeof(struct reloc);
+#else /* OBJ_COFF */
+const int md_reloc_size = sizeof(struct relocation_info);
+#endif /* OBJ_COFF */
+
+/***************************
+ * Local i80960 routines *
+ ************************** */
+
+static void brcnt_emit(); /* Emit branch-prediction instrumentation code */
+static char * brlab_next(); /* Return next branch local label */
+void brtab_emit(); /* Emit br-predict instrumentation table */
+static void cobr_fmt(); /* Generate COBR instruction */
+static void ctrl_fmt(); /* Generate CTRL instruction */
+static char * emit(); /* Emit (internally) binary */
+static int get_args(); /* Break arguments out of comma-separated list */
+static void get_cdisp(); /* Handle COBR or CTRL displacement */
+static char * get_ispec(); /* Find index specification string */
+static int get_regnum(); /* Translate text to register number */
+static int i_scan(); /* Lexical scan of instruction source */
+static void mem_fmt(); /* Generate MEMA or MEMB instruction */
+static void mema_to_memb(); /* Convert MEMA instruction to MEMB format */
+static segT parse_expr(); /* Parse an expression */
+static int parse_ldconst();/* Parse and replace a 'ldconst' pseudo-op */
+static void parse_memop(); /* Parse a memory operand */
+static void parse_po(); /* Parse machine-dependent pseudo-op */
+static void parse_regop(); /* Parse a register operand */
+static void reg_fmt(); /* Generate a REG format instruction */
+void reloc_callj(); /* Relocate a 'callj' instruction */
+static void relax_cobr(); /* "De-optimize" cobr into compare/branch */
+static void s_leafproc(); /* Process '.leafproc' pseudo-op */
+static void s_sysproc(); /* Process '.sysproc' pseudo-op */
+static int shift_ok(); /* Will a 'shlo' substiture for a 'ldconst'? */
+static void syntax(); /* Give syntax error */
+static int targ_has_sfr(); /* Target chip supports spec-func register? */
+static int targ_has_iclass();/* Target chip supports instruction set? */
+/* static void unlink_sym(); */ /* Remove a symbol from the symbol list */
+
+/* See md_parse_option() for meanings of these options */
+static char norelax = 0; /* True if -norelax switch seen */
+static char instrument_branches = 0; /* True if -b switch seen */
+
+/* Characters that always start a comment.
+ * If the pre-processor is disabled, these aren't very useful.
+ */
+char comment_chars[] = "#";
+
+/* Characters that only start a comment at the beginning of
+ * a line. If the line seems to have the form '# 123 filename'
+ * .line and .file directives will appear in the pre-processed output.
+ *
+ * Note that input_file.c hand checks for '#' at the beginning of the
+ * first line of the input file. This is because the compiler outputs
+ * #NO_APP at the beginning of its output.
+ */
+
+/* Also note that comments started like this one will always work. */
+
+char line_comment_chars[] = "";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant,
+ * as in 0f12.456 or 0d1.2345e12
+ */
+char FLT_CHARS[] = "fFdDtT";
+
+
+/* Table used by base assembler to relax addresses based on varying length
+ * instructions. The fields are:
+ * 1) most positive reach of this state,
+ * 2) most negative reach of this state,
+ * 3) how many bytes this mode will add to the size of the current frag
+ * 4) which index into the table to try if we can't fit into this one.
+ *
+ * For i80960, the only application is the (de-)optimization of cobr
+ * instructions into separate compare and branch instructions when a 13-bit
+ * displacement won't hack it.
+ */
+const relax_typeS
+ md_relax_table[] = {
+ {0, 0, 0,0}, /* State 0 => no more relaxation possible */
+ {4088, -4096, 0,2}, /* State 1: conditional branch (cobr) */
+ {0x800000-8,-0x800000,4,0}, /* State 2: compare (reg) & branch (ctrl) */
+ };
+
+
+/* These are the machine dependent pseudo-ops.
+ *
+ * This table describes all the machine specific pseudo-ops the assembler
+ * has to support. The fields are:
+ * pseudo-op name without dot
+ * function to call to execute this pseudo-op
+ * integer arg to pass to the function
+ */
+#define S_LEAFPROC 1
+#define S_SYSPROC 2
+
+const pseudo_typeS
+ md_pseudo_table[] = {
+
+ { "bss", s_lcomm, 1 },
+ { "extended", float_cons, 't' },
+ { "leafproc", parse_po, S_LEAFPROC },
+ { "sysproc", parse_po, S_SYSPROC },
+
+ { "word", cons, 4 },
+ { "quad", big_cons, 16 },
+
+ { 0, 0, 0 }
+ };
+
+/* Macros to extract info from an 'expressionS' structure 'e' */
+#define adds(e) e.X_add_symbol
+#define subs(e) e.X_subtract_symbol
+#define offs(e) e.X_add_number
+#define segs(e) e.X_seg
+
+
+ /* Branch-prediction bits for CTRL/COBR format opcodes */
+#define BP_MASK 0x00000002 /* Mask for branch-prediction bit */
+#define BP_TAKEN 0x00000000 /* Value to OR in to predict branch */
+#define BP_NOT_TAKEN 0x00000002 /* Value to OR in to predict no branch */
+
+
+ /* Some instruction opcodes that we need explicitly */
+#define BE 0x12000000
+#define BG 0x11000000
+#define BGE 0x13000000
+#define BL 0x14000000
+#define BLE 0x16000000
+#define BNE 0x15000000
+#define BNO 0x10000000
+#define BO 0x17000000
+#define CHKBIT 0x5a002700
+#define CMPI 0x5a002080
+#define CMPO 0x5a002000
+
+#define B 0x08000000
+#define BAL 0x0b000000
+#define CALL 0x09000000
+#define CALLS 0x66003800
+#define RET 0x0a000000
+
+
+ /* These masks are used to build up a set of MEMB mode bits. */
+#define A_BIT 0x0400
+#define I_BIT 0x0800
+#define MEMB_BIT 0x1000
+#define D_BIT 0x2000
+
+
+ /* Mask for the only mode bit in a MEMA instruction (if set, abase reg is used) */
+#define MEMA_ABASE 0x2000
+
+ /* Info from which a MEMA or MEMB format instruction can be generated */
+ typedef struct {
+ long opcode; /* (First) 32 bits of instruction */
+ int disp; /* 0-(none), 12- or, 32-bit displacement needed */
+ char *e; /* The expression in the source instruction from
+ * which the displacement should be determined
+ */
+ } memS;
+
+
+/* The two pieces of info we need to generate a register operand */
+struct regop {
+ int mode; /* 0 =>local/global/spec reg; 1=> literal or fp reg */
+ int special; /* 0 =>not a sfr; 1=> is a sfr (not valid w/mode=0) */
+ int n; /* Register number or literal value */
+};
+
+
+/* Number and assembler mnemonic for all registers that can appear in operands */
+static struct {
+ char *reg_name;
+ int reg_num;
+} regnames[] = {
+ { "pfp", 0 }, { "sp", 1 }, { "rip", 2 }, { "r3", 3 },
+ { "r4", 4 }, { "r5", 5 }, { "r6", 6 }, { "r7", 7 },
+ { "r8", 8 }, { "r9", 9 }, { "r10", 10 }, { "r11", 11 },
+ { "r12", 12 }, { "r13", 13 }, { "r14", 14 }, { "r15", 15 },
+ { "g0", 16 }, { "g1", 17 }, { "g2", 18 }, { "g3", 19 },
+ { "g4", 20 }, { "g5", 21 }, { "g6", 22 }, { "g7", 23 },
+ { "g8", 24 }, { "g9", 25 }, { "g10", 26 }, { "g11", 27 },
+ { "g12", 28 }, { "g13", 29 }, { "g14", 30 }, { "fp", 31 },
+
+ /* Numbers for special-function registers are for assembler internal
+ * use only: they are scaled back to range [0-31] for binary output.
+ */
+# define SF0 32
+
+ { "sf0", 32 }, { "sf1", 33 }, { "sf2", 34 }, { "sf3", 35 },
+ { "sf4", 36 }, { "sf5", 37 }, { "sf6", 38 }, { "sf7", 39 },
+ { "sf8", 40 }, { "sf9", 41 }, { "sf10",42 }, { "sf11",43 },
+ { "sf12",44 }, { "sf13",45 }, { "sf14",46 }, { "sf15",47 },
+ { "sf16",48 }, { "sf17",49 }, { "sf18",50 }, { "sf19",51 },
+ { "sf20",52 }, { "sf21",53 }, { "sf22",54 }, { "sf23",55 },
+ { "sf24",56 }, { "sf25",57 }, { "sf26",58 }, { "sf27",59 },
+ { "sf28",60 }, { "sf29",61 }, { "sf30",62 }, { "sf31",63 },
+
+ /* Numbers for floating point registers are for assembler internal use
+ * only: they are scaled back to [0-3] for binary output.
+ */
+# define FP0 64
+
+ { "fp0", 64 }, { "fp1", 65 }, { "fp2", 66 }, { "fp3", 67 },
+
+ { NULL, 0 }, /* END OF LIST */
+};
+
+#define IS_RG_REG(n) ((0 <= (n)) && ((n) < SF0))
+#define IS_SF_REG(n) ((SF0 <= (n)) && ((n) < FP0))
+#define IS_FP_REG(n) ((n) >= FP0)
+
+/* Number and assembler mnemonic for all registers that can appear as 'abase'
+ * (indirect addressing) registers.
+ */
+static struct {
+ char *areg_name;
+ int areg_num;
+} aregs[] = {
+ { "(pfp)", 0 }, { "(sp)", 1 }, { "(rip)", 2 }, { "(r3)", 3 },
+ { "(r4)", 4 }, { "(r5)", 5 }, { "(r6)", 6 }, { "(r7)", 7 },
+ { "(r8)", 8 }, { "(r9)", 9 }, { "(r10)", 10 }, { "(r11)", 11 },
+ { "(r12)", 12 }, { "(r13)", 13 }, { "(r14)", 14 }, { "(r15)", 15 },
+ { "(g0)", 16 }, { "(g1)", 17 }, { "(g2)", 18 }, { "(g3)", 19 },
+ { "(g4)", 20 }, { "(g5)", 21 }, { "(g6)", 22 }, { "(g7)", 23 },
+ { "(g8)", 24 }, { "(g9)", 25 }, { "(g10)", 26 }, { "(g11)", 27 },
+ { "(g12)", 28 }, { "(g13)", 29 }, { "(g14)", 30 }, { "(fp)", 31 },
+
+# define IPREL 32
+ /* for assembler internal use only: this number never appears in binary
+ * output.
+ */
+ { "(ip)", IPREL },
+
+ { NULL, 0 }, /* END OF LIST */
+};
+
+
+/* Hash tables */
+static struct hash_control *op_hash = NULL; /* Opcode mnemonics */
+static struct hash_control *reg_hash = NULL; /* Register name hash table */
+static struct hash_control *areg_hash = NULL; /* Abase register hash table */
+
+
+/* Architecture for which we are assembling */
+#define ARCH_ANY 0 /* Default: no architecture checking done */
+#define ARCH_KA 1
+#define ARCH_KB 2
+#define ARCH_MC 3
+#define ARCH_CA 4
+int architecture = ARCH_ANY; /* Architecture requested on invocation line */
+int iclasses_seen = 0; /* OR of instruction classes (I_* constants)
+ * for which we've actually assembled
+ * instructions.
+ */
+
+
+/* BRANCH-PREDICTION INSTRUMENTATION
+ *
+ * The following supports generation of branch-prediction instrumentation
+ * (turned on by -b switch). The instrumentation collects counts
+ * of branches taken/not-taken for later input to a utility that will
+ * set the branch prediction bits of the instructions in accordance with
+ * the behavior observed. (Note that the KX series does not have
+ * brach-prediction.)
+ *
+ * The instrumentation consists of:
+ *
+ * (1) before and after each conditional branch, a call to an external
+ * routine that increments and steps over an inline counter. The
+ * counter itself, initialized to 0, immediately follows the call
+ * instruction. For each branch, the counter following the branch
+ * is the number of times the branch was not taken, and the difference
+ * between the counters is the number of times it was taken. An
+ * example of an instrumented conditional branch:
+ *
+ * call BR_CNT_FUNC
+ * .word 0
+ * LBRANCH23: be label
+ * call BR_CNT_FUNC
+ * .word 0
+ *
+ * (2) a table of pointers to the instrumented branches, so that an
+ * external postprocessing routine can locate all of the counters.
+ * the table begins with a 2-word header: a pointer to the next in
+ * a linked list of such tables (initialized to 0); and a count
+ * of the number of entries in the table (exclusive of the header.
+ *
+ * Note that input source code is expected to already contain calls
+ * an external routine that will link the branch local table into a
+ * list of such tables.
+ */
+
+static int br_cnt = 0; /* Number of branches instrumented so far.
+ * Also used to generate unique local labels
+ * for each instrumented branch
+ */
+
+#define BR_LABEL_BASE "LBRANCH"
+/* Basename of local labels on instrumented
+ * branches, to avoid conflict with compiler-
+ * generated local labels.
+ */
+
+#define BR_CNT_FUNC "__inc_branch"
+/* Name of the external routine that will
+ * increment (and step over) an inline counter.
+ */
+
+#define BR_TAB_NAME "__BRANCH_TABLE__"
+/* Name of the table of pointers to branches.
+ * A local (i.e., non-external) symbol.
+ */
+
+/*****************************************************************************
+ * md_begin: One-time initialization.
+ *
+ * Set up hash tables.
+ *
+ **************************************************************************** */
+void
+ md_begin()
+{
+ int i; /* Loop counter */
+ const struct i960_opcode *oP; /* Pointer into opcode table */
+ char *retval; /* Value returned by hash functions */
+
+ if (((op_hash = hash_new()) == 0)
+ || ((reg_hash = hash_new()) == 0)
+ || ((areg_hash = hash_new()) == 0)) {
+ as_fatal("virtual memory exceeded");
+ }
+
+ retval = ""; /* For some reason, the base assembler uses an empty
+ * string for "no error message", instead of a NULL
+ * pointer.
+ */
+
+ for (oP=i960_opcodes; oP->name && !*retval; oP++) {
+ retval = hash_insert(op_hash, oP->name, oP);
+ }
+
+ for (i=0; regnames[i].reg_name && !*retval; i++) {
+ retval = hash_insert(reg_hash, regnames[i].reg_name,
+ &regnames[i].reg_num);
+ }
+
+ for (i=0; aregs[i].areg_name && !*retval; i++){
+ retval = hash_insert(areg_hash, aregs[i].areg_name,
+ &aregs[i].areg_num);
+ }
+
+ if (*retval) {
+ as_fatal("Hashing returned \"%s\".", retval);
+ }
+} /* md_begin() */
+
+/*****************************************************************************
+ * md_end: One-time final cleanup
+ *
+ * None necessary
+ *
+ **************************************************************************** */
+void
+ md_end()
+{
+}
+
+/*****************************************************************************
+ * md_assemble: Assemble an instruction
+ *
+ * Assumptions about the passed-in text:
+ * - all comments, labels removed
+ * - text is an instruction
+ * - all white space compressed to single blanks
+ * - all character constants have been replaced with decimal
+ *
+ **************************************************************************** */
+void
+ md_assemble(textP)
+char *textP; /* Source text of instruction */
+{
+ char *args[4]; /* Parsed instruction text, containing NO whitespace:
+ * arg[0]->opcode mnemonic
+ * arg[1-3]->operands, with char constants
+ * replaced by decimal numbers
+ */
+ int n_ops; /* Number of instruction operands */
+
+ struct i960_opcode *oP;
+ /* Pointer to instruction description */
+ int branch_predict;
+ /* TRUE iff opcode mnemonic included branch-prediction
+ * suffix (".f" or ".t")
+ */
+ long bp_bits; /* Setting of branch-prediction bit(s) to be OR'd
+ * into instruction opcode of CTRL/COBR format
+ * instructions.
+ */
+ int n; /* Offset of last character in opcode mnemonic */
+
+ static const char bp_error_msg[] = "branch prediction invalid on this opcode";
+
+
+ /* Parse instruction into opcode and operands */
+ memset(args, '\0', sizeof(args));
+ n_ops = i_scan(textP, args);
+ if (n_ops == -1){
+ return; /* Error message already issued */
+ }
+
+ /* Do "macro substitution" (sort of) on 'ldconst' pseudo-instruction */
+ if (!strcmp(args[0],"ldconst")){
+ n_ops = parse_ldconst(args);
+ if (n_ops == -1){
+ return;
+ }
+ }
+
+ /* Check for branch-prediction suffix on opcode mnemonic, strip it off */
+ n = strlen(args[0]) - 1;
+ branch_predict = 0;
+ bp_bits = 0;
+ if (args[0][n-1] == '.' && (args[0][n] == 't' || args[0][n] == 'f')){
+ /* We could check here to see if the target architecture
+ * supports branch prediction, but why bother? The bit
+ * will just be ignored by processors that don't use it.
+ */
+ branch_predict = 1;
+ bp_bits = (args[0][n] == 't') ? BP_TAKEN : BP_NOT_TAKEN;
+ args[0][n-1] = '\0'; /* Strip suffix from opcode mnemonic */
+ }
+
+ /* Look up opcode mnemonic in table and check number of operands.
+ * Check that opcode is legal for the target architecture.
+ * If all looks good, assemble instruction.
+ */
+ oP = (struct i960_opcode *) hash_find(op_hash, args[0]);
+ if (!oP || !targ_has_iclass(oP->iclass)) {
+ as_bad("invalid opcode, \"%s\".", args[0]);
+
+ } else if (n_ops != oP->num_ops) {
+ as_bad("improper number of operands. expecting %d, got %d", oP->num_ops, n_ops);
+
+ } else {
+ switch (oP->format){
+ case FBRA:
+ case CTRL:
+ ctrl_fmt(args[1], oP->opcode | bp_bits, oP->num_ops);
+ if (oP->format == FBRA){
+ /* Now generate a 'bno' to same arg */
+ ctrl_fmt(args[1], BNO | bp_bits, 1);
+ }
+ break;
+ case COBR:
+ case COJ:
+ cobr_fmt(args, oP->opcode | bp_bits, oP);
+ break;
+ case REG:
+ if (branch_predict){
+ as_warn(bp_error_msg);
+ }
+ reg_fmt(args, oP);
+ break;
+ case MEM1:
+ case MEM2:
+ case MEM4:
+ case MEM8:
+ case MEM12:
+ case MEM16:
+ if (branch_predict){
+ as_warn(bp_error_msg);
+ }
+ mem_fmt(args, oP);
+ break;
+ case CALLJ:
+ if (branch_predict){
+ as_warn(bp_error_msg);
+ }
+ /* Output opcode & set up "fixup" (relocation);
+ * flag relocation as 'callj' type.
+ */
+ know(oP->num_ops == 1);
+ get_cdisp(args[1], "CTRL", oP->opcode, 24, 0, 1);
+ break;
+ default:
+ BAD_CASE(oP->format);
+ break;
+ }
+ }
+} /* md_assemble() */
+
+/*****************************************************************************
+ * md_number_to_chars: convert a number to target byte order
+ *
+ **************************************************************************** */
+void
+ md_number_to_chars(buf, value, n)
+char *buf; /* Put output here */
+long value; /* The integer to be converted */
+int n; /* Number of bytes to output (significant bytes
+ * in 'value')
+ */
+{
+ while (n--){
+ *buf++ = value;
+ value >>= 8;
+ }
+
+ /* XXX line number probably botched for this warning message. */
+ if (value != 0 && value != -1){
+ as_bad("Displacement too long for instruction field length.");
+ }
+
+ return;
+} /* md_number_to_chars() */
+
+/*****************************************************************************
+ * md_chars_to_number: convert from target byte order to host byte order.
+ *
+ **************************************************************************** */
+int
+ md_chars_to_number(val, n)
+unsigned char *val; /* Value in target byte order */
+int n; /* Number of bytes in the input */
+{
+ int retval;
+
+ for (retval=0; n--;){
+ retval <<= 8;
+ retval |= val[n];
+ }
+ return retval;
+}
+
+
+#define MAX_LITTLENUMS 6
+#define LNUM_SIZE sizeof(LITTLENUM_TYPE)
+
+/*****************************************************************************
+ * md_atof: convert ascii to floating point
+ *
+ * Turn a string at input_line_pointer into a floating point constant of type
+ * 'type', and store the appropriate bytes at *litP. The number of LITTLENUMS
+ * emitted is returned at 'sizeP'. An error message is returned, or a pointer
+ * to an empty message if OK.
+ *
+ * Note we call the i386 floating point routine, rather than complicating
+ * things with more files or symbolic links.
+ *
+ **************************************************************************** */
+char * md_atof(type, litP, sizeP)
+int type;
+char *litP;
+int *sizeP;
+{
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ int prec;
+ char *t;
+ char *atof_ieee();
+
+ switch (type) {
+ case 'f':
+ case 'F':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ prec = 4;
+ break;
+
+ case 't':
+ case 'T':
+ prec = 5;
+ type = 'x'; /* That's what atof_ieee() understands */
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to md_atof()";
+ }
+
+ t = atof_ieee(input_line_pointer, type, words);
+ if (t){
+ input_line_pointer = t;
+ }
+
+ *sizeP = prec * LNUM_SIZE;
+
+ /* Output the LITTLENUMs in REVERSE order in accord with i80960
+ * word-order. (Dunno why atof_ieee doesn't do it in the right
+ * order in the first place -- probably because it's a hack of
+ * atof_m68k.)
+ */
+
+ for (wordP = words + prec - 1; prec--;){
+ md_number_to_chars(litP, (long) (*wordP--), LNUM_SIZE);
+ litP += sizeof(LITTLENUM_TYPE);
+ }
+
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+
+/*****************************************************************************
+ * md_number_to_imm
+ *
+ **************************************************************************** */
+void
+ md_number_to_imm(buf, val, n)
+char *buf;
+long val;
+int n;
+{
+ md_number_to_chars(buf, val, n);
+}
+
+
+/*****************************************************************************
+ * md_number_to_disp
+ *
+ **************************************************************************** */
+void
+ md_number_to_disp(buf, val, n)
+char *buf;
+long val;
+int n;
+{
+ md_number_to_chars(buf, val, n);
+}
+
+/*****************************************************************************
+ * md_number_to_field:
+ *
+ * Stick a value (an address fixup) into a bit field of
+ * previously-generated instruction.
+ *
+ **************************************************************************** */
+void
+ md_number_to_field(instrP, val, bfixP)
+char *instrP; /* Pointer to instruction to be fixed */
+long val; /* Address fixup value */
+bit_fixS *bfixP; /* Description of bit field to be fixed up */
+{
+ int numbits; /* Length of bit field to be fixed */
+ long instr; /* 32-bit instruction to be fixed-up */
+ long sign; /* 0 or -1, according to sign bit of 'val' */
+
+ /* Convert instruction back to host byte order
+ */
+ instr = md_chars_to_number(instrP, 4);
+
+ /* Surprise! -- we stored the number of bits
+ * to be modified rather than a pointer to a structure.
+ */
+ numbits = (int)bfixP;
+ if (numbits == 1){
+ /* This is a no-op, stuck here by reloc_callj() */
+ return;
+ }
+
+ know ((numbits == 13) || (numbits == 24));
+
+ /* Propagate sign bit of 'val' for the given number of bits.
+ * Result should be all 0 or all 1
+ */
+ sign = val >> ((int)numbits - 1);
+ if (((val < 0) && (sign != -1))
+ || ((val > 0) && (sign != 0))){
+ as_bad("Fixup of %d too large for field width of %d",
+ val, numbits);
+ } else {
+ /* Put bit field into instruction and write back in target
+ * byte order.
+ */
+ val &= ~(-1 << (int)numbits); /* Clear unused sign bits */
+ instr |= val;
+ md_number_to_chars(instrP, instr, 4);
+ }
+} /* md_number_to_field() */
+
+
+/*****************************************************************************
+ * md_parse_option
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option. For the 960, these are:
+ *
+ * -norelax:
+ * Conditional branch instructions that require displacements
+ * greater than 13 bits (or that have external targets) should
+ * generate errors. The default is to replace each such
+ * instruction with the corresponding compare (or chkbit) and
+ * branch instructions. Note that the Intel "j" cobr directives
+ * are ALWAYS "de-optimized" in this way when necessary,
+ * regardless of the setting of this option.
+ *
+ * -b:
+ * Add code to collect information about branches taken, for
+ * later optimization of branch prediction bits by a separate
+ * tool. COBR and CNTL format instructions have branch
+ * prediction bits (in the CX architecture); if "BR" represents
+ * an instruction in one of these classes, the following rep-
+ * resents the code generated by the assembler:
+ *
+ * call <increment routine>
+ * .word 0 # pre-counter
+ * Label: BR
+ * call <increment routine>
+ * .word 0 # post-counter
+ *
+ * A table of all such "Labels" is also generated.
+ *
+ *
+ * -AKA, -AKB, -AKC, -ASA, -ASB, -AMC, -ACA:
+ * Select the 80960 architecture. Instructions or features not
+ * supported by the selected architecture cause fatal errors.
+ * The default is to generate code for any instruction or feature
+ * that is supported by SOME version of the 960 (even if this
+ * means mixing architectures!).
+ *
+ **************************************************************************** */
+int
+ md_parse_option(argP, cntP, vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ char *p;
+ struct tabentry { char *flag; int arch; };
+ static struct tabentry arch_tab[] = {
+ "KA", ARCH_KA,
+ "KB", ARCH_KB,
+ "SA", ARCH_KA, /* Synonym for KA */
+ "SB", ARCH_KB, /* Synonym for KB */
+ "KC", ARCH_MC, /* Synonym for MC */
+ "MC", ARCH_MC,
+ "CA", ARCH_CA,
+ NULL, 0
+ };
+ struct tabentry *tp;
+
+ if (!strcmp(*argP,"norelax")){
+ norelax = 1;
+
+ } else if (**argP == 'b'){
+ instrument_branches = 1;
+
+ } else if (**argP == 'A'){
+ p = (*argP) + 1;
+
+ for (tp = arch_tab; tp->flag != NULL; tp++){
+ if (!strcmp(p,tp->flag)){
+ break;
+ }
+ }
+
+ if (tp->flag == NULL){
+ as_bad("unknown architecture: %s", p);
+ } else {
+ architecture = tp->arch;
+ }
+ } else {
+ /* Unknown option */
+ (*argP)++;
+ return 0;
+ }
+ **argP = '\0'; /* Done parsing this switch */
+ return 1;
+}
+
+/*****************************************************************************
+ * md_convert_frag:
+ * Called by base assembler after address relaxation is finished: modify
+ * variable fragments according to how much relaxation was done.
+ *
+ * If the fragment substate is still 1, a 13-bit displacement was enough
+ * to reach the symbol in question. Set up an address fixup, but otherwise
+ * leave the cobr instruction alone.
+ *
+ * If the fragment substate is 2, a 13-bit displacement was not enough.
+ * Replace the cobr with a two instructions (a compare and a branch).
+ *
+ **************************************************************************** */
+void
+ md_convert_frag(headers, fragP)
+object_headers *headers;
+fragS * fragP;
+{
+ fixS *fixP; /* Structure describing needed address fix */
+
+ switch (fragP->fr_subtype){
+ case 1:
+ /* LEAVE SINGLE COBR INSTRUCTION */
+ fixP = fix_new(fragP,
+ fragP->fr_opcode-fragP->fr_literal,
+ 4,
+ fragP->fr_symbol,
+ 0,
+ fragP->fr_offset,
+ 1,
+ 0);
+
+ fixP->fx_bit_fixP = (bit_fixS *) 13; /* size of bit field */
+ break;
+ case 2:
+ /* REPLACE COBR WITH COMPARE/BRANCH INSTRUCTIONS */
+ relax_cobr(fragP);
+ break;
+ default:
+ BAD_CASE(fragP->fr_subtype);
+ break;
+ }
+}
+
+/*****************************************************************************
+ * md_estimate_size_before_relax: How much does it look like *fragP will grow?
+ *
+ * Called by base assembler just before address relaxation.
+ * Return the amount by which the fragment will grow.
+ *
+ * Any symbol that is now undefined will not become defined; cobr's
+ * based on undefined symbols will have to be replaced with a compare
+ * instruction and a branch instruction, and the code fragment will grow
+ * by 4 bytes.
+ *
+ **************************************************************************** */
+int
+ md_estimate_size_before_relax(fragP, segment_type)
+register fragS *fragP;
+register segT segment_type;
+{
+ /* If symbol is undefined in this segment, go to "relaxed" state
+ * (compare and branch instructions instead of cobr) right now.
+ */
+ if (S_GET_SEGMENT(fragP->fr_symbol) != segment_type) {
+ relax_cobr(fragP);
+ return 4;
+ }
+ return 0;
+} /* md_estimate_size_before_relax() */
+
+
+/*****************************************************************************
+ * md_ri_to_chars:
+ * This routine exists in order to overcome machine byte-order problems
+ * when dealing with bit-field entries in the relocation_info struct.
+ *
+ * But relocation info will be used on the host machine only (only
+ * executable code is actually downloaded to the i80960). Therefore,
+ * we leave it in host byte order.
+ *
+ **************************************************************************** */
+void md_ri_to_chars(where, ri)
+char *where;
+struct relocation_info *ri;
+{
+ *((struct relocation_info *) where) = *ri; /* structure assignment */
+} /* md_ri_to_chars() */
+
+#ifndef WORKING_DOT_WORD
+
+int md_short_jump_size = 0;
+int md_long_jump_size = 0;
+
+void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr;
+long to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("failed sanity check.");
+}
+
+void
+ md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("failed sanity check.");
+}
+#endif
+
+/*************************************************************
+ * *
+ * FOLLOWING ARE THE LOCAL ROUTINES, IN ALPHABETICAL ORDER *
+ * *
+ ************************************************************ */
+
+
+
+/*****************************************************************************
+ * brcnt_emit: Emit code to increment inline branch counter.
+ *
+ * See the comments above the declaration of 'br_cnt' for details on
+ * branch-prediction instrumentation.
+ **************************************************************************** */
+static void
+ brcnt_emit()
+{
+ ctrl_fmt(BR_CNT_FUNC,CALL,1);/* Emit call to "increment" routine */
+ emit(0); /* Emit inline counter to be incremented */
+}
+
+/*****************************************************************************
+ * brlab_next: generate the next branch local label
+ *
+ * See the comments above the declaration of 'br_cnt' for details on
+ * branch-prediction instrumentation.
+ **************************************************************************** */
+static char *
+ brlab_next()
+{
+ static char buf[20];
+
+ sprintf(buf, "%s%d", BR_LABEL_BASE, br_cnt++);
+ return buf;
+}
+
+/*****************************************************************************
+ * brtab_emit: generate the fetch-prediction branch table.
+ *
+ * See the comments above the declaration of 'br_cnt' for details on
+ * branch-prediction instrumentation.
+ *
+ * The code emitted here would be functionally equivalent to the following
+ * example assembler source.
+ *
+ * .data
+ * .align 2
+ * BR_TAB_NAME:
+ * .word 0 # link to next table
+ * .word 3 # length of table
+ * .word LBRANCH0 # 1st entry in table proper
+ * .word LBRANCH1
+ * .word LBRANCH2
+ ***************************************************************************** */
+void
+ brtab_emit()
+{
+ int i;
+ char buf[20];
+ char *p; /* Where the binary was output to */
+ fixS *fixP; /*->description of deferred address fixup */
+
+ if (!instrument_branches){
+ return;
+ }
+
+ subseg_new(SEG_DATA,0); /* .data */
+ frag_align(2,0); /* .align 2 */
+ record_alignment(now_seg,2);
+ colon(BR_TAB_NAME); /* BR_TAB_NAME: */
+ emit(0); /* .word 0 #link to next table */
+ emit(br_cnt); /* .word n #length of table */
+
+ for (i=0; i<br_cnt; i++){
+ sprintf(buf, "%s%d", BR_LABEL_BASE, i);
+ p = emit(0);
+ fixP = fix_new(frag_now,
+ p - frag_now->fr_literal,
+ 4,
+ symbol_find(buf),
+ 0,
+ 0,
+ 0,
+ 0);
+ fixP->fx_im_disp = 2; /* 32-bit displacement fix */
+ }
+}
+
+/*****************************************************************************
+ * cobr_fmt: generate a COBR-format instruction
+ *
+ **************************************************************************** */
+static
+ void
+ cobr_fmt(arg, opcode, oP)
+char *arg[]; /* arg[0]->opcode mnemonic, arg[1-3]->operands (ascii) */
+long opcode; /* Opcode, with branch-prediction bits already set
+ * if necessary.
+ */
+struct i960_opcode *oP;
+/*->description of instruction */
+{
+ long instr; /* 32-bit instruction */
+ struct regop regop; /* Description of register operand */
+ int n; /* Number of operands */
+ int var_frag; /* 1 if varying length code fragment should
+ * be emitted; 0 if an address fix
+ * should be emitted.
+ */
+
+ instr = opcode;
+ n = oP->num_ops;
+
+ if (n >= 1) {
+ /* First operand (if any) of a COBR is always a register
+ * operand. Parse it.
+ */
+ parse_regop(&regop, arg[1], oP->operand[0]);
+ instr |= (regop.n << 19) | (regop.mode << 13);
+ }
+ if (n >= 2) {
+ /* Second operand (if any) of a COBR is always a register
+ * operand. Parse it.
+ */
+ parse_regop(&regop, arg[2], oP->operand[1]);
+ instr |= (regop.n << 14) | regop.special;
+ }
+
+
+ if (n < 3){
+ emit(instr);
+
+ } else {
+ if (instrument_branches){
+ brcnt_emit();
+ colon(brlab_next());
+ }
+
+ /* A third operand to a COBR is always a displacement.
+ * Parse it; if it's relaxable (a cobr "j" directive, or any
+ * cobr other than bbs/bbc when the "-norelax" option is not in
+ * use) set up a variable code fragment; otherwise set up an
+ * address fix.
+ */
+ var_frag = !norelax || (oP->format == COJ); /* TRUE or FALSE */
+ get_cdisp(arg[3], "COBR", instr, 13, var_frag, 0);
+
+ if (instrument_branches){
+ brcnt_emit();
+ }
+ }
+} /* cobr_fmt() */
+
+
+/*****************************************************************************
+ * ctrl_fmt: generate a CTRL-format instruction
+ *
+ **************************************************************************** */
+static
+ void
+ ctrl_fmt(targP, opcode, num_ops)
+char *targP; /* Pointer to text of lone operand (if any) */
+long opcode; /* Template of instruction */
+int num_ops; /* Number of operands */
+{
+ int instrument; /* TRUE iff we should add instrumentation to track
+ * how often the branch is taken
+ */
+
+
+ if (num_ops == 0){
+ emit(opcode); /* Output opcode */
+ } else {
+
+ instrument = instrument_branches && (opcode != CALL)
+ && (opcode != B) && (opcode != RET) && (opcode != BAL);
+
+ if (instrument){
+ brcnt_emit();
+ colon(brlab_next());
+ }
+
+ /* The operand MUST be an ip-relative displacment. Parse it
+ * and set up address fix for the instruction we just output.
+ */
+ get_cdisp(targP, "CTRL", opcode, 24, 0, 0);
+
+ if (instrument){
+ brcnt_emit();
+ }
+ }
+
+}
+
+
+/*****************************************************************************
+ * emit: output instruction binary
+ *
+ * Output instruction binary, in target byte order, 4 bytes at a time.
+ * Return pointer to where it was placed.
+ *
+ **************************************************************************** */
+static
+ char *
+ emit(instr)
+long instr; /* Word to be output, host byte order */
+{
+ char *toP; /* Where to output it */
+
+ toP = frag_more(4); /* Allocate storage */
+ md_number_to_chars(toP, instr, 4); /* Convert to target byte order */
+ return toP;
+}
+
+
+/*****************************************************************************
+ * get_args: break individual arguments out of comma-separated list
+ *
+ * Input assumptions:
+ * - all comments and labels have been removed
+ * - all strings of whitespace have been collapsed to a single blank.
+ * - all character constants ('x') have been replaced with decimal
+ *
+ * Output:
+ * args[0] is untouched. args[1] points to first operand, etc. All args:
+ * - are NULL-terminated
+ * - contain no whitespace
+ *
+ * Return value:
+ * Number of operands (0,1,2, or 3) or -1 on error.
+ *
+ **************************************************************************** */
+static int get_args(p, args)
+register char *p; /* Pointer to comma-separated operands; MUCKED BY US */
+char *args[]; /* Output arg: pointers to operands placed in args[1-3].
+ * MUST ACCOMMODATE 4 ENTRIES (args[0-3]).
+ */
+{
+ register int n; /* Number of operands */
+ register char *to;
+ /* char buf[4]; */
+ /* int len; */
+
+
+ /* Skip lead white space */
+ while (*p == ' '){
+ p++;
+ }
+
+ if (*p == '\0'){
+ return 0;
+ }
+
+ n = 1;
+ args[1] = p;
+
+ /* Squeze blanks out by moving non-blanks toward start of string.
+ * Isolate operands, whenever comma is found.
+ */
+ to = p;
+ while (*p != '\0'){
+
+ if (*p == ' '){
+ p++;
+
+ } else if (*p == ','){
+
+ /* Start of operand */
+ if (n == 3){
+ as_bad("too many operands");
+ return -1;
+ }
+ *to++ = '\0'; /* Terminate argument */
+ args[++n] = to; /* Start next argument */
+ p++;
+
+ } else {
+ *to++ = *p++;
+ }
+ }
+ *to = '\0';
+ return n;
+}
+
+
+/*****************************************************************************
+ * get_cdisp: handle displacement for a COBR or CTRL instruction.
+ *
+ * Parse displacement for a COBR or CTRL instruction.
+ *
+ * If successful, output the instruction opcode and set up for it,
+ * depending on the arg 'var_frag', either:
+ * o an address fixup to be done when all symbol values are known, or
+ * o a varying length code fragment, with address fixup info. This
+ * will be done for cobr instructions that may have to be relaxed
+ * in to compare/branch instructions (8 bytes) if the final address
+ * displacement is greater than 13 bits.
+ *
+ **************************************************************************** */
+static
+ void
+ get_cdisp(dispP, ifmtP, instr, numbits, var_frag, callj)
+char *dispP; /*->displacement as specified in source instruction */
+char *ifmtP; /*->"COBR" or "CTRL" (for use in error message) */
+long instr; /* Instruction needing the displacement */
+int numbits; /* # bits of displacement (13 for COBR, 24 for CTRL) */
+int var_frag; /* 1 if varying length code fragment should be emitted;
+ * 0 if an address fix should be emitted.
+ */
+int callj; /* 1 if callj relocation should be done; else 0 */
+{
+ expressionS e; /* Parsed expression */
+ fixS *fixP; /* Structure describing needed address fix */
+ char *outP; /* Where instruction binary is output to */
+
+ fixP = NULL;
+
+ switch (parse_expr(dispP,&e)) {
+
+ case SEG_GOOF:
+ as_bad("expression syntax error");
+ break;
+
+ case SEG_TEXT:
+ case SEG_UNKNOWN:
+ if (var_frag) {
+ outP = frag_more(8); /* Allocate worst-case storage */
+ md_number_to_chars(outP, instr, 4);
+ frag_variant(rs_machine_dependent, 4, 4, 1,
+ adds(e), offs(e), outP, 0, 0);
+ } else {
+ /* Set up a new fix structure, so address can be updated
+ * when all symbol values are known.
+ */
+ outP = emit(instr);
+ fixP = fix_new(frag_now,
+ outP - frag_now->fr_literal,
+ 4,
+ adds(e),
+ 0,
+ offs(e),
+ 1,
+ 0);
+
+ fixP->fx_callj = callj;
+
+ /* We want to modify a bit field when the address is
+ * known. But we don't need all the garbage in the
+ * bit_fix structure. So we're going to lie and store
+ * the number of bits affected instead of a pointer.
+ */
+ fixP->fx_bit_fixP = (bit_fixS *) numbits;
+ }
+ break;
+
+ case SEG_DATA:
+ case SEG_BSS:
+ as_bad("attempt to branch into different segment");
+ break;
+
+ default:
+ as_bad("target of %s instruction must be a label", ifmtP);
+ break;
+ }
+}
+
+
+/*****************************************************************************
+ * get_ispec: parse a memory operand for an index specification
+ *
+ * Here, an "index specification" is taken to be anything surrounded
+ * by square brackets and NOT followed by anything else.
+ *
+ * If it's found, detach it from the input string, remove the surrounding
+ * square brackets, and return a pointer to it. Otherwise, return NULL.
+ *
+ **************************************************************************** */
+static
+ char *
+ get_ispec(textP)
+char *textP; /*->memory operand from source instruction, no white space */
+{
+ char *start; /*->start of index specification */
+ char *end; /*->end of index specification */
+
+ /* Find opening square bracket, if any
+ */
+ start = strchr(textP, '[');
+
+ if (start != NULL){
+
+ /* Eliminate '[', detach from rest of operand */
+ *start++ = '\0';
+
+ end = strchr(start, ']');
+
+ if (end == NULL){
+ as_bad("unmatched '['");
+
+ } else {
+ /* Eliminate ']' and make sure it was the last thing
+ * in the string.
+ */
+ *end = '\0';
+ if (*(end+1) != '\0'){
+ as_bad("garbage after index spec ignored");
+ }
+ }
+ }
+ return start;
+}
+
+/*****************************************************************************
+ * get_regnum:
+ *
+ * Look up a (suspected) register name in the register table and return the
+ * associated register number (or -1 if not found).
+ *
+ **************************************************************************** */
+static
+ int
+ get_regnum(regname)
+char *regname; /* Suspected register name */
+{
+ int *rP;
+
+ rP = (int *) hash_find(reg_hash, regname);
+ return (rP == NULL) ? -1 : *rP;
+}
+
+
+/*****************************************************************************
+ * i_scan: perform lexical scan of ascii assembler instruction.
+ *
+ * Input assumptions:
+ * - input string is an i80960 instruction (not a pseudo-op)
+ * - all comments and labels have been removed
+ * - all strings of whitespace have been collapsed to a single blank.
+ *
+ * Output:
+ * args[0] points to opcode, other entries point to operands. All strings:
+ * - are NULL-terminated
+ * - contain no whitespace
+ * - have character constants ('x') replaced with a decimal number
+ *
+ * Return value:
+ * Number of operands (0,1,2, or 3) or -1 on error.
+ *
+ **************************************************************************** */
+static int i_scan(iP, args)
+register char *iP; /* Pointer to ascii instruction; MUCKED BY US. */
+char *args[]; /* Output arg: pointers to opcode and operands placed
+ * here. MUST ACCOMMODATE 4 ENTRIES.
+ */
+{
+
+ /* Isolate opcode */
+ if (*(iP) == ' ') {
+ iP++;
+ } /* Skip lead space, if any */
+ args[0] = iP;
+ for (; *iP != ' '; iP++) {
+ if (*iP == '\0') {
+ /* There are no operands */
+ if (args[0] == iP) {
+ /* We never moved: there was no opcode either! */
+ as_bad("missing opcode");
+ return -1;
+ }
+ return 0;
+ }
+ }
+ *iP++ = '\0'; /* Terminate opcode */
+ return(get_args(iP, args));
+} /* i_scan() */
+
+
+/*****************************************************************************
+ * mem_fmt: generate a MEMA- or MEMB-format instruction
+ *
+ **************************************************************************** */
+static void mem_fmt(args, oP)
+char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */
+struct i960_opcode *oP; /* Pointer to description of instruction */
+{
+ int i; /* Loop counter */
+ struct regop regop; /* Description of register operand */
+ char opdesc; /* Operand descriptor byte */
+ memS instr; /* Description of binary to be output */
+ char *outP; /* Where the binary was output to */
+ expressionS expr; /* Parsed expression */
+ fixS *fixP; /*->description of deferred address fixup */
+
+ memset(&instr, '\0', sizeof(memS));
+ instr.opcode = oP->opcode;
+
+ /* Process operands. */
+ for (i = 1; i <= oP->num_ops; i++){
+ opdesc = oP->operand[i-1];
+
+ if (MEMOP(opdesc)){
+ parse_memop(&instr, args[i], oP->format);
+ } else {
+ parse_regop(&regop, args[i], opdesc);
+ instr.opcode |= regop.n << 19;
+ }
+ }
+
+ /* Output opcode */
+ outP = emit(instr.opcode);
+
+ if (instr.disp == 0){
+ return;
+ }
+
+ /* Parse and process the displacement */
+ switch (parse_expr(instr.e,&expr)){
+
+ case SEG_GOOF:
+ as_bad("expression syntax error");
+ break;
+
+ case SEG_ABSOLUTE:
+ if (instr.disp == 32){
+ (void) emit(offs(expr)); /* Output displacement */
+ } else {
+ /* 12-bit displacement */
+ if (offs(expr) & ~0xfff){
+ /* Won't fit in 12 bits: convert already-output
+ * instruction to MEMB format, output
+ * displacement.
+ */
+ mema_to_memb(outP);
+ (void) emit(offs(expr));
+ } else {
+ /* WILL fit in 12 bits: OR into opcode and
+ * overwrite the binary we already put out
+ */
+ instr.opcode |= offs(expr);
+ md_number_to_chars(outP, instr.opcode, 4);
+ }
+ }
+ break;
+
+ case SEG_DIFFERENCE:
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_UNKNOWN:
+ if (instr.disp == 12){
+ /* Displacement is dependent on a symbol, whose value
+ * may change at link time. We HAVE to reserve 32 bits.
+ * Convert already-output opcode to MEMB format.
+ */
+ mema_to_memb(outP);
+ }
+
+ /* Output 0 displacement and set up address fixup for when
+ * this symbol's value becomes known.
+ */
+ outP = emit((long) 0);
+ fixP = fix_new(frag_now,
+ outP - frag_now->fr_literal,
+ 4,
+ adds(expr),
+ subs(expr),
+ offs(expr),
+ 0,
+ 0);
+ fixP->fx_im_disp = 2; /* 32-bit displacement fix */
+ break;
+
+ default:
+ BAD_CASE(segs(expr));
+ break;
+ }
+} /* memfmt() */
+
+
+/*****************************************************************************
+ * mema_to_memb: convert a MEMA-format opcode to a MEMB-format opcode.
+ *
+ * There are 2 possible MEMA formats:
+ * - displacement only
+ * - displacement + abase
+ *
+ * They are distinguished by the setting of the MEMA_ABASE bit.
+ *
+ **************************************************************************** */
+static void mema_to_memb(opcodeP)
+char *opcodeP; /* Where to find the opcode, in target byte order */
+{
+ long opcode; /* Opcode in host byte order */
+ long mode; /* Mode bits for MEMB instruction */
+
+ opcode = md_chars_to_number(opcodeP, 4);
+ know(!(opcode & MEMB_BIT));
+
+ mode = MEMB_BIT | D_BIT;
+ if (opcode & MEMA_ABASE){
+ mode |= A_BIT;
+ }
+
+ opcode &= 0xffffc000; /* Clear MEMA offset and mode bits */
+ opcode |= mode; /* Set MEMB mode bits */
+
+ md_number_to_chars(opcodeP, opcode, 4);
+} /* mema_to_memb() */
+
+
+/*****************************************************************************
+ * parse_expr: parse an expression
+ *
+ * Use base assembler's expression parser to parse an expression.
+ * It, unfortunately, runs off a global which we have to save/restore
+ * in order to make it work for us.
+ *
+ * An empty expression string is treated as an absolute 0.
+ *
+ * Return "segment" to which the expression evaluates.
+ * Return SEG_GOOF regardless of expression evaluation if entire input
+ * string is not consumed in the evaluation -- tolerate no dangling junk!
+ *
+ **************************************************************************** */
+static
+ segT
+ parse_expr(textP, expP)
+char *textP; /* Text of expression to be parsed */
+expressionS *expP; /* Where to put the results of parsing */
+{
+ char *save_in; /* Save global here */
+ segT seg; /* Segment to which expression evaluates */
+ symbolS *symP;
+
+ know(textP);
+
+ if (*textP == '\0') {
+ /* Treat empty string as absolute 0 */
+ expP->X_add_symbol = expP->X_subtract_symbol = NULL;
+ expP->X_add_number = 0;
+ seg = expP->X_seg = SEG_ABSOLUTE;
+
+ } else {
+ save_in = input_line_pointer; /* Save global */
+ input_line_pointer = textP; /* Make parser work for us */
+
+ seg = expression(expP);
+ if (input_line_pointer - textP != strlen(textP)) {
+ /* Did not consume all of the input */
+ seg = SEG_GOOF;
+ }
+ symP = expP->X_add_symbol;
+ if (symP && (hash_find(reg_hash, S_GET_NAME(symP)))) {
+ /* Register name in an expression */
+ seg = SEG_GOOF;
+ }
+
+ input_line_pointer = save_in; /* Restore global */
+ }
+ return seg;
+}
+
+
+/*****************************************************************************
+ * parse_ldcont:
+ * Parse and replace a 'ldconst' pseudo-instruction with an appropriate
+ * i80960 instruction.
+ *
+ * Assumes the input consists of:
+ * arg[0] opcode mnemonic ('ldconst')
+ * arg[1] first operand (constant)
+ * arg[2] name of register to be loaded
+ *
+ * Replaces opcode and/or operands as appropriate.
+ *
+ * Returns the new number of arguments, or -1 on failure.
+ *
+ **************************************************************************** */
+static
+ int
+ parse_ldconst(arg)
+char *arg[]; /* See above */
+{
+ int n; /* Constant to be loaded */
+ int shift; /* Shift count for "shlo" instruction */
+ static char buf[5]; /* Literal for first operand */
+ static char buf2[5]; /* Literal for second operand */
+ expressionS e; /* Parsed expression */
+
+
+ arg[3] = NULL; /* So we can tell at the end if it got used or not */
+
+ switch (parse_expr(arg[1],&e)){
+
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ /* We're dependent on one or more symbols -- use "lda" */
+ arg[0] = "lda";
+ break;
+
+ case SEG_ABSOLUTE:
+ /* Try the following mappings:
+ * ldconst 0,<reg> ->mov 0,<reg>
+ * ldconst 31,<reg> ->mov 31,<reg>
+ * ldconst 32,<reg> ->addo 1,31,<reg>
+ * ldconst 62,<reg> ->addo 31,31,<reg>
+ * ldconst 64,<reg> ->shlo 8,3,<reg>
+ * ldconst -1,<reg> ->subo 1,0,<reg>
+ * ldconst -31,<reg>->subo 31,0,<reg>
+ *
+ * anthing else becomes:
+ * lda xxx,<reg>
+ */
+ n = offs(e);
+ if ((0 <= n) && (n <= 31)){
+ arg[0] = "mov";
+
+ } else if ((-31 <= n) && (n <= -1)){
+ arg[0] = "subo";
+ arg[3] = arg[2];
+ sprintf(buf, "%d", -n);
+ arg[1] = buf;
+ arg[2] = "0";
+
+ } else if ((32 <= n) && (n <= 62)){
+ arg[0] = "addo";
+ arg[3] = arg[2];
+ arg[1] = "31";
+ sprintf(buf, "%d", n-31);
+ arg[2] = buf;
+
+ } else if ((shift = shift_ok(n)) != 0){
+ arg[0] = "shlo";
+ arg[3] = arg[2];
+ sprintf(buf, "%d", shift);
+ arg[1] = buf;
+ sprintf(buf2, "%d", n >> shift);
+ arg[2] = buf2;
+
+ } else {
+ arg[0] = "lda";
+ }
+ break;
+
+ default:
+ as_bad("invalid constant");
+ return -1;
+ break;
+ }
+ return (arg[3] == 0) ? 2: 3;
+}
+
+/*****************************************************************************
+ * parse_memop: parse a memory operand
+ *
+ * This routine is based on the observation that the 4 mode bits of the
+ * MEMB format, taken individually, have fairly consistent meaning:
+ *
+ * M3 (bit 13): 1 if displacement is present (D_BIT)
+ * M2 (bit 12): 1 for MEMB instructions (MEMB_BIT)
+ * M1 (bit 11): 1 if index is present (I_BIT)
+ * M0 (bit 10): 1 if abase is present (A_BIT)
+ *
+ * So we parse the memory operand and set bits in the mode as we find
+ * things. Then at the end, if we go to MEMB format, we need only set
+ * the MEMB bit (M2) and our mode is built for us.
+ *
+ * Unfortunately, I said "fairly consistent". The exceptions:
+ *
+ * DBIA
+ * 0100 Would seem illegal, but means "abase-only".
+ *
+ * 0101 Would seem to mean "abase-only" -- it means IP-relative.
+ * Must be converted to 0100.
+ *
+ * 0110 Would seem to mean "index-only", but is reserved.
+ * We turn on the D bit and provide a 0 displacement.
+ *
+ * The other thing to observe is that we parse from the right, peeling
+ * things * off as we go: first any index spec, then any abase, then
+ * the displacement.
+ *
+ **************************************************************************** */
+static
+ void
+ parse_memop(memP, argP, optype)
+memS *memP; /* Where to put the results */
+char *argP; /* Text of the operand to be parsed */
+int optype; /* MEM1, MEM2, MEM4, MEM8, MEM12, or MEM16 */
+{
+ char *indexP; /* Pointer to index specification with "[]" removed */
+ char *p; /* Temp char pointer */
+ char iprel_flag;/* True if this is an IP-relative operand */
+ int regnum; /* Register number */
+ int scale; /* Scale factor: 1,2,4,8, or 16. Later converted
+ * to internal format (0,1,2,3,4 respectively).
+ */
+ int mode; /* MEMB mode bits */
+ int *intP; /* Pointer to register number */
+
+ /* The following table contains the default scale factors for each
+ * type of memory instruction. It is accessed using (optype-MEM1)
+ * as an index -- thus it assumes the 'optype' constants are assigned
+ * consecutive values, in the order they appear in this table
+ */
+ static int def_scale[] = {
+ 1, /* MEM1 */
+ 2, /* MEM2 */
+ 4, /* MEM4 */
+ 8, /* MEM8 */
+ -1, /* MEM12 -- no valid default */
+ 16 /* MEM16 */
+ };
+
+
+ iprel_flag = mode = 0;
+
+ /* Any index present? */
+ indexP = get_ispec(argP);
+ if (indexP) {
+ p = strchr(indexP, '*');
+ if (p == NULL) {
+ /* No explicit scale -- use default for this
+ *instruction type.
+ */
+ scale = def_scale[ optype - MEM1 ];
+ } else {
+ *p++ = '\0'; /* Eliminate '*' */
+
+ /* Now indexP->a '\0'-terminated register name,
+ * and p->a scale factor.
+ */
+
+ if (!strcmp(p,"16")){
+ scale = 16;
+ } else if (strchr("1248",*p) && (p[1] == '\0')){
+ scale = *p - '0';
+ } else {
+ scale = -1;
+ }
+ }
+
+ regnum = get_regnum(indexP); /* Get index reg. # */
+ if (!IS_RG_REG(regnum)){
+ as_bad("invalid index register");
+ return;
+ }
+
+ /* Convert scale to its binary encoding */
+ switch (scale){
+ case 1: scale = 0 << 7; break;
+ case 2: scale = 1 << 7; break;
+ case 4: scale = 2 << 7; break;
+ case 8: scale = 3 << 7; break;
+ case 16: scale = 4 << 7; break;
+ default: as_bad("invalid scale factor"); return;
+ };
+
+ memP->opcode |= scale | regnum; /* Set index bits in opcode */
+ mode |= I_BIT; /* Found a valid index spec */
+ }
+
+ /* Any abase (Register Indirect) specification present? */
+ if ((p = strrchr(argP,'(')) != NULL) {
+ /* "(" is there -- does it start a legal abase spec?
+ * (If not it could be part of a displacement expression.)
+ */
+ intP = (int *) hash_find(areg_hash, p);
+ if (intP != NULL){
+ /* Got an abase here */
+ regnum = *intP;
+ *p = '\0'; /* discard register spec */
+ if (regnum == IPREL){
+ /* We have to specialcase ip-rel mode */
+ iprel_flag = 1;
+ } else {
+ memP->opcode |= regnum << 14;
+ mode |= A_BIT;
+ }
+ }
+ }
+
+ /* Any expression present? */
+ memP->e = argP;
+ if (*argP != '\0'){
+ mode |= D_BIT;
+ }
+
+ /* Special-case ip-relative addressing */
+ if (iprel_flag){
+ if (mode & I_BIT){
+ syntax();
+ } else {
+ memP->opcode |= 5 << 10; /* IP-relative mode */
+ memP->disp = 32;
+ }
+ return;
+ }
+
+ /* Handle all other modes */
+ switch (mode){
+ case D_BIT | A_BIT:
+ /* Go with MEMA instruction format for now (grow to MEMB later
+ * if 12 bits is not enough for the displacement).
+ * MEMA format has a single mode bit: set it to indicate
+ * that abase is present.
+ */
+ memP->opcode |= MEMA_ABASE;
+ memP->disp = 12;
+ break;
+
+ case D_BIT:
+ /* Go with MEMA instruction format for now (grow to MEMB later
+ * if 12 bits is not enough for the displacement).
+ */
+ memP->disp = 12;
+ break;
+
+ case A_BIT:
+ /* For some reason, the bit string for this mode is not
+ * consistent: it should be 0 (exclusive of the MEMB bit),
+ * so we set it "by hand" here.
+ */
+ memP->opcode |= MEMB_BIT;
+ break;
+
+ case A_BIT | I_BIT:
+ /* set MEMB bit in mode, and OR in mode bits */
+ memP->opcode |= mode | MEMB_BIT;
+ break;
+
+ case I_BIT:
+ /* Treat missing displacement as displacement of 0 */
+ mode |= D_BIT;
+ /***********************
+ * Fall into next case *
+ ********************** */
+ case D_BIT | A_BIT | I_BIT:
+ case D_BIT | I_BIT:
+ /* set MEMB bit in mode, and OR in mode bits */
+ memP->opcode |= mode | MEMB_BIT;
+ memP->disp = 32;
+ break;
+
+ default:
+ syntax();
+ break;
+ }
+}
+
+/*****************************************************************************
+ * parse_po: parse machine-dependent pseudo-op
+ *
+ * This is a top-level routine for machine-dependent pseudo-ops. It slurps
+ * up the rest of the input line, breaks out the individual arguments,
+ * and dispatches them to the correct handler.
+ **************************************************************************** */
+static
+ void
+ parse_po(po_num)
+int po_num; /* Pseudo-op number: currently S_LEAFPROC or S_SYSPROC */
+{
+ char *args[4]; /* Pointers operands, with no embedded whitespace.
+ * arg[0] unused.
+ * arg[1-3]->operands
+ */
+ int n_ops; /* Number of operands */
+ char *p; /* Pointer to beginning of unparsed argument string */
+ char eol; /* Character that indicated end of line */
+
+ extern char is_end_of_line[];
+
+ /* Advance input pointer to end of line. */
+ p = input_line_pointer;
+ while (!is_end_of_line[ *input_line_pointer ]){
+ input_line_pointer++;
+ }
+ eol = *input_line_pointer; /* Save end-of-line char */
+ *input_line_pointer = '\0'; /* Terminate argument list */
+
+ /* Parse out operands */
+ n_ops = get_args(p, args);
+ if (n_ops == -1){
+ return;
+ }
+
+ /* Dispatch to correct handler */
+ switch (po_num){
+ case S_SYSPROC: s_sysproc(n_ops, args); break;
+ case S_LEAFPROC: s_leafproc(n_ops, args); break;
+ default: BAD_CASE(po_num); break;
+ }
+
+ /* Restore eol, so line numbers get updated correctly. Base assembler
+ * assumes we leave input pointer pointing at char following the eol.
+ */
+ *input_line_pointer++ = eol;
+}
+
+/*****************************************************************************
+ * parse_regop: parse a register operand.
+ *
+ * In case of illegal operand, issue a message and return some valid
+ * information so instruction processing can continue.
+ **************************************************************************** */
+static
+ void
+ parse_regop(regopP, optext, opdesc)
+struct regop *regopP; /* Where to put description of register operand */
+char *optext; /* Text of operand */
+char opdesc; /* Descriptor byte: what's legal for this operand */
+{
+ int n; /* Register number */
+ expressionS e; /* Parsed expression */
+
+ /* See if operand is a register */
+ n = get_regnum(optext);
+ if (n >= 0){
+ if (IS_RG_REG(n)){
+ /* global or local register */
+ if (!REG_ALIGN(opdesc,n)){
+ as_bad("unaligned register");
+ }
+ regopP->n = n;
+ regopP->mode = 0;
+ regopP->special = 0;
+ return;
+ } else if (IS_FP_REG(n) && FP_OK(opdesc)){
+ /* Floating point register, and it's allowed */
+ regopP->n = n - FP0;
+ regopP->mode = 1;
+ regopP->special = 0;
+ return;
+ } else if (IS_SF_REG(n) && SFR_OK(opdesc)){
+ /* Special-function register, and it's allowed */
+ regopP->n = n - SF0;
+ regopP->mode = 0;
+ regopP->special = 1;
+ if (!targ_has_sfr(regopP->n)){
+ as_bad("no such sfr in this architecture");
+ }
+ return;
+ }
+ } else if (LIT_OK(opdesc)){
+ /*
+ * How about a literal?
+ */
+ regopP->mode = 1;
+ regopP->special = 0;
+ if (FP_OK(opdesc)){ /* floating point literal acceptable */
+ /* Skip over 0f, 0d, or 0e prefix */
+ if ( (optext[0] == '0')
+ && (optext[1] >= 'd')
+ && (optext[1] <= 'f') ){
+ optext += 2;
+ }
+
+ if (!strcmp(optext,"0.0") || !strcmp(optext,"0") ){
+ regopP->n = 0x10;
+ return;
+ }
+ if (!strcmp(optext,"1.0") || !strcmp(optext,"1") ){
+ regopP->n = 0x16;
+ return;
+ }
+
+ } else { /* fixed point literal acceptable */
+ if ((parse_expr(optext,&e) != SEG_ABSOLUTE)
+ || (offs(e) < 0) || (offs(e) > 31)){
+ as_bad("illegal literal");
+ offs(e) = 0;
+ }
+ regopP->n = offs(e);
+ return;
+ }
+ }
+
+ /* Nothing worked */
+ syntax();
+ regopP->mode = 0; /* Register r0 is always a good one */
+ regopP->n = 0;
+ regopP->special = 0;
+} /* parse_regop() */
+
+/*****************************************************************************
+ * reg_fmt: generate a REG-format instruction
+ *
+ **************************************************************************** */
+static void reg_fmt(args, oP)
+char *args[]; /* args[0]->opcode mnemonic, args[1-3]->operands */
+struct i960_opcode *oP; /* Pointer to description of instruction */
+{
+ long instr; /* Binary to be output */
+ struct regop regop; /* Description of register operand */
+ int n_ops; /* Number of operands */
+
+
+ instr = oP->opcode;
+ n_ops = oP->num_ops;
+
+ if (n_ops >= 1){
+ parse_regop(&regop, args[1], oP->operand[0]);
+
+ if ((n_ops == 1) && !(instr & M3)){
+ /* 1-operand instruction in which the dst field should
+ * be used (instead of src1).
+ */
+ regop.n <<= 19;
+ if (regop.special){
+ regop.mode = regop.special;
+ }
+ regop.mode <<= 13;
+ regop.special = 0;
+ } else {
+ /* regop.n goes in bit 0, needs no shifting */
+ regop.mode <<= 11;
+ regop.special <<= 5;
+ }
+ instr |= regop.n | regop.mode | regop.special;
+ }
+
+ if (n_ops >= 2) {
+ parse_regop(&regop, args[2], oP->operand[1]);
+
+ if ((n_ops == 2) && !(instr & M3)){
+ /* 2-operand instruction in which the dst field should
+ * be used instead of src2).
+ */
+ regop.n <<= 19;
+ if (regop.special){
+ regop.mode = regop.special;
+ }
+ regop.mode <<= 13;
+ regop.special = 0;
+ } else {
+ regop.n <<= 14;
+ regop.mode <<= 12;
+ regop.special <<= 6;
+ }
+ instr |= regop.n | regop.mode | regop.special;
+ }
+ if (n_ops == 3){
+ parse_regop(&regop, args[3], oP->operand[2]);
+ if (regop.special){
+ regop.mode = regop.special;
+ }
+ instr |= (regop.n <<= 19) | (regop.mode <<= 13);
+ }
+ emit(instr);
+}
+
+
+/*****************************************************************************
+ * relax_cobr:
+ * Replace cobr instruction in a code fragment with equivalent branch and
+ * compare instructions, so it can reach beyond a 13-bit displacement.
+ * Set up an address fix/relocation for the new branch instruction.
+ *
+ **************************************************************************** */
+
+/* This "conditional jump" table maps cobr instructions into equivalent
+ * compare and branch opcodes.
+ */
+static
+ struct {
+ long compare;
+ long branch;
+ } coj[] = { /* COBR OPCODE: */
+ CHKBIT, BNO, /* 0x30 - bbc */
+ CMPO, BG, /* 0x31 - cmpobg */
+ CMPO, BE, /* 0x32 - cmpobe */
+ CMPO, BGE, /* 0x33 - cmpobge */
+ CMPO, BL, /* 0x34 - cmpobl */
+ CMPO, BNE, /* 0x35 - cmpobne */
+ CMPO, BLE, /* 0x36 - cmpoble */
+ CHKBIT, BO, /* 0x37 - bbs */
+ CMPI, BNO, /* 0x38 - cmpibno */
+ CMPI, BG, /* 0x39 - cmpibg */
+ CMPI, BE, /* 0x3a - cmpibe */
+ CMPI, BGE, /* 0x3b - cmpibge */
+ CMPI, BL, /* 0x3c - cmpibl */
+ CMPI, BNE, /* 0x3d - cmpibne */
+ CMPI, BLE, /* 0x3e - cmpible */
+ CMPI, BO, /* 0x3f - cmpibo */
+ };
+
+static
+ void
+ relax_cobr(fragP)
+register fragS *fragP; /* fragP->fr_opcode is assumed to point to
+ * the cobr instruction, which comes at the
+ * end of the code fragment.
+ */
+{
+ int opcode, src1, src2, m1, s2;
+ /* Bit fields from cobr instruction */
+ long bp_bits; /* Branch prediction bits from cobr instruction */
+ long instr; /* A single i960 instruction */
+ char *iP; /*->instruction to be replaced */
+ fixS *fixP; /* Relocation that can be done at assembly time */
+
+ /* PICK UP & PARSE COBR INSTRUCTION */
+ iP = fragP->fr_opcode;
+ instr = md_chars_to_number(iP, 4);
+ opcode = ((instr >> 24) & 0xff) - 0x30; /* "-0x30" for table index */
+ src1 = (instr >> 19) & 0x1f;
+ m1 = (instr >> 13) & 1;
+ s2 = instr & 1;
+ src2 = (instr >> 14) & 0x1f;
+ bp_bits= instr & BP_MASK;
+
+ /* GENERATE AND OUTPUT COMPARE INSTRUCTION */
+ instr = coj[opcode].compare
+ | src1 | (m1 << 11) | (s2 << 6) | (src2 << 14);
+ md_number_to_chars(iP, instr, 4);
+
+ /* OUTPUT BRANCH INSTRUCTION */
+ md_number_to_chars(iP+4, coj[opcode].branch | bp_bits, 4);
+
+ /* SET UP ADDRESS FIXUP/RELOCATION */
+ fixP = fix_new(fragP,
+ iP+4 - fragP->fr_literal,
+ 4,
+ fragP->fr_symbol,
+ 0,
+ fragP->fr_offset,
+ 1,
+ 0);
+
+ fixP->fx_bit_fixP = (bit_fixS *) 24; /* Store size of bit field */
+
+ fragP->fr_fix += 4;
+ frag_wane(fragP);
+}
+
+
+/*****************************************************************************
+ * reloc_callj: Relocate a 'callj' instruction
+ *
+ * This is a "non-(GNU)-standard" machine-dependent hook. The base
+ * assembler calls it when it decides it can relocate an address at
+ * assembly time instead of emitting a relocation directive.
+ *
+ * Check to see if the relocation involves a 'callj' instruction to a:
+ * sysproc: Replace the default 'call' instruction with a 'calls'
+ * leafproc: Replace the default 'call' instruction with a 'bal'.
+ * other proc: Do nothing.
+ *
+ * See b.out.h for details on the 'n_other' field in a symbol structure.
+ *
+ * IMPORTANT!:
+ * Assumes the caller has already figured out, in the case of a leafproc,
+ * to use the 'bal' entry point, and has substituted that symbol into the
+ * passed fixup structure.
+ *
+ **************************************************************************** */
+void reloc_callj(fixP)
+fixS *fixP; /* Relocation that can be done at assembly time */
+{
+ char *where; /*->the binary for the instruction being relocated */
+
+ if (!fixP->fx_callj) {
+ return;
+ } /* This wasn't a callj instruction in the first place */
+
+ where = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+ if (TC_S_IS_SYSPROC(fixP->fx_addsy)) {
+ /* Symbol is a .sysproc: replace 'call' with 'calls'.
+ * System procedure number is (other-1).
+ */
+ md_number_to_chars(where, CALLS|TC_S_GET_SYSPROC(fixP->fx_addsy), 4);
+
+ /* Nothing else needs to be done for this instruction.
+ * Make sure 'md_number_to_field()' will perform a no-op.
+ */
+ fixP->fx_bit_fixP = (bit_fixS *) 1;
+
+ } else if (TC_S_IS_CALLNAME(fixP->fx_addsy)) {
+ /* Should not happen: see block comment above */
+ as_fatal("Trying to 'bal' to %s", S_GET_NAME(fixP->fx_addsy));
+
+ } else if (TC_S_IS_BALNAME(fixP->fx_addsy)) {
+ /* Replace 'call' with 'bal'; both instructions have
+ * the same format, so calling code should complete
+ * relocation as if nothing happened here.
+ */
+ md_number_to_chars(where, BAL, 4);
+ } else if (TC_S_IS_BADPROC(fixP->fx_addsy)) {
+ as_bad("Looks like a proc, but can't tell what kind.\n");
+ } /* switch on proc type */
+
+ /* else Symbol is neither a sysproc nor a leafproc */
+
+ return;
+} /* reloc_callj() */
+
+
+/*****************************************************************************
+ * s_leafproc: process .leafproc pseudo-op
+ *
+ * .leafproc takes two arguments, the second one is optional:
+ * arg[1]: name of 'call' entry point to leaf procedure
+ * arg[2]: name of 'bal' entry point to leaf procedure
+ *
+ * If the two arguments are identical, or if the second one is missing,
+ * the first argument is taken to be the 'bal' entry point.
+ *
+ * If there are 2 distinct arguments, we must make sure that the 'bal'
+ * entry point immediately follows the 'call' entry point in the linked
+ * list of symbols.
+ *
+ **************************************************************************** */
+static void s_leafproc(n_ops, args)
+int n_ops; /* Number of operands */
+char *args[]; /* args[1]->1st operand, args[2]->2nd operand */
+{
+ symbolS *callP; /* Pointer to leafproc 'call' entry point symbol */
+ symbolS *balP; /* Pointer to leafproc 'bal' entry point symbol */
+
+ if ((n_ops != 1) && (n_ops != 2)) {
+ as_bad("should have 1 or 2 operands");
+ return;
+ } /* Check number of arguments */
+
+ /* Find or create symbol for 'call' entry point. */
+ callP = symbol_find_or_make(args[1]);
+
+ if (TC_S_IS_CALLNAME(callP)) {
+ as_warn("Redefining leafproc %s", S_GET_NAME(callP));
+ } /* is leafproc */
+
+ /* If that was the only argument, use it as the 'bal' entry point.
+ * Otherwise, mark it as the 'call' entry point and find or create
+ * another symbol for the 'bal' entry point.
+ */
+ if ((n_ops == 1) || !strcmp(args[1],args[2])) {
+ TC_S_FORCE_TO_BALNAME(callP);
+
+ } else {
+ TC_S_FORCE_TO_CALLNAME(callP);
+
+ balP = symbol_find_or_make(args[2]);
+ if (TC_S_IS_CALLNAME(balP)) {
+ as_warn("Redefining leafproc %s", S_GET_NAME(balP));
+ }
+ TC_S_FORCE_TO_BALNAME(balP);
+
+ tc_set_bal_of_call(callP, balP);
+ } /* if only one arg, or the args are the same */
+
+ return;
+} /* s_leafproc() */
+
+
+/*
+ * s_sysproc: process .sysproc pseudo-op
+ *
+ * .sysproc takes two arguments:
+ * arg[1]: name of entry point to system procedure
+ * arg[2]: 'entry_num' (index) of system procedure in the range
+ * [0,31] inclusive.
+ *
+ * For [ab].out, we store the 'entrynum' in the 'n_other' field of
+ * the symbol. Since that entry is normally 0, we bias 'entrynum'
+ * by adding 1 to it. It must be unbiased before it is used.
+ */
+static void s_sysproc(n_ops, args)
+int n_ops; /* Number of operands */
+char *args[]; /* args[1]->1st operand, args[2]->2nd operand */
+{
+ expressionS exp;
+ symbolS *symP;
+
+ if (n_ops != 2) {
+ as_bad("should have two operands");
+ return;
+ } /* bad arg count */
+
+ /* Parse "entry_num" argument and check it for validity. */
+ if ((parse_expr(args[2],&exp) != SEG_ABSOLUTE)
+ || (offs(exp) < 0)
+ || (offs(exp) > 31)) {
+ as_bad("'entry_num' must be absolute number in [0,31]");
+ return;
+ }
+
+ /* Find/make symbol and stick entry number (biased by +1) into it */
+ symP = symbol_find_or_make(args[1]);
+
+ if (TC_S_IS_SYSPROC(symP)) {
+ as_warn("Redefining entrynum for sysproc %s", S_GET_NAME(symP));
+ } /* redefining */
+
+ TC_S_SET_SYSPROC(symP, offs(exp)); /* encode entry number */
+ TC_S_FORCE_TO_SYSPROC(symP);
+
+ return;
+} /* s_sysproc() */
+
+
+/*****************************************************************************
+ * shift_ok:
+ * Determine if a "shlo" instruction can be used to implement a "ldconst".
+ * This means that some number X < 32 can be shifted left to produce the
+ * constant of interest.
+ *
+ * Return the shift count, or 0 if we can't do it.
+ * Caller calculates X by shifting original constant right 'shift' places.
+ *
+ **************************************************************************** */
+static
+ int
+ shift_ok(n)
+int n; /* The constant of interest */
+{
+ int shift; /* The shift count */
+
+ if (n <= 0){
+ /* Can't do it for negative numbers */
+ return 0;
+ }
+
+ /* Shift 'n' right until a 1 is about to be lost */
+ for (shift = 0; (n & 1) == 0; shift++){
+ n >>= 1;
+ }
+
+ if (n >= 32){
+ return 0;
+ }
+ return shift;
+}
+
+
+/*****************************************************************************
+ * syntax: issue syntax error
+ *
+ **************************************************************************** */
+static void syntax() {
+ as_bad("syntax error");
+} /* syntax() */
+
+
+/*****************************************************************************
+ * targ_has_sfr:
+ * Return TRUE iff the target architecture supports the specified
+ * special-function register (sfr).
+ *
+ **************************************************************************** */
+static
+ int
+ targ_has_sfr(n)
+int n; /* Number (0-31) of sfr */
+{
+ switch (architecture){
+ case ARCH_KA:
+ case ARCH_KB:
+ case ARCH_MC:
+ return 0;
+ case ARCH_CA:
+ default:
+ return ((0 <= n) && (n <= 2));
+ }
+}
+
+
+/*****************************************************************************
+ * targ_has_iclass:
+ * Return TRUE iff the target architecture supports the indicated
+ * class of instructions.
+ *
+ **************************************************************************** */
+static
+ int
+ targ_has_iclass(ic)
+int ic; /* Instruction class; one of:
+ * I_BASE, I_CX, I_DEC, I_KX, I_FP, I_MIL, I_CASIM
+ */
+{
+ iclasses_seen |= ic;
+ switch (architecture){
+ case ARCH_KA: return ic & (I_BASE | I_KX);
+ case ARCH_KB: return ic & (I_BASE | I_KX | I_FP | I_DEC);
+ case ARCH_MC: return ic & (I_BASE | I_KX | I_FP | I_DEC | I_MIL);
+ case ARCH_CA: return ic & (I_BASE | I_CX | I_CASIM);
+ default:
+ if ((iclasses_seen & (I_KX|I_FP|I_DEC|I_MIL))
+ && (iclasses_seen & I_CX)){
+ as_warn("architecture of opcode conflicts with that of earlier instruction(s)");
+ iclasses_seen &= ~ic;
+ }
+ return 1;
+ }
+}
+
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void
+ md_operand (expressionP)
+expressionS *expressionP;
+{
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *md_undefined_symbol(name)
+char *name;
+{
+ return 0;
+} /* md_undefined_symbol() */
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the i960, they're relative to the address of the instruction,
+ which we have set up as the address of the fixup too. */
+long
+ md_pcrel_from (fixP)
+fixS *fixP;
+{
+ return fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+void
+ md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ if (!fixP->fx_bit_fixP) {
+
+ switch (fixP->fx_im_disp) {
+ case 0:
+ fixP->fx_addnumber = val;
+ md_number_to_imm(place, val, fixP->fx_size, fixP);
+ break;
+ case 1:
+ md_number_to_disp(place,
+ fixP->fx_pcrel ? val + fixP->fx_pcrel_adjust : val,
+ fixP->fx_size);
+ break;
+ case 2: /* fix requested for .long .word etc */
+ md_number_to_chars(place, val, fixP->fx_size);
+ break;
+ default:
+ as_fatal("Internal error in md_apply_fix() in file \"%s\"", __FILE__);
+ } /* OVE: maybe one ought to put _imm _disp _chars in one md-func */
+ } else {
+ md_number_to_field(place, val, fixP->fx_bit_fixP);
+ }
+
+ return;
+} /* md_apply_fix() */
+
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+void tc_bout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };
+ struct relocation_info ri;
+ symbolS *symbolP;
+
+ /* JF this is for paranoia */
+ memset((char *)&ri, '\0', sizeof(ri));
+
+ know((symbolP = fixP->fx_addsy) != 0);
+
+ /* These two 'cuz of NS32K */
+ ri.r_callj = fixP->fx_callj;
+
+ ri.r_length = nbytes_r_length[fixP->fx_size];
+ ri.r_pcrel = fixP->fx_pcrel;
+ ri.r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file;
+
+ if (!S_IS_DEFINED(symbolP)) {
+ ri.r_extern = 1;
+ ri.r_index = symbolP->sy_number;
+ } else {
+ ri.r_extern = 0;
+ ri.r_index = S_GET_TYPE(symbolP);
+ }
+
+ /* Output the relocation information in machine-dependent form. */
+ md_ri_to_chars(where, &ri);
+
+ return;
+} /* tc_bout_fix_to_chars() */
+
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+/* Align an address by rounding it up to the specified boundary.
+ */
+long md_section_align(seg, addr)
+segT seg;
+long addr; /* Address to be rounded up */
+{
+ return((addr + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));
+} /* md_section_align() */
+
+#ifdef OBJ_COFF
+void tc_headers_hook(headers)
+object_headers *headers;
+{
+ /* FIXME: remove this line */ /* unsigned short arch_flag = 0; */
+
+ if ((iclasses_seen == I_BASE) || (iclasses_seen == 0)) {
+ headers->filehdr.f_flags |= F_I960CORE;
+ } else if (iclasses_seen & I_CX){
+ headers->filehdr.f_flags |= F_I960CA;
+ } else if (iclasses_seen & I_MIL){
+ headers->filehdr.f_flags |= F_I960MC;
+ } else if (iclasses_seen & (I_DEC|I_FP)){
+ headers->filehdr.f_flags |= F_I960KB;
+ } else {
+ headers->filehdr.f_flags |= F_I960KA;
+ } /* set arch flag */
+
+ if (flagseen['R']) {
+ headers->filehdr.f_magic = I960RWMAGIC;
+ headers->aouthdr.magic = OMAGIC;
+ } else {
+ headers->filehdr.f_magic = I960ROMAGIC;
+ headers->aouthdr.magic = NMAGIC;
+ } /* set magic numbers */
+
+ return;
+} /* tc_headers_hook() */
+#endif /* OBJ_COFF */
+
+/*
+ * Things going on here:
+ *
+ * For bout, We need to assure a couple of simplifying
+ * assumptions about leafprocs for the linker: the leafproc
+ * entry symbols will be defined in the same assembly in
+ * which they're declared with the '.leafproc' directive;
+ * and if a leafproc has both 'call' and 'bal' entry points
+ * they are both global or both local.
+ *
+ * For coff, the call symbol has a second aux entry that
+ * contains the bal entry point. The bal symbol becomes a
+ * label.
+ *
+ * For coff representation, the call symbol has a second aux entry that
+ * contains the bal entry point. The bal symbol becomes a label.
+ *
+ */
+
+void tc_crawl_symbol_chain(headers)
+object_headers *headers;
+{
+ symbolS *symbolP;
+
+ for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
+#ifdef OBJ_COFF
+ if (TC_S_IS_SYSPROC(symbolP)) {
+ /* second aux entry already contains the sysproc number */
+ S_SET_NUMBER_AUXILIARY(symbolP, 2);
+ S_SET_STORAGE_CLASS(symbolP, C_SCALL);
+ S_SET_DATA_TYPE(symbolP, S_GET_DATA_TYPE(symbolP) | (DT_FCN << N_BTSHFT));
+ continue;
+ } /* rewrite sysproc */
+#endif /* OBJ_COFF */
+
+ if (!TC_S_IS_BALNAME(symbolP) && !TC_S_IS_CALLNAME(symbolP)) {
+ continue;
+ } /* Not a leafproc symbol */
+
+ if (!S_IS_DEFINED(symbolP)) {
+ as_bad("leafproc symbol '%s' undefined", S_GET_NAME(symbolP));
+ } /* undefined leaf */
+
+ if (TC_S_IS_CALLNAME(symbolP)) {
+ symbolS *balP = tc_get_bal_of_call(symbolP);
+ if (S_IS_EXTERNAL(symbolP) != S_IS_EXTERNAL(balP)) {
+ S_SET_EXTERNAL(symbolP);
+ S_SET_EXTERNAL(balP);
+ as_warn("Warning: making leafproc entries %s and %s both global\n",
+ S_GET_NAME(symbolP), S_GET_NAME(balP));
+ } /* externality mismatch */
+ } /* if callname */
+ } /* walk the symbol chain */
+
+ return;
+} /* tc_crawl_symbol_chain() */
+
+/*
+ * For aout or bout, the bal immediately follows the call.
+ *
+ * For coff, we cheat and store a pointer to the bal symbol
+ * in the second aux entry of the call.
+ */
+
+void tc_set_bal_of_call(callP, balP)
+symbolS *callP;
+symbolS *balP;
+{
+ know(TC_S_IS_CALLNAME(callP));
+ know(TC_S_IS_BALNAME(balP));
+
+#ifdef OBJ_COFF
+
+ callP->sy_symbol.ost_auxent[1].x_bal.x_balntry = (int) balP;
+ S_SET_NUMBER_AUXILIARY(callP,2);
+
+#elif defined(OBJ_AOUT) || defined(OBJ_BOUT)
+
+ /* If the 'bal' entry doesn't immediately follow the 'call'
+ * symbol, unlink it from the symbol list and re-insert it.
+ */
+ if (symbol_next(callP) != balP) {
+ symbol_remove(balP, &symbol_rootP, &symbol_lastP);
+ symbol_append(balP, callP, &symbol_rootP, &symbol_lastP);
+ } /* if not in order */
+
+#else
+ (as yet unwritten.);
+#endif /* switch on OBJ_FORMAT */
+
+ return;
+} /* tc_set_bal_of_call() */
+
+char *_tc_get_bal_of_call(callP)
+symbolS *callP;
+{
+ symbolS *retval;
+
+ know(TC_S_IS_CALLNAME(callP));
+
+#ifdef OBJ_COFF
+ retval = (symbolS *) (callP->sy_symbol.ost_auxent[1].x_bal.x_balntry);
+#elif defined(OBJ_AOUT) || defined(OBJ_BOUT)
+ retval = symbol_next(callP);
+#else
+ (as yet unwritten.);
+#endif /* switch on OBJ_FORMAT */
+
+ know(TC_S_IS_BALNAME(retval));
+ return((char *) retval);
+} /* _tc_get_bal_of_call() */
+
+void tc_coff_symbol_emit_hook(symbolP)
+symbolS *symbolP;
+{
+ if (TC_S_IS_CALLNAME(symbolP)) {
+#ifdef OBJ_COFF
+ symbolS *balP = tc_get_bal_of_call(symbolP);
+
+ /* second aux entry contains the bal entry point */
+ /* S_SET_NUMBER_AUXILIARY(symbolP, 2); */
+ symbolP->sy_symbol.ost_auxent[1].x_bal.x_balntry = S_GET_VALUE(balP);
+ S_SET_STORAGE_CLASS(symbolP, (!SF_GET_LOCAL(symbolP) ? C_LEAFEXT : C_LEAFSTAT));
+ S_SET_DATA_TYPE(symbolP, S_GET_DATA_TYPE(symbolP) | (DT_FCN << N_BTSHFT));
+ /* fix up the bal symbol */
+ S_SET_STORAGE_CLASS(balP, C_LABEL);
+#endif /* OBJ_COFF */
+ } /* only on calls */
+
+ return;
+} /* tc_coff_symbol_emit_hook() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-i960.c */
diff --git a/gnu/usr.bin/as/config/tc-i960.h b/gnu/usr.bin/as/config/tc-i960.h
new file mode 100644
index 0000000..236c9b1
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-i960.h
@@ -0,0 +1,281 @@
+/* tc-i960.h - Basic 80960 instruction formats.
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef TC_I960
+#define TC_I960 1
+
+#define NO_LISTING
+
+/*
+ * The 'COJ' instructions are actually COBR instructions with the 'b' in
+ * the mnemonic replaced by a 'j'; they are ALWAYS "de-optimized" if necessary:
+ * if the displacement will not fit in 13 bits, the assembler will replace them
+ * with the corresponding compare and branch instructions.
+ *
+ * All of the 'MEMn' instructions are the same format; the 'n' in the name
+ * indicates the default index scale factor (the size of the datum operated on).
+ *
+ * The FBRA formats are not actually an instruction format. They are the
+ * "convenience directives" for branching on floating-point comparisons,
+ * each of which generates 2 instructions (a 'bno' and one other branch).
+ *
+ * The CALLJ format is not actually an instruction format. It indicates that
+ * the instruction generated (a CTRL-format 'call') should have its relocation
+ * specially flagged for link-time replacement with a 'bal' or 'calls' if
+ * appropriate.
+ */
+
+/* tailor gas */
+#define SYMBOLS_NEED_BACKPOINTERS
+#define LOCAL_LABELS_FB
+#define WANT_BITFIELDS
+
+/* tailor the coff format */
+#define OBJ_COFF_SECTION_HEADER_HAS_ALIGNMENT
+#define OBJ_COFF_MAX_AUXENTRIES (2)
+
+/* other */
+#define CTRL 0
+#define COBR 1
+#define COJ 2
+#define REG 3
+#define MEM1 4
+#define MEM2 5
+#define MEM4 6
+#define MEM8 7
+#define MEM12 8
+#define MEM16 9
+#define FBRA 10
+#define CALLJ 11
+
+/* Masks for the mode bits in REG format instructions */
+#define M1 0x0800
+#define M2 0x1000
+#define M3 0x2000
+
+/* Generate the 12-bit opcode for a REG format instruction by placing the
+ * high 8 bits in instruction bits 24-31, the low 4 bits in instruction bits
+ * 7-10.
+ */
+
+#define REG_OPC(opc) ((opc & 0xff0) << 20) | ((opc & 0xf) << 7)
+
+/* Generate a template for a REG format instruction: place the opcode bits
+ * in the appropriate fields and OR in mode bits for the operands that will not
+ * be used. I.e.,
+ * set m1=1, if src1 will not be used
+ * set m2=1, if src2 will not be used
+ * set m3=1, if dst will not be used
+ *
+ * Setting the "unused" mode bits to 1 speeds up instruction execution(!).
+ * The information is also useful to us because some 1-operand REG instructions
+ * use the src1 field, others the dst field; and some 2-operand REG instructions
+ * use src1/src2, others src1/dst. The set mode bits enable us to distinguish.
+ */
+#define R_0(opc) ( REG_OPC(opc) | M1 | M2 | M3 ) /* No operands */
+#define R_1(opc) ( REG_OPC(opc) | M2 | M3 ) /* 1 operand: src1 */
+#define R_1D(opc) ( REG_OPC(opc) | M1 | M2 ) /* 1 operand: dst */
+#define R_2(opc) ( REG_OPC(opc) | M3 ) /* 2 ops: src1/src2 */
+#define R_2D(opc) ( REG_OPC(opc) | M2 ) /* 2 ops: src1/dst */
+#define R_3(opc) ( REG_OPC(opc) ) /* 3 operands */
+
+/* DESCRIPTOR BYTES FOR REGISTER OPERANDS
+ *
+ * Interpret names as follows:
+ * R: global or local register only
+ * RS: global, local, or (if target allows) special-function register only
+ * RL: global or local register, or integer literal
+ * RSL: global, local, or (if target allows) special-function register;
+ * or integer literal
+ * F: global, local, or floating-point register
+ * FL: global, local, or floating-point register; or literal (including
+ * floating point)
+ *
+ * A number appended to a name indicates that registers must be aligned,
+ * as follows:
+ * 2: register number must be multiple of 2
+ * 4: register number must be multiple of 4
+ */
+
+#define SFR 0x10 /* Mask for the "sfr-OK" bit */
+#define LIT 0x08 /* Mask for the "literal-OK" bit */
+#define FP 0x04 /* Mask for "floating-point-OK" bit */
+
+/* This macro ors the bits together. Note that 'align' is a mask
+ * for the low 0, 1, or 2 bits of the register number, as appropriate.
+ */
+#define OP(align,lit,fp,sfr) ( align | lit | fp | sfr )
+
+#define R OP( 0, 0, 0, 0 )
+#define RS OP( 0, 0, 0, SFR )
+#define RL OP( 0, LIT, 0, 0 )
+#define RSL OP( 0, LIT, 0, SFR )
+#define F OP( 0, 0, FP, 0 )
+#define FL OP( 0, LIT, FP, 0 )
+#define R2 OP( 1, 0, 0, 0 )
+#define RL2 OP( 1, LIT, 0, 0 )
+#define F2 OP( 1, 0, FP, 0 )
+#define FL2 OP( 1, LIT, FP, 0 )
+#define R4 OP( 3, 0, 0, 0 )
+#define RL4 OP( 3, LIT, 0, 0 )
+#define F4 OP( 3, 0, FP, 0 )
+#define FL4 OP( 3, LIT, FP, 0 )
+
+#define M 0x7f /* Memory operand (MEMA & MEMB format instructions) */
+
+/* Macros to extract info from the register operand descriptor byte 'od'.
+ */
+#define SFR_OK(od) (od & SFR) /* TRUE if sfr operand allowed */
+#define LIT_OK(od) (od & LIT) /* TRUE if literal operand allowed */
+#define FP_OK(od) (od & FP) /* TRUE if floating-point op allowed */
+#define REG_ALIGN(od,n) ((od & 0x3 & n) == 0)
+/* TRUE if reg #n is properly aligned */
+#define MEMOP(od) (od == M) /* TRUE if operand is a memory operand*/
+
+/* Classes of 960 intructions:
+ * - each instruction falls into one class.
+ * - each target architecture supports one or more classes.
+ *
+ * EACH CONSTANT MUST CONTAIN 1 AND ONLY 1 SET BIT!: see targ_has_iclass().
+ */
+#define I_BASE 0x01 /* 80960 base instruction set */
+#define I_CX 0x02 /* 80960Cx instruction */
+#define I_DEC 0x04 /* Decimal instruction */
+#define I_FP 0x08 /* Floating point instruction */
+#define I_KX 0x10 /* 80960Kx instruction */
+#define I_MIL 0x20 /* Military instruction */
+
+/* MEANING OF 'n_other' in the symbol record.
+ *
+ * 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)
+
+
+/* i960 uses a custom relocation record. */
+
+/* let obj-aout.h know */
+#define CUSTOM_RELOC_FORMAT 1
+/* let a.out.gnu.h know */
+#define N_RELOCATION_INFO_DECLARED 1
+struct relocation_info {
+ int r_address; /* File address of item to be relocated */
+ unsigned
+ r_index: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 */
+};
+
+/* hacks for tracking callj's */
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+
+#define TC_S_IS_SYSPROC(s) ((1 <= S_GET_OTHER(s)) && (S_GET_OTHER(s) <= 32))
+#define TC_S_IS_BALNAME(s) (S_GET_OTHER(s) == N_BALNAME)
+#define TC_S_IS_CALLNAME(s) (S_GET_OTHER(s) == N_CALLNAME)
+#define TC_S_IS_BADPROC(s) ((S_GET_OTHER(s) != 0) && !TC_S_IS_CALLNAME(s) && !TC_S_IS_BALNAME(s) && !TC_S_IS_SYSPROC(s))
+
+#define TC_S_SET_SYSPROC(s, p) (S_SET_OTHER((s), (p)+1))
+#define TC_S_GET_SYSPROC(s) (S_GET_OTHER(s)-1)
+
+#define TC_S_FORCE_TO_BALNAME(s) (S_SET_OTHER((s), N_BALNAME))
+#define TC_S_FORCE_TO_CALLNAME(s) (S_SET_OTHER((s), N_CALLNAME))
+#define TC_S_FORCE_TO_SYSPROC(s) {;}
+
+#elif defined(OBJ_COFF)
+
+#define TC_S_IS_SYSPROC(s) (S_GET_STORAGE_CLASS(s) == C_SCALL)
+#define TC_S_IS_BALNAME(s) (SF_GET_BALNAME(s))
+#define TC_S_IS_CALLNAME(s) (SF_GET_CALLNAME(s))
+#define TC_S_IS_BADPROC(s) (TC_S_IS_SYSPROC(s) && TC_S_GET_SYSPROC(s) < 0 && 31 < TC_S_GET_SYSPROC(s))
+
+#define TC_S_SET_SYSPROC(s, p) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx = (p))
+#define TC_S_GET_SYSPROC(s) ((s)->sy_symbol.ost_auxent[1].x_sc.x_stindx)
+
+#define TC_S_FORCE_TO_BALNAME(s) (SF_SET_BALNAME(s))
+#define TC_S_FORCE_TO_CALLNAME(s) (SF_SET_CALLNAME(s))
+#define TC_S_FORCE_TO_SYSPROC(s) (S_SET_STORAGE_CLASS((s), C_SCALL))
+
+#else /* switch on OBJ */
+you lose
+#endif /* witch on OBJ */
+
+#if __STDC__ == 1
+
+ void brtab_emit(void);
+void reloc_callj(); /* this is really reloc_callj(fixS *fixP) but I don't want to change header inclusion order. */
+void tc_set_bal_of_call(); /* this is really tc_set_bal_of_call(symbolS *callP, symbolS *balP) */
+
+#else /* not __STDC__ */
+
+void brtab_emit();
+void reloc_callj();
+void tc_set_bal_of_call();
+
+#endif /* not __STDC__ */
+
+char *_tc_get_bal_of_call(); /* this is really symbolS *tc_get_bal_of_call(symbolS *callP). */
+#define tc_get_bal_of_call(c) ((symbolS *) _tc_get_bal_of_call(c))
+#endif
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-i960.h */
diff --git a/gnu/usr.bin/as/config/tc-m68851.h b/gnu/usr.bin/as/config/tc-m68851.h
new file mode 100644
index 0000000..8e69702
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-m68851.h
@@ -0,0 +1,304 @@
+/* This file is tc-m68851.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * pmmu.h
+ */
+
+/* I suppose we have to copyright this file. Someone on the net sent it
+ to us as part of the changes for the m68851 Memory Management Unit */
+
+/* Copyright (C) 1987 Free Software Foundation, Inc.
+
+ This file is part of Gas, the GNU Assembler.
+
+ The GNU assembler 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 GNU Assembler General
+ Public License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ the GNU Assembler, but only under the conditions described in the
+ GNU Assembler General Public License. A copy of this license is
+ supposed to have been given to you along with the GNU Assembler
+ 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. */
+
+#ifdef m68851
+
+/*
+ I didn't use much imagination in choosing the
+ following codes, so many of them aren't very
+ mnemonic. -rab
+
+ P pmmu register
+ Possible values:
+ 000 TC Translation Control reg
+ 100 CAL Current Access Level
+ 101 VAL Validate Access Level
+ 110 SCC Stack Change Control
+ 111 AC Access Control
+
+ W wide pmmu registers
+ Possible values:
+ 001 DRP Dma Root Pointer
+ 010 SRP Supervisor Root Pointer
+ 011 CRP Cpu Root Pointer
+
+ f function code register
+ 0 SFC
+ 1 DFC
+
+ V VAL register only
+
+ X BADx, BACx
+ 100 BAD Breakpoint Acknowledge Data
+ 101 BAC Breakpoint Acknowledge Control
+
+ Y PSR
+ Z PCSR
+
+ | memory (modes 2-6, 7.*)
+
+ */
+
+/*
+ * these defines should be in m68k.c but
+ * i put them here to keep all the m68851 stuff
+ * together -rab
+ * JF--Make sure these #s don't clash with the ones in m68k.c
+ * That would be BAD.
+ */
+#define TC (FPS+1) /* 48 */
+#define DRP (TC+1) /* 49 */
+#define SRP (DRP+1) /* 50 */
+#define CRP (SRP+1) /* 51 */
+#define CAL (CRP+1) /* 52 */
+#define VAL (CAL+1) /* 53 */
+#define SCC (VAL+1) /* 54 */
+#define AC (SCC+1) /* 55 */
+#define BAD (AC+1) /* 56,57,58,59, 60,61,62,63 */
+#define BAC (BAD+8) /* 64,65,66,67, 68,69,70,71 */
+#define PSR (BAC+8) /* 72 */
+#define PCSR (PSR+1) /* 73 */
+
+/* name */ /* opcode */ /* match */ /* args */
+
+{"pbac", one(0xf0c7), one(0xffbf), "Bc"},
+{"pbacw", one(0xf087), one(0xffbf), "Bc"},
+{"pbas", one(0xf0c6), one(0xffbf), "Bc"},
+{"pbasw", one(0xf086), one(0xffbf), "Bc"},
+{"pbbc", one(0xf0c1), one(0xffbf), "Bc"},
+{"pbbcw", one(0xf081), one(0xffbf), "Bc"},
+{"pbbs", one(0xf0c0), one(0xffbf), "Bc"},
+{"pbbsw", one(0xf080), one(0xffbf), "Bc"},
+{"pbcc", one(0xf0cf), one(0xffbf), "Bc"},
+{"pbccw", one(0xf08f), one(0xffbf), "Bc"},
+{"pbcs", one(0xf0ce), one(0xffbf), "Bc"},
+{"pbcsw", one(0xf08e), one(0xffbf), "Bc"},
+{"pbgc", one(0xf0cd), one(0xffbf), "Bc"},
+{"pbgcw", one(0xf08d), one(0xffbf), "Bc"},
+{"pbgs", one(0xf0cc), one(0xffbf), "Bc"},
+{"pbgsw", one(0xf08c), one(0xffbf), "Bc"},
+{"pbic", one(0xf0cb), one(0xffbf), "Bc"},
+{"pbicw", one(0xf08b), one(0xffbf), "Bc"},
+{"pbis", one(0xf0ca), one(0xffbf), "Bc"},
+{"pbisw", one(0xf08a), one(0xffbf), "Bc"},
+{"pblc", one(0xf0c3), one(0xffbf), "Bc"},
+{"pblcw", one(0xf083), one(0xffbf), "Bc"},
+{"pbls", one(0xf0c2), one(0xffbf), "Bc"},
+{"pblsw", one(0xf082), one(0xffbf), "Bc"},
+{"pbsc", one(0xf0c5), one(0xffbf), "Bc"},
+{"pbscw", one(0xf085), one(0xffbf), "Bc"},
+{"pbss", one(0xf0c4), one(0xffbf), "Bc"},
+{"pbssw", one(0xf084), one(0xffbf), "Bc"},
+{"pbwc", one(0xf0c9), one(0xffbf), "Bc"},
+{"pbwcw", one(0xf089), one(0xffbf), "Bc"},
+{"pbws", one(0xf0c8), one(0xffbf), "Bc"},
+{"pbwsw", one(0xf088), one(0xffbf), "Bc"},
+
+
+{"pdbac", two(0xf048, 0x0007), two(0xfff8, 0xffff), "DsBw"},
+{"pdbas", two(0xf048, 0x0006), two(0xfff8, 0xffff), "DsBw"},
+{"pdbbc", two(0xf048, 0x0001), two(0xfff8, 0xffff), "DsBw"},
+{"pdbbs", two(0xf048, 0x0000), two(0xfff8, 0xffff), "DsBw"},
+{"pdbcc", two(0xf048, 0x000f), two(0xfff8, 0xffff), "DsBw"},
+{"pdbcs", two(0xf048, 0x000e), two(0xfff8, 0xffff), "DsBw"},
+{"pdbgc", two(0xf048, 0x000d), two(0xfff8, 0xffff), "DsBw"},
+{"pdbgs", two(0xf048, 0x000c), two(0xfff8, 0xffff), "DsBw"},
+{"pdbic", two(0xf048, 0x000b), two(0xfff8, 0xffff), "DsBw"},
+{"pdbis", two(0xf048, 0x000a), two(0xfff8, 0xffff), "DsBw"},
+{"pdblc", two(0xf048, 0x0003), two(0xfff8, 0xffff), "DsBw"},
+{"pdbls", two(0xf048, 0x0002), two(0xfff8, 0xffff), "DsBw"},
+{"pdbsc", two(0xf048, 0x0005), two(0xfff8, 0xffff), "DsBw"},
+{"pdbss", two(0xf048, 0x0004), two(0xfff8, 0xffff), "DsBw"},
+{"pdbwc", two(0xf048, 0x0009), two(0xfff8, 0xffff), "DsBw"},
+{"pdbws", two(0xf048, 0x0008), two(0xfff8, 0xffff), "DsBw"},
+
+{"pflusha", two(0xf000, 0x2400), two(0xffff, 0xffff), "" },
+
+{"pflush", two(0xf000, 0x3010), two(0xffc0, 0xfe10), "T3T9" },
+{"pflush", two(0xf000, 0x3810), two(0xffc0, 0xfe10), "T3T9&s" },
+{"pflush", two(0xf000, 0x3008), two(0xffc0, 0xfe18), "D3T9" },
+{"pflush", two(0xf000, 0x3808), two(0xffc0, 0xfe18), "D3T9&s" },
+{"pflush", two(0xf000, 0x3000), two(0xffc0, 0xfe1e), "f3T9" },
+{"pflush", two(0xf000, 0x3800), two(0xffc0, 0xfe1e), "f3T9&s" },
+
+{"pflushs", two(0xf000, 0x3410), two(0xfff8, 0xfe10), "T3T9" },
+{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe00), "T3T9&s" },
+{"pflushs", two(0xf000, 0x3408), two(0xfff8, 0xfe18), "D3T9" },
+{"pflushs", two(0xf000, 0x3c08), two(0xfff8, 0xfe18), "D3T9&s" },
+{"pflushs", two(0xf000, 0x3400), two(0xfff8, 0xfe1e), "f3T9" },
+{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe1e), "f3T9&s"},
+
+{"pflushr", two(0xf000, 0xa000), two(0xffc0, 0xffff), "|s" },
+
+{"ploadr", two(0xf000, 0x2210), two(0xffc0, 0xfff0), "T3&s" },
+{"ploadr", two(0xf000, 0x2208), two(0xffc0, 0xfff8), "D3&s" },
+{"ploadr", two(0xf000, 0x2200), two(0xffc0, 0xfffe), "f3&s" },
+{"ploadw", two(0xf000, 0x2010), two(0xffc0, 0xfff0), "T3&s" },
+{"ploadw", two(0xf000, 0x2008), two(0xffc0, 0xfff8), "D3&s" },
+{"ploadw", two(0xf000, 0x2000), two(0xffc0, 0xfffe), "f3&s" },
+
+ /* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "*sP8" },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "P8%s" },
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "|sW8" },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "W8~s" },
+
+ /* BADx, BACx */
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xe3e3), "*sX3" },
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xe3e3), "X3%s" },
+
+ /* PSR, PCSR */
+ /* {"pmove", two(0xf000, 0x6100), two(oxffc0, oxffff), "*sZ8" }, */
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xffff), "*sY8" },
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xffff), "Y8%s" },
+{"pmove", two(0xf000, 0x6600), two(0xffc0, 0xffff), "Z8%s" },
+
+{"prestore", one(0xf140), one(0xffc0), "&s"},
+{"prestore", one(0xf158), one(0xfff8), "+s"},
+{"psave", one(0xf100), one(0xffc0), "&s"},
+{"psave", one(0xf100), one(0xffc0), "+s"},
+
+{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "@s"},
+{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "@s"},
+{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "@s"},
+{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "@s"},
+{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "@s"},
+{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "@s"},
+{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "@s"},
+{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "@s"},
+{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "@s"},
+{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "@s"},
+{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "@s"},
+{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "@s"},
+{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "@s"},
+{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "@s"},
+{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "@s"},
+{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "@s"},
+
+{"ptestr", two(0xf000, 0x8210), two(0xffc0, 0xe3f0), "T3&sQ8" },
+{"ptestr", two(0xf000, 0x8310), two(0xffc0, 0xe310), "T3&sQ8A9" },
+{"ptestr", two(0xf000, 0x8208), two(0xffc0, 0xe3f8), "D3&sQ8" },
+{"ptestr", two(0xf000, 0x8308), two(0xffc0, 0xe318), "D3&sQ8A9" },
+{"ptestr", two(0xf000, 0x8200), two(0xffc0, 0xe3fe), "f3&sQ8" },
+{"ptestr", two(0xf000, 0x8300), two(0xffc0, 0xe31e), "f3&sQ8A9" },
+
+{"ptestw", two(0xf000, 0x8010), two(0xffc0, 0xe3f0), "T3&sQ8" },
+{"ptestw", two(0xf000, 0x8110), two(0xffc0, 0xe310), "T3&sQ8A9" },
+{"ptestw", two(0xf000, 0x8008), two(0xffc0, 0xe3f8), "D3&sQ8" },
+{"ptestw", two(0xf000, 0x8108), two(0xffc0, 0xe318), "D3&sQ8A9" },
+{"ptestw", two(0xf000, 0x8000), two(0xffc0, 0xe3fe), "f3&sQ8" },
+{"ptestw", two(0xf000, 0x8100), two(0xffc0, 0xe31e), "f3&sQ8A9" },
+
+{"ptrapacw", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w"},
+{"ptrapacl", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l"},
+{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), ""},
+
+{"ptrapasw", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w"},
+{"ptrapasl", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l"},
+{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), ""},
+
+{"ptrapbcw", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w"},
+{"ptrapbcl", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l"},
+{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), ""},
+
+{"ptrapbsw", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w"},
+{"ptrapbsl", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l"},
+{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), ""},
+
+{"ptrapccw", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w"},
+{"ptrapccl", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l"},
+{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), ""},
+
+{"ptrapcsw", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w"},
+{"ptrapcsl", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l"},
+{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), ""},
+
+{"ptrapgcw", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w"},
+{"ptrapgcl", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l"},
+{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), ""},
+
+{"ptrapgsw", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w"},
+{"ptrapgsl", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l"},
+{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), ""},
+
+{"ptrapicw", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w"},
+{"ptrapicl", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l"},
+{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), ""},
+
+{"ptrapisw", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w"},
+{"ptrapisl", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l"},
+{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), ""},
+
+{"ptraplcw", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w"},
+{"ptraplcl", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l"},
+{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), ""},
+
+{"ptraplsw", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w"},
+{"ptraplsl", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l"},
+{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), ""},
+
+{"ptrapscw", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w"},
+{"ptrapscl", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l"},
+{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), ""},
+
+{"ptrapssw", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w"},
+{"ptrapssl", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l"},
+{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), ""},
+
+{"ptrapwcw", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w"},
+{"ptrapwcl", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l"},
+{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), ""},
+
+{"ptrapwsw", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w"},
+{"ptrapwsl", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l"},
+{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), ""},
+
+{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s"},
+{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s" },
+
+#endif /* m68851 */
+
+/* end of tc-m68851.h */
diff --git a/gnu/usr.bin/as/config/tc-m68k.c b/gnu/usr.bin/as/config/tc-m68k.c
new file mode 100644
index 0000000..dc4d3e8
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-m68k.c
@@ -0,0 +1,4088 @@
+/* tc-m68k.c All the m68020 specific stuff in one convenient, huge,
+ slow to compile, easy to find file.
+
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <ctype.h>
+
+#include "as.h"
+
+#include "obstack.h"
+
+/* note that this file includes real declarations and thus can only be included by one source file per executable. */
+#include "opcode/m68k.h"
+#ifdef TE_SUN
+/* This variable contains the value to write out at the beginning of
+ the a.out file. The 2<<16 means that this is a 68020 file instead
+ of an old-style 68000 file */
+
+long omagic = 2<<16|OMAGIC; /* Magic byte for header file */
+#else
+long omagic = OMAGIC;
+#endif
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "|";
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments like this one will always work. */
+const char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+
+const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ */
+
+const int md_reloc_size = 8; /* Size of relocation record */
+
+/* Its an arbitrary name: This means I don't approve of it */
+/* See flames below */
+static struct obstack robyn;
+
+#define TAB(x,y) (((x)<<2)+(y))
+#define TABTYPE(xy) ((xy) >> 2)
+#define BYTE 0
+#define SHORT 1
+#define LONG 2
+#define SZ_UNDEF 3
+
+#define BRANCH 1
+#define FBRANCH 2
+#define PCREL 3
+#define BCC68000 4
+#define DBCC 5
+#define PCLEA 6
+
+/* Operands we can parse: (And associated modes)
+
+ numb: 8 bit num
+ numw: 16 bit num
+ numl: 32 bit num
+ dreg: data reg 0-7
+ reg: address or data register
+ areg: address register
+ apc: address register, PC, ZPC or empty string
+ num: 16 or 32 bit num
+ num2: like num
+ sz: w or l if omitted, l assumed
+ scale: 1 2 4 or 8 if omitted, 1 assumed
+
+ 7.4 IMMED #num --> NUM
+ 0.? DREG dreg --> dreg
+ 1.? AREG areg --> areg
+ 2.? AINDR areg@ --> *(areg)
+ 3.? AINC areg@+ --> *(areg++)
+ 4.? ADEC areg@- --> *(--areg)
+ 5.? AOFF apc@(numw) --> *(apc+numw) -- empty string and ZPC not allowed here
+ 6.? AINDX apc@(num,reg:sz:scale) --> *(apc+num+reg*scale)
+ 6.? AINDX apc@(reg:sz:scale) --> same, with num=0
+ 6.? APODX apc@(num)@(num2,reg:sz:scale) --> *(*(apc+num)+num2+reg*scale)
+ 6.? APODX apc@(num)@(reg:sz:scale) --> same, with num2=0
+ 6.? AMIND apc@(num)@(num2) --> *(*(apc+num)+num2) (previous mode without an index reg)
+ 6.? APRDX apc@(num,reg:sz:scale)@(num2) --> *(*(apc+num+reg*scale)+num2)
+ 6.? APRDX apc@(reg:sz:scale)@(num2) --> same, with num=0
+ 7.0 ABSL num:sz --> *(num)
+ num --> *(num) (sz L assumed)
+ *** MSCR otherreg --> Magic
+ With -l option
+ 5.? AOFF apc@(num) --> *(apc+num) -- empty string and ZPC not allowed here still
+
+ examples:
+ #foo #0x35 #12
+ d2
+ a4
+ a3@
+ a5@+
+ a6@-
+ a2@(12) pc@(14)
+ a1@(5,d2:w:1) @(45,d6:l:4)
+ pc@(a2) @(d4)
+ etc...
+
+
+ #name@(numw) -->turn into PC rel mode
+ apc@(num8,reg:sz:scale) --> *(apc+num8+reg*scale)
+
+ */
+
+enum operand_type {
+ IMMED = 1,
+ DREG,
+ AREG,
+ AINDR,
+ ADEC,
+ AINC,
+ AOFF,
+ AINDX,
+ APODX,
+ AMIND,
+ APRDX,
+ ABSL,
+ MSCR,
+ REGLST,
+};
+
+
+struct m68k_exp {
+ char *e_beg;
+ char *e_end;
+ expressionS e_exp;
+ short e_siz; /* 0 == default 1 == short/byte 2 == word 3 == long */
+};
+
+/* DATA and ADDR have to be contiguous, so that reg-DATA gives 0-7 == data reg,
+ 8-15 == addr reg for operands that take both types */
+
+enum _register {
+ DATA = 1, /* 1- 8 == data registers 0-7 */
+ DATA0 = DATA,
+ DATA1,
+ DATA2,
+ DATA3,
+ DATA4,
+ DATA5,
+ DATA6,
+ DATA7,
+
+ ADDR,
+ ADDR0 = ADDR,
+ ADDR1,
+ ADDR2,
+ ADDR3,
+ ADDR4,
+ ADDR5,
+ ADDR6,
+ ADDR7,
+
+ /* Note that COPNUM == processor #1 -- COPNUM+7 == #8, which stores as 000 */
+ /* I think... */
+
+ SP = ADDR7,
+
+ FPREG, /* Eight FP registers */
+ FP0 = FPREG,
+ FP1,
+ FP2,
+ FP3,
+ FP4,
+ FP5,
+ FP6,
+ FP7,
+ COPNUM = (FPREG+8), /* Co-processor #1-#8 */
+ COP0 = COPNUM,
+ COP1,
+ COP2,
+ COP3,
+ COP4,
+ COP5,
+ COP6,
+ COP7,
+ PC, /* Program counter */
+ ZPC, /* Hack for Program space, but 0 addressing */
+ SR, /* Status Reg */
+ CCR, /* Condition code Reg */
+
+ /* These have to be in order for the movec instruction to work. */
+ USP, /* User Stack Pointer */
+ ISP, /* Interrupt stack pointer */
+ SFC,
+ DFC,
+ CACR,
+ VBR,
+ CAAR,
+ MSP,
+ ITT0,
+ ITT1,
+ DTT0,
+ DTT1,
+ MMUSR,
+ TC,
+ SRP,
+ URP,
+ /* end of movec ordering constraints */
+
+ FPI,
+ FPS,
+ FPC,
+
+ DRP,
+ CRP,
+ CAL,
+ VAL,
+ SCC,
+ AC,
+ BAD,
+ BAD0 = BAD,
+ BAD1,
+ BAD2,
+ BAD3,
+ BAD4,
+ BAD5,
+ BAD6,
+ BAD7,
+ BAC,
+ BAC0 = BAC,
+ BAC1,
+ BAC2,
+ BAC3,
+ BAC4,
+ BAC5,
+ BAC6,
+ BAC7,
+ PSR,
+ PCSR,
+
+ IC, /* instruction cache token */
+ DC, /* data cache token */
+ NC, /* no cache token */
+ BC, /* both caches token */
+
+};
+
+/* Internal form of an operand. */
+struct m68k_op {
+ char *error; /* Couldn't parse it */
+ enum operand_type mode; /* What mode this instruction is in. */
+ enum _register reg; /* Base register */
+ struct m68k_exp *con1;
+ int ireg; /* Index register */
+ int isiz; /* 0 == unspec 1 == byte(?) 2 == short 3 == long */
+ int imul; /* Multipy ireg by this (1,2,4,or 8) */
+ struct m68k_exp *con2;
+};
+
+/* internal form of a 68020 instruction */
+struct m68k_it {
+ char *error;
+ char *args; /* list of opcode info */
+ int numargs;
+
+ int numo; /* Number of shorts in opcode */
+ short opcode[11];
+
+ struct m68k_op operands[6];
+
+ int nexp; /* number of exprs in use */
+ struct m68k_exp exprs[4];
+
+ int nfrag; /* Number of frags we have to produce */
+ struct {
+ int fragoff; /* Where in the current opcode[] the frag ends */
+ symbolS *fadd;
+ long foff;
+ int fragty;
+ } fragb[4];
+
+ int nrel; /* Num of reloc strucs in use */
+ struct {
+ int n;
+ symbolS *add,
+ *sub,
+ *got;
+ long off;
+ char wid;
+ char pcrel;
+ enum reloc_type rtype;
+ } reloc[5]; /* Five is enough??? */
+};
+
+#define cpu_of_arch(x) ((x) & m68000up)
+#define float_of_arch(x) ((x) & mfloat)
+#define mmu_of_arch(x) ((x) & mmmu)
+
+static struct m68k_it the_ins; /* the instruction being assembled */
+
+/* Macros for adding things to the m68k_it struct */
+
+#define addword(w) the_ins.opcode[the_ins.numo++]=(w)
+
+/* Like addword, but goes BEFORE general operands */
+#define insop(w) { \
+ int z; \
+ for (z=the_ins.numo;z>opcode->m_codenum;--z) \
+ the_ins.opcode[z]=the_ins.opcode[z-1]; \
+ for (z=0;z<the_ins.nrel;z++) \
+ the_ins.reloc[z].n+=2; \
+ the_ins.opcode[opcode->m_codenum]=w; \
+ the_ins.numo++; \
+ }
+
+
+#define add_exp(beg,end) (the_ins.exprs[the_ins.nexp].e_beg=beg, \
+ the_ins.exprs[the_ins.nexp].e_end=end, \
+ &the_ins.exprs[the_ins.nexp++] \
+ )
+
+
+/* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch*/
+#define add_fix(width, exp, pc_rel, r_type) { \
+ the_ins.reloc[the_ins.nrel].n= ((width) == 'B') ? (the_ins.numo*2-1) : \
+ (((width) == 'b') ? ((the_ins.numo-1)*2) : (the_ins.numo*2)); \
+ the_ins.reloc[the_ins.nrel].add=adds((exp)); \
+ the_ins.reloc[the_ins.nrel].sub=subs((exp)); \
+ the_ins.reloc[the_ins.nrel].off=offs((exp)); \
+ the_ins.reloc[the_ins.nrel].got=gots((exp)); \
+ the_ins.reloc[the_ins.nrel].wid=width; \
+ the_ins.reloc[the_ins.nrel].pcrel=pc_rel; \
+ the_ins.reloc[the_ins.nrel++].rtype=r_type; \
+ }
+
+#define add_frag(add,off,type) {\
+ the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo;\
+ the_ins.fragb[the_ins.nfrag].fadd=add;\
+ the_ins.fragb[the_ins.nfrag].foff=off;\
+ the_ins.fragb[the_ins.nfrag++].fragty=type;\
+ }
+
+#define isvar(exp) ((exp) && (adds(exp) || subs(exp) || gots(exp)))
+
+#define seg(exp) ((exp)->e_exp.X_seg)
+#define adds(exp) ((exp)->e_exp.X_add_symbol)
+#define subs(exp) ((exp)->e_exp.X_subtract_symbol)
+#define offs(exp) ((exp)->e_exp.X_add_number)
+#define gots(exp) ((exp)->e_exp.X_got_symbol)
+
+
+struct m68k_incant {
+ char *m_operands;
+ unsigned long m_opcode;
+ short m_opnum;
+ short m_codenum;
+ enum m68k_architecture m_arch;
+ struct m68k_incant *m_next;
+};
+
+#define getone(x) ((((x)->m_opcode)>>16)&0xffff)
+#define gettwo(x) (((x)->m_opcode)&0xffff)
+
+
+#if __STDC__ == 1
+
+static char *crack_operand(char *str, struct m68k_op *opP);
+static int get_num(struct m68k_exp *exp, int ok);
+static int get_regs(int i, char *str, struct m68k_op *opP);
+static int reverse_16_bits(int in);
+static int reverse_8_bits(int in);
+static int try_index(char **s, struct m68k_op *opP);
+static void install_gen_operand(int mode, int val);
+static void install_operand(int mode, int val);
+static void s_bss(void);
+static void s_data1(void);
+static void s_data2(void);
+static void s_even(void);
+static void s_proc(void);
+
+#else /* not __STDC__ */
+
+static char *crack_operand();
+static int get_num();
+static int get_regs();
+static int reverse_16_bits();
+static int reverse_8_bits();
+static int try_index();
+static void install_gen_operand();
+static void install_operand();
+static void s_bss();
+static void s_data1();
+static void s_data2();
+static void s_even();
+static void s_proc();
+
+#endif /* not __STDC__ */
+
+static enum m68k_architecture current_architecture = 0;
+
+/* BCC68000 is for patching in an extra jmp instruction for long offsets
+ on the 68000. The 68000 doesn't support long branches with branchs */
+
+/* This table desribes how you change sizes for the various types of variable
+ size expressions. This version only supports two kinds. */
+
+/* Note that calls to frag_var need to specify the maximum expansion needed */
+/* This is currently 10 bytes for DBCC */
+
+/* The fields are:
+ How far Forward this mode will reach:
+ How far Backward this mode will reach:
+ How many bytes this mode will add to the size of the frag
+ Which mode to go to if the offset won't fit in this one
+ */
+const relax_typeS
+ md_relax_table[] = {
+ { 1, 1, 0, 0 }, /* First entries aren't used */
+ { 1, 1, 0, 0 }, /* For no good reason except */
+ { 1, 1, 0, 0 }, /* that the VAX doesn't either */
+ { 1, 1, 0, 0 },
+
+ { (127), (-128), 0, TAB(BRANCH,SHORT)},
+ { (32767), (-32768), 2, TAB(BRANCH,LONG) },
+ { 0, 0, 4, 0 },
+ { 1, 1, 0, 0 },
+
+ { 1, 1, 0, 0 }, /* FBRANCH doesn't come BYTE */
+ { (32767), (-32768), 2, TAB(FBRANCH,LONG)},
+ { 0, 0, 4, 0 },
+ { 1, 1, 0, 0 },
+
+ { 1, 1, 0, 0 }, /* PCREL doesn't come BYTE */
+ { (32767), (-32768), 2, TAB(PCREL,LONG)},
+ { 0, 0, 4, 0 },
+ { 1, 1, 0, 0 },
+
+ { (127), (-128), 0, TAB(BCC68000,SHORT)},
+ { (32767), (-32768), 2, TAB(BCC68000,LONG) },
+ { 0, 0, 6, 0 }, /* jmp long space */
+ { 1, 1, 0, 0 },
+
+ { 1, 1, 0, 0 }, /* DBCC doesn't come BYTE */
+ { (32767), (-32768), 2, TAB(DBCC,LONG) },
+ { 0, 0, 10, 0 }, /* bra/jmp long space */
+ { 1, 1, 0, 0 },
+
+ { 1, 1, 0, 0 }, /* PCLEA doesn't come BYTE */
+ { 32767, -32768, 2, TAB(PCLEA,LONG) },
+ { 0, 0, 6, 0 },
+ { 1, 1, 0, 0 },
+
+ };
+
+/* These are the machine dependent pseudo-ops. These are included so
+ the assembler can work on the output from the SUN C compiler, which
+ generates these.
+ */
+
+/* This table describes all the machine specific pseudo-ops the assembler
+ has to support. The fields are:
+ pseudo-op name without dot
+ function to call to execute this pseudo-op
+ Integer arg to pass to the function
+ */
+const pseudo_typeS md_pseudo_table[] = {
+ { "data1", s_data1, 0 },
+ { "data2", s_data2, 0 },
+ { "bss", s_bss, 0 },
+ { "even", s_even, 0 },
+ { "skip", s_space, 0 },
+ { "proc", s_proc, 0 },
+ { 0, 0, 0 }
+};
+
+
+/* #define isbyte(x) ((x) >= -128 && (x) <= 127) */
+/* #define isword(x) ((x) >= -32768 && (x) <= 32767) */
+
+#define issbyte(x) ((x) >= -128 && (x) <= 127)
+#define isubyte(x) ((x) >= 0 && (x) <= 255)
+#define issword(x) ((x) >= -32768 && (x) <= 32767)
+#define isuword(x) ((x) >= 0 && (x) <= 65535)
+
+#define isbyte(x) ((x) >= -128 && (x) <= 255)
+#define isword(x) ((x) >= -32768 && (x) <= 65535)
+#define islong(x) (1)
+
+extern char *input_line_pointer;
+
+enum {
+ FAIL = 0,
+ OK = 1,
+};
+
+/* JF these tables here are for speed at the expense of size */
+/* You can replace them with the #if 0 versions if you really
+ need space and don't mind it running a bit slower */
+
+static char mklower_table[256];
+#define mklower(c) (mklower_table[(unsigned char)(c)])
+static char notend_table[256];
+static char alt_notend_table[256];
+#define notend(s) (!(notend_table[(unsigned char)(*s)] || (*s == ':' &&\
+ alt_notend_table[(unsigned char)(s[1])])))
+
+#if 0
+#define mklower(c) (isupper(c) ? tolower(c) : c)
+#endif
+
+/* Handle the extra arg for fix_new when doing PIC */
+#ifdef PIC
+#define FIX_NO_RELOC NO_RELOC, NULL
+#else
+#define FIX_NO_RELOC NO_RELOC
+#endif /* PIC */
+
+
+/* JF modified this to handle cases where the first part of a symbol name
+ looks like a register */
+
+/*
+ * m68k_reg_parse() := if it looks like a register, return it's token &
+ * advance the pointer.
+ */
+
+enum _register m68k_reg_parse(ccp)
+register char **ccp;
+{
+#ifndef MAX_REG_NAME_LEN
+#define MAX_REG_NAME_LEN (6)
+#endif /* MAX_REG_NAME_LEN */
+ register char c[MAX_REG_NAME_LEN];
+ char *p, *q;
+ register int n = 0,
+ ret = FAIL;
+
+ c[0] = mklower(ccp[0][0]);
+#ifdef REGISTER_PREFIX
+ if (c[0] != REGISTER_PREFIX) {
+ return(FAIL);
+ } /* need prefix */
+#endif
+
+ for (p = c, q = ccp[0]; p < c + MAX_REG_NAME_LEN; ++p, ++q)
+ {
+ if (*q == 0)
+ {
+ *p = 0;
+ break;
+ }
+ else
+ *p = mklower(*q);
+ } /* downcase */
+
+ switch (c[0]) {
+ case 'a':
+ if (c[1] >= '0' && c[1] <= '7') {
+ n=2;
+ ret=ADDR+c[1]-'0';
+ }
+#ifndef NO_68851
+ else if (c[1] == 'c') {
+ n = 2;
+ ret = AC;
+ }
+#endif
+ break;
+#ifndef NO_68851
+ case 'b':
+ if (c[1] == 'a') {
+ if (c[2] == 'd') {
+ if (c[3] >= '0' && c[3] <= '7') {
+ n = 4;
+ ret = BAD + c[3] - '0';
+ }
+ } /* BAD */
+ if (c[2] == 'c') {
+ if (c[3] >= '0' && c[3] <= '7') {
+ n = 4;
+ ret = BAC + c[3] - '0';
+ }
+ } /* BAC */
+ } else if (c[1] == 'c') {
+ n = 2;
+ ret = BC;
+ } /* BC */
+ break;
+#endif
+ case 'c':
+#ifndef NO_68851
+ if (c[1] == 'a' && c[2] == 'l') {
+ n = 3;
+ ret = CAL;
+ } else
+#endif
+ /* This supports both CCR and CC as the ccr reg. */
+ if (c[1] == 'c' && c[2] == 'r') {
+ n=3;
+ ret = CCR;
+ } else if (c[1] == 'c') {
+ n=2;
+ ret = CCR;
+ } else if (c[1] == 'a' && (c[2] == 'a' || c[2] == 'c') && c[3] == 'r') {
+ n=4;
+ ret = c[2] == 'a' ? CAAR : CACR;
+ }
+#ifndef NO_68851
+ else if (c[1] == 'r' && c[2] == 'p') {
+ n = 3;
+ ret = (CRP);
+ }
+#endif
+ break;
+ case 'd':
+ if (c[1] >= '0' && c[1] <= '7') {
+ n = 2;
+ ret = DATA + c[1] - '0';
+ } else if (c[1] == 'f' && c[2] == 'c') {
+ n = 3;
+ ret = DFC;
+ } else if (c[1] == 'c') {
+ n = 2;
+ ret = DC;
+ } else if (c[1] == 't' && c[2] == 't') {
+ if ('0' <= c[3] && c[3] <= '1') {
+ n = 4;
+ ret = DTT0 + (c[3] - '0');
+ } /* DTT[01] */
+ }
+#ifndef NO_68851
+ else if (c[1] == 'r' && c[2] == 'p') {
+ n = 3;
+ ret = (DRP);
+ }
+#endif
+ break;
+ case 'f':
+ if (c[1] == 'p') {
+ if (c[2] >= '0' && c[2] <= '7') {
+ n=3;
+ ret = FPREG+c[2]-'0';
+ if (c[3] == ':')
+ ccp[0][3]=',';
+ } else if (c[2] == 'i') {
+ n=3;
+ ret = FPI;
+ } else if (c[2] == 's') {
+ n= (c[3] == 'r' ? 4 : 3);
+ ret = FPS;
+ } else if (c[2] == 'c') {
+ n= (c[3] == 'r' ? 4 : 3);
+ ret = FPC;
+ }
+ }
+ break;
+ case 'i':
+ if (c[1] == 's' && c[2] == 'p') {
+ n = 3;
+ ret = ISP;
+ } else if (c[1] == 'c') {
+ n = 2;
+ ret = IC;
+ } else if (c[1] == 't' && c[2] == 't') {
+ if ('0' <= c[3] && c[3] <= '1') {
+ n = 4;
+ ret = ITT0 + (c[3] - '0');
+ } /* ITT[01] */
+ }
+ break;
+ case 'm':
+ if (c[1] == 's' && c[2] == 'p') {
+ n = 3;
+ ret = MSP;
+ } else if (c[1] == 'm' && c[2] == 'u' && c[3] == 's' && c[4] == 'r') {
+ n = 5;
+ ret = MMUSR;
+ }
+ break;
+ case 'n':
+ if (c[1] == 'c') {
+ n = 2;
+ ret = NC;
+ }
+ break;
+ case 'p':
+ if (c[1] == 'c') {
+#ifndef NO_68851
+ if (c[2] == 's' && c[3] == 'r') {
+ n=4;
+ ret = (PCSR);
+ } else
+#endif
+ {
+ n=2;
+ ret = PC;
+ }
+ }
+#ifndef NO_68851
+ else if (c[1] == 's' && c[2] == 'r') {
+ n = 3;
+ ret = (PSR);
+ }
+#endif
+ break;
+ case 's':
+#ifndef NO_68851
+ if (c[1] == 'c' && c[2] == 'c') {
+ n = 3;
+ ret = (SCC);
+ } else
+#endif
+ if (c[1] == 'r') {
+ if (c[2] == 'p') {
+ n = 3;
+ ret = SRP;
+ } else {
+ n = 2;
+ ret = SR;
+ } /* srp else sr */
+ } else if (c[1] == 'p') {
+ n = 2;
+ ret = SP;
+ } else if (c[1] == 'f' && c[2] == 'c') {
+ n = 3;
+ ret = SFC;
+ }
+ break;
+ case 't':
+ if (c[1] == 'c') {
+ n = 2;
+ ret = TC;
+ }
+ break;
+ case 'u':
+ if (c[1] == 's' && c[2] == 'p') {
+ n=3;
+ ret = USP;
+ } else if (c[1] == 'r' && c[2] == 'p') {
+ n = 3;
+ ret = URP;
+ }
+ break;
+ case 'v':
+#ifndef NO_68851
+ if (c[1] == 'a' && c[2] == 'l') {
+ n = 3;
+ ret = (VAL);
+ } else
+#endif
+ if (c[1] == 'b' && c[2] == 'r') {
+ n=3;
+ ret = VBR;
+ }
+ break;
+ case 'z':
+ if (c[1] == 'p' && c[2] == 'c') {
+ n=3;
+ ret = ZPC;
+ }
+ break;
+ default:
+ break;
+ }
+ if (n) {
+#ifdef REGISTER_PREFIX
+ n++;
+#endif
+ if (isalnum(ccp[0][n]) || ccp[0][n] == '_')
+ ret=FAIL;
+ else
+ ccp[0]+=n;
+ } else
+ ret = FAIL;
+ return ret;
+}
+
+#define SKIP_WHITE() { str++; if (*str == ' ') str++;}
+
+/*
+ * m68k_ip_op := '#' + <anything>
+ * | <register> + range_sep + get_regs
+ * ;
+ *
+ * range_sep := '/' | '-' ;
+ *
+ * SKIP_WHITE := <empty> | ' ' ;
+ *
+ */
+
+int
+ m68k_ip_op(str,opP)
+char *str;
+register struct m68k_op *opP;
+{
+ char *strend;
+ long i;
+ char *parse_index();
+
+ if (*str == ' ') {
+ str++;
+ } /* Find the beginning of the string */
+
+ if (!*str) {
+ opP->error="Missing operand";
+ return FAIL;
+ } /* Out of gas */
+
+ for (strend = str; *strend; strend++) ;;
+
+ --strend;
+
+ if (*str == '#') {
+ str++;
+ opP->con1=add_exp(str,strend);
+ opP->mode=IMMED;
+ return OK;
+ } /* Guess what: A constant. Shar and enjoy */
+
+ i = m68k_reg_parse(&str);
+
+ /* is a register, is exactly a register, and is followed by '@' */
+
+ if ((i == FAIL || *str != '\0') && *str != '@') {
+ char *stmp;
+
+ if (i != FAIL && (*str == '/' || *str == '-')) {
+ opP->mode=REGLST;
+ return(get_regs(i,str,opP));
+ }
+ if ((stmp=strchr(str,'@')) != '\0') {
+ opP->con1=add_exp(str,stmp-1);
+ if (stmp == strend) {
+ opP->mode=AINDX;
+ return(OK);
+ }
+
+ if ((current_architecture & m68020up) == 0) {
+ return(FAIL);
+ } /* if target is not a '20 or better */
+
+ stmp++;
+ if (*stmp++ != '(' || *strend-- != ')') {
+ opP->error="Malformed operand";
+ return(FAIL);
+ }
+ i=try_index(&stmp,opP);
+ opP->con2=add_exp(stmp,strend);
+
+ if (i == FAIL) {
+ opP->mode=AMIND;
+ } else {
+ opP->mode=APODX;
+ }
+ return(OK);
+ } /* if there's an '@' */
+ opP->mode = ABSL;
+ opP->con1 = add_exp(str,strend);
+ return(OK);
+ } /* not a register, not exactly a register, or no '@' */
+
+ opP->reg=i;
+
+ if (*str == '\0') {
+ if (i >= DATA+0 && i <= DATA+7)
+ opP->mode=DREG;
+ else if (i >= ADDR+0 && i <= ADDR+7)
+ opP->mode=AREG;
+ else
+ opP->mode=MSCR;
+ return OK;
+ }
+
+ if ((i<ADDR+0 || i>ADDR+7) && i != PC && i != ZPC && i != FAIL) { /* Can't indirect off non address regs */
+ opP->error="Invalid indirect register";
+ return FAIL;
+ }
+ know(*str == '@');
+
+ str++;
+ switch (*str) {
+ case '\0':
+ opP->mode=AINDR;
+ return OK;
+ case '-':
+ opP->mode=ADEC;
+ return OK;
+ case '+':
+ opP->mode=AINC;
+ return OK;
+ case '(':
+ str++;
+ break;
+ default:
+ opP->error="Junk after indirect";
+ return FAIL;
+ }
+ /* Some kind of indexing involved. Lets find out how bad it is */
+ i=try_index(&str,opP);
+ /* Didn't start with an index reg, maybe its offset or offset,reg */
+ if (i == FAIL) {
+ char *beg_str;
+
+ beg_str=str;
+ for (i=1;i;) {
+ switch (*str++) {
+ case '\0':
+ opP->error="Missing )";
+ return FAIL;
+ case ',': i=0; break;
+ case '(': i++; break;
+ case ')': --i; break;
+ }
+ }
+ /* if (str[-3] == ':') {
+ int siz;
+
+ switch (str[-2]) {
+ case 'b':
+ case 'B':
+ siz=1;
+ break;
+ case 'w':
+ case 'W':
+ siz=2;
+ break;
+ case 'l':
+ case 'L':
+ siz=3;
+ break;
+ default:
+ opP->error="Specified size isn't :w or :l";
+ return FAIL;
+ }
+ opP->con1=add_exp(beg_str,str-4);
+ opP->con1->e_siz=siz;
+ } else */
+ opP->con1=add_exp(beg_str,str-2);
+ /* Should be offset,reg */
+ if (str[-1] == ',') {
+ i=try_index(&str,opP);
+ if (i == FAIL) {
+ opP->error="Malformed index reg";
+ return FAIL;
+ }
+ }
+ }
+ /* We've now got offset) offset,reg) or reg) */
+
+ if (*str == '\0') {
+ /* Th-the-thats all folks */
+ if (opP->reg == FAIL) opP->mode = AINDX; /* Other form of indirect */
+ else if (opP->ireg == FAIL) opP->mode = AOFF;
+ else opP->mode = AINDX;
+ return(OK);
+ }
+ /* Next thing had better be another @ */
+ if (*str != '@' || str[1] != '(') {
+ opP->error = "junk after indirect";
+ return(FAIL);
+ }
+
+ if ((current_architecture & m68020up) == 0) {
+ return(FAIL);
+ } /* if target is not a '20 or better */
+
+ str+=2;
+
+ if (opP->ireg != FAIL) {
+ opP->mode = APRDX;
+
+ i = try_index(&str, opP);
+ if (i != FAIL) {
+ opP->error = "Two index registers! not allowed!";
+ return(FAIL);
+ }
+ } else {
+ i = try_index(&str, opP);
+ }
+
+ if (i == FAIL) {
+ char *beg_str;
+
+ beg_str = str;
+
+ for (i = 1; i; ) {
+ switch (*str++) {
+ case '\0':
+ opP->error="Missing )";
+ return(FAIL);
+ case ',': i=0; break;
+ case '(': i++; break;
+ case ')': --i; break;
+ }
+ }
+
+ opP->con2=add_exp(beg_str,str-2);
+
+ if (str[-1] == ',') {
+ if (opP->ireg != FAIL) {
+ opP->error = "Can't have two index regs";
+ return(FAIL);
+ }
+
+ i = try_index(&str, opP);
+
+ if (i == FAIL) {
+ opP->error = "malformed index reg";
+ return(FAIL);
+ }
+
+ opP->mode = APODX;
+ } else if (opP->ireg != FAIL) {
+ opP->mode = APRDX;
+ } else {
+ opP->mode = AMIND;
+ }
+ } else {
+ opP->mode = APODX;
+ }
+
+ if (*str != '\0') {
+ opP->error="Junk after indirect";
+ return FAIL;
+ }
+ return(OK);
+} /* m68k_ip_op() */
+
+/*
+ *
+ * try_index := data_or_address_register + ')' + SKIP_W
+ * | data_or_address_register + ':' + SKIP_W + size_spec + SKIP_W + multiplier + ')' + SKIP_W
+ *
+ * multiplier := <empty>
+ * | ':' + multiplier_number
+ * ;
+ *
+ * multiplier_number := '1' | '2' | '4' | '8' ;
+ *
+ * size_spec := 'l' | 'L' | 'w' | 'W' ;
+ *
+ * SKIP_W := <empty> | ' ' ;
+ *
+ */
+
+static int try_index(s,opP)
+char **s;
+struct m68k_op *opP;
+{
+ register int i;
+ char *ss;
+#define SKIP_W() { ss++; if (*ss == ' ') ss++;}
+
+ ss= *s;
+ /* SKIP_W(); */
+ i=m68k_reg_parse(&ss);
+ if (!(i >= DATA+0 && i <= ADDR+7)) { /* if i is not DATA or ADDR reg */
+ *s=ss;
+ return FAIL;
+ }
+ opP->ireg=i;
+ /* SKIP_W(); */
+ if (*ss == ')') {
+ opP->isiz=0;
+ opP->imul=1;
+ SKIP_W();
+ *s=ss;
+ return OK;
+ }
+ if (*ss != ':') {
+ opP->error="Missing : in index register";
+ *s=ss;
+ return FAIL;
+ }
+ SKIP_W();
+ switch (*ss) {
+ case 'w':
+ case 'W':
+ opP->isiz=2;
+ break;
+ case 'l':
+ case 'L':
+ opP->isiz=3;
+ break;
+ default:
+ opP->error="Index register size spec not :w or :l";
+ *s=ss;
+ return FAIL;
+ }
+ SKIP_W();
+ if (*ss == ':') {
+ SKIP_W();
+ switch (*ss) {
+ case '1':
+ case '2':
+ case '4':
+ case '8':
+ opP->imul= *ss-'0';
+ break;
+ default:
+ opP->error="index multiplier not 1, 2, 4 or 8";
+ *s=ss;
+ return FAIL;
+ }
+ SKIP_W();
+ } else opP->imul=1;
+ if (*ss != ')') {
+ opP->error="Missing )";
+ *s=ss;
+ return FAIL;
+ }
+ SKIP_W();
+ *s=ss;
+ return OK;
+} /* try_index() */
+
+#ifdef TEST1 /* TEST1 tests m68k_ip_op(), which parses operands */
+main()
+{
+ char buf[128];
+ struct m68k_op thark;
+
+ for (;;) {
+ if (!gets(buf))
+ break;
+ memset(&thark, '\0', sizeof(thark));
+ if (!m68k_ip_op(buf,&thark)) printf("FAIL:");
+ if (thark.error)
+ printf("op1 error %s in %s\n",thark.error,buf);
+ printf("mode %d, reg %d, ",thark.mode,thark.reg);
+ if (thark.b_const)
+ printf("Constant: '%.*s',",1+thark.e_const-thark.b_const,thark.b_const);
+ printf("ireg %d, isiz %d, imul %d ",thark.ireg,thark.isiz,thark.imul);
+ if (thark.b_iadd)
+ printf("Iadd: '%.*s'",1+thark.e_iadd-thark.b_iadd,thark.b_iadd);
+ printf("\n");
+ }
+ exit(0);
+}
+
+#endif
+
+
+static struct hash_control* op_hash = NULL; /* handle of the OPCODE hash table
+ NULL means any use before m68k_ip_begin()
+ will crash */
+
+
+/*
+ * m 6 8 k _ i p ( )
+ *
+ * This converts a string into a 68k instruction.
+ * The string must be a bare single instruction in sun format
+ * with RMS-style 68020 indirects
+ * (example: )
+ *
+ * It provides some error messages: at most one fatal error message (which
+ * stops the scan) and at most one warning message for each operand.
+ * The 68k instruction is returned in exploded form, since we have no
+ * knowledge of how you parse (or evaluate) your expressions.
+ * We do however strip off and decode addressing modes and operation
+ * mnemonic.
+ *
+ * This function's value is a string. If it is not "" then an internal
+ * logic error was found: read this code to assign meaning to the string.
+ * No argument string should generate such an error string:
+ * it means a bug in our code, not in the user's text.
+ *
+ * You MUST have called m68k_ip_begin() once and m86_ip_end() never before using
+ * this function.
+ */
+
+/* JF this function no longer returns a useful value. Sorry */
+void m68k_ip (instring)
+char *instring;
+{
+ register char *p;
+ register struct m68k_op *opP;
+ register struct m68k_incant *opcode;
+ register char *s;
+ register int tmpreg = 0,
+ baseo = 0,
+ outro = 0,
+ nextword;
+ int siz1,
+ siz2;
+ char c;
+ int losing;
+ int opsfound;
+ int reloc_type;
+ char *crack_operand();
+ LITTLENUM_TYPE words[6];
+ LITTLENUM_TYPE *wordp;
+
+ if (*instring == ' ')
+ instring++; /* skip leading whitespace */
+
+ /* Scan up to end of operation-code, which MUST end in end-of-string
+ or exactly 1 space. */
+ for (p = instring; *p != '\0'; p++)
+ if (*p == ' ')
+ break;
+
+
+ if (p == instring) {
+ the_ins.error = "No operator";
+ the_ins.opcode[0] = NULL;
+ /* the_ins.numo=1; */
+ return;
+ }
+
+ /* p now points to the end of the opcode name, probably whitespace.
+ make sure the name is null terminated by clobbering the whitespace,
+ look it up in the hash table, then fix it back. */
+ c = *p;
+ *p = '\0';
+ opcode = (struct m68k_incant *)hash_find (op_hash, instring);
+ *p = c;
+
+ if (opcode == NULL) {
+ the_ins.error = "Unknown operator";
+ the_ins.opcode[0] = NULL;
+ /* the_ins.numo=1; */
+ return;
+ }
+
+ /* found a legitimate opcode, start matching operands */
+ while (*p == ' ') ++p;
+
+ for (opP = &the_ins.operands[0]; *p; opP++) {
+
+ p = crack_operand(p, opP);
+
+ if (opP->error) {
+ the_ins.error=opP->error;
+ return;
+ }
+ }
+
+ opsfound = opP - &the_ins.operands[0];
+
+ /* This ugly hack is to support the floating pt opcodes in their standard form */
+ /* Essentially, we fake a first enty of type COP#1 */
+ if (opcode->m_operands[0] == 'I') {
+ int n;
+
+ for (n=opsfound;n>0;--n)
+ the_ins.operands[n]=the_ins.operands[n-1];
+
+ /* memcpy((char *)(&the_ins.operands[1]), (char *)(&the_ins.operands[0]), opsfound*sizeof(the_ins.operands[0])); */
+ memset((char *)(&the_ins.operands[0]), '\0', sizeof(the_ins.operands[0]));
+ the_ins.operands[0].mode=MSCR;
+ the_ins.operands[0].reg=COPNUM; /* COP #1 */
+ opsfound++;
+ }
+
+ /* We've got the operands. Find an opcode that'll accept them */
+ for (losing = 0; ; ) {
+ /* if we didn't get the right number of ops,
+ or we have no common model with this pattern
+ then reject this pattern. */
+
+ if (opsfound != opcode->m_opnum
+ || ((opcode->m_arch & current_architecture) == 0)) {
+
+ ++losing;
+
+ } else {
+ for (s=opcode->m_operands, opP = &the_ins.operands[0]; *s && !losing; s += 2, opP++) {
+ /* Warning: this switch is huge! */
+ /* I've tried to organize the cases into this order:
+ non-alpha first, then alpha by letter. lower-case goes directly
+ before uppercase counterpart. */
+ /* Code with multiple case ...: gets sorted by the lowest case ...
+ it belongs to. I hope this makes sense. */
+ switch (*s) {
+#ifdef PIC
+ case ' ':
+ /* this operand is just here to indicate a jump-table branch */
+ if (!picmode)
+ losing++;
+ break;
+#endif /* PIC */
+
+ case '!':
+ if (opP->mode == MSCR || opP->mode == IMMED
+ || opP->mode == DREG || opP->mode == AREG
+ || opP->mode == AINC || opP->mode == ADEC
+ || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '#':
+ if (opP->mode != IMMED)
+ losing++;
+ else {
+ long t;
+
+ t=get_num(opP->con1,80);
+ if (s[1] == 'b' && !isbyte(t))
+ losing++;
+ else if (s[1] == 'w' && !isword(t))
+ losing++;
+ }
+ break;
+
+ case '^':
+ case 'T':
+ if (opP->mode != IMMED)
+ losing++;
+ break;
+
+ case '$':
+ if (opP->mode == MSCR || opP->mode == AREG ||
+ opP->mode == IMMED || opP->reg == PC || opP->reg == ZPC || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '%':
+ if (opP->mode == MSCR || opP->reg == PC ||
+ opP->reg == ZPC || opP->mode == REGLST)
+ losing++;
+ break;
+
+
+ case '&':
+ if (opP->mode == MSCR || opP->mode == DREG ||
+ opP->mode == AREG || opP->mode == IMMED || opP->reg == PC || opP->reg == ZPC ||
+ opP->mode == AINC || opP->mode == ADEC || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '*':
+ if (opP->mode == MSCR || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '+':
+ if (opP->mode != AINC)
+ losing++;
+ break;
+
+ case '-':
+ if (opP->mode != ADEC)
+ losing++;
+ break;
+
+ case '/':
+ if (opP->mode == MSCR || opP->mode == AREG ||
+ opP->mode == AINC || opP->mode == ADEC || opP->mode == IMMED || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case ';':
+ if (opP->mode == MSCR || opP->mode == AREG || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '?':
+ if (opP->mode == MSCR || opP->mode == AREG ||
+ opP->mode == AINC || opP->mode == ADEC || opP->mode == IMMED || opP->reg == PC ||
+ opP->reg == ZPC || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '@':
+ if (opP->mode == MSCR || opP->mode == AREG ||
+ opP->mode == IMMED || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case '~': /* For now! (JF FOO is this right?) */
+ if (opP->mode == MSCR || opP->mode == DREG ||
+ opP->mode == AREG || opP->mode == IMMED || opP->reg == PC || opP->reg == ZPC || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case 'A':
+ if (opP->mode != AREG)
+ losing++;
+ break;
+ case 'a':
+ if (opP->mode != AINDR) {
+ ++losing;
+ } /* if not address register indirect */
+ break;
+ case 'B': /* FOO */
+ if (opP->mode != ABSL || (flagseen['S'] && instring[0] == 'j'
+ && instring[1] == 'b'
+ && instring[2] == 's'
+ && instring[3] == 'r'))
+ losing++;
+ break;
+
+ case 'C':
+ if (opP->mode != MSCR || opP->reg != CCR)
+ losing++;
+ break;
+
+ case 'd': /* FOO This mode is a KLUDGE!! */
+ if (opP->mode != AOFF && (opP->mode != ABSL ||
+ opP->con1->e_beg[0] != '(' || opP->con1->e_end[0] != ')'))
+ losing++;
+ break;
+
+ case 'D':
+ if (opP->mode != DREG)
+ losing++;
+ break;
+
+ case 'F':
+ if (opP->mode != MSCR || opP->reg<(FPREG+0) || opP->reg>(FPREG+7))
+ losing++;
+ break;
+
+ case 'I':
+ if (opP->mode != MSCR || opP->reg<COPNUM ||
+ opP->reg >= COPNUM+7)
+ losing++;
+ break;
+
+ case 'J':
+ if (opP->mode != MSCR
+ || opP->reg < USP
+ || opP->reg > URP
+ || cpu_of_arch(current_architecture) < m68010 /* before 68010 had none */
+ || (cpu_of_arch(current_architecture) < m68020
+ && opP->reg != SFC
+ && opP->reg != DFC
+ && opP->reg != USP
+ && opP->reg != VBR) /* 68010's had only these */
+ || (cpu_of_arch(current_architecture) < m68040
+ && opP->reg != SFC
+ && opP->reg != DFC
+ && opP->reg != USP
+ && opP->reg != VBR
+ && opP->reg != CACR
+ && opP->reg != CAAR
+ && opP->reg != MSP
+ && opP->reg != ISP) /* 680[23]0's have only these */
+ || (cpu_of_arch(current_architecture) == m68040 /* 68040 has all but this */
+ && opP->reg == CAAR)) {
+ losing++;
+ } /* doesn't cut it */
+ break;
+
+ case 'k':
+ if (opP->mode != IMMED)
+ losing++;
+ break;
+
+ case 'l':
+ case 'L':
+ if (opP->mode == DREG || opP->mode == AREG || opP->mode == FPREG) {
+ if (s[1] == '8')
+ losing++;
+ else {
+ opP->mode=REGLST;
+ opP->reg=1<<(opP->reg-DATA);
+ }
+ } else if (opP->mode != REGLST) {
+ losing++;
+ } else if (s[1] == '8' && opP->reg&0x0FFffFF)
+ losing++;
+ else if (s[1] == '3' && opP->reg&0x7000000)
+ losing++;
+ break;
+
+ case 'M':
+ if (opP->mode != IMMED)
+ losing++;
+ else {
+ long t;
+
+ t=get_num(opP->con1,80);
+ if (!issbyte(t) || isvar(opP->con1))
+ losing++;
+ }
+ break;
+
+ case 'O':
+ if (opP->mode != DREG && opP->mode != IMMED)
+ losing++;
+ break;
+
+ case 'Q':
+ if (opP->mode != IMMED)
+ losing++;
+ else {
+ long t;
+
+ t=get_num(opP->con1,80);
+ if (t<1 || t>8 || isvar(opP->con1))
+ losing++;
+ }
+ break;
+
+ case 'R':
+ if (opP->mode != DREG && opP->mode != AREG)
+ losing++;
+ break;
+
+ case 's':
+ if (opP->mode != MSCR || !(opP->reg == FPI || opP->reg == FPS || opP->reg == FPC))
+ losing++;
+ break;
+
+ case 'S':
+ if (opP->mode != MSCR || opP->reg != SR)
+ losing++;
+ break;
+
+ case 'U':
+ if (opP->mode != MSCR || opP->reg != USP)
+ losing++;
+ break;
+
+ /* JF these are out of order. We could put them
+ in order if we were willing to put up with
+ bunches of #ifdef m68851s in the code */
+#ifndef NO_68851
+ /* Memory addressing mode used by pflushr */
+ case '|':
+ if (opP->mode == MSCR || opP->mode == DREG ||
+ opP->mode == AREG || opP->mode == REGLST)
+ losing++;
+ break;
+
+ case 'f':
+ if (opP->mode != MSCR || (opP->reg != SFC && opP->reg != DFC))
+ losing++;
+ break;
+
+ case 'P':
+ if (opP->mode != MSCR || (opP->reg != TC && opP->reg != CAL &&
+ opP->reg != VAL && opP->reg != SCC && opP->reg != AC))
+ losing++;
+ break;
+
+ case 'V':
+ if (opP->reg != VAL)
+ losing++;
+ break;
+
+ case 'W':
+ if (opP->mode != MSCR || (opP->reg != DRP && opP->reg != SRP &&
+ opP->reg != CRP))
+ losing++;
+ break;
+
+ case 'X':
+ if (opP->mode != MSCR ||
+ (!(opP->reg >= BAD && opP->reg <= BAD+7) &&
+ !(opP->reg >= BAC && opP->reg <= BAC+7)))
+ losing++;
+ break;
+
+ case 'Y':
+ if (opP->reg != PSR)
+ losing++;
+ break;
+
+ case 'Z':
+ if (opP->reg != PCSR)
+ losing++;
+ break;
+#endif
+ case 'c':
+ if (opP->reg != NC
+ && opP->reg != IC
+ && opP->reg != DC
+ && opP->reg != BC) {
+ losing++;
+ } /* not a cache specifier. */
+ break;
+
+ case '_':
+ if (opP->mode != ABSL) {
+ ++losing;
+ } /* not absolute */
+ break;
+
+ default:
+ as_fatal("Internal error: Operand mode %c unknown in line %s of file \"%s\"",
+ *s, __LINE__, __FILE__);
+ } /* switch on type of operand */
+
+ if (losing) break;
+ } /* for each operand */
+ } /* if immediately wrong */
+
+ if (!losing) {
+ break;
+ } /* got it. */
+
+ opcode = opcode->m_next;
+
+ if (!opcode) {
+ the_ins.error = "instruction/operands mismatch";
+ return;
+ } /* Fell off the end */
+
+ losing = 0;
+ }
+
+ /* now assemble it */
+
+ the_ins.args=opcode->m_operands;
+ the_ins.numargs=opcode->m_opnum;
+ the_ins.numo=opcode->m_codenum;
+ the_ins.opcode[0]=getone(opcode);
+ the_ins.opcode[1]=gettwo(opcode);
+
+ for (s = the_ins.args, opP = &the_ins.operands[0]; *s; s += 2, opP++) {
+ /* This switch is a doozy.
+ Watch the first step; its a big one! */
+ switch (s[0]) {
+
+#ifdef PIC
+ case ' ':
+ /* this operand is just here to indicate a jump-table branch */
+ break;
+#endif /* PIC */
+
+ case '*':
+ case '~':
+ case '%':
+ case ';':
+ case '@':
+ case '!':
+ case '&':
+ case '$':
+ case '?':
+ case '/':
+#ifndef NO_68851
+ case '|':
+#endif
+
+#ifdef PIC
+ /* Use GLOB_DAT for operand references in PIC mode */
+ if (picmode)
+ reloc_type = RELOC_GLOB_DAT;
+ else
+#endif /* PIC */
+ reloc_type = NO_RELOC;
+
+ switch (opP->mode) {
+ int literal;
+
+ case IMMED:
+ tmpreg=0x3c; /* 7.4 */
+ if (*opP->con1->e_beg == ':') {
+ ++opP->con1->e_beg;
+ literal = 1;
+ } else
+ literal = 0;
+ if (strchr("bwl",s[1])) nextword=get_num(opP->con1,80);
+ else nextword=nextword=get_num(opP->con1,0);
+ if (isvar(opP->con1)) {
+#ifdef PIC
+ /* KLUDGE!!! In PIC assembly, an immediate reference to
+ __GLOBAL_OFFSET_TABLE_ is turned into a pc-relative
+ reference to __GLOBAL_OFFSET_TABLE_ - 6,
+ for the sake of Sun compatibility. */
+ if (s[1] == 'l' && picmode && gots(opP->con1)) {
+ offs(opP->con1) -= 6;
+ add_fix(s[1], opP->con1, 1, NO_RELOC);
+ } else
+#endif /* PIC */
+ add_fix(s[1],opP->con1,0,reloc_type);
+ }
+ switch (s[1]) {
+ case 'b':
+ if (!isbyte(nextword))
+ opP->error="operand out of range";
+ addword(nextword);
+ baseo=0;
+ break;
+ case 'w':
+ if (!isword(nextword))
+ opP->error="operand out of range";
+ addword(nextword);
+ baseo=0;
+ break;
+ case 'l':
+ addword(nextword>>16);
+ addword(nextword);
+ baseo=0;
+ break;
+
+ case 'f':
+ baseo=2;
+ outro=8;
+ break;
+ case 'F':
+ baseo=4;
+ outro=11;
+ break;
+ case 'x':
+ baseo=6;
+ outro=15;
+ break;
+ case 'p':
+ baseo=6;
+ outro= -1;
+ break;
+ default:
+ as_fatal("Internal error: Can't decode %c%c in line %s of file \"%s\"",
+ *s, s[1], __LINE__, __FILE__);
+ }
+ if (!baseo)
+ break;
+
+ if (literal) {
+ if (seg(opP->con1) == SEG_BIG)
+ goto bignum;
+ while (baseo -= 2) {
+ addword(0);
+ addword(0);
+ }
+ addword(nextword>>16);
+ addword(nextword);
+ break;
+ }
+
+ /* We gotta put out some float */
+ if (seg(opP->con1) != SEG_BIG) {
+ int_to_gen(nextword);
+ gen_to_words(words,baseo,(long int)outro);
+ for (wordp=words;baseo--;wordp++)
+ addword(*wordp);
+ break;
+ } /* Its BIG */
+ if (offs(opP->con1)>0) {
+ as_warn("Bignum assumed to be binary bit-pattern");
+ bignum:
+ if (offs(opP->con1)>baseo) {
+ as_warn("Bignum too big for %c format; truncated",s[1]);
+ offs(opP->con1)=baseo;
+ }
+ baseo-=offs(opP->con1);
+ for (wordp=generic_bignum+offs(opP->con1)-1;offs(opP->con1)--;--wordp)
+ addword(*wordp);
+ while (baseo--)
+ addword(0);
+ break;
+ }
+ gen_to_words(words,baseo,(long)outro);
+ for (wordp=words;baseo--;wordp++)
+ addword(*wordp);
+ break;
+ case DREG:
+ tmpreg=opP->reg-DATA; /* 0.dreg */
+ break;
+ case AREG:
+ tmpreg=0x08+opP->reg-ADDR; /* 1.areg */
+ break;
+ case AINDR:
+ tmpreg=0x10+opP->reg-ADDR; /* 2.areg */
+ break;
+ case ADEC:
+ tmpreg=0x20+opP->reg-ADDR; /* 4.areg */
+ break;
+ case AINC:
+ tmpreg=0x18+opP->reg-ADDR; /* 3.areg */
+ break;
+ case AOFF:
+
+ nextword=get_num(opP->con1,80);
+ /* Force into index mode. Hope this works */
+
+ /* We do the first bit for 32-bit displacements,
+ and the second bit for 16 bit ones. It is
+ possible that we should make the default be
+ WORD instead of LONG, but I think that'd
+ break GCC, so we put up with a little
+ inefficiency for the sake of working output.
+ */
+
+ if ( !issword(nextword)
+ || ( isvar(opP->con1)
+ && ((opP->con1->e_siz == 0
+ && flagseen['l'] == 0)
+ || opP->con1->e_siz == 3))) {
+
+ if (opP->reg == PC)
+ tmpreg=0x3B; /* 7.3 */
+ else
+ tmpreg=0x30+opP->reg-ADDR; /* 6.areg */
+ if (isvar(opP->con1)) {
+ if (opP->reg == PC && !subs(opP->con1)) {
+ add_frag(adds(opP->con1),
+ offs(opP->con1),
+ TAB(PCLEA,SZ_UNDEF));
+ break;
+ } else {
+ addword(0x0170);
+ add_fix('l',opP->con1,0,reloc_type);
+ }
+ } else
+ addword(0x0170);
+ addword(nextword>>16);
+ } else {
+ if (opP->reg == PC)
+ tmpreg=0x3A; /* 7.2 */
+ else
+ tmpreg=0x28+opP->reg-ADDR; /* 5.areg */
+
+ if (isvar(opP->con1)) {
+ if (opP->reg == PC) {
+ add_fix('w',opP->con1,1,NO_RELOC);
+ } else
+ add_fix('w',opP->con1,0,reloc_type);
+ }
+ }
+ addword(nextword);
+ break;
+
+ case APODX:
+ case AMIND:
+ case APRDX:
+ know(current_architecture & m68020up);
+ /* intentional fall-through */
+ case AINDX:
+ nextword=0;
+ baseo=get_num(opP->con1,80);
+ outro=get_num(opP->con2,80);
+ /* Figure out the 'addressing mode' */
+ /* Also turn on the BASE_DISABLE bit, if needed */
+ if (opP->reg == PC || opP->reg == ZPC) {
+ tmpreg=0x3b; /* 7.3 */
+ if (opP->reg == ZPC)
+ nextword|=0x80;
+ } else if (opP->reg == FAIL) {
+ nextword|=0x80;
+ tmpreg=0x30; /* 6.garbage */
+ } else tmpreg=0x30+opP->reg-ADDR; /* 6.areg */
+
+ siz1= (opP->con1) ? opP->con1->e_siz : 0;
+ siz2= (opP->con2) ? opP->con2->e_siz : 0;
+
+ /* Index register stuff */
+ if (opP->ireg >= DATA+0 && opP->ireg <= ADDR+7) {
+ nextword|=(opP->ireg-DATA)<<12;
+
+ if (opP->isiz == 0 || opP->isiz == 3)
+ nextword|=0x800;
+ switch (opP->imul) {
+ case 1: break;
+ case 2: nextword|=0x200; break;
+ case 4: nextword|=0x400; break;
+ case 8: nextword|=0x600; break;
+ default: as_fatal("failed sanity check.");
+ }
+ /* IF its simple,
+ GET US OUT OF HERE! */
+
+ /* Must be INDEX, with an index
+ register. Address register
+ cannot be ZERO-PC, and either
+ :b was forced, or we know
+ it will fit */
+ if (opP->mode == AINDX
+ && opP->reg != FAIL
+ && opP->reg != ZPC
+ && (siz1 == 1
+ || ( issbyte(baseo)
+ && !isvar(opP->con1)))) {
+ nextword +=baseo&0xff;
+ addword(nextword);
+ if (isvar(opP->con1))
+ add_fix('B',opP->con1,0,reloc_type);
+ break;
+ }
+ } else
+ nextword|=0x40; /* No index reg */
+
+ /* It aint simple */
+ nextword|=0x100;
+ /* If the guy specified a width, we assume that
+ it is wide enough. Maybe it isn't. If so, we lose
+ */
+ switch (siz1) {
+ case 0:
+ if (isvar(opP->con1) || !issword(baseo)) {
+ siz1=3;
+ nextword|=0x30;
+ } else if (baseo == 0)
+ nextword|=0x10;
+ else {
+ nextword|=0x20;
+ siz1=2;
+ }
+ break;
+ case 1:
+ as_warn("Byte dispacement won't work. Defaulting to :w");
+ case 2:
+ nextword|=0x20;
+ break;
+ case 3:
+ nextword|=0x30;
+ break;
+ }
+
+ /* Figure out innner displacement stuff */
+ if (opP->mode != AINDX) {
+ switch (siz2) {
+ case 0:
+ if (isvar(opP->con2) || !issword(outro)) {
+ siz2=3;
+ nextword|=0x3;
+ } else if (outro == 0)
+ nextword|=0x1;
+ else {
+ nextword|=0x2;
+ siz2=2;
+ }
+ break;
+ case 1:
+ as_warn("Byte dispacement won't work. Defaulting to :w");
+ case 2:
+ nextword|=0x2;
+ break;
+ case 3:
+ nextword|=0x3;
+ break;
+ }
+ if (opP->mode == APODX) nextword|=0x04;
+ else if (opP->mode == AMIND) nextword|=0x40;
+ }
+ addword(nextword);
+
+ if (isvar(opP->con1)) {
+ if (opP->reg == PC || opP->reg == ZPC) {
+ add_fix(siz1 == 3 ? 'l' : 'w',opP->con1,1,NO_RELOC);
+ opP->con1->e_exp.X_add_number+=6;
+ } else
+ add_fix(siz1 == 3 ? 'l' : 'w',opP->con1,0,reloc_type);
+ }
+ if (siz1 == 3)
+ addword(baseo>>16);
+ if (siz1)
+ addword(baseo);
+
+ if (isvar(opP->con2)) {
+ if (opP->reg == PC || opP->reg == ZPC) {
+ add_fix(siz2 == 3 ? 'l' : 'w',opP->con2,1,NO_RELOC);
+ opP->con1->e_exp.X_add_number+=6;
+ } else
+ add_fix(siz2 == 3 ? 'l' : 'w',opP->con2,0,reloc_type);
+ }
+ if (siz2 == 3)
+ addword(outro>>16);
+ if (siz2)
+ addword(outro);
+
+ break;
+
+ case ABSL:
+ nextword=get_num(opP->con1,80);
+ switch (opP->con1->e_siz) {
+ default:
+ as_warn("Unknown size for absolute reference");
+ case 0:
+ if (!isvar(opP->con1) && issword(offs(opP->con1))) {
+ tmpreg=0x38; /* 7.0 */
+ addword(nextword);
+ break;
+ }
+ /* Don't generate pc relative code
+ on 68010 and 68000 */
+ if (isvar(opP->con1)
+ && !subs(opP->con1)
+ && seg(opP->con1) == SEG_TEXT
+ && now_seg == SEG_TEXT
+ && cpu_of_arch(current_architecture) >= m68020
+ && !flagseen['S']
+ && !strchr("~%&$?", s[0])) {
+ tmpreg=0x3A; /* 7.2 */
+ add_frag(adds(opP->con1),
+ offs(opP->con1),
+ TAB(PCREL,SZ_UNDEF));
+ break;
+ }
+ case 3: /* Fall through into long */
+ if (isvar(opP->con1))
+ add_fix('l',opP->con1,0,NO_RELOC);
+
+ tmpreg=0x39; /* 7.1 mode */
+ addword(nextword>>16);
+ addword(nextword);
+ break;
+
+ case 2: /* Word */
+ if (isvar(opP->con1))
+ add_fix('w',opP->con1,0,NO_RELOC);
+
+ tmpreg=0x38; /* 7.0 mode */
+ addword(nextword);
+ break;
+ }
+ break;
+ case MSCR:
+ default:
+ as_bad("unknown/incorrect operand");
+ /* abort(); */
+ }
+ install_gen_operand(s[1],tmpreg);
+ break;
+
+ case '#':
+ case '^':
+ switch (s[1]) { /* JF: I hate floating point! */
+ case 'j':
+ tmpreg=70;
+ break;
+ case '8':
+ tmpreg=20;
+ break;
+ case 'C':
+ tmpreg=50;
+ break;
+ case '3':
+ default:
+ tmpreg=80;
+ break;
+ }
+ tmpreg=get_num(opP->con1,tmpreg);
+ if (isvar(opP->con1))
+ add_fix(s[1],opP->con1,0,NO_RELOC);
+ switch (s[1]) {
+ case 'b': /* Danger: These do no check for
+ certain types of overflow.
+ user beware! */
+ if (!isbyte(tmpreg))
+ opP->error="out of range";
+ insop(tmpreg);
+ if (isvar(opP->con1))
+ the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
+ break;
+ case 'w':
+ if (!isword(tmpreg))
+ opP->error="out of range";
+ insop(tmpreg);
+ if (isvar(opP->con1))
+ the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
+ break;
+ case 'l':
+ insop(tmpreg); /* Because of the way insop works, we put these two out backwards */
+ insop(tmpreg>>16);
+ if (isvar(opP->con1))
+ the_ins.reloc[the_ins.nrel-1].n=(opcode->m_codenum)*2;
+ break;
+ case '3':
+ tmpreg&=0xFF;
+ case '8':
+ case 'C':
+ install_operand(s[1],tmpreg);
+ break;
+ default:
+ as_fatal("Internal error: Unknown mode #%c in line %s of file \"%s\"", s[1], __LINE__, __FILE__);
+ }
+ break;
+
+ case '+':
+ case '-':
+ case 'A':
+ case 'a':
+ install_operand(s[1], opP->reg - ADDR);
+ break;
+
+ case 'B':
+ tmpreg = get_num(opP->con1, 80);
+ switch (s[1]) {
+ case 'B':
+ /* Offset is relative to next word */
+ opP->con1->e_exp.X_add_number -= 1;
+ add_fix('B', opP->con1, 1,NO_RELOC);
+ break;
+ case 'W':
+ add_fix('w', opP->con1, 1,NO_RELOC);
+ addword(0);
+ break;
+ case 'L':
+ long_branch:
+ if (cpu_of_arch(current_architecture) < m68020) /* 68000 or 010 */
+ as_warn("Can't use long branches on 68000/68010");
+ the_ins.opcode[the_ins.numo-1]|=0xff;
+ add_fix('l',opP->con1,1,NO_RELOC);
+ addword(0);
+ addword(0);
+ break;
+ case 'g':
+#ifdef PIC
+ /* If we have the optional kludgey 2nd operand,
+ make this go via the jump table. */
+ if (picmode && s[2] == ' ') {
+ the_ins.opcode[the_ins.numo-1] |= 0xFF;
+ add_fix('l', opP->con1, 1, RELOC_JMP_TBL);
+ addword(0);
+ addword(0);
+ break;
+ }
+#endif /* PIC */
+ if (subs(opP->con1)) /* We can't relax it */
+ goto long_branch;
+
+ /* This could either be a symbol, or an
+ absolute address. No matter, the
+ frag hacking will finger it out.
+ Not quite: it can't switch from
+ BRANCH to BCC68000 for the case
+ where opnd is absolute (it needs
+ to use the 68000 hack since no
+ conditional abs jumps). */
+ if (((cpu_of_arch(current_architecture) < m68020) || (0 == adds(opP->con1)))
+ && (the_ins.opcode[0] >= 0x6200)
+ && (the_ins.opcode[0] <= 0x6f00)) {
+ add_frag(adds(opP->con1),offs(opP->con1),TAB(BCC68000,SZ_UNDEF));
+ } else {
+ add_frag(adds(opP->con1),offs(opP->con1),TAB(BRANCH,SZ_UNDEF));
+ }
+ break;
+ case 'w':
+ if (isvar(opP->con1)) {
+ /* check for DBcc instruction */
+ if ((the_ins.opcode[0] & 0xf0f8) == 0x50c8) {
+ /* size varies if patch */
+ /* needed for long form */
+ add_frag(adds(opP->con1),offs(opP->con1),TAB(DBCC,SZ_UNDEF));
+ break;
+ }
+
+ /* Don't ask! */
+ opP->con1->e_exp.X_add_number+=2;
+ add_fix('w',opP->con1,1,NO_RELOC);
+ }
+ addword(0);
+ break;
+ case 'C': /* Fixed size LONG coproc branches */
+ the_ins.opcode[the_ins.numo-1]|=0x40;
+ /* Offset the displacement to be relative to byte disp location */
+ /* Coproc branches don't have a byte disp option, but they are
+ compatible with the ordinary branches, which do... */
+ opP->con1->e_exp.X_add_number+=4;
+ add_fix('l',opP->con1,1,NO_RELOC);
+ addword(0);
+ addword(0);
+ break;
+ case 'c': /* Var size Coprocesssor branches */
+ if (subs(opP->con1)) {
+ add_fix('l',opP->con1,1,NO_RELOC);
+ add_frag((symbolS *)0,(long)0,TAB(FBRANCH,LONG));
+ } else if (adds(opP->con1)) {
+ add_frag(adds(opP->con1),offs(opP->con1),TAB(FBRANCH,SZ_UNDEF));
+ } else {
+ /* add_frag((symbolS *)0,offs(opP->con1),TAB(FBRANCH,SHORT)); */
+ the_ins.opcode[the_ins.numo-1]|=0x40;
+ add_fix('l',opP->con1,1,NO_RELOC);
+ addword(0);
+ addword(4);
+ }
+ break;
+ default:
+ as_fatal("Internal error: operand type B%c unknown in line %s of file \"%s\"",
+ s[1], __LINE__, __FILE__);
+ }
+ break;
+
+ case 'C': /* Ignore it */
+ break;
+
+ case 'd': /* JF this is a kludge */
+ if (opP->mode == AOFF) {
+ install_operand('s',opP->reg-ADDR);
+ } else {
+ char *tmpP;
+
+ tmpP=opP->con1->e_end-2;
+ opP->con1->e_beg++;
+ opP->con1->e_end-=4; /* point to the , */
+ baseo=m68k_reg_parse(&tmpP);
+ if (baseo<ADDR+0 || baseo>ADDR+7) {
+ as_bad("Unknown address reg, using A0");
+ baseo=0;
+ } else baseo-=ADDR;
+ install_operand('s',baseo);
+ }
+ tmpreg=get_num(opP->con1,80);
+ if (!issword(tmpreg)) {
+ as_warn("Expression out of range, using 0");
+ tmpreg=0;
+ }
+ addword(tmpreg);
+ break;
+
+ case 'D':
+ install_operand(s[1],opP->reg-DATA);
+ break;
+
+ case 'F':
+ install_operand(s[1],opP->reg-FPREG);
+ break;
+
+ case 'I':
+ tmpreg=1+opP->reg-COPNUM;
+ if (tmpreg == 8)
+ tmpreg=0;
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'J': /* JF foo */
+ switch (opP->reg) {
+ case SFC: tmpreg=0x000; break;
+ case DFC: tmpreg=0x001; break;
+ case CACR: tmpreg=0x002; break;
+ case TC: tmpreg=0x003; break;
+ case ITT0: tmpreg=0x004; break;
+ case ITT1: tmpreg=0x005; break;
+ case DTT0: tmpreg=0x006; break;
+ case DTT1: tmpreg=0x007; break;
+
+ case USP: tmpreg=0x800; break;
+ case VBR: tmpreg=0x801; break;
+ case CAAR: tmpreg=0x802; break;
+ case MSP: tmpreg=0x803; break;
+ case ISP: tmpreg=0x804; break;
+ case MMUSR: tmpreg=0x805; break;
+ case URP: tmpreg=0x806; break;
+ case SRP: tmpreg=0x807; break;
+ default:
+ as_fatal("failed sanity check.");
+ }
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'k':
+ tmpreg=get_num(opP->con1,55);
+ install_operand(s[1],tmpreg&0x7f);
+ break;
+
+ case 'l':
+ tmpreg=opP->reg;
+ if (s[1] == 'w') {
+ if (tmpreg&0x7FF0000)
+ as_bad("Floating point register in register list");
+ insop(reverse_16_bits(tmpreg));
+ } else {
+ if (tmpreg&0x700FFFF)
+ as_bad("Wrong register in floating-point reglist");
+ install_operand(s[1],reverse_8_bits(tmpreg>>16));
+ }
+ break;
+
+ case 'L':
+ tmpreg=opP->reg;
+ if (s[1] == 'w') {
+ if (tmpreg&0x7FF0000)
+ as_bad("Floating point register in register list");
+ insop(tmpreg);
+ } else if (s[1] == '8') {
+ if (tmpreg&0x0FFFFFF)
+ as_bad("incorrect register in reglist");
+ install_operand(s[1],tmpreg>>24);
+ } else {
+ if (tmpreg&0x700FFFF)
+ as_bad("wrong register in floating-point reglist");
+ else
+ install_operand(s[1],tmpreg>>16);
+ }
+ break;
+
+ case 'M':
+ install_operand(s[1],get_num(opP->con1,60));
+ break;
+
+ case 'O':
+ tmpreg= (opP->mode == DREG)
+ ? 0x20+opP->reg-DATA
+ : (get_num(opP->con1,40)&0x1F);
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'Q':
+ tmpreg=get_num(opP->con1,10);
+ if (tmpreg == 8)
+ tmpreg=0;
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'R':
+ /* This depends on the fact that ADDR registers are
+ eight more than their corresponding DATA regs, so
+ the result will have the ADDR_REG bit set */
+ install_operand(s[1],opP->reg-DATA);
+ break;
+
+ case 's':
+ if (opP->reg == FPI) tmpreg=0x1;
+ else if (opP->reg == FPS) tmpreg=0x2;
+ else if (opP->reg == FPC) tmpreg=0x4;
+ else as_fatal("failed sanity check.");
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'S': /* Ignore it */
+ break;
+
+ case 'T':
+ install_operand(s[1],get_num(opP->con1,30));
+ break;
+
+ case 'U': /* Ignore it */
+ break;
+
+ case 'c':
+ switch (opP->reg) {
+ case NC: tmpreg = 0; break;
+ case DC: tmpreg = 1; break;
+ case IC: tmpreg = 2; break;
+ case BC: tmpreg = 3; break;
+ default:
+ as_fatal("failed sanity check");
+ } /* switch on cache token */
+ install_operand(s[1], tmpreg);
+ break;
+#ifndef NO_68851
+ /* JF: These are out of order, I fear. */
+ case 'f':
+ switch (opP->reg) {
+ case SFC:
+ tmpreg=0;
+ break;
+ case DFC:
+ tmpreg=1;
+ break;
+ default:
+ as_fatal("failed sanity check.");
+ }
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'P':
+ switch (opP->reg) {
+ case TC:
+ tmpreg=0;
+ break;
+ case CAL:
+ tmpreg=4;
+ break;
+ case VAL:
+ tmpreg=5;
+ break;
+ case SCC:
+ tmpreg=6;
+ break;
+ case AC:
+ tmpreg=7;
+ break;
+ default:
+ as_fatal("failed sanity check.");
+ }
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'V':
+ if (opP->reg == VAL)
+ break;
+ as_fatal("failed sanity check.");
+
+ case 'W':
+ switch (opP->reg) {
+
+ case DRP:
+ tmpreg=1;
+ break;
+ case SRP:
+ tmpreg=2;
+ break;
+ case CRP:
+ tmpreg=3;
+ break;
+ default:
+ as_fatal("failed sanity check.");
+ }
+ install_operand(s[1],tmpreg);
+ break;
+
+ case 'X':
+ switch (opP->reg) {
+ case BAD: case BAD+1: case BAD+2: case BAD+3:
+ case BAD+4: case BAD+5: case BAD+6: case BAD+7:
+ tmpreg = (4 << 10) | ((opP->reg - BAD) << 2);
+ break;
+
+ case BAC: case BAC+1: case BAC+2: case BAC+3:
+ case BAC+4: case BAC+5: case BAC+6: case BAC+7:
+ tmpreg = (5 << 10) | ((opP->reg - BAC) << 2);
+ break;
+
+ default:
+ as_fatal("failed sanity check.");
+ }
+ install_operand(s[1], tmpreg);
+ break;
+ case 'Y':
+ know(opP->reg == PSR);
+ break;
+ case 'Z':
+ know(opP->reg == PCSR);
+ break;
+#endif /* m68851 */
+ case '_':
+ tmpreg=get_num(opP->con1,80);
+ install_operand(s[1], tmpreg);
+ break;
+ default:
+ as_fatal("Internal error: Operand type %c unknown in line %s of file \"%s\"", s[0], __LINE__, __FILE__);
+ }
+ }
+ /* By the time whe get here (FINALLY) the_ins contains the complete
+ instruction, ready to be emitted... */
+} /* m68k_ip() */
+
+/*
+ * get_regs := '/' + ?
+ * | '-' + <register>
+ * | '-' + <register> + ?
+ * | <empty>
+ * ;
+ *
+
+ * The idea here must be to scan in a set of registers but I don't
+ * understand it. Looks awfully sloppy to me but I don't have any doc on
+ * this format so...
+
+ *
+ *
+ */
+
+static int get_regs(i,str,opP)
+int i;
+struct m68k_op *opP;
+char *str;
+{
+ /* 26, 25, 24, 23-16, 15-8, 0-7 */
+ /* Low order 24 bits encoded fpc,fps,fpi,fp7-fp0,a7-a0,d7-d0 */
+ unsigned long cur_regs = 0;
+ int reg1,
+ reg2;
+
+#define ADD_REG(x) { if (x == FPI) cur_regs|=(1<<24);\
+else if (x == FPS) cur_regs|=(1<<25);\
+else if (x == FPC) cur_regs|=(1<<26);\
+else cur_regs|=(1<<(x-1)); }
+
+ reg1=i;
+ for (;;) {
+ if (*str == '/') {
+ ADD_REG(reg1);
+ str++;
+ } else if (*str == '-') {
+ str++;
+ reg2=m68k_reg_parse(&str);
+ if (reg2<DATA || reg2 >= FPREG+8 || reg1 == FPI || reg1 == FPS || reg1 == FPC) {
+ opP->error="unknown register in register list";
+ return FAIL;
+ }
+ while (reg1 <= reg2) {
+ ADD_REG(reg1);
+ reg1++;
+ }
+ if (*str == '\0')
+ break;
+ } else if (*str == '\0') {
+ ADD_REG(reg1);
+ break;
+ } else {
+ opP->error="unknow character in register list";
+ return FAIL;
+ }
+ /* DJA -- Bug Fix. Did't handle d1-d2/a1 until the following instruction was added */
+ if (*str == '/')
+ str ++;
+ reg1=m68k_reg_parse(&str);
+ if ((reg1<DATA || reg1 >= FPREG+8) && !(reg1 == FPI || reg1 == FPS || reg1 == FPC)) {
+ opP->error="unknown register in register list";
+ return FAIL;
+ }
+ }
+ opP->reg=cur_regs;
+ return OK;
+} /* get_regs() */
+
+static int reverse_16_bits(in)
+int in;
+{
+ int out=0;
+ int n;
+
+ static int mask[16] = {
+ 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
+ 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000
+ };
+ for (n=0;n<16;n++) {
+ if (in&mask[n])
+ out|=mask[15-n];
+ }
+ return out;
+} /* reverse_16_bits() */
+
+static int reverse_8_bits(in)
+int in;
+{
+ int out=0;
+ int n;
+
+ static int mask[8] = {
+ 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
+ };
+
+ for (n=0;n<8;n++) {
+ if (in&mask[n])
+ out|=mask[7-n];
+ }
+ return out;
+} /* reverse_8_bits() */
+
+static void install_operand(mode,val)
+int mode;
+int val;
+{
+ switch (mode) {
+ case 's':
+ the_ins.opcode[0]|=val & 0xFF; /* JF FF is for M kludge */
+ break;
+ case 'd':
+ the_ins.opcode[0]|=val<<9;
+ break;
+ case '1':
+ the_ins.opcode[1]|=val<<12;
+ break;
+ case '2':
+ the_ins.opcode[1]|=val<<6;
+ break;
+ case '3':
+ the_ins.opcode[1]|=val;
+ break;
+ case '4':
+ the_ins.opcode[2]|=val<<12;
+ break;
+ case '5':
+ the_ins.opcode[2]|=val<<6;
+ break;
+ case '6':
+ /* DANGER! This is a hack to force cas2l and cas2w cmds
+ to be three words long! */
+ the_ins.numo++;
+ the_ins.opcode[2]|=val;
+ break;
+ case '7':
+ the_ins.opcode[1]|=val<<7;
+ break;
+ case '8':
+ the_ins.opcode[1]|=val<<10;
+ break;
+#ifndef NO_68851
+ case '9':
+ the_ins.opcode[1]|=val<<5;
+ break;
+#endif
+
+ case 't':
+ the_ins.opcode[1]|=(val<<10)|(val<<7);
+ break;
+ case 'D':
+ the_ins.opcode[1]|=(val<<12)|val;
+ break;
+ case 'g':
+ the_ins.opcode[0]|=val=0xff;
+ break;
+ case 'i':
+ the_ins.opcode[0]|=val<<9;
+ break;
+ case 'C':
+ the_ins.opcode[1]|=val;
+ break;
+ case 'j':
+ the_ins.opcode[1]|=val;
+ the_ins.numo++; /* What a hack */
+ break;
+ case 'k':
+ the_ins.opcode[1]|=val<<4;
+ break;
+ case 'b':
+ case 'w':
+ case 'l':
+ break;
+ case 'e':
+ the_ins.opcode[0] |= (val << 6);
+ break;
+ case 'L':
+ the_ins.opcode[1] = (val >> 16);
+ the_ins.opcode[2] = val & 0xffff;
+ break;
+ case 'c':
+ default:
+ as_fatal("failed sanity check.");
+ }
+} /* install_operand() */
+
+static void install_gen_operand(mode,val)
+int mode;
+int val;
+{
+ switch (mode) {
+ case 's':
+ the_ins.opcode[0]|=val;
+ break;
+ case 'd':
+ /* This is a kludge!!! */
+ the_ins.opcode[0]|=(val&0x07)<<9|(val&0x38)<<3;
+ break;
+ case 'b':
+ case 'w':
+ case 'l':
+ case 'f':
+ case 'F':
+ case 'x':
+ case 'p':
+ the_ins.opcode[0]|=val;
+ break;
+ /* more stuff goes here */
+ default:
+ as_fatal("failed sanity check.");
+ }
+} /* install_gen_operand() */
+
+/*
+ * verify that we have some number of paren pairs, do m68k_ip_op(), and
+ * then deal with the bitfield hack.
+ */
+
+static char *crack_operand(str,opP)
+register char *str;
+register struct m68k_op *opP;
+{
+ register int parens;
+ register int c;
+ register char *beg_str;
+
+ if (!str) {
+ return str;
+ }
+ beg_str=str;
+ for (parens=0;*str && (parens>0 || notend(str));str++) {
+ if (*str == '(') parens++;
+ else if (*str == ')') {
+ if (!parens) { /* ERROR */
+ opP->error="Extra )";
+ return str;
+ }
+ --parens;
+ }
+ }
+ if (!*str && parens) { /* ERROR */
+ opP->error="Missing )";
+ return str;
+ }
+ c= *str;
+ *str='\0';
+ if (m68k_ip_op(beg_str,opP) == FAIL) {
+ *str=c;
+ return str;
+ }
+ *str=c;
+ if (c == '}')
+ c= *++str; /* JF bitfield hack */
+ if (c) {
+ c= *++str;
+ if (!c)
+ as_bad("Missing operand");
+ }
+ return str;
+}
+
+/* See the comment up above where the #define notend(... is */
+#if 0
+notend(s)
+char *s;
+{
+ if (*s == ',') return 0;
+ if (*s == '{' || *s == '}')
+ return 0;
+ if (*s != ':') return 1;
+ /* This kludge here is for the division cmd, which is a kludge */
+ if (index("aAdD#",s[1])) return 0;
+ return 1;
+}
+#endif
+
+/*
+ * Generate a new fixup for one of the relocs in the_ins.
+ */
+static void
+ make_fix(m, where)
+int m;
+char *where;
+{
+ int n;
+
+ switch (the_ins.reloc[m].wid) {
+ case 'B':
+ case 'b':
+ n=1;
+ break;
+ case '3':
+ case 'w':
+ n=2;
+ break;
+ case 'l':
+ n=4;
+ break;
+ default:
+ as_fatal("Don't know how to figure width of %c in md_assemble()",the_ins.reloc[m].wid);
+ }
+ fix_new(frag_now,
+ where - frag_now->fr_literal + the_ins.reloc[m].n,
+ n,
+ the_ins.reloc[m].add,
+ the_ins.reloc[m].sub,
+ the_ins.reloc[m].off,
+ the_ins.reloc[m].pcrel,
+ the_ins.reloc[m].rtype
+#ifdef PIC
+ , the_ins.reloc[m].got
+#endif /* PIC */
+ );
+#ifdef PIC
+ if (the_ins.reloc[m].rtype == RELOC_GLOB_DAT
+ && the_ins.reloc[m].add != NULL)
+ the_ins.reloc[m].add->sy_forceout = 1;
+#endif /* PIC */
+}
+
+/* This is the guts of the machine-dependent assembler. STR points to a
+ machine dependent instruction. This function is supposed to emit
+ the frags/bytes it assembles to.
+ */
+void
+ md_assemble(str)
+char *str;
+{
+ char *er;
+ short *fromP;
+ char *toP = NULL;
+ int m,n = 0;
+ char *to_beg_P;
+ int shorts_this_frag;
+
+
+ if (current_architecture == 0) {
+ current_architecture = (m68020
+#ifndef NO_68881
+ | m68881
+#endif
+#ifndef NO_68851
+ | m68851
+#endif
+ );
+ } /* default current_architecture */
+
+ memset((char *)(&the_ins), '\0', sizeof(the_ins)); /* JF for paranoia sake */
+ m68k_ip(str);
+ er=the_ins.error;
+ if (!er) {
+ for (n=the_ins.numargs;n;--n)
+ if (the_ins.operands[n].error) {
+ er=the_ins.operands[n].error;
+ break;
+ }
+ }
+ if (er) {
+ as_bad("\"%s\" -- Statement '%s' ignored",er,str);
+ return;
+ }
+
+ if (the_ins.nfrag == 0) { /* No frag hacking involved; just put it out */
+ toP=frag_more(2*the_ins.numo);
+ fromP= &the_ins.opcode[0];
+ for (m=the_ins.numo;m;--m) {
+ md_number_to_chars(toP,(long)(*fromP),2);
+ toP+=2;
+ fromP++;
+ }
+ /* put out symbol-dependent info */
+ for (m = 0; m < the_ins.nrel; m++) {
+ make_fix(m, toP-the_ins.numo*2);
+ }
+ return;
+ }
+
+ /* There's some frag hacking */
+ for (n=0,fromP= &the_ins.opcode[0];n<the_ins.nfrag;n++) {
+ int wid;
+
+ if (n == 0) wid=2*the_ins.fragb[n].fragoff;
+ else wid=2*(the_ins.numo-the_ins.fragb[n-1].fragoff);
+ toP=frag_more(wid);
+ to_beg_P=toP;
+ shorts_this_frag=0;
+ for (m=wid/2;m;--m) {
+ md_number_to_chars(toP,(long)(*fromP),2);
+ toP+=2;
+ fromP++;
+ shorts_this_frag++;
+ }
+ for (m=0;m<the_ins.nrel;m++) {
+ if ((the_ins.reloc[m].n) >= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */) {
+ the_ins.reloc[m].n-= 2*shorts_this_frag /* 2*the_ins.fragb[n].fragoff */;
+ break;
+ }
+ if (the_ins.reloc[m].wid == 0)
+ continue;
+ make_fix(m, toP-the_ins.numo*2);
+ the_ins.reloc[m].wid=0;
+ }
+ /* know(the_ins.fragb[n].fadd); */
+ (void)frag_var(rs_machine_dependent,10,0,(relax_substateT)(the_ins.fragb[n].fragty),
+ the_ins.fragb[n].fadd,the_ins.fragb[n].foff,to_beg_P);
+ }
+ n=(the_ins.numo-the_ins.fragb[n-1].fragoff);
+ shorts_this_frag=0;
+ if (n) {
+ toP=frag_more(n*sizeof(short));
+ while (n--) {
+ md_number_to_chars(toP,(long)(*fromP),2);
+ toP+=2;
+ fromP++;
+ shorts_this_frag++;
+ }
+ }
+ for (m=0;m<the_ins.nrel;m++) {
+ if (the_ins.reloc[m].wid == 0)
+ continue;
+ make_fix(m, toP - /* the_ins.numo */ shorts_this_frag*2);
+ }
+}
+
+/* This function is called once, at assembler startup time. This should
+ set up all the tables, etc that the MD part of the assembler needs
+ */
+void
+ md_begin()
+{
+ /*
+ * md_begin -- set up hash tables with 68000 instructions.
+ * similar to what the vax assembler does. ---phr
+ */
+ /* RMS claims the thing to do is take the m68k-opcode.h table, and make
+ a copy of it at runtime, adding in the information we want but isn't
+ there. I think it'd be better to have an awk script hack the table
+ at compile time. Or even just xstr the table and use it as-is. But
+ my lord ghod hath spoken, so we do it this way. Excuse the ugly var
+ names. */
+
+ register const struct m68k_opcode *ins;
+ register struct m68k_incant *hack,
+ *slak;
+ register char *retval = 0; /* empty string, or error msg text */
+ register unsigned int i;
+ register char c;
+
+ if ((op_hash = hash_new()) == NULL)
+ as_fatal("Virtual memory exhausted");
+
+ obstack_begin(&robyn,4000);
+ for (ins = m68k_opcodes; ins < endop; ins++) {
+ hack=slak=(struct m68k_incant *)obstack_alloc(&robyn,sizeof(struct m68k_incant));
+ do {
+ /* we *could* ignore insns that don't match our
+ arch here but just leaving them out of the
+ hash. */
+ slak->m_operands=ins->args;
+ slak->m_opnum=strlen(slak->m_operands)/2;
+ slak->m_arch = ins->arch;
+ slak->m_opcode=ins->opcode;
+ /* This is kludgey */
+ slak->m_codenum=((ins->match)&0xffffL) ? 2 : 1;
+ if ((ins+1) != endop && !strcmp(ins->name,(ins+1)->name)) {
+ slak->m_next=(struct m68k_incant *) obstack_alloc(&robyn,sizeof(struct m68k_incant));
+ ins++;
+ } else
+ slak->m_next=0;
+ slak=slak->m_next;
+ } while (slak);
+
+ retval = hash_insert (op_hash, ins->name,(char *)hack);
+ /* Didn't his mommy tell him about null pointers? */
+ if (retval && *retval)
+ as_fatal("Internal Error: Can't hash %s: %s",ins->name,retval);
+ }
+
+ for (i = 0; i < sizeof(mklower_table) ; i++)
+ mklower_table[i] = (isupper(c = (char) i)) ? tolower(c) : c;
+
+ for (i = 0 ; i < sizeof(notend_table) ; i++) {
+ notend_table[i] = 0;
+ alt_notend_table[i] = 0;
+ }
+ notend_table[','] = 1;
+ notend_table['{'] = 1;
+ notend_table['}'] = 1;
+ alt_notend_table['a'] = 1;
+ alt_notend_table['A'] = 1;
+ alt_notend_table['d'] = 1;
+ alt_notend_table['D'] = 1;
+ alt_notend_table['#'] = 1;
+ alt_notend_table['f'] = 1;
+ alt_notend_table['F'] = 1;
+#ifdef REGISTER_PREFIX
+ alt_notend_table[REGISTER_PREFIX] = 1;
+#endif
+}
+
+#if 0
+#define notend(s) ((*s == ',' || *s == '}' || *s == '{' \
+ || (*s == ':' && strchr("aAdD#", s[1]))) \
+ ? 0 : 1)
+#endif
+
+/* This funciton is called once, before the assembler exits. It is
+ supposed to do any final cleanup for this part of the assembler.
+ */
+void
+ md_end()
+{
+}
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+char *
+ md_atof(type,litP,sizeP)
+char type;
+char *litP;
+int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee();
+
+ switch (type) {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to MD_ATOF()";
+ }
+ t=atof_ieee(input_line_pointer,type,words);
+ if (t)
+ input_line_pointer=t;
+
+ *sizeP=prec * sizeof(LITTLENUM_TYPE);
+ for (wordP=words;prec--;) {
+ md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
+ litP+=sizeof(LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
+ for use in the a.out file, and stores them in the array pointed to by buf.
+ This knows about the endian-ness of the target machine and does
+ THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
+ 2 (short) and 4 (long) Floating numbers are put out as a series of
+ LITTLENUMS (shorts, here at least)
+ */
+void
+ md_number_to_chars(buf, val, n)
+char *buf;
+long val;
+int n;
+{
+ switch (n) {
+ case 1:
+ *buf++=val;
+ break;
+ case 2:
+ *buf++=(val>>8);
+ *buf++=val;
+ break;
+ case 4:
+ *buf++=(val>>24);
+ *buf++=(val>>16);
+ *buf++=(val>>8);
+ *buf++=val;
+ break;
+ default:
+ as_fatal("failed sanity check.");
+ }
+}
+
+void
+ md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ switch (fixP->fx_size) {
+ case 1:
+ *buf++ = val;
+ break;
+ case 2:
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ case 4:
+ *buf++ = (val >> 24);
+ *buf++ = (val >> 16);
+ *buf++ = (val >> 8);
+ *buf++ = val;
+ break;
+ default:
+ BAD_CASE (fixP->fx_size);
+ }
+}
+
+
+/* *fragP has been relaxed to its final size, and now needs to have
+ the bytes inside it modified to conform to the new size There is UGLY
+ MAGIC here. ..
+ */
+void
+ md_convert_frag(headers, fragP)
+object_headers *headers;
+register fragS *fragP;
+{
+ long disp;
+ long ext = 0;
+
+ /* Address in object code of the displacement. */
+ register int object_address = fragP->fr_fix + fragP->fr_address;
+
+#ifdef IBM_COMPILER_SUX
+ /* This is wrong but it convinces the native rs6000 compiler to
+ generate the code we want. */
+ register char *buffer_address = fragP->fr_literal;
+ buffer_address += fragP->fr_fix;
+#else /* IBM_COMPILER_SUX */
+ /* Address in gas core of the place to store the displacement. */
+ register char *buffer_address = fragP->fr_fix + fragP->fr_literal;
+#endif /* IBM_COMPILER_SUX */
+
+ /* No longer true: know(fragP->fr_symbol); */
+
+ /* The displacement of the address, from current location. */
+ disp = fragP->fr_symbol ? S_GET_VALUE(fragP->fr_symbol) : 0;
+ disp = (disp + fragP->fr_offset) - object_address;
+
+ switch (fragP->fr_subtype) {
+ case TAB(BCC68000,BYTE):
+ case TAB(BRANCH,BYTE):
+ know(issbyte(disp));
+ if (disp == 0)
+ as_bad("short branch with zero offset: use :w");
+ fragP->fr_opcode[1]=disp;
+ ext=0;
+ break;
+ case TAB(DBCC,SHORT):
+ know(issword(disp));
+ ext=2;
+ break;
+ case TAB(BCC68000,SHORT):
+ case TAB(BRANCH,SHORT):
+ know(issword(disp));
+ fragP->fr_opcode[1]=0x00;
+ ext=2;
+ break;
+ case TAB(BRANCH,LONG):
+ if (cpu_of_arch(current_architecture) < m68020) {
+ if (fragP->fr_opcode[0] == 0x61) {
+ fragP->fr_opcode[0]= 0x4E;
+ fragP->fr_opcode[1]= 0xB9; /* JBSR with ABSL LONG offset */
+ subseg_change(SEG_TEXT, 0);
+
+ fix_new(fragP,
+ fragP->fr_fix,
+ 4,
+ fragP->fr_symbol,
+ 0,
+ fragP->fr_offset,
+ 0,
+ FIX_NO_RELOC);
+
+ fragP->fr_fix+=4;
+ ext=0;
+ } else if (fragP->fr_opcode[0] == 0x60) {
+ fragP->fr_opcode[0]= 0x4E;
+ fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */
+ subseg_change(SEG_TEXT, 0);
+ fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset,0,
+ FIX_NO_RELOC);
+ fragP->fr_fix+=4;
+ ext=0;
+ } else {
+ as_bad("Long branch offset not supported.");
+ }
+ } else {
+ fragP->fr_opcode[1]=0xff;
+ ext=4;
+ }
+ break;
+ case TAB(BCC68000,LONG):
+ /* only Bcc 68000 instructions can come here */
+ /* change bcc into b!cc/jmp absl long */
+ fragP->fr_opcode[0] ^= 0x01; /* invert bcc */
+ fragP->fr_opcode[1] = 0x6; /* branch offset = 6 */
+
+ /* JF: these used to be fr_opcode[2,3], but they may be in a
+ different frag, in which case refering to them is a no-no.
+ Only fr_opcode[0,1] are guaranteed to work. */
+ *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */
+ *buffer_address++ = 0xf9;
+ fragP->fr_fix += 2; /* account for jmp instruction */
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset,0,
+ FIX_NO_RELOC);
+ fragP->fr_fix += 4;
+ ext=0;
+ break;
+ case TAB(DBCC,LONG):
+ /* only DBcc 68000 instructions can come here */
+ /* change dbcc into dbcc/jmp absl long */
+ /* JF: these used to be fr_opcode[2-7], but that's wrong */
+ *buffer_address++ = 0x00; /* branch offset = 4 */
+ *buffer_address++ = 0x04;
+ *buffer_address++ = 0x60; /* put in bra pc+6 */
+ *buffer_address++ = 0x06;
+ *buffer_address++ = 0x4e; /* put in jmp long (0x4ef9) */
+ *buffer_address++ = 0xf9;
+
+ fragP->fr_fix += 6; /* account for bra/jmp instructions */
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset,0,
+ FIX_NO_RELOC);
+ fragP->fr_fix += 4;
+ ext=0;
+ break;
+ case TAB(FBRANCH,SHORT):
+ know((fragP->fr_opcode[1]&0x40) == 0);
+ ext=2;
+ break;
+ case TAB(FBRANCH,LONG):
+ fragP->fr_opcode[1]|=0x40; /* Turn on LONG bit */
+ ext=4;
+ break;
+ case TAB(PCREL,SHORT):
+ ext=2;
+ break;
+ case TAB(PCREL,LONG):
+ /* The thing to do here is force it to ABSOLUTE LONG, since
+ PCREL is really trying to shorten an ABSOLUTE address anyway */
+ /* JF FOO This code has not been tested */
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0, fragP->fr_offset, 0, FIX_NO_RELOC);
+ if ((fragP->fr_opcode[1] & 0x3F) != 0x3A)
+ as_bad("Internal error (long PC-relative operand) for insn 0x%04lx at 0x%lx",
+ fragP->fr_opcode[0],fragP->fr_address);
+ fragP->fr_opcode[1]&= ~0x3F;
+ fragP->fr_opcode[1]|=0x39; /* Mode 7.1 */
+ fragP->fr_fix+=4;
+ /* md_number_to_chars(buffer_address,
+ (long)(fragP->fr_symbol->sy_value + fragP->fr_offset),
+ 4); */
+ ext=0;
+ break;
+ case TAB(PCLEA,SHORT):
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol, (symbolS *) 0, fragP->fr_offset, 1, FIX_NO_RELOC);
+ fragP->fr_opcode[1] &= ~0x3F;
+ fragP->fr_opcode[1] |= 0x3A;
+ ext=2;
+ break;
+ case TAB(PCLEA,LONG):
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol, (symbolS *) 0, fragP->fr_offset + 2, 1, FIX_NO_RELOC);
+ *buffer_address++ = 0x01;
+ *buffer_address++ = 0x70;
+ fragP->fr_fix+=2;
+ /* buffer_address+=2; */
+ ext=4;
+ break;
+
+} /* switch on subtype */
+
+ if (ext) {
+ md_number_to_chars(buffer_address, (long) disp, (int) ext);
+ fragP->fr_fix += ext;
+ /* H_SET_TEXT_SIZE(headers, H_GET_TEXT_SIZE(headers) + ext); */
+ } /* if extending */
+
+ return;
+} /* md_convert_frag() */
+
+/* Force truly undefined symbols to their maximum size, and generally set up
+ the frag list to be relaxed
+ */
+int md_estimate_size_before_relax(fragP, segment)
+register fragS *fragP;
+segT segment;
+{
+ int old_fix;
+ register char *buffer_address = fragP->fr_fix + fragP->fr_literal;
+
+ old_fix = fragP->fr_fix;
+
+ /* handle SZ_UNDEF first, it can be changed to BYTE or SHORT */
+ switch (fragP->fr_subtype) {
+
+ case TAB(BRANCH,SZ_UNDEF): {
+ if ((fragP->fr_symbol != NULL) /* Not absolute */
+ && S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ fragP->fr_subtype = TAB(TABTYPE(fragP->fr_subtype), BYTE);
+ break;
+ } else if ((fragP->fr_symbol == 0) || (cpu_of_arch(current_architecture) < m68020)) {
+ /* On 68000, or for absolute value, switch to abs long */
+ /* FIXME, we should check abs val, pick short or long */
+ if (fragP->fr_opcode[0] == 0x61) {
+ fragP->fr_opcode[0]= 0x4E;
+ fragP->fr_opcode[1]= 0xB9; /* JSR with ABSL LONG offset */
+ subseg_change(SEG_TEXT, 0);
+ fix_new(fragP, fragP->fr_fix, 4,
+ fragP->fr_symbol, 0, fragP->fr_offset, 0, FIX_NO_RELOC);
+ fragP->fr_fix+=4;
+ frag_wane(fragP);
+ } else if (fragP->fr_opcode[0] == 0x60) {
+ fragP->fr_opcode[0]= 0x4E;
+ fragP->fr_opcode[1]= 0xF9; /* JMP with ABSL LONG offset */
+ subseg_change(SEG_TEXT, 0);
+ fix_new(fragP, fragP->fr_fix, 4,
+ fragP->fr_symbol, 0, fragP->fr_offset, 0, FIX_NO_RELOC);
+ fragP->fr_fix+=4;
+ frag_wane(fragP);
+ } else {
+ as_warn("Long branch offset to extern symbol not supported.");
+ }
+ } else if (flagseen['l']) { /* Symbol is still undefined. Make it simple */
+ fix_new(fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
+ (symbolS *) 0, fragP->fr_offset, 1, FIX_NO_RELOC);
+ fragP->fr_fix += 2;
+ fragP->fr_opcode[1] = 0x00;
+ frag_wane(fragP);
+ } else {
+ fix_new(fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
+ (symbolS *) 0, fragP->fr_offset, 1,
+#ifdef PIC
+ /* With -k, make all external branches go via the jump table. */
+ (picmode? RELOC_JMP_TBL: NO_RELOC), NULL
+#else
+ NO_RELOC
+#endif
+ );
+ fragP->fr_fix += 4;
+ fragP->fr_opcode[1] = 0xff;
+ frag_wane(fragP);
+ break;
+ }
+
+ break;
+ } /* case TAB(BRANCH,SZ_UNDEF) */
+
+ case TAB(FBRANCH,SZ_UNDEF): {
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment || flagseen['l']) {
+ fragP->fr_subtype = TAB(FBRANCH,SHORT);
+ fragP->fr_var += 2;
+ } else {
+ fragP->fr_subtype = TAB(FBRANCH,LONG);
+ fragP->fr_var += 4;
+ }
+ break;
+ } /* TAB(FBRANCH,SZ_UNDEF) */
+
+ case TAB(PCREL,SZ_UNDEF): {
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment || flagseen['l']) {
+ fragP->fr_subtype = TAB(PCREL,SHORT);
+ fragP->fr_var += 2;
+ } else {
+ fragP->fr_subtype = TAB(PCREL,LONG);
+ fragP->fr_var += 4;
+ }
+ break;
+ } /* TAB(PCREL,SZ_UNDEF) */
+
+ case TAB(BCC68000,SZ_UNDEF): {
+ if ((fragP->fr_symbol != NULL)
+ && S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ fragP->fr_subtype=TAB(BCC68000,BYTE);
+ break;
+ }
+ /* only Bcc 68000 instructions can come here */
+ /* change bcc into b!cc/jmp absl long */
+ fragP->fr_opcode[0] ^= 0x01; /* invert bcc */
+ if (flagseen['l']) {
+ fragP->fr_opcode[1] = 0x04; /* branch offset = 6 */
+ /* JF: these were fr_opcode[2,3] */
+ buffer_address[0] = 0x4e; /* put in jmp long (0x4ef9) */
+ buffer_address[1] = 0xf8;
+ fragP->fr_fix += 2; /* account for jmp instruction */
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0,
+ fragP->fr_offset, 0, FIX_NO_RELOC);
+ fragP->fr_fix += 2;
+ } else {
+ fragP->fr_opcode[1] = 0x06; /* branch offset = 6 */
+ /* JF: these were fr_opcode[2,3] */
+ buffer_address[2] = 0x4e; /* put in jmp long (0x4ef9) */
+ buffer_address[3] = 0xf9;
+ fragP->fr_fix += 2; /* account for jmp instruction */
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 0, FIX_NO_RELOC);
+ fragP->fr_fix += 4;
+ }
+ frag_wane(fragP);
+ break;
+ } /* case TAB(BCC68000,SZ_UNDEF) */
+
+ case TAB(DBCC,SZ_UNDEF): {
+ if (fragP->fr_symbol != NULL && S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ fragP->fr_subtype=TAB(DBCC,SHORT);
+ fragP->fr_var+=2;
+ break;
+ }
+ /* only DBcc 68000 instructions can come here */
+ /* change dbcc into dbcc/jmp absl long */
+ /* JF: these used to be fr_opcode[2-4], which is wrong. */
+ buffer_address[0] = 0x00; /* branch offset = 4 */
+ buffer_address[1] = 0x04;
+ buffer_address[2] = 0x60; /* put in bra pc + ... */
+
+ if (flagseen['l']) {
+ /* JF: these were fr_opcode[5-7] */
+ buffer_address[3] = 0x04; /* plus 4 */
+ buffer_address[4] = 0x4e;/* Put in Jump Word */
+ buffer_address[5] = 0xf8;
+ fragP->fr_fix += 6; /* account for bra/jmp instruction */
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, fragP->fr_fix, 2, fragP->fr_symbol, 0,
+ fragP->fr_offset, 0, FIX_NO_RELOC);
+ fragP->fr_fix += 2;
+ } else {
+ /* JF: these were fr_opcode[5-7] */
+ buffer_address[3] = 0x06; /* Plus 6 */
+ buffer_address[4] = 0x4e; /* put in jmp long (0x4ef9) */
+ buffer_address[5] = 0xf9;
+ fragP->fr_fix += 6; /* account for bra/jmp instruction */
+ subseg_change(SEG_TEXT,0);
+ fix_new(fragP, fragP->fr_fix, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 0, FIX_NO_RELOC);
+ fragP->fr_fix += 4;
+ }
+
+ frag_wane(fragP);
+ break;
+ } /* case TAB(DBCC,SZ_UNDEF) */
+
+ case TAB(PCLEA,SZ_UNDEF): {
+ if ((S_GET_SEGMENT(fragP->fr_symbol)) == segment || flagseen['l']) {
+ fragP->fr_subtype=TAB(PCLEA,SHORT);
+ fragP->fr_var+=2;
+ } else {
+ fragP->fr_subtype=TAB(PCLEA,LONG);
+ fragP->fr_var+=6;
+ }
+ break;
+ } /* TAB(PCLEA,SZ_UNDEF) */
+
+ default:
+ break;
+
+ } /* switch on subtype looking for SZ_UNDEF's. */
+
+ /* now that SZ_UNDEF are taken care of, check others */
+ switch (fragP->fr_subtype) {
+ case TAB(BCC68000,BYTE):
+ case TAB(BRANCH,BYTE):
+ /* We can't do a short jump to the next instruction,
+ so we force word mode. */
+ if (fragP->fr_symbol && S_GET_VALUE(fragP->fr_symbol) == 0 &&
+ fragP->fr_symbol->sy_frag == fragP->fr_next) {
+ fragP->fr_subtype=TAB(TABTYPE(fragP->fr_subtype),SHORT);
+ fragP->fr_var+=2;
+ }
+ break;
+ default:
+ break;
+}
+ return fragP->fr_var + fragP->fr_fix - old_fix;
+}
+
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+/* the bit-field entries in the relocation_info struct plays hell
+ with the byte-order problems of cross-assembly. So as a hack,
+ I added this mach. dependent ri twiddler. Ugly, but it gets
+ you there. -KWK */
+/* on m68k: first 4 bytes are normal unsigned long, next three bytes
+ are symbolnum, most sig. byte first. Last byte is broken up with
+ bit 7 as pcrel, bits 6 & 5 as length, bit 4 as pcrel, and the lower
+ nibble as nuthin. (on Sun 3 at least) */
+/* Translate the internal relocation information into target-specific
+ format. */
+#ifdef comment
+void
+ md_ri_to_chars(the_bytes, ri)
+char *the_bytes;
+struct reloc_info_generic *ri;
+{
+ /* this is easy */
+ md_number_to_chars(the_bytes, ri->r_address, 4);
+ /* now the fun stuff */
+ the_bytes[4] = (ri->r_symbolnum >> 16) & 0x0ff;
+ the_bytes[5] = (ri->r_symbolnum >> 8) & 0x0ff;
+ the_bytes[6] = ri->r_symbolnum & 0x0ff;
+ the_bytes[7] = (((ri->r_pcrel << 7) & 0x80) | ((ri->r_length << 5) & 0x60) |
+ ((ri->r_extern << 4) & 0x10));
+}
+#endif /* comment */
+
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };
+ long r_symbolnum;
+ int r_flags;
+
+ know(fixP->fx_addsy != NULL);
+
+ md_number_to_chars(where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy)
+ ? S_GET_TYPE(fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+ r_flags = (fixP->fx_pcrel? 0x80: 0)
+ | ((nbytes_r_length[fixP->fx_size] & 3) << 5)
+ | (!S_IS_DEFINED(fixP->fx_addsy)? 0x10: 0);
+
+#ifdef PIC
+ switch (fixP->fx_r_type) {
+ case NO_RELOC:
+ break;
+ case RELOC_32:
+ if (picmode && S_IS_EXTERNAL(fixP->fx_addsy)) {
+ r_symbolnum = fixP->fx_addsy->sy_number;
+ r_flags |= 0x10; /* set extern bit */
+ }
+ break;
+ case RELOC_GLOB_DAT:
+ r_flags |= 8; /* set baserel bit */
+ r_symbolnum = fixP->fx_addsy->sy_number;
+ if (S_IS_EXTERNAL(fixP->fx_addsy))
+ r_flags |= 0x10;
+ break;
+ case RELOC_JMP_TBL:
+ r_flags |= 4; /* set jmptable bit */
+ break;
+ case RELOC_RELATIVE:
+ /* should never happen */
+ r_flags |= 2; /* set relative bit */
+ break;
+ }
+#endif /* PIC */
+
+ where[4] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[6] = r_symbolnum & 0x0ff;
+ where[7] = r_flags;
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+#ifndef WORKING_DOT_WORD
+const int md_short_jump_size = 4;
+const int md_long_jump_size = 6;
+
+void
+ md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol)
+char *ptr;
+long from_addr,
+ to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - (from_addr+2);
+
+ md_number_to_chars(ptr ,(long)0x6000,2);
+ md_number_to_chars(ptr+2,(long)offset,2);
+}
+
+void
+ md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)
+char *ptr;
+long from_addr,
+ to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ if (cpu_of_arch(current_architecture) < m68020) {
+ offset=to_addr-S_GET_VALUE(to_symbol);
+ md_number_to_chars(ptr ,(long)0x4EF9,2);
+ md_number_to_chars(ptr+2,(long)offset,4);
+ fix_new(frag,(ptr+2)-frag->fr_literal,4,to_symbol,(symbolS *)0,(long)0,0,
+ FIX_NO_RELOC);
+ } else {
+ offset=to_addr - (from_addr+2);
+ md_number_to_chars(ptr ,(long)0x60ff,2);
+ md_number_to_chars(ptr+2,(long)offset,4);
+ }
+}
+
+#endif
+/* Different values of OK tell what its OK to return. Things that aren't OK are an error (what a shock, no?)
+
+ 0: Everything is OK
+ 10: Absolute 1:8 only
+ 20: Absolute 0:7 only
+ 30: absolute 0:15 only
+ 40: Absolute 0:31 only
+ 50: absolute 0:127 only
+ 55: absolute -64:63 only
+ 60: absolute -128:127 only
+ 70: absolute 0:4095 only
+ 80: No bignums
+
+ */
+
+static int get_num(exp,ok)
+struct m68k_exp *exp;
+int ok;
+{
+#ifdef TEST2
+ long l = 0;
+
+ if (!exp->e_beg)
+ return 0;
+ if (*exp->e_beg == '0') {
+ if (exp->e_beg[1] == 'x')
+ sscanf(exp->e_beg+2,"%x",&l);
+ else
+ sscanf(exp->e_beg+1,"%O",&l);
+ return l;
+ }
+ return atol(exp->e_beg);
+#else
+ char *save_in;
+ char c_save;
+
+ if (!exp) {
+ /* Can't do anything */
+ return 0;
+ }
+ if (!exp->e_beg || !exp->e_end) {
+ seg(exp)=SEG_ABSOLUTE;
+ adds(exp)=0;
+ subs(exp)=0;
+ offs(exp)= (ok == 10) ? 1 : 0;
+ as_warn("Null expression defaults to %ld",offs(exp));
+ return 0;
+ }
+
+ exp->e_siz=0;
+ if (/* ok != 80 && */exp->e_end[-1] == ':' && (exp->e_end-exp->e_beg) >= 2) {
+ switch (exp->e_end[0]) {
+ case 's':
+ case 'S':
+ case 'b':
+ case 'B':
+ exp->e_siz=1;
+ break;
+ case 'w':
+ case 'W':
+ exp->e_siz=2;
+ break;
+ case 'l':
+ case 'L':
+ exp->e_siz=3;
+ break;
+ default:
+ as_bad("Unknown size for expression \"%c\"",exp->e_end[0]);
+ }
+ exp->e_end-=2;
+ }
+ c_save=exp->e_end[1];
+ exp->e_end[1]='\0';
+ save_in=input_line_pointer;
+ input_line_pointer=exp->e_beg;
+ switch (expression(&(exp->e_exp))) {
+ case SEG_PASS1:
+ seg(exp)=SEG_ABSOLUTE;
+ adds(exp)=0;
+ subs(exp)=0;
+ offs(exp)= (ok == 10) ? 1 : 0;
+ as_warn("Unknown expression: '%s' defaulting to %d",exp->e_beg,offs(exp));
+ break;
+
+ case SEG_ABSENT:
+ /* Do the same thing the VAX asm does */
+ seg(exp)=SEG_ABSOLUTE;
+ adds(exp)=0;
+ subs(exp)=0;
+ offs(exp)=0;
+ if (ok == 10) {
+ as_warn("expression out of range: defaulting to 1");
+ offs(exp)=1;
+ }
+ break;
+ case SEG_ABSOLUTE:
+ switch (ok) {
+ case 10:
+ if (offs(exp)<1 || offs(exp)>8) {
+ as_warn("expression out of range: defaulting to 1");
+ offs(exp)=1;
+ }
+ break;
+ case 20:
+ if (offs(exp)<0 || offs(exp)>7)
+ goto outrange;
+ break;
+ case 30:
+ if (offs(exp)<0 || offs(exp)>15)
+ goto outrange;
+ break;
+ case 40:
+ if (offs(exp)<0 || offs(exp)>32)
+ goto outrange;
+ break;
+ case 50:
+ if (offs(exp)<0 || offs(exp)>127)
+ goto outrange;
+ break;
+ case 55:
+ if (offs(exp)<-64 || offs(exp)>63)
+ goto outrange;
+ break;
+ case 60:
+ if (offs(exp)<-128 || offs(exp)>127)
+ goto outrange;
+ break;
+ case 70:
+ if (offs(exp)<0 || offs(exp)>4095) {
+ outrange:
+ as_warn("expression out of range: defaulting to 0");
+ offs(exp)=0;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ if (ok >= 10 && ok <= 70) {
+ seg(exp)=SEG_ABSOLUTE;
+ adds(exp)=0;
+ subs(exp)=0;
+ offs(exp)= (ok == 10) ? 1 : 0;
+ as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
+ }
+ break;
+ case SEG_BIG:
+ if (ok == 80 && offs(exp)<0) { /* HACK! Turn it into a long */
+ LITTLENUM_TYPE words[6];
+
+ gen_to_words(words,2,8L);/* These numbers are magic! */
+ seg(exp)=SEG_ABSOLUTE;
+ adds(exp)=0;
+ subs(exp)=0;
+ offs(exp)=words[1]|(words[0]<<16);
+ } else if (ok != 0) {
+ seg(exp)=SEG_ABSOLUTE;
+ adds(exp)=0;
+ subs(exp)=0;
+ offs(exp)= (ok == 10) ? 1 : 0;
+ as_warn("Can't deal with expression \"%s\": defaulting to %ld",exp->e_beg,offs(exp));
+ }
+ break;
+ default:
+ as_fatal("failed sanity check.");
+ }
+ if (input_line_pointer != exp->e_end+1)
+ as_bad("Ignoring junk after expression");
+ exp->e_end[1]=c_save;
+ input_line_pointer=save_in;
+ if (exp->e_siz) {
+ switch (exp->e_siz) {
+ case 1:
+ if (!isbyte(offs(exp)))
+ as_warn("expression doesn't fit in BYTE");
+ break;
+ case 2:
+ if (!isword(offs(exp)))
+ as_warn("expression doesn't fit in WORD");
+ break;
+ }
+ }
+ return offs(exp);
+#endif
+} /* get_num() */
+
+/* These are the back-ends for the various machine dependent pseudo-ops. */
+void demand_empty_rest_of_line(); /* Hate those extra verbose names */
+
+static void s_data1() {
+ subseg_new(SEG_DATA,1);
+ demand_empty_rest_of_line();
+} /* s_data1() */
+
+static void s_data2() {
+ subseg_new(SEG_DATA,2);
+ demand_empty_rest_of_line();
+} /* s_data2() */
+
+static void s_bss() {
+ /* We don't support putting frags in the BSS segment, but we
+ can put them into initialized data for now... */
+ subseg_new(SEG_DATA,255); /* FIXME-SOON */
+ demand_empty_rest_of_line();
+} /* s_bss() */
+
+static void s_even() {
+ register int temp;
+ register long temp_fill;
+
+ temp = 1; /* JF should be 2? */
+ temp_fill = get_absolute_expression ();
+ if ( ! need_pass_2 ) /* Never make frag if expect extra pass. */
+ frag_align (temp, (int)temp_fill);
+ demand_empty_rest_of_line();
+} /* s_even() */
+
+static void s_proc() {
+ demand_empty_rest_of_line();
+} /* s_proc() */
+
+/* s_space is defined in read.c .skip is simply an alias to it. */
+
+/*
+ * md_parse_option
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option. These are:
+ *
+ * -[A]m[c]68000, -[A]m[c]68008, -[A]m[c]68010, -[A]m[c]68020, -[A]m[c]68030, -[A]m[c]68040
+ * -[A]m[c]68881, -[A]m[c]68882, -[A]m[c]68851
+ * Select the architecture. Instructions or features not
+ * supported by the selected architecture cause fatal
+ * errors. More than one may be specified. The default is
+ * -m68020 -m68851 -m68881. Note that -m68008 is a synonym
+ * for -m68000, and -m68882 is a synonym for -m68881.
+ *
+ * MAYBE_FLOAT_TOO is defined below so that specifying a processor type
+ * (e.g. m68020) also requests that float instructions be included. This
+ * is the default setup, mostly to avoid hassling users. A better
+ * rearrangement of this structure would be to add an option to DENY
+ * floating point opcodes, for people who want to really know there's none
+ * of that funny floaty stuff going on. FIXME-later.
+ */
+#ifndef MAYBE_FLOAT_TOO
+#define MAYBE_FLOAT_TOO m68881
+#endif
+
+int md_parse_option(argP,cntP,vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ switch (**argP) {
+ case 'l': /* -l means keep external to 2 bit offset
+ rather than 16 bit one */
+ break;
+
+ case 'S': /* -S means that jbsr's always turn into jsr's. */
+ break;
+
+ case 'A':
+ (*argP)++;
+ /* intentional fall-through */
+ case 'm':
+ (*argP)++;
+
+ if (**argP == 'c') {
+ (*argP)++;
+ } /* allow an optional "c" */
+
+ if (!strcmp(*argP, "68000")
+ || !strcmp(*argP, "68008")) {
+ current_architecture |= m68000;
+ } else if (!strcmp(*argP, "68010")) {
+#ifdef TE_SUN
+ omagic= 1<<16|OMAGIC;
+#endif
+ current_architecture |= m68010;
+
+ } else if (!strcmp(*argP, "68020")) {
+ current_architecture |= m68020 | MAYBE_FLOAT_TOO;
+
+ } else if (!strcmp(*argP, "68030")) {
+ current_architecture |= m68030 | MAYBE_FLOAT_TOO;
+
+ } else if (!strcmp(*argP, "68040")) {
+ current_architecture |= m68040 | MAYBE_FLOAT_TOO;
+
+ } else if (!strcmp(*argP, "68060")) {
+ current_architecture |= m68040 | MAYBE_FLOAT_TOO;
+
+#ifndef NO_68881
+ } else if (!strcmp(*argP, "68881")) {
+ current_architecture |= m68881;
+
+ } else if (!strcmp(*argP, "68882")) {
+ current_architecture |= m68882;
+
+#endif /* NO_68881 */
+#ifndef NO_68851
+ } else if (!strcmp(*argP,"68851")) {
+ current_architecture |= m68851;
+
+#endif /* NO_68851 */
+ } else {
+ as_warn("Unknown architecture, \"%s\". option ignored", *argP);
+ } /* switch on architecture */
+
+ while (**argP) (*argP)++;
+
+ break;
+
+ case 'p':
+ if (!strcmp(*argP,"pic")) {
+ (*argP) += 3;
+ break; /* -pic, Position Independent Code */
+ } else {
+ return(0);
+ } /* pic or not */
+
+#ifdef PIC
+ case 'k':
+ case 'K':
+ /* Predefine GOT symbol */
+ GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
+ break;
+#endif /* PIC */
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+
+#ifdef TEST2
+
+/* TEST2: Test md_assemble() */
+/* Warning, this routine probably doesn't work anymore */
+
+main()
+{
+ struct m68k_it the_ins;
+ char buf[120];
+ char *cp;
+ int n;
+
+ m68k_ip_begin();
+ for (;;) {
+ if (!gets(buf) || !*buf)
+ break;
+ if (buf[0] == '|' || buf[1] == '.')
+ continue;
+ for (cp=buf;*cp;cp++)
+ if (*cp == '\t')
+ *cp=' ';
+ if (is_label(buf))
+ continue;
+ memset(&the_ins, '\0', sizeof(the_ins));
+ m68k_ip(&the_ins,buf);
+ if (the_ins.error) {
+ printf("Error %s in %s\n",the_ins.error,buf);
+ } else {
+ printf("Opcode(%d.%s): ",the_ins.numo,the_ins.args);
+ for (n=0;n<the_ins.numo;n++)
+ printf(" 0x%x",the_ins.opcode[n]&0xffff);
+ printf(" ");
+ print_the_insn(&the_ins.opcode[0],stdout);
+ (void)putchar('\n');
+ }
+ for (n=0;n<strlen(the_ins.args)/2;n++) {
+ if (the_ins.operands[n].error) {
+ printf("op%d Error %s in %s\n",n,the_ins.operands[n].error,buf);
+ continue;
+ }
+ printf("mode %d, reg %d, ",the_ins.operands[n].mode,the_ins.operands[n].reg);
+ if (the_ins.operands[n].b_const)
+ printf("Constant: '%.*s', ",1+the_ins.operands[n].e_const-the_ins.operands[n].b_const,the_ins.operands[n].b_const);
+ printf("ireg %d, isiz %d, imul %d, ",the_ins.operands[n].ireg,the_ins.operands[n].isiz,the_ins.operands[n].imul);
+ if (the_ins.operands[n].b_iadd)
+ printf("Iadd: '%.*s',",1+the_ins.operands[n].e_iadd-the_ins.operands[n].b_iadd,the_ins.operands[n].b_iadd);
+ (void)putchar('\n');
+ }
+ }
+ m68k_ip_end();
+ return 0;
+}
+
+is_label(str)
+char *str;
+{
+ while (*str == ' ')
+ str++;
+ while (*str && *str != ' ')
+ str++;
+ if (str[-1] == ':' || str[1] == '=')
+ return 1;
+ return 0;
+}
+
+#endif
+
+/* Possible states for relaxation:
+
+ 0 0 branch offset byte (bra, etc)
+ 0 1 word
+ 0 2 long
+
+ 1 0 indexed offsets byte a0@(32,d4:w:1) etc
+ 1 1 word
+ 1 2 long
+
+ 2 0 two-offset index word-word a0@(32,d4)@(45) etc
+ 2 1 word-long
+ 2 2 long-word
+ 2 3 long-long
+
+ */
+
+
+
+#ifdef DONTDEF
+abort()
+{
+ printf("ABORT!\n");
+ exit(12);
+}
+
+print_frags()
+{
+ fragS *fragP;
+ extern fragS *text_frag_root;
+
+ for (fragP=text_frag_root;fragP;fragP=fragP->fr_next) {
+ printf("addr %lu next 0x%x fix %ld var %ld symbol 0x%x offset %ld\n",
+ fragP->fr_address,fragP->fr_next,fragP->fr_fix,fragP->fr_var,fragP->fr_symbol,fragP->fr_offset);
+ printf("opcode 0x%x type %d subtype %d\n\n",fragP->fr_opcode,fragP->fr_type,fragP->fr_subtype);
+ }
+ fflush(stdout);
+ return 0;
+}
+#endif
+
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+ md_undefined_symbol (name)
+char *name;
+{
+ return 0;
+}
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void
+ md_operand (expressionP)
+expressionS *expressionP;
+{
+}
+
+/* Round up a section size to the appropriate boundary. */
+long
+ md_section_align (segment, size)
+segT segment;
+long size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the 68k, they're relative to the address of the offset. */
+long
+ md_pcrel_from (fixP)
+fixS *fixP;
+{
+ return(fixP->fx_where + fixP->fx_frag->fr_address);
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-m68k.c */
diff --git a/gnu/usr.bin/as/config/tc-m68k.h b/gnu/usr.bin/as/config/tc-m68k.h
new file mode 100644
index 0000000..33d8d96
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-m68k.h
@@ -0,0 +1,62 @@
+/* This file is tc-m68k.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file is tp-generic.h and is intended to be a template for
+ * target processor specific header files.
+ */
+
+#define MID_M68K 135
+#define MID_M68K4K 136
+#include <machine/param.h>
+
+#define TC_M68K 1
+
+#ifdef OLD_GAS
+#define REVERSE_SORT_RELOCS
+#endif /* OLD_GAS */
+
+#define AOUT_MACHTYPE MID_MACHINE
+#define LOCAL_LABELS_FB
+
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+
+#define LISTING_WORD_SIZE 2 /* A word is 2 bytes */
+#define LISTING_LHS_WIDTH 2 /* One word on the first line */
+#define LISTING_LHS_WIDTH_SECOND 2 /* One word on the second line */
+#define LISTING_LHS_CONT_LINES 4 /* And 4 lines max */
+#define LISTING_HEADER "68K GAS "
+
+/* Copied from write.c */
+#define M68K_AIM_KLUDGE(aim, this_state,this_type) \
+ if (aim == 0 && this_state == 4) { /* hard encoded from tc-m68k.c */ \
+ aim=this_type->rlx_forward+1; /* Force relaxation into word mode */ \
+ }
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-m68k.h */
diff --git a/gnu/usr.bin/as/config/tc-m68kmote.h b/gnu/usr.bin/as/config/tc-m68kmote.h
new file mode 100644
index 0000000..70afae3
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-m68kmote.h
@@ -0,0 +1,64 @@
+/* This file is tc-m68kmote.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file is tp-generic.h and is intended to be a template for
+ * target processor specific header files.
+ */
+
+#define TC_M68K 1
+
+#ifdef TE_SUN3
+/* This variable contains the value to write out at the beginning of
+ the a.out file. The 2<<16 means that this is a 68020 file instead
+ of an old-style 68000 file */
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (2<<16|OMAGIC); /* Magic byte for file header */
+#endif /* TE_SUN3 */
+
+#define AOUT_MACHTYPE 0x2
+#define REVERSE_SORT_RELOCS /* FIXME-NOW: this line can be removed. */
+#define LOCAL_LABELS_FB
+
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+
+#define LISTING_WORD_SIZE 2 /* A word is 2 bytes */
+#define LISTING_LHS_WIDTH 3 /* 3 word on the first line */
+#define LISTING_LHS_WIDTH_SECOND 3 /* One word on the second line */
+#define LISTING_LHS_CONT_LINES 4 /* And 4 lines max */
+#define LISTING_HEADER "68K GAS "
+
+/* Copied from write.c */
+#define M68K_AIM_KLUDGE(aim, this_state,this_type) \
+ if (aim == 0 && this_state == 4) { /* hard encoded from tc-m68k.c */ \
+ aim=this_type->rlx_forward+1; /* Force relaxation into word mode */ \
+ }
+#define MRI
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-m68kmote.h */
diff --git a/gnu/usr.bin/as/config/tc-m88k.c b/gnu/usr.bin/as/config/tc-m88k.c
new file mode 100644
index 0000000..34c6ba3
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-m88k.c
@@ -0,0 +1,1435 @@
+/* m88k.c -- Assembler for the Motorola 88000
+ Contributed by Devon Bowen of Buffalo University
+ and Torbjorn Granlund of the Swedish Institute of Computer Science.
+ Copyright (C) 1989-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "as.h"
+#include "opcode/m88k.h"
+
+struct m88k_insn
+{
+ unsigned long opcode;
+ expressionS exp;
+ enum reloc_type reloc;
+};
+
+#if __STDC__ == 1
+
+static int calcop(struct m88k_opcode *format, char *param, struct m88k_insn *insn);
+
+#else /* not __STDC__ */
+
+static int calcop();
+
+#endif /* not __STDC__ */
+
+char *getval ();
+char *get_reg ();
+char *get_imm16 ();
+char *get_bf ();
+char *get_pcr ();
+char *get_cmp ();
+char *get_cnd ();
+char *get_cr ();
+char *get_fcr ();
+char *get_vec9 ();
+
+struct field_val_assoc
+{
+ char *name;
+ unsigned val;
+};
+
+struct field_val_assoc cr_regs[] =
+{
+ {"PID", 0},
+ {"PSR", 1},
+ {"EPSR", 2},
+ {"SSBR", 3},
+ {"SXIP", 4},
+ {"SNIP", 5},
+ {"SFIP", 6},
+ {"VBR", 7},
+ {"DMT0", 8},
+ {"DMD0", 9},
+ {"DMA0", 10},
+ {"DMT1", 11},
+ {"DMD1", 12},
+ {"DMA1", 13},
+ {"DMT2", 14},
+ {"DMD2", 15},
+ {"DMA2", 16},
+ {"SR0", 17},
+ {"SR1", 18},
+ {"SR2", 19},
+ {"SR3", 20},
+
+ {NULL, 0},
+};
+
+struct field_val_assoc fcr_regs[] =
+{
+ {"FPECR", 0},
+ {"FPHS1", 1},
+ {"FPLS1", 2},
+ {"FPHS2", 3},
+ {"FPLS2", 4},
+ {"FPPT", 5},
+ {"FPRH", 6},
+ {"FPRL", 7},
+ {"FPIT", 8},
+
+ {"FPSR", 62},
+ {"FPCR", 63},
+
+ {NULL, 0},
+};
+
+struct field_val_assoc cmpslot[] =
+{
+/* Integer Floating point */
+ {"nc", 0},
+ {"cp", 1},
+ {"eq", 2},
+ {"ne", 3},
+ {"gt", 4},
+ {"le", 5},
+ {"lt", 6},
+ {"ge", 7},
+ {"hi", 8}, {"ou", 8},
+ {"ls", 9}, {"ib", 9},
+ {"lo", 10}, {"in", 10},
+ {"hs", 11}, {"ob", 11},
+
+ {NULL, 0},
+};
+
+struct field_val_assoc cndmsk[] =
+{
+ {"gt0", 1},
+ {"eq0", 2},
+ {"ge0", 3},
+ {"lt0", 12},
+ {"ne0", 13},
+ {"le0", 14},
+
+ {NULL, 0},
+};
+
+extern char *myname;
+static struct hash_control *op_hash = NULL;
+
+/* These bits should be turned off in the first address of every segment */
+int md_seg_align = 7;
+
+/* This is the number to put at the beginning of the a.out file */
+long omagic = OMAGIC;
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment */
+char comment_chars[] = ";";
+
+/* These chars only start a comment at the beginning of a line. */
+char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* as in 0f123.456 */
+/* or 0H1.234E-12 (see exp chars above) */
+char FLT_CHARS[] = "dDfF";
+
+extern void float_cons (), cons (), s_globl (), s_line (),
+ s_space (), s_set (), stringer (), s_lcomm ();
+static void s_bss ();
+
+const pseudo_typeS md_pseudo_table[] = {
+ {"align", s_align_bytes, 0 },
+ {"def", s_set, 0},
+ {"dfloat", float_cons, 'd'},
+ {"ffloat", float_cons, 'f'},
+ {"global", s_globl, 0},
+ {"half", cons, 2 },
+ {"bss", s_bss, 0},
+ {"string", stringer, 0},
+ {"word", cons, 4 },
+ {"zero", s_space, 0},
+ {0}
+};
+
+const int md_reloc_size = 12; /* Size of relocation record */
+
+void
+md_begin ()
+{
+ char *retval = NULL;
+ unsigned int i = 0;
+
+ /* initialize hash table */
+
+ op_hash = hash_new ();
+ if (op_hash == NULL)
+ as_fatal ("Could not initialize hash table");
+
+ /* loop until you see the end of the list */
+
+ while (*m88k_opcodes[i].name)
+ {
+ char *name = m88k_opcodes[i].name;
+
+ /* hash each mnemonic and record its position */
+
+ retval = hash_insert (op_hash, name, &m88k_opcodes[i]);
+
+ if (retval != NULL && *retval != '\0')
+ as_fatal ("Can't hash instruction '%s':%s",
+ m88k_opcodes[i].name, retval);
+
+ /* skip to next unique mnemonic or end of list */
+
+ for (i++; !strcmp (m88k_opcodes[i].name, name); i++)
+ ;
+ }
+}
+
+int
+md_parse_option (argP, cntP, vecP)
+ char **argP;
+ int *cntP;
+ char ***vecP;
+{
+ as_warn ("unknown option: -%s", *argP);
+ return(0);
+}
+
+void
+md_assemble (op)
+ char *op;
+{
+ char *param, *thisfrag;
+ struct m88k_opcode *format;
+ struct m88k_insn insn;
+
+ assert (op);
+
+ /* skip over instruction to find parameters */
+
+ for (param = op; *param != 0 && !isspace (*param); param++)
+ ;
+ if (*param != 0)
+ *param++ = 0;
+
+ /* try to find the instruction in the hash table */
+
+ if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL)
+ {
+ as_fatal ("Invalid mnemonic '%s'", op);
+ return;
+ }
+
+ /* try parsing this instruction into insn */
+
+ insn.exp.X_add_symbol = 0;
+ insn.exp.X_subtract_symbol = 0;
+ insn.exp.X_add_number = 0;
+ insn.exp.X_seg = 0;
+ insn.reloc = NO_RELOC;
+
+ while (!calcop(format, param, &insn))
+ {
+ /* if it doesn't parse try the next instruction */
+
+ if (!strcmp (format[0].name, format[1].name))
+ format++;
+ else
+ {
+ as_fatal ("Parameter syntax error");
+ return;
+ }
+ }
+
+ /* grow the current frag and plop in the opcode */
+
+ thisfrag = frag_more (4);
+ md_number_to_chars (thisfrag, insn.opcode, 4);
+
+ /* if this instruction requires labels mark it for later */
+
+ switch (insn.reloc)
+ {
+ case NO_RELOC:
+ break;
+
+ case RELOC_LO16:
+ case RELOC_HI16:
+ fix_new (frag_now,
+ thisfrag - frag_now->fr_literal + 2,
+ 2,
+ insn.exp.X_add_symbol,
+ insn.exp.X_subtract_symbol,
+ insn.exp.X_add_number,
+ 0,
+ insn.reloc);
+ break;
+
+ case RELOC_IW16:
+ fix_new (frag_now,
+ thisfrag - frag_now->fr_literal,
+ 4,
+ insn.exp.X_add_symbol,
+ insn.exp.X_subtract_symbol,
+ insn.exp.X_add_number,
+ 0,
+ insn.reloc);
+ break;
+
+ case RELOC_PC16:
+ fix_new (frag_now,
+ thisfrag - frag_now->fr_literal + 2,
+ 2,
+ insn.exp.X_add_symbol,
+ insn.exp.X_subtract_symbol,
+ insn.exp.X_add_number,
+ 1,
+ insn.reloc);
+ break;
+
+ case RELOC_PC26:
+ fix_new (frag_now,
+ thisfrag - frag_now->fr_literal,
+ 4,
+ insn.exp.X_add_symbol,
+ insn.exp.X_subtract_symbol,
+ insn.exp.X_add_number,
+ 1,
+ insn.reloc);
+ break;
+
+ default:
+ as_fatal ("Unknown relocation type");
+ break;
+ }
+}
+
+int
+calcop (format, param, insn)
+ struct m88k_opcode *format;
+ char *param;
+ struct m88k_insn *insn;
+{
+ char *fmt = format->op_spec;
+ int f;
+ unsigned val;
+ unsigned opcode;
+
+ insn->opcode = format->opcode;
+ opcode = 0;
+
+ for (;;)
+ {
+ if (param == 0)
+ return 0;
+ f = *fmt++;
+ switch (f)
+ {
+ case 0:
+ insn->opcode |= opcode;
+ return *param == 0;
+
+ default:
+ if (f != *param++)
+ return 0;
+ break;
+
+ case 'd':
+ param = get_reg (param, &val);
+ opcode |= val << 21;
+ break;
+
+ case '1':
+ param = get_reg (param, &val);
+ opcode |= val << 16;
+ break;
+
+ case '2':
+ param = get_reg (param, &val);
+ opcode |= val;
+ break;
+
+ case '3':
+ param = get_reg (param, &val);
+ opcode |= (val << 16) | val;
+ break;
+
+ case 'I':
+ param = get_imm16 (param, insn);
+ break;
+
+ case 'b':
+ param = get_bf (param, &val);
+ opcode |= val;
+ break;
+
+ case 'p':
+ param = get_pcr (param, insn, RELOC_PC16);
+ break;
+
+ case 'P':
+ param = get_pcr (param, insn, RELOC_PC26);
+ break;
+
+ case 'B':
+ param = get_cmp (param, &val);
+ opcode |= val;
+ break;
+
+ case 'M':
+ param = get_cnd (param, &val);
+ opcode |= val;
+ break;
+
+ case 'c':
+ param = get_cr (param, &val);
+ opcode |= val << 5;
+ break;
+
+ case 'f':
+ param = get_fcr (param, &val);
+ opcode |= val << 5;
+ break;
+
+ case 'V':
+ param = get_vec9 (param, &val);
+ opcode |= val;
+ break;
+
+ case '?':
+ /* Having this here repeats the warning somtimes.
+ But can't we stand that? */
+ as_warn ("Use of obsolete instruction");
+ break;
+ }
+ }
+}
+
+char *
+match_name (param, assoc_tab, valp)
+ char *param;
+ struct field_val_assoc *assoc_tab;
+ unsigned *valp;
+{
+ int i;
+ char *name;
+ int name_len;
+
+ for (i = 0;; i++)
+ {
+ name = assoc_tab[i].name;
+ if (name == NULL)
+ return NULL;
+ name_len = strlen (name);
+ if (!strncmp (param, name, name_len))
+ {
+ *valp = assoc_tab[i].val;
+ return param + name_len;
+ }
+ }
+}
+
+char *
+get_reg (param, regnop)
+ char *param;
+ unsigned *regnop;
+{
+ unsigned c;
+ unsigned regno;
+
+ c = *param++;
+ if (c == 'r')
+ {
+ regno = *param++ - '0';
+ if (regno < 10)
+ {
+ if (regno == 0)
+ {
+ *regnop = 0;
+ return param;
+ }
+ c = *param - '0';
+ if (c < 10)
+ {
+ regno = regno * 10 + c;
+ if (c < 32)
+ {
+ *regnop = regno;
+ return param + 1;
+ }
+ }
+ else
+ {
+ *regnop = regno;
+ return param;
+ }
+ }
+ return NULL;
+ }
+ else if (c == 's' && param[0] == 'p')
+ {
+ *regnop = 31;
+ return param + 1;
+ }
+
+ return 0;
+}
+
+char *
+get_imm16 (param, insn)
+ char *param;
+ struct m88k_insn *insn;
+{
+ enum reloc_type reloc = NO_RELOC;
+ unsigned int val;
+ segT seg;
+ char *save_ptr;
+
+ if (!strncmp (param, "hi16", 4) && !isalnum (param[4]))
+ {
+ reloc = RELOC_HI16;
+ param += 4;
+ }
+ else if (!strncmp (param, "lo16", 4) && !isalnum (param[4]))
+ {
+ reloc = RELOC_LO16;
+ param += 4;
+ }
+ else if (!strncmp (param, "iw16", 4) && !isalnum (param[4]))
+ {
+ reloc = RELOC_IW16;
+ param += 4;
+ }
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ seg = expression (&insn->exp);
+ param = input_line_pointer;
+ input_line_pointer = save_ptr;
+
+ val = insn->exp.X_add_number;
+
+ if (seg == SEG_ABSOLUTE)
+ {
+ /* Insert the value now, and reset reloc to NO_RELOC. */
+ if (reloc == NO_RELOC)
+ {
+ /* Warn about too big expressions if not surrounded by xx16. */
+ if (val > 0xffff)
+ as_warn ("Expression truncated to 16 bits");
+ }
+
+ if (reloc == RELOC_HI16)
+ val >>= 16;
+
+ insn->opcode |= val & 0xffff;
+ reloc = NO_RELOC;
+ }
+ else if (reloc == NO_RELOC)
+ /* We accept a symbol even without lo16, hi16, etc, and assume
+ lo16 was intended. */
+ reloc = RELOC_LO16;
+
+ insn->reloc = reloc;
+
+ return param;
+}
+
+char *
+get_pcr (param, insn, reloc)
+ char *param;
+ struct m88k_insn *insn;
+ enum reloc_type reloc;
+{
+ char *saveptr, *saveparam;
+ segT seg;
+
+ saveptr = input_line_pointer;
+ input_line_pointer = param;
+
+ seg = expression (&insn->exp);
+
+ saveparam = input_line_pointer;
+ input_line_pointer = saveptr;
+
+ /* Botch: We should relocate now if SEG_ABSOLUTE. */
+ insn->reloc = reloc;
+
+ return saveparam;
+}
+
+char *
+get_cmp (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned int val;
+ char *save_ptr;
+
+ save_ptr = param;
+
+ param = match_name (param, cmpslot, valp);
+ val = *valp;
+
+ if (param == NULL)
+ {
+ param = save_ptr;
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ val = get_absolute_expression ();
+ param = input_line_pointer;
+ input_line_pointer = save_ptr;
+
+ if (val >= 32)
+ {
+ as_warn ("Expression truncated to 5 bits");
+ val %= 32;
+ }
+ }
+
+ *valp = val << 21;
+ return param;
+}
+
+char *
+get_cnd (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned int val;
+
+ if (isdigit (*param))
+ {
+ param = getval (param, &val);
+
+ if (val >= 32)
+ {
+ as_warn ("Expression truncated to 5 bits");
+ val %= 32;
+ }
+ }
+ else
+ {
+ if (isupper (*param))
+ *param = tolower (*param);
+
+ if (isupper (param[1]))
+ param[1] = tolower (param[1]);
+
+ param = match_name (param, cndmsk, valp);
+
+ if (param == NULL)
+ return NULL;
+
+ val = *valp;
+ }
+
+ *valp = val << 21;
+ return param;
+}
+
+char *
+get_bf2 (param, bc)
+ char *param;
+ int bc;
+{
+ int depth = 0;
+ int c;
+
+ for (;;)
+ {
+ c = *param;
+ if (c == 0)
+ return param;
+ else if (c == '(')
+ depth++;
+ else if (c == ')')
+ depth--;
+ else if (c == bc && depth <= 0)
+ return param;
+ param++;
+ }
+}
+
+char *
+get_bf_offset_expression (param, offsetp)
+ char *param;
+ unsigned *offsetp;
+{
+ unsigned offset;
+
+ if (isalpha (param[0]))
+ {
+ if (isupper (param[0]))
+ param[0] = tolower (param[0]);
+ if (isupper (param[1]))
+ param[1] = tolower (param[1]);
+
+ param = match_name (param, cmpslot, offsetp);
+
+ return param;
+ }
+ else
+ {
+ input_line_pointer = param;
+ offset = get_absolute_expression ();
+ param = input_line_pointer;
+ }
+
+ *offsetp = offset;
+ return param;
+}
+
+char *
+get_bf (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned offset = 0;
+ unsigned width = 0;
+ char *xp;
+ char *save_ptr;
+
+ xp = get_bf2 (param, '<');
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ if (*xp == 0)
+ {
+ /* We did not find '<'. We have an offset (width implicitly 32). */
+ param = get_bf_offset_expression (param, &offset);
+ if (param == NULL)
+ return NULL;
+ input_line_pointer = save_ptr;
+ }
+ else
+ {
+ *xp++ = 0; /* Overwrite the '<' */
+ param = get_bf2 (xp, '>');
+ if (*param == 0)
+ return NULL;
+ *param++ = 0; /* Overwrite the '>' */
+
+ width = get_absolute_expression ();
+ xp = get_bf_offset_expression (xp, &offset);
+ input_line_pointer = save_ptr;
+
+ if (xp + 1 != param)
+ return NULL;
+ }
+
+ *valp = ((width % 32) << 5) | (offset % 32);
+
+ return param;
+}
+
+char *
+get_cr (param, regnop)
+ char *param;
+ unsigned *regnop;
+{
+ unsigned regno;
+ unsigned c;
+/* int i; FIXME remove this */
+/* int name_len; FIXME remove this */
+
+ if (!strncmp (param, "cr", 2))
+ {
+ param += 2;
+
+ regno = *param++ - '0';
+ if (regno < 10)
+ {
+ if (regno == 0)
+ {
+ *regnop = 0;
+ return param;
+ }
+ c = *param - '0';
+ if (c < 10)
+ {
+ regno = regno * 10 + c;
+ if (c < 64)
+ {
+ *regnop = regno;
+ return param + 1;
+ }
+ }
+ else
+ {
+ *regnop = regno;
+ return param;
+ }
+ }
+ return NULL;
+ }
+
+ param = match_name (param, cr_regs, regnop);
+
+ return param;
+}
+
+char *
+get_fcr (param, regnop)
+ char *param;
+ unsigned *regnop;
+{
+ unsigned regno;
+ unsigned c;
+/* int i; FIXME remove this */
+/* int name_len; FIXME: remove this */
+
+ if (!strncmp (param, "fcr", 3))
+ {
+ param += 3;
+
+ regno = *param++ - '0';
+ if (regno < 10)
+ {
+ if (regno == 0)
+ {
+ *regnop = 0;
+ return param;
+ }
+ c = *param - '0';
+ if (c < 10)
+ {
+ regno = regno * 10 + c;
+ if (c < 64)
+ {
+ *regnop = regno;
+ return param + 1;
+ }
+ }
+ else
+ {
+ *regnop = regno;
+ return param;
+ }
+ }
+ return NULL;
+ }
+
+ param = match_name (param, fcr_regs, regnop);
+
+ return param;
+}
+
+char *
+get_vec9 (param, valp)
+ char *param;
+ unsigned *valp;
+{
+ unsigned val;
+ char *save_ptr;
+
+ save_ptr = input_line_pointer;
+ input_line_pointer = param;
+ val = get_absolute_expression ();
+ param = input_line_pointer;
+ input_line_pointer = save_ptr;
+
+ if (val >= 1 << 9)
+ as_warn ("Expression truncated to 9 bits");
+
+ *valp = val % (1 << 9);
+
+ return param;
+}
+
+#define hexval(z) \
+ (isdigit (z) ? (z) - '0' : \
+ islower (z) ? (z) - 'a' + 10 : \
+ isupper (z) ? (z) - 'A' + 10 : -1)
+
+char *
+getval (param, valp)
+ char *param;
+ unsigned int *valp;
+{
+ unsigned int val = 0;
+ unsigned int c;
+
+ c = *param++;
+ if (c == '0')
+ {
+ c = *param++;
+ if (c == 'x' || c == 'X')
+ {
+ c = *param++;
+ c = hexval (c);
+ while (c < 16)
+ {
+ val = val * 16 + c;
+ c = *param++;
+ c = hexval (c);
+ }
+ }
+ else
+ {
+ c -= '0';
+ while (c < 8)
+ {
+ val = val * 8 + c;
+ c = *param++ - '0';
+ }
+ }
+ }
+ else
+ {
+ c -= '0';
+ while (c < 10)
+ {
+ val = val * 10 + c;
+ c = *param++ - '0';
+ }
+ }
+
+ *valp = val;
+ return param - 1;
+}
+
+void
+md_number_to_chars (buf, val, nbytes)
+char *buf;
+long val;
+int nbytes;
+{
+ switch (nbytes)
+ {
+ case 4:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ case 2:
+ *buf++ = val >> 8;
+ case 1:
+ *buf = val;
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+#ifdef comment
+
+void
+md_number_to_imm (buf, val, nbytes, fixP, seg_type)
+unsigned char *buf;
+unsigned int val;
+int nbytes;
+fixS *fixP;
+int seg_type;
+{
+ if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC)
+ {
+ switch (nbytes)
+ {
+ case 4:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ case 2:
+ *buf++ = val >> 8;
+ case 1:
+ *buf = val;
+ break;
+
+ default:
+ abort ();
+ }
+ return;
+ }
+
+ switch (fixP->fx_r_type)
+ {
+ case RELOC_IW16:
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_LO16:
+ buf[0] = val >> 8;
+ buf[1] = val;
+ break;
+
+ case RELOC_HI16:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ break;
+
+ case RELOC_PC16:
+ val += 4;
+ buf[0] = val >> 10;
+ buf[1] = val >> 2;
+ break;
+
+ case RELOC_PC26:
+ val += 4;
+ buf[0] |= (val >> 26) & 0x03;
+ buf[1] = val >> 18;
+ buf[2] = val >> 10;
+ buf[3] = val >> 2;
+ break;
+
+ case RELOC_32:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ default:
+ as_fatal ("Bad relocation type");
+ break;
+ }
+}
+#endif /* comment */
+
+/* Apply a fixS to the frags, now that we know the value it ought to
+ hold. */
+
+void md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ fixP->fx_addnumber = val;
+
+
+ switch (fixP->fx_r_type) {
+
+ case RELOC_IW16:
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_LO16:
+ buf[0] = val >> 8;
+ buf[1] = val;
+ break;
+
+ case RELOC_HI16:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ break;
+
+ case RELOC_PC16:
+ val += 4;
+ buf[0] = val >> 10;
+ buf[1] = val >> 2;
+ break;
+
+ case RELOC_PC26:
+ val += 4;
+ buf[0] |= (val >> 26) & 0x03;
+ buf[1] = val >> 18;
+ buf[2] = val >> 10;
+ buf[3] = val >> 2;
+ break;
+
+ case RELOC_32:
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case NO_RELOC:
+ switch (fixP->fx_size) {
+ case 4:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ case 2:
+ *buf++ = val >> 8;
+ case 1:
+ *buf = val;
+ break;
+
+ default:
+ abort ();
+ }
+
+ default:
+ as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
+ break;
+ }
+
+ return;
+} /* md_apply_fix() */
+
+void
+md_number_to_disp (buf, val, nbytes)
+char *buf;
+int val;
+int nbytes;
+{
+ as_fatal ("md_number_to_disp not defined");
+ md_number_to_chars (buf, val, nbytes);
+}
+
+void
+md_number_to_field (buf, val, nbytes)
+char *buf;
+int val;
+int nbytes;
+{
+ as_fatal ("md_number_to_field not defined");
+ md_number_to_chars (buf, val, nbytes);
+}
+
+#define MAX_LITTLENUMS 6
+
+/* Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+char *
+md_atof (type, litP, sizeP)
+ char type;
+ char *litP;
+ int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee ();
+
+ switch (type)
+ {
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to MD_ATOF()";
+ }
+ t=atof_ieee (input_line_pointer, type, words);
+ if (t)
+ input_line_pointer=t;
+
+ *sizeP=prec * sizeof (LITTLENUM_TYPE);
+ for (wordP=words;prec--;)
+ {
+ md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
+ litP+=sizeof (LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+int md_short_jump_size = 4;
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ long from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
+ fix_new (frag,
+ ptr - frag->fr_literal,
+ 4,
+ to_symbol,
+ (symbolS *) 0,
+ (long int) 0,
+ 0,
+ RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */
+}
+
+int md_long_jump_size = 4;
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ long from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ ptr[0] = 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00;
+ fix_new (frag,
+ ptr - frag->fr_literal,
+ 4,
+ to_symbol,
+ (symbolS *) 0,
+ (long int) 0,
+ 0,
+ RELOC_PC26);
+}
+
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ fragS *fragP;
+ segT segment_type;
+{
+ as_fatal("Relaxation should never occur");
+ return(0);
+}
+
+const relax_typeS md_relax_table[] = {0};
+
+void
+md_convert_frag (headers, fragP)
+object_headers *headers;
+ fragS *fragP;
+{
+ as_fatal ("Relaxation should never occur");
+}
+
+void
+md_end ()
+{
+}
+
+#ifdef comment
+
+/*
+ * Risc relocations are completely different, so it needs
+ * this machine dependent routine to emit them.
+ */
+void
+emit_relocations (fixP, segment_address_in_file)
+ fixS *fixP;
+ relax_addressT segment_address_in_file;
+{
+ struct reloc_info_m88k ri;
+ symbolS *symbolP;
+ extern char *next_object_file_charP;
+
+ bzero ((char *) &ri, sizeof (ri));
+ for (; fixP; fixP = fixP->fx_next) {
+
+ if (fixP->fx_r_type >= NO_RELOC) {
+ fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);
+ abort ();
+ }
+
+ if ((symbolP = fixP->fx_addsy) != NULL) {
+ ri.r_address = fixP->fx_frag->fr_address +
+ fixP->fx_where - segment_address_in_file;
+ if ((symbolP->sy_type & N_TYPE) == N_UNDF) {
+ ri.r_extern = 1;
+ ri.r_symbolnum = symbolP->sy_number;
+ } else {
+ ri.r_extern = 0;
+ ri.r_symbolnum = symbolP->sy_type & N_TYPE;
+ }
+ if (symbolP && symbolP->sy_frag) {
+ ri.r_addend = symbolP->sy_frag->fr_address;
+ }
+ ri.r_type = fixP->fx_r_type;
+ if (fixP->fx_pcrel) {
+/* ri.r_addend -= fixP->fx_where; */
+ ri.r_addend -= ri.r_address;
+ } else {
+ ri.r_addend = fixP->fx_addnumber;
+ }
+
+/* md_ri_to_chars ((char *) &ri, ri); */
+ append (&next_object_file_charP, (char *)& ri, sizeof (ri));
+ }
+ }
+ return;
+}
+#endif /* comment */
+
+/* Translate internal representation of relocation info to target format.
+
+ On m88k: first 4 bytes are normal unsigned long address,
+ next three bytes are index, most sig. byte first.
+ Byte 7 is broken up with bit 7 as external,
+ bits 6, 5, & 4 unused, and the lower four bits as relocation
+ type.
+ Next 4 bytes are long addend. */
+
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ long r_index;
+ long r_extern;
+ long r_addend = 0;
+ long r_address;
+
+ know(fixP->fx_addsy);
+
+ if (!S_IS_DEFINED(fixP->fx_addsy)) {
+ r_extern = 1;
+ r_index = fixP->fx_addsy->sy_number;
+ } else {
+ r_extern = 0;
+ r_index = S_GET_TYPE(fixP->fx_addsy);
+ }
+
+ /* this is easy */
+ md_number_to_chars(where,
+ r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ /* now the fun stuff */
+ where[4] = (r_index >> 16) & 0x0ff;
+ where[5] = (r_index >> 8) & 0x0ff;
+ where[6] = r_index & 0x0ff;
+ where[7] = ((r_extern << 7) & 0x80) | (0 & 0x70) | (fixP->fx_r_type & 0xf);
+
+ /* Also easy */
+ if (fixP->fx_addsy->sy_frag) {
+ r_addend = fixP->fx_addsy->sy_frag->fr_address;
+ }
+
+ if (fixP->fx_pcrel) {
+ r_addend -= r_address;
+ } else {
+ r_addend = fixP->fx_addnumber;
+ }
+
+ md_number_to_chars(&where[8], r_addend, 4);
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+
+static void
+s_bss()
+{
+ char *name;
+ char c;
+ char *p;
+ int temp, bss_align = 1;
+ symbolS *symbolP;
+ extern char is_end_of_line[256];
+
+ name = input_line_pointer;
+ c = get_symbol_end();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if ( * input_line_pointer != ',' )
+ {
+ as_warn("Expected comma after name");
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer ++;
+ if ((temp = get_absolute_expression()) < 0)
+ {
+ as_warn("BSS length (%d.) <0! Ignored.", temp);
+ ignore_rest_of_line();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ bss_align = get_absolute_expression();
+ while (local_bss_counter % bss_align != 0)
+ local_bss_counter++;
+ }
+
+ if (!S_IS_DEFINED(symbolP)
+ || (S_GET_SEGMENT(symbolP) == SEG_BSS
+ && S_GET_VALUE(symbolP) == local_bss_counter)) {
+ S_SET_VALUE(symbolP, local_bss_counter);
+ S_SET_SEGMENT(symbolP, SEG_BSS);
+ symbolP->sy_frag = &bss_address_frag;
+ local_bss_counter += temp;
+ } else {
+ as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
+ S_GET_VALUE(symbolP), local_bss_counter );
+ }
+ while (!is_end_of_line[*input_line_pointer])
+ {
+ input_line_pointer++;
+ }
+
+ return;
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *md_undefined_symbol(name)
+char *name;
+{
+ return 0;
+} /* md_undefined_symbol() */
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void md_operand(expressionP)
+expressionS *expressionP;
+{
+} /* md_operand() */
+
+/* Round up a section size to the appropriate boundary. */
+long md_section_align(segment, size)
+segT segment;
+long size;
+{
+ return((size + 7) & ~7); /* Round all sects to multiple of 8 */
+} /* md_section_align() */
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the sparc, they're relative to the address of the offset, plus
+ its size. This gets us to the following instruction.
+ (??? Is this right? FIXME-SOON) */
+long md_pcrel_from(fixP)
+fixS *fixP;
+{
+ return(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address);
+} /* md_pcrel_from() */
+
+ /* end of tc-m88k.c */
diff --git a/gnu/usr.bin/as/config/tc-m88k.h b/gnu/usr.bin/as/config/tc-m88k.h
new file mode 100644
index 0000000..f518085
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-m88k.h
@@ -0,0 +1,35 @@
+/* m88k.h -- Assembler for the Motorola 88000
+ Contributed by Devon Bowen of Buffalo University
+ and Torbjorn Granlund of the Swedish Institute of Computer Science.
+ Copyright (C) 1989-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TC_M88K 1
+
+#define NO_LISTING
+#define NO_DOT_PSEUDOS
+#define ALLOW_ATSIGN
+
+#define LOCAL_LABEL(name) (name[0] == '@' \
+ && ( name[1] == 'L' || name[1] == '.' ))
+
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+
+ /* end of tc-m88k.h */
diff --git a/gnu/usr.bin/as/config/tc-mips.c b/gnu/usr.bin/as/config/tc-mips.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-mips.c
diff --git a/gnu/usr.bin/as/config/tc-mips.h b/gnu/usr.bin/as/config/tc-mips.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-mips.h
diff --git a/gnu/usr.bin/as/config/tc-ns32k.c b/gnu/usr.bin/as/config/tc-ns32k.c
new file mode 100644
index 0000000..e82b07b
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-ns32k.c
@@ -0,0 +1,2015 @@
+/* ns32k.c -- Assemble on the National Semiconductor 32k series
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*#define SHOW_NUM 1*/ /* uncomment for debugging */
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef USG
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include "opcode/ns32k.h"
+
+#include "as.h"
+
+#include "obstack.h"
+
+/* Macros */
+#define IIF_ENTRIES 13 /* number of entries in iif */
+#define PRIVATE_SIZE 256 /* size of my garbage memory */
+#define MAX_ARGS 4
+#define DEFAULT -1 /* addr_mode returns this value when plain constant or label is encountered */
+
+#define IIF(ptr,a1,c1,e1,g1,i1,k1,m1,o1,q1,s1,u1) \
+ iif.iifP[ptr].type= a1; \
+ iif.iifP[ptr].size= c1; \
+ iif.iifP[ptr].object= e1; \
+ iif.iifP[ptr].object_adjust= g1; \
+ iif.iifP[ptr].pcrel= i1; \
+ iif.iifP[ptr].pcrel_adjust= k1; \
+ iif.iifP[ptr].im_disp= m1; \
+ iif.iifP[ptr].relax_substate= o1; \
+ iif.iifP[ptr].bit_fixP= q1; \
+ iif.iifP[ptr].addr_mode= s1; \
+ iif.iifP[ptr].bsr= u1;
+
+#ifdef TE_SEQUENT
+#define LINE_COMMENT_CHARS "|"
+#define ABSOLUTE_PREFIX '@'
+#define IMMEDIATE_PREFIX '#'
+#endif
+
+#ifndef LINE_COMMENT_CHARS
+#define LINE_COMMENT_CHARS "#"
+#endif
+
+const char comment_chars[] = "#";
+const char line_comment_chars[] = LINE_COMMENT_CHARS;
+#if !defined(ABSOLUTE_PREFIX) && !defined(IMMEDIATE_PREFIX)
+#define ABSOLUTE_PREFIX '@' /* One or the other MUST be defined */
+#endif
+
+struct addr_mode {
+ char mode; /* addressing mode of operand (0-31) */
+ char scaled_mode; /* mode combined with scaled mode */
+ char scaled_reg; /* register used in scaled+1 (1-8) */
+ char float_flag; /* set if R0..R7 was F0..F7 ie a floating-point-register */
+ char am_size; /* estimated max size of general addr-mode parts*/
+ char im_disp; /* if im_disp == 1 we have a displacement */
+ char pcrel; /* 1 if pcrel, this is really redundant info */
+ char disp_suffix[2]; /* length of displacement(s), 0=undefined */
+ char *disp[2]; /* pointer(s) at displacement(s)
+ or immediates(s) (ascii) */
+ char index_byte; /* index byte */
+};
+typedef struct addr_mode addr_modeS;
+
+
+char *freeptr,*freeptr_static; /* points at some number of free bytes */
+struct hash_control *inst_hash_handle;
+
+struct ns32k_opcode *desc; /* pointer at description of instruction */
+addr_modeS addr_modeP;
+char EXP_CHARS[] = "eE";
+char FLT_CHARS[] = "fd"; /* we don't want to support lowercase, do we */
+
+/* UPPERCASE denotes live names
+ * when an instruction is built, IIF is used as an intermidiate form to store
+ * the actual parts of the instruction. A ns32k machine instruction can
+ * be divided into a couple of sub PARTs. When an instruction is assembled
+ * the appropriate PART get an assignment. When an IIF has been completed it's
+ * converted to a FRAGment as specified in AS.H */
+
+/* internal structs */
+struct option {
+ char *pattern;
+ unsigned long or;
+ unsigned long and;
+};
+
+typedef struct {
+ int type; /* how to interpret object */
+ int size; /* Estimated max size of object */
+ unsigned long object; /* binary data */
+ int object_adjust; /* number added to object */
+ int pcrel; /* True if object is pcrel */
+ int pcrel_adjust; /* length in bytes from the
+ instruction start to the
+ displacement */
+ int im_disp; /* True if the object is a displacement */
+ relax_substateT relax_substate; /* Initial relaxsubstate */
+ bit_fixS *bit_fixP; /* Pointer at bit_fix struct */
+ int addr_mode; /* What addrmode do we associate with this iif-entry */
+ char bsr; /* Sequent hack */
+}iif_entryT; /* Internal Instruction Format */
+
+struct int_ins_form {
+ int instr_size; /* Max size of instruction in bytes. */
+ iif_entryT iifP[IIF_ENTRIES + 1];
+};
+struct int_ins_form iif;
+expressionS exprP;
+char *input_line_pointer;
+/* description of the PARTs in IIF
+ *object[n]:
+ * 0 total length in bytes of entries in iif
+ * 1 opcode
+ * 2 index_byte_a
+ * 3 index_byte_b
+ * 4 disp_a_1
+ * 5 disp_a_2
+ * 6 disp_b_1
+ * 7 disp_b_2
+ * 8 imm_a
+ * 9 imm_b
+ * 10 implied1
+ * 11 implied2
+ *
+ * For every entry there is a datalength in bytes. This is stored in size[n].
+ * 0, the objectlength is not explicitly given by the instruction
+ * and the operand is undefined. This is a case for relaxation.
+ * Reserve 4 bytes for the final object.
+ *
+ * 1, the entry contains one byte
+ * 2, the entry contains two bytes
+ * 3, the entry contains three bytes
+ * 4, the entry contains four bytes
+ * etc
+ *
+ * Furthermore, every entry has a data type identifier in type[n].
+ *
+ * 0, the entry is void, ignore it.
+ * 1, the entry is a binary number.
+ * 2, the entry is a pointer at an expression.
+ * Where expression may be as simple as a single '1',
+ * and as complicated as foo-bar+12,
+ * foo and bar may be undefined but suffixed by :{b|w|d} to
+ * control the length of the object.
+ *
+ * 3, the entry is a pointer at a bignum struct
+ *
+ *
+ * The low-order-byte coresponds to low physical memory.
+ * Obviously a FRAGment must be created for each valid disp in PART whose
+ * datalength is undefined (to bad) .
+ * The case where just the expression is undefined is less severe and is
+ * handled by fix. Here the number of bytes in the objectfile is known.
+ * With this representation we simplify the assembly and separates the
+ * machine dependent/independent parts in a more clean way (said OE)
+ */
+
+struct option opt1[]= /* restore, exit */
+{
+ { "r0", 0x80, 0xff },
+ { "r1", 0x40, 0xff },
+ { "r2", 0x20, 0xff },
+ { "r3", 0x10, 0xff },
+ { "r4", 0x08, 0xff },
+ { "r5", 0x04, 0xff },
+ { "r6", 0x02, 0xff },
+ { "r7", 0x01, 0xff },
+ { 0 , 0x00, 0xff }
+};
+struct option opt2[]= /* save, enter */
+{
+ { "r0", 0x01, 0xff },
+ { "r1", 0x02, 0xff },
+ { "r2", 0x04, 0xff },
+ { "r3", 0x08, 0xff },
+ { "r4", 0x10, 0xff },
+ { "r5", 0x20, 0xff },
+ { "r6", 0x40, 0xff },
+ { "r7", 0x80, 0xff },
+ { 0 , 0x00, 0xff }
+};
+struct option opt3[]= /* setcfg */
+{
+ { "c", 0x8, 0xff },
+ { "m", 0x4, 0xff },
+ { "f", 0x2, 0xff },
+ { "i", 0x1, 0xff },
+ { 0 , 0x0, 0xff }
+};
+struct option opt4[]= /* cinv */
+{
+ { "a", 0x4, 0xff },
+ { "i", 0x2, 0xff },
+ { "d", 0x1, 0xff },
+ { 0 , 0x0, 0xff }
+};
+struct option opt5[]= /* string inst */
+{
+ { "b", 0x2, 0xff },
+ { "u", 0xc, 0xff },
+ { "w", 0x4, 0xff },
+ { 0 , 0x0, 0xff }
+};
+struct option opt6[]= /* plain reg ext,cvtp etc */
+{
+ { "r0", 0x00, 0xff },
+ { "r1", 0x01, 0xff },
+ { "r2", 0x02, 0xff },
+ { "r3", 0x03, 0xff },
+ { "r4", 0x04, 0xff },
+ { "r5", 0x05, 0xff },
+ { "r6", 0x06, 0xff },
+ { "r7", 0x07, 0xff },
+ { 0 , 0x00, 0xff }
+};
+
+#if !defined(NS32032) && !defined(NS32532)
+#define NS32032
+#endif
+
+struct option cpureg_532[]= /* lpr spr */
+{
+ { "us", 0x0, 0xff },
+ { "dcr", 0x1, 0xff },
+ { "bpc", 0x2, 0xff },
+ { "dsr", 0x3, 0xff },
+ { "car", 0x4, 0xff },
+ { "fp", 0x8, 0xff },
+ { "sp", 0x9, 0xff },
+ { "sb", 0xa, 0xff },
+ { "usp", 0xb, 0xff },
+ { "cfg", 0xc, 0xff },
+ { "psr", 0xd, 0xff },
+ { "intbase", 0xe, 0xff },
+ { "mod", 0xf, 0xff },
+ { 0 , 0x00, 0xff }
+};
+struct option mmureg_532[]= /* lmr smr */
+{
+ { "mcr", 0x9, 0xff },
+ { "msr", 0xa, 0xff },
+ { "tear", 0xb, 0xff },
+ { "ptb0", 0xc, 0xff },
+ { "ptb1", 0xd, 0xff },
+ { "ivar0", 0xe, 0xff },
+ { "ivar1", 0xf, 0xff },
+ { 0 , 0x0, 0xff }
+};
+
+struct option cpureg_032[]= /* lpr spr */
+{
+ { "upsr", 0x0, 0xff },
+ { "fp", 0x8, 0xff },
+ { "sp", 0x9, 0xff },
+ { "sb", 0xa, 0xff },
+ { "psr", 0xd, 0xff },
+ { "intbase", 0xe, 0xff },
+ { "mod", 0xf, 0xff },
+ { 0 , 0x0, 0xff }
+};
+struct option mmureg_032[]= /* lmr smr */
+{
+ { "bpr0", 0x0, 0xff },
+ { "bpr1", 0x1, 0xff },
+ { "pf0", 0x4, 0xff },
+ { "pf1", 0x5, 0xff },
+ { "sc", 0x8, 0xff },
+ { "msr", 0xa, 0xff },
+ { "bcnt", 0xb, 0xff },
+ { "ptb0", 0xc, 0xff },
+ { "ptb1", 0xd, 0xff },
+ { "eia", 0xf, 0xff },
+ { 0 , 0x0, 0xff }
+};
+
+#if defined(NS32532)
+struct option *cpureg = cpureg_532;
+struct option *mmureg = mmureg_532;
+#else
+struct option *cpureg = cpureg_032;
+struct option *mmureg = mmureg_032;
+#endif
+
+
+const pseudo_typeS md_pseudo_table[]={ /* so far empty */
+ { 0, 0, 0 }
+};
+
+#define IND(x,y) (((x)<<2)+(y))
+
+/* those are index's to relax groups in md_relax_table
+ ie it must be multiplied by 4 to point at a group start. Viz IND(x,y)
+ Se function relax_segment in write.c for more info */
+
+#define BRANCH 1
+#define PCREL 2
+
+/* those are index's to entries in a relax group */
+
+#define BYTE 0
+#define WORD 1
+#define DOUBLE 2
+#define UNDEF 3
+/* Those limits are calculated from the displacement start in memory.
+ The ns32k uses the begining of the instruction as displacement base.
+ This type of displacements could be handled here by moving the limit window
+ up or down. I choose to use an internal displacement base-adjust as there
+ are other routines that must consider this. Also, as we have two various
+ offset-adjusts in the ns32k (acb versus br/brs/jsr/bcond), two set of limits
+ would have had to be used.
+ Now we dont have to think about that. */
+
+
+const relax_typeS md_relax_table[] = {
+ { 1, 1, 0, 0 },
+ { 1, 1, 0, 0 },
+ { 1, 1, 0, 0 },
+ { 1, 1, 0, 0 },
+
+ { (63), (-64), 1, IND(BRANCH,WORD) },
+ { (8191), (-8192), 2, IND(BRANCH,DOUBLE) },
+ { 0, 0, 4, 0 },
+ { 1, 1, 0, 0 }
+};
+
+/* Array used to test if mode contains displacements.
+ Value is true if mode contains displacement. */
+
+char disp_test[] = { 0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,
+ 1,1,1,0,0,1,1,0,
+ 1,1,1,1,1,1,1,1 };
+
+/* Array used to calculate max size of displacements */
+
+char disp_size[] = { 4,1,2,0,4 };
+
+#ifdef PIC
+/* In pic-mode all external pc-relative references are jmpslot
+ references except references to __GLOBAL_OFFSET_TABLE_. */
+static symbolS *got_symbol;
+
+/* The size of got-offsets. */
+static int got_offset_size = 2;
+#endif
+
+
+
+#if __STDC__ == 1
+
+static segT evaluate_expr(expressionS *resultP, char *ptr);
+static void md_number_to_disp(char *buf, long val, int n);
+static void md_number_to_imm(char *buf, long val, int n);
+
+#else /* not __STDC__ */
+
+static segT evaluate_expr();
+static void md_number_to_disp();
+static void md_number_to_imm();
+
+#endif /* not __STDC__ */
+
+/* Parses a general operand into an addressingmode struct
+
+ in: pointer at operand in ascii form
+ pointer at addr_mode struct for result
+ the level of recursion. (always 0 or 1)
+
+ out: data in addr_mode struct
+ */
+int addr_mode(operand,addr_modeP,recursive_level)
+char *operand;
+register addr_modeS *addr_modeP;
+int recursive_level;
+{
+ register char *str;
+ register int i;
+ register int strl;
+ register int mode;
+ int j;
+ mode = DEFAULT; /* default */
+ addr_modeP->scaled_mode=0; /* why not */
+ addr_modeP->scaled_reg=0; /* if 0, not scaled index */
+ addr_modeP->float_flag=0;
+ addr_modeP->am_size=0;
+ addr_modeP->im_disp=0;
+ addr_modeP->pcrel=0; /* not set in this function */
+ addr_modeP->disp_suffix[0]=0;
+ addr_modeP->disp_suffix[1]=0;
+ addr_modeP->disp[0]=NULL;
+ addr_modeP->disp[1]=NULL;
+ str=operand;
+ if (str[0] == 0) {return (0);} /* we don't want this */
+ strl=strlen(str);
+ switch (str[0]) {
+ /* the following three case statements controls the mode-chars
+ this is the place to ed if you want to change them */
+#ifdef ABSOLUTE_PREFIX
+ case ABSOLUTE_PREFIX:
+ if (str[strl-1] == ']') break;
+ addr_modeP->mode=21; /* absolute */
+ addr_modeP->disp[0]=str+1;
+ return (-1);
+#endif
+#ifdef IMMEDIATE_PREFIX
+ case IMMEDIATE_PREFIX:
+ if (str[strl-1] == ']') break;
+ addr_modeP->mode=20; /* immediate */
+ addr_modeP->disp[0]=str+1;
+ return (-1);
+#endif
+ case '.':
+ if (str[strl-1] != ']') {
+ switch (str[1]) {
+ case'-':case'+':
+ if (str[2] != '\000') {
+ addr_modeP->mode=27; /* pc-relativ */
+ addr_modeP->disp[0]=str+2;
+ return (-1);
+ }
+ default:
+ as_warn("Invalid syntax in PC-relative addressing mode");
+ return(0);
+ }
+ }
+ break;
+ case'e':
+ if (str[strl-1] != ']') {
+ if ((!strncmp(str,"ext(",4)) && strl>7) { /* external */
+ addr_modeP->disp[0]=str+4;
+ i=0;
+ j=2;
+ do { /* disp[0]'s termination point */
+ j+=1;
+ if (str[j] == '(') i++;
+ if (str[j] == ')') i--;
+ } while (j < strl && i != 0);
+ if (i != 0 || !(str[j+1] == '-' || str[j+1] == '+') ) {
+ as_warn("Invalid syntax in External addressing mode");
+ return(0);
+ }
+ str[j]='\000'; /* null terminate disp[0] */
+ addr_modeP->disp[1]=str+j+2;
+ addr_modeP->mode=22;
+ return (-1);
+ }
+ }
+ break;
+ default:;
+ }
+ strl=strlen(str);
+ switch (strl) {
+ case 2:
+ switch (str[0]) {
+ case'f':addr_modeP->float_flag=1;
+ case'r':
+ if (str[1] >= '0' && str[1] < '8') {
+ addr_modeP->mode=str[1]-'0';
+ return (-1);
+ }
+ }
+ case 3:
+ if (!strncmp(str,"tos",3)) {
+ addr_modeP->mode=23; /* TopOfStack */
+ return (-1);
+ }
+ default:;
+ }
+ if (strl>4) {
+ if (str[strl - 1] == ')') {
+ if (str[strl - 2] == ')') {
+ if (!strncmp(&str[strl-5],"(fp",3)) {
+ mode=16; /* Memory Relative */
+ }
+ if (!strncmp(&str[strl-5],"(sp",3)) {
+ mode=17;
+ }
+ if (!strncmp(&str[strl-5],"(sb",3)) {
+ mode=18;
+ }
+ if (mode != DEFAULT) { /* memory relative */
+ addr_modeP->mode=mode;
+ j=strl-5; /* temp for end of disp[0] */
+ i=0;
+ do {
+ strl-=1;
+ if (str[strl] == ')') i++;
+ if (str[strl] == '(') i--;
+ } while (strl>-1 && i != 0);
+ if (i != 0) {
+ as_warn("Invalid syntax in Memory Relative addressing mode");
+ return(0);
+ }
+ addr_modeP->disp[1]=str;
+ addr_modeP->disp[0]=str+strl+1;
+ str[j]='\000'; /* null terminate disp[0] */
+ str[strl]='\000'; /* null terminate disp[1] */
+ return (-1);
+ }
+ }
+ switch (str[strl-3]) {
+ case'r':case'R':
+ if (str[strl - 2] >= '0' && str[strl - 2] < '8' && str[strl - 4] == '(') {
+ addr_modeP->mode=str[strl-2]-'0'+8;
+ addr_modeP->disp[0]=str;
+ str[strl-4]=0;
+ return (-1); /* reg rel */
+ }
+ default:
+ if (!strncmp(&str[strl-4],"(fp",3)) {
+ mode=24;
+ }
+ if (!strncmp(&str[strl-4],"(sp",3)) {
+ mode=25;
+ }
+ if (!strncmp(&str[strl-4],"(sb",3)) {
+ mode=26;
+ }
+ if (!strncmp(&str[strl-4],"(pc",3)) {
+ mode=27;
+ }
+ if (mode != DEFAULT) {
+ addr_modeP->mode=mode;
+ addr_modeP->disp[0]=str;
+ str[strl-4]='\0';
+ return (-1); /* memory space */
+ }
+ }
+ }
+ /* no trailing ')' do we have a ']' ? */
+ if (str[strl - 1] == ']') {
+ switch (str[strl-2]) {
+ case'b':mode=28;break;
+ case'w':mode=29;break;
+ case'd':mode=30;break;
+ case'q':mode=31;break;
+ default:;
+ as_warn("Invalid scaled-indexed mode, use (b,w,d,q)");
+ if (str[strl - 3] != ':' || str[strl - 6] != '[' ||
+ str[strl - 5] == 'r' || str[strl - 4] < '0' || str[strl - 4] > '7') {
+ as_warn("Syntax in scaled-indexed mode, use [Rn:m] where n=[0..7] m={b,w,d,q}");
+ }
+ } /* scaled index */
+ {
+ if (recursive_level>0) {
+ as_warn("Scaled-indexed addressing mode combined with scaled-index");
+ return(0);
+ }
+ addr_modeP->am_size+=1; /* scaled index byte */
+ j=str[strl-4]-'0'; /* store temporary */
+ str[strl-6]='\000'; /* nullterminate for recursive call */
+ i=addr_mode(str,addr_modeP,1);
+ if (!i || addr_modeP->mode == 20) {
+ as_warn("Invalid or illegal addressing mode combined with scaled-index");
+ return(0);
+ }
+ addr_modeP->scaled_mode=addr_modeP->mode; /* store the inferior mode */
+ addr_modeP->mode=mode;
+ addr_modeP->scaled_reg=j+1;
+ return (-1);
+ }
+ }
+ }
+ addr_modeP->mode = DEFAULT; /* default to whatever */
+ addr_modeP->disp[0]=str;
+ return (-1);
+}
+
+/* ptr points at string
+ addr_modeP points at struct with result
+ This routine calls addr_mode to determine the general addr.mode of
+ the operand. When this is ready it parses the displacements for size
+ specifying suffixes and determines size of immediate mode via ns32k-opcode.
+ Also builds index bytes if needed.
+ */
+int get_addr_mode(ptr,addr_modeP)
+char *ptr;
+addr_modeS *addr_modeP;
+{
+ int tmp;
+ addr_mode(ptr,addr_modeP,0);
+ if (addr_modeP->mode == DEFAULT || addr_modeP->scaled_mode == -1) {
+ /* resolve ambigious operands, this shouldn't
+ be necessary if one uses standard NSC operand
+ syntax. But the sequent compiler doesn't!!!
+ This finds a proper addressinging mode if it
+ is implicitly stated. See ns32k-opcode.h */
+ (void)evaluate_expr(&exprP,ptr); /* this call takes time Sigh! */
+ if (addr_modeP->mode == DEFAULT) {
+ if (exprP.X_add_symbol || exprP.X_subtract_symbol) {
+ addr_modeP->mode=desc->default_model; /* we have a label */
+ } else {
+ addr_modeP->mode=desc->default_modec; /* we have a constant */
+ }
+ } else {
+ if (exprP.X_add_symbol || exprP.X_subtract_symbol) {
+ addr_modeP->scaled_mode=desc->default_model;
+ } else {
+ addr_modeP->scaled_mode=desc->default_modec;
+ }
+ }
+ /* must put this mess down in addr_mode to handle the scaled case better */
+ }
+ /* It appears as the sequent compiler wants an absolute when we have a
+ label without @. Constants becomes immediates besides the addr case.
+ Think it does so with local labels too, not optimum, pcrel is better.
+ When I have time I will make gas check this and select pcrel when possible
+ Actually that is trivial.
+ */
+ if (tmp=addr_modeP->scaled_reg) { /* build indexbyte */
+ tmp--; /* remember regnumber comes incremented for flagpurpose */
+ tmp|=addr_modeP->scaled_mode<<3;
+ addr_modeP->index_byte=(char)tmp;
+ addr_modeP->am_size+=1;
+ }
+ if (disp_test[addr_modeP->mode]) { /* there was a displacement, probe for length specifying suffix*/
+ {
+ register char c;
+ register char suffix;
+ register char suffix_sub;
+ register int i;
+ register char *toP;
+ register char *fromP;
+
+ addr_modeP->pcrel=0;
+ if (disp_test[addr_modeP->mode]) { /* there is a displacement */
+ if (addr_modeP->mode == 27 || addr_modeP->scaled_mode == 27) { /* do we have pcrel. mode */
+ addr_modeP->pcrel=1;
+ }
+ addr_modeP->im_disp=1;
+ for (i=0;i<2;i++) {
+ suffix_sub=suffix=0;
+ if (toP=addr_modeP->disp[i]) { /* suffix of expression, the largest size rules */
+ fromP=toP;
+ while (c = *fromP++) {
+ *toP++=c;
+ if (c == ':') {
+ switch (*fromP) {
+ case '\0':
+ as_warn("Premature end of suffix--Defaulting to d");
+ suffix=4;
+ continue;
+ case 'b':suffix_sub=1;break;
+ case 'w':suffix_sub=2;break;
+ case 'd':suffix_sub=4;break;
+ default:
+ as_warn("Bad suffix after ':' use {b|w|d} Defaulting to d");
+ suffix=4;
+ }
+ fromP++;
+ toP--; /* So we write over the ':' */
+ if (suffix<suffix_sub) suffix=suffix_sub;
+ }
+ }
+ *toP='\0'; /* terminate properly */
+ addr_modeP->disp_suffix[i]=suffix;
+ addr_modeP->am_size+=suffix ? suffix : 4;
+ }
+ }
+ }
+ }
+ } else {
+ if (addr_modeP->mode == 20) { /* look in ns32k_opcode for size */
+ addr_modeP->disp_suffix[0]=addr_modeP->am_size=desc->im_size;
+ addr_modeP->im_disp=0;
+ }
+ }
+ return addr_modeP->mode;
+}
+
+
+/* read an optionlist */
+void optlist(str,optionP,default_map)
+char *str; /* the string to extract options from */
+struct option *optionP; /* how to search the string */
+unsigned long *default_map; /* default pattern and output */
+{
+ register int i,j,k,strlen1,strlen2;
+ register char *patternP,*strP;
+ strlen1=strlen(str);
+ if (strlen1<1) {
+ as_fatal("Very short instr to option, ie you can't do it on a NULLstr");
+ }
+ for (i = 0; optionP[i].pattern != 0; i++) {
+ strlen2=strlen(optionP[i].pattern);
+ for (j=0;j<strlen1;j++) {
+ patternP=optionP[i].pattern;
+ strP = &str[j];
+ for (k=0;k<strlen2;k++) {
+ if (*(strP++) != *(patternP++)) break;
+ }
+ if (k == strlen2) { /* match */
+ *default_map|=optionP[i].or;
+ *default_map&=optionP[i].and;
+ }
+ }
+ }
+}
+/* search struct for symbols
+ This function is used to get the short integer form of reg names
+ in the instructions lmr, smr, lpr, spr
+ return true if str is found in list */
+
+int list_search(str,optionP,default_map)
+char *str; /* the string to match */
+struct option *optionP; /* list to search */
+unsigned long *default_map; /* default pattern and output */
+{
+ register int i;
+ for (i = 0; optionP[i].pattern != 0; i++) {
+ if (!strncmp(optionP[i].pattern,str,20)) { /* use strncmp to be safe */
+ *default_map|=optionP[i].or;
+ *default_map&=optionP[i].and;
+ return -1;
+ }
+ }
+ as_warn("No such entry in list. (cpu/mmu register)");
+ return 0;
+}
+static segT evaluate_expr(resultP,ptr)
+expressionS *resultP;
+char *ptr;
+{
+ register char *tmp_line;
+ register segT segment;
+ tmp_line = input_line_pointer;
+ input_line_pointer = ptr;
+ segment = expression(&exprP);
+ input_line_pointer = tmp_line;
+ return(segment);
+}
+
+/* Convert operands to iif-format and adds bitfields to the opcode.
+ Operands are parsed in such an order that the opcode is updated from
+ its most significant bit, that is when the operand need to alter the
+ opcode.
+ Be carefull not to put to objects in the same iif-slot.
+ */
+
+void encode_operand(argc,argv,operandsP,suffixP,im_size,opcode_bit_ptr)
+int argc;
+char **argv;
+char *operandsP;
+char *suffixP;
+char im_size;
+char opcode_bit_ptr;
+{
+ register int i,j;
+ int pcrel,tmp,b,loop,pcrel_adjust;
+ for (loop=0;loop<argc;loop++) {
+ i=operandsP[loop<<1]-'1'; /* what operand are we supposed to work on */
+ if (i>3) as_fatal("Internal consistency error. check ns32k-opcode.h");
+ pcrel=0;
+ pcrel_adjust=0;
+ tmp=0;
+ switch (operandsP[(loop<<1)+1]) {
+ case 'f': /* operand of sfsr turns out to be a nasty specialcase */
+ opcode_bit_ptr-=5;
+ case 'F': /* 32 bit float general form */
+ case 'L': /* 64 bit float */
+ case 'Q': /* quad-word */
+ case 'B': /* byte */
+ case 'W': /* word */
+ case 'D': /* double-word */
+ case 'A': /* double-word gen-address-form ie no regs allowed */
+ get_addr_mode(argv[i],&addr_modeP);
+ iif.instr_size+=addr_modeP.am_size;
+ if (opcode_bit_ptr == desc->opcode_size) b = 4; else b = 6;
+ for (j=b;j<(b+2);j++) {
+ if (addr_modeP.disp[j-b]) {
+ IIF(j,
+ 2,
+ addr_modeP.disp_suffix[j-b],
+ (unsigned long)addr_modeP.disp[j-b],
+ 0,
+ addr_modeP.pcrel,
+ iif.instr_size-addr_modeP.am_size, /* this aint used (now) */
+ addr_modeP.im_disp,
+ IND(BRANCH,BYTE),
+ NULL,
+ addr_modeP.scaled_reg ? addr_modeP.scaled_mode:addr_modeP.mode,
+ 0);
+ }
+ }
+ opcode_bit_ptr-=5;
+ iif.iifP[1].object|=((long)addr_modeP.mode)<<opcode_bit_ptr;
+ if (addr_modeP.scaled_reg) {
+ j=b/2;
+ IIF(j,1,1, (unsigned long)addr_modeP.index_byte,0,0,0,0,0, NULL,-1,0);
+ }
+ break;
+ case 'b': /* multiple instruction disp */
+ freeptr++; /* OVE:this is an useful hack */
+ tmp = (int) sprintf(freeptr,
+ "((%s-1)*%d)\000",
+ argv[i], desc->im_size);
+ argv[i]=freeptr;
+ freeptr=(char*)tmp;
+ pcrel-=1; /* make pcrel 0 inspite of what case 'p': wants */
+ /* fall thru */
+ case 'p': /* displacement - pc relative addressing */
+ pcrel+=1;
+ /* fall thru */
+ case 'd': /* displacement */
+ iif.instr_size+=suffixP[i] ? suffixP[i] : 4;
+ IIF(12, 2, suffixP[i], (unsigned long)argv[i], 0,
+ pcrel, pcrel_adjust, 1, IND(BRANCH,BYTE), NULL,-1,0);
+ break;
+ case 'H': /* sequent-hack: the linker wants a bit set when bsr */
+ pcrel=1;
+ iif.instr_size+=suffixP[i] ? suffixP[i] : 4;
+ IIF(12, 2, suffixP[i], (unsigned long)argv[i], 0,
+ pcrel, pcrel_adjust, 1, IND(BRANCH,BYTE), NULL,-1, 1);
+ break;
+ case 'q': /* quick */
+ opcode_bit_ptr-=4;
+ IIF(11,2,42,(unsigned long)argv[i],0,0,0,0,0,
+ bit_fix_new(4,opcode_bit_ptr,-8,7,0,1,0),-1,0);
+ break;
+ case 'r': /* register number (3 bits) */
+ list_search(argv[i],opt6,&tmp);
+ opcode_bit_ptr-=3;
+ iif.iifP[1].object|=tmp<<opcode_bit_ptr;
+ break;
+ case 'O': /* setcfg instruction optionslist */
+ optlist(argv[i],opt3,&tmp);
+ opcode_bit_ptr-=4;
+ iif.iifP[1].object|=tmp<<15;
+ break;
+ case 'C': /* cinv instruction optionslist */
+ optlist(argv[i],opt4,&tmp);
+ opcode_bit_ptr-=4;
+ iif.iifP[1].object|=tmp<<15;/*insert the regtype in opcode */
+ break;
+ case 'S': /* stringinstruction optionslist */
+ optlist(argv[i],opt5,&tmp);
+ opcode_bit_ptr-=4;
+ iif.iifP[1].object|=tmp<<15;
+ break;
+ case 'u':case 'U': /* registerlist */
+ IIF(10,1,1,0,0,0,0,0,0,NULL,-1,0);
+ switch (operandsP[(i<<1)+1]) {
+ case 'u': /* restore, exit */
+ optlist(argv[i],opt1,&iif.iifP[10].object);
+ break;
+ case 'U': /* save,enter */
+ optlist(argv[i],opt2,&iif.iifP[10].object);
+ break;
+ }
+ iif.instr_size+=1;
+ break;
+ case 'M': /* mmu register */
+ list_search(argv[i],mmureg,&tmp);
+ opcode_bit_ptr-=4;
+ iif.iifP[1].object|=tmp<<opcode_bit_ptr;
+ break;
+ case 'P': /* cpu register */
+ list_search(argv[i],cpureg,&tmp);
+ opcode_bit_ptr-=4;
+ iif.iifP[1].object|=tmp<<opcode_bit_ptr;
+ break;
+ case 'g': /* inss exts */
+ iif.instr_size+=1; /* 1 byte is allocated after the opcode */
+ IIF(10,2,1,
+ (unsigned long)argv[i], /* i always 2 here */
+ 0,0,0,0,0,
+ bit_fix_new(3,5,0,7,0,0,0), /* a bit_fix is targeted to the byte */
+ -1,0);
+ case 'G':
+ IIF(11,2,42,
+ (unsigned long)argv[i], /* i always 3 here */
+ 0,0,0,0,0,
+ bit_fix_new(5,0,1,32,-1,0,-1),-1,0);
+ break;
+ case 'i':
+ iif.instr_size+=1;
+ b=2+i; /* put the extension byte after opcode */
+ IIF(b,2,1,0,0,0,0,0,0,0,-1,0);
+ default:
+ as_fatal("Bad opcode-table-option, check in file ns32k-opcode.h");
+ }
+ }
+}
+
+/* in: instruction line
+ out: internal structure of instruction
+ that has been prepared for direct conversion to fragment(s) and
+ fixes in a systematical fashion
+ Return-value = recursive_level
+ */
+/* build iif of one assembly text line */
+int parse(line,recursive_level)
+char *line;
+int recursive_level;
+{
+ register char *lineptr,c,suffix_separator;
+ register int i;
+ int argc,arg_type;
+ char sqr,sep;
+ char suffix[MAX_ARGS],*argv[MAX_ARGS];/* no more than 4 operands */
+ if (recursive_level <= 0) { /* called from md_assemble */
+ for (lineptr=line; (*lineptr) != '\0' && (*lineptr) != ' '; lineptr++);
+ c = *lineptr;
+ *lineptr = '\0';
+ desc = (struct ns32k_opcode*) hash_find(inst_hash_handle,line);
+ if (!desc) {
+ as_fatal("No such opcode");
+ }
+ *lineptr = c;
+ } else {
+ lineptr = line;
+ }
+ argc = 0;
+ if (*desc->operands != NULL) {
+ if (*lineptr++ != '\0') {
+ sqr='[';
+ sep=',';
+ while (*lineptr != '\0') {
+ if (desc->operands[argc << 1]) {
+ suffix[argc] = 0;
+ arg_type =
+ desc->operands[(argc << 1) + 1];
+ switch (arg_type) {
+ case 'd':
+ case 'b':
+ case 'p':
+ case 'H': /* the operand is supposed to be a displacement */
+ /* Hackwarning: do not forget to update the 4 cases above when editing ns32k-opcode.h */
+ suffix_separator = ':';
+ break;
+ default:
+ suffix_separator = '\255'; /* if this char occurs we loose */
+ }
+ suffix[argc] = 0; /* 0 when no ':' is encountered */
+ argv[argc] = freeptr;
+ *freeptr = '\0';
+ while ((c = *lineptr) != '\0' && c != sep) {
+ if (c == sqr) {
+ if (sqr == '[') {
+ sqr = ']';
+ sep = '\0';
+ } else {
+ sqr = '[';
+ sep = ',';
+ }
+ }
+ if (c == suffix_separator) { /* ':' - label/suffix separator */
+ switch (lineptr[1]) {
+ case 'b': suffix[argc] = 1; break;
+ case 'w': suffix[argc] = 2; break;
+ case 'd': suffix[argc] = 4; break;
+ default: as_warn("Bad suffix, defaulting to d");
+ suffix[argc] = 4;
+ if (lineptr[1] == '\0' || lineptr[1] == sep) {
+ lineptr += 1;
+ continue;
+ }
+ }
+ lineptr += 2;
+ continue;
+ }
+ *freeptr++ = c;
+ lineptr++;
+ }
+ *freeptr++ = '\0';
+ argc += 1;
+ if (*lineptr == '\0') continue;
+ lineptr += 1;
+ } else {
+ as_fatal("Too many operands passed to instruction");
+ }
+ }
+ }
+ }
+ if (argc != strlen(desc->operands) / 2) {
+ if (strlen(desc->default_args) != 0) { /* we can apply default, dont goof */
+ if (parse(desc->default_args,1) != 1) { /* check error in default */
+ as_fatal("Wrong numbers of operands in default, check ns32k-opcodes.h");
+ }
+ } else {
+ as_fatal("Wrong number of operands");
+ }
+
+ }
+ for (i = 0; i < IIF_ENTRIES; i++) {
+ iif.iifP[i].type = 0; /* mark all entries as void*/
+ }
+
+ /* build opcode iif-entry */
+ iif.instr_size = desc->opcode_size / 8;
+ IIF(1,1,iif.instr_size,desc->opcode_seed,0,0,0,0,0,0,-1,0);
+
+ /* this call encodes operands to iif format */
+ if (argc) {
+ encode_operand(argc,
+ argv,
+ &desc->operands[0],
+ &suffix[0],
+ desc->im_size,
+ desc->opcode_size);
+ }
+ return(recursive_level);
+}
+
+
+/* Convert iif to fragments.
+ From this point we start to dribble with functions in other files than
+ this one.(Except hash.c) So, if it's possible to make an iif for an other
+ CPU, you don't need to know what frags, relax, obstacks, etc is in order
+ to port this assembler. You only need to know if it's possible to reduce
+ your cpu-instruction to iif-format (takes some work) and adopt the other
+ md_? parts according to given instructions
+ Note that iif was invented for the clean ns32k`s architecure.
+ */
+void convert_iif() {
+ int i;
+ bit_fixS *bit_fixP;
+ fragS *inst_frag;
+ char *inst_offset;
+ char *inst_opcode;
+ char *memP;
+ segT segment;
+ int l;
+ int k;
+ int rem_size; /* count the remaining bytes of instruction */
+ char type;
+ char size = 0;
+ int size_so_far = 0; /* used to calculate pcrel_adjust */
+ int pcrel_symbols = 0;/* kludge by jkp@hut.fi to make
+ movd _foo(pc),_bar(pc) work.
+ It should be done with two frags
+ for one insn, but I don't understand
+ enough to make it work */
+
+ rem_size = iif.instr_size;
+ memP = frag_more(iif.instr_size); /* make sure we have enough bytes for instruction */
+ inst_opcode = memP;
+ inst_offset = (char *)(memP-frag_now->fr_literal);
+ inst_frag = frag_now;
+ for (i=0; i < IIF_ENTRIES; i++) { /* jkp kludge alert */
+ if (iif.iifP[i].type && iif.iifP[i].size == 0 &&
+ iif.iifP[i].pcrel) {
+ evaluate_expr(&exprP, (char *)iif.iifP[i].object);
+ if (exprP.X_add_symbol || exprP.X_subtract_symbol)
+ pcrel_symbols++;
+ }
+ }
+ for (i=0;i<IIF_ENTRIES;i++) {
+ if (type=iif.iifP[i].type) { /* the object exist, so handle it */
+#ifdef PIC
+ int reloc_mode;
+ if ((i == 4 || i == 6)
+ && picmode
+ && (iif.iifP[i].addr_mode == 18 || iif.iifP[i].addr_mode == 26))
+ reloc_mode = RELOC_GLOB_DAT;
+ else
+ reloc_mode = NO_RELOC;
+#else
+ int reloc_mode = NO_RELOC;
+#endif
+ switch (size=iif.iifP[i].size) {
+ case 42: size=0; /* it's a bitfix that operates on an existing object*/
+ if (iif.iifP[i].bit_fixP->fx_bit_base) { /* expand fx_bit_base to point at opcode */
+ iif.iifP[i].bit_fixP->fx_bit_base = (long) inst_opcode;
+ }
+ case 8: /* bignum or doublefloat */
+ memset(memP, '\0', 8);
+ case 1:case 2:case 3:case 4:/* the final size in objectmemory is known */
+ bit_fixP = iif.iifP[i].bit_fixP;
+ switch (type) {
+ case 1: /* the object is pure binary */
+ if (bit_fixP || iif.iifP[i].pcrel) {
+ fix_new_ns32k(frag_now,
+ (long)(memP-frag_now->fr_literal),
+ size,
+ 0,
+ 0,
+ iif.iifP[i].object,
+ iif.iifP[i].pcrel,
+ (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/
+ iif.iifP[i].im_disp,
+ bit_fixP,
+ iif.iifP[i].bsr, /* sequent hack */
+ reloc_mode);
+ } else { /* good, just put them bytes out */
+ switch (iif.iifP[i].im_disp) {
+ case 0:
+ md_number_to_chars(memP,iif.iifP[i].object,size);break;
+ case 1:
+ md_number_to_disp(memP,iif.iifP[i].object,size);break;
+ default: as_fatal("iif convert internal pcrel/binary");
+ }
+ }
+ memP+=size;
+ rem_size-=size;
+ break;
+ case 2: /* the object is a pointer at an expression, so unpack
+ it, note that bignums may result from the expression
+ */
+ if ((segment = evaluate_expr(&exprP, (char*)iif.iifP[i].object)) == SEG_BIG || size == 8) {
+ if ((k=exprP.X_add_number)>0) { /* we have a bignum ie a quad */
+ /* this can only happens in a long suffixed instruction */
+ memset(memP, '\0', size); /* size normally is 8 */
+ if (k*2>size) as_warn("Bignum too big for long");
+ if (k == 3) memP += 2;
+ for (l=0;k>0;k--,l+=2) {
+ md_number_to_chars(memP+l,generic_bignum[l>>1],sizeof(LITTLENUM_TYPE));
+ }
+ } else { /* flonum */
+ LITTLENUM_TYPE words[4];
+
+ switch (size) {
+ case 4:
+ gen_to_words(words,2,8);
+ md_number_to_imm(memP ,(long)words[0],sizeof(LITTLENUM_TYPE));
+ md_number_to_imm(memP+sizeof(LITTLENUM_TYPE),(long)words[1],sizeof(LITTLENUM_TYPE));
+ break;
+ case 8:
+ gen_to_words(words,4,11);
+ md_number_to_imm(memP ,(long)words[0],sizeof(LITTLENUM_TYPE));
+ md_number_to_imm(memP+sizeof(LITTLENUM_TYPE) ,(long)words[1],sizeof(LITTLENUM_TYPE));
+ md_number_to_imm(memP+2*sizeof(LITTLENUM_TYPE),(long)words[2],sizeof(LITTLENUM_TYPE));
+ md_number_to_imm(memP+3*sizeof(LITTLENUM_TYPE),(long)words[3],sizeof(LITTLENUM_TYPE));
+ break;
+ }
+ }
+ memP+=size;
+ rem_size-=size;
+ break;
+ }
+ if (bit_fixP ||
+ exprP.X_add_symbol ||
+ exprP.X_subtract_symbol ||
+ iif.iifP[i].pcrel) { /* fixit */
+ /* the expression was undefined due to an undefined label */
+ /* create a fix so we can fix the object later */
+ exprP.X_add_number+=iif.iifP[i].object_adjust;
+ fix_new_ns32k(frag_now,
+ (long)(memP-frag_now->fr_literal),
+ size,
+ exprP.X_add_symbol,
+ exprP.X_subtract_symbol,
+ exprP.X_add_number,
+ iif.iifP[i].pcrel,
+ (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/
+ iif.iifP[i].im_disp,
+ bit_fixP,
+ iif.iifP[i].bsr, /* sequent hack */
+ reloc_mode);
+
+ } else { /* good, just put them bytes out */
+ switch (iif.iifP[i].im_disp) {
+ case 0:
+ md_number_to_imm(memP,exprP.X_add_number,size);break;
+ case 1:
+ md_number_to_disp(memP,exprP.X_add_number,size);break;
+ default: as_fatal("iif convert internal pcrel/pointer");
+ }
+ }
+ memP+=size;
+ rem_size-=size;
+ break;
+ default: as_fatal("Internal logic error in iif.iifP[n].type");
+ }
+ break;
+ case 0: /* To bad, the object may be undefined as far as its final
+ nsize in object memory is concerned. The size of the object
+ in objectmemory is not explicitly given.
+ If the object is defined its length can be determined and
+ a fix can replace the frag.
+ */
+ {
+ int temp;
+ segment = evaluate_expr(&exprP, (char*)iif.iifP[i].object);
+ if (((exprP.X_add_symbol || exprP.X_subtract_symbol) &&
+ !iif.iifP[i].pcrel) || pcrel_symbols >= 2 /*jkp*/) { /* OVE: hack, clamp to 4 bytes */
+#ifdef PIC
+ if (reloc_mode == RELOC_GLOB_DAT && got_offset_size == 2) {
+ size = 2;
+ /* rewind the bytes not used */
+ obstack_blank_fast(&frags, -2);
+ } else
+#endif
+ size=4; /* we dont wan't to frag this, use 4 so it reaches */
+ fix_new_ns32k(frag_now,
+ (long)(memP-frag_now->fr_literal),
+ size,
+ exprP.X_add_symbol,
+ exprP.X_subtract_symbol,
+ exprP.X_add_number,
+ pcrel_symbols >= 2 ? iif.iifP[i].pcrel : 0, /*jkp*//* never iif.iifP[i].pcrel, */
+ (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/
+ 1, /* always iif.iifP[i].im_disp, */
+ 0,0,
+ reloc_mode);
+ memP+=size;
+ rem_size-=4;
+ break; /* exit this absolute hack */
+ }
+
+ if (exprP.X_add_symbol || exprP.X_subtract_symbol) { /* frag it */
+ if (exprP.X_subtract_symbol) { /* We cant relax this case */
+ as_fatal("Can't relax difference");
+ } else {
+ /* at this stage we must undo some of the effect caused
+ by frag_more, ie we must make sure that frag_var causes
+ frag_new to creat a valid fix-size in the frag it`s closing
+ */
+ temp = -(rem_size-4);
+ obstack_blank_fast(&frags,temp);
+ /* we rewind none, some or all of the requested size we
+ requested by the first frag_more for this iif chunk.
+ Note: that we allocate 4 bytes to an object we NOT YET
+ know the size of, thus rem_size-4.
+ */
+ (void) frag_variant(rs_machine_dependent,
+ 4,
+ 0,
+ IND(BRANCH,UNDEF), /* expecting the worst */
+ exprP.X_add_symbol,
+ exprP.X_add_number,
+ inst_opcode,
+ (char)size_so_far, /*iif.iifP[i].pcrel_adjust);*/
+ iif.iifP[i].bsr); /* sequent linker hack */
+ rem_size -= 4;
+ if (rem_size > 0) {
+ memP = frag_more(rem_size);
+ }
+ }
+ } else {/* Double work, this is done in md_number_to_disp */
+ /* exprP.X_add_number; fixme-soon what was this supposed to be? xoxorich. */
+ if (-64 <= exprP.X_add_number && exprP.X_add_number <= 63) {
+ size = 1;
+ } else {
+ if (-8192 <= exprP.X_add_number && exprP.X_add_number <= 8191) {
+ size = 2;
+
+ /* Dave Taylor <taylor@think.com> says: Note: The reason the lower
+ limit is -0x1f000000 and not -0x20000000 is that, according to
+ Nat'l Semi's data sheet on the ns32532, ``the pattern 11100000
+ for the most significant byte of the displacement is reserved by
+ National for future enhancements''. */
+ } else if (/* -0x40000000 <= exprP.X_add_number &&
+ exprP.X_add_number <= 0x3fffffff */
+ -0x1f000000 <= exprP.X_add_number &&
+ exprP.X_add_number <= 0x1fffffff) {
+ size = 4;
+ } else {
+ as_warn("Displacement too large for :d");
+ size = 4;
+ }
+ }
+ /* rewind the bytes not used */
+ temp = -(4-size);
+ md_number_to_disp(memP,exprP.X_add_number,size);
+ obstack_blank_fast(&frags,temp);
+ memP += size;
+ rem_size -= 4; /* we allocated this amount */
+ }
+ }
+ break;
+ default:
+ as_fatal("Internal logic error in iif.iifP[].type");
+ }
+ size_so_far += size;
+ size = 0;
+ }
+ }
+}
+
+void md_assemble(line)
+char *line;
+{
+ freeptr=freeptr_static;
+ parse(line,0); /* explode line to more fix form in iif */
+ convert_iif(); /* convert iif to frags, fix's etc */
+#ifdef SHOW_NUM
+ printf(" \t\t\t%s\n",line);
+#endif
+}
+
+
+void md_begin() {
+ /* build a hashtable of the instructions */
+ register const struct ns32k_opcode *ptr;
+ register char *stat;
+ inst_hash_handle=hash_new();
+ for (ptr=ns32k_opcodes;ptr<endop;ptr++) {
+ if (*(stat=hash_insert(inst_hash_handle,ptr->name,(char*)ptr))) {
+ as_fatal("Can't hash %s: %s", ptr->name,stat); /*fatal*/
+ exit(0);
+ }
+ }
+ freeptr_static=(char*)malloc(PRIVATE_SIZE); /* some private space please! */
+}
+
+
+void
+ md_end() {
+ free(freeptr_static);
+ }
+
+/* Must be equal to MAX_PRECISON in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+/* Turn the string pointed to by litP into a floating point constant of type
+ type, and emit the appropriate bytes. The number of LITTLENUMS emitted
+ is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+char *
+ md_atof(type,litP,sizeP)
+char type;
+char *litP;
+int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ extern char *atof_ieee();
+ char *t;
+
+ switch (type) {
+ case 'f':
+ prec = 2;
+ break;
+
+ case 'd':
+ prec = 4;
+ break;
+ default:
+ *sizeP = 0;
+ return "Bad call to MD_ATOF()";
+ }
+ t = atof_ieee(input_line_pointer, type, words);
+ if (t)
+ input_line_pointer=t;
+
+ *sizeP = prec * sizeof(LITTLENUM_TYPE);
+ for (wordP = words +prec; prec--;) {
+ md_number_to_chars(litP, (long)(*--wordP), sizeof(LITTLENUM_TYPE));
+ litP+=sizeof(LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+}
+
+/* Convert number to chars in correct order */
+
+void
+ md_number_to_chars(buf, value, nbytes)
+char *buf;
+long value;
+int nbytes;
+{
+ while (nbytes--) {
+#ifdef SHOW_NUM
+ printf("%x ",value & 0xff);
+#endif
+ *buf++ = value; /* Lint wants & MASK_CHAR. */
+ value >>= BITS_PER_CHAR;
+ }
+} /* md_number_to_chars() */
+
+
+/* This is a variant of md_numbers_to_chars. The reason for its' existence
+ is the fact that ns32k uses Huffman coded displacements. This implies
+ that the bit order is reversed in displacements and that they are prefixed
+ with a size-tag.
+
+ binary: msb->lsb
+ 0xxxxxxx byte
+ 10xxxxxx xxxxxxxx word
+ 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word
+
+ This must be taken care of and we do it here!
+ */
+static void md_number_to_disp(buf, val, n)
+char *buf;
+long val;
+char n;
+{
+ switch (n) {
+ case 1:
+ if (val < -64 || val > 63)
+{
+fprintf(stderr, "val = %d\n", val);
+ as_warn("Byte displacement out of range. line number not valid");
+}
+ val &= 0x7f;
+#ifdef SHOW_NUM
+ printf("%x ",val & 0xff);
+#endif
+ *buf++ = val;
+ break;
+ case 2:
+ if (val < -8192 || val > 8191)
+ as_warn("Word displacement out of range. line number not valid");
+ val&=0x3fff;
+ val|=0x8000;
+#ifdef SHOW_NUM
+ printf("%x ",val>>8 & 0xff);
+#endif
+ *buf++=(val>>8);
+#ifdef SHOW_NUM
+ printf("%x ",val & 0xff);
+#endif
+ *buf++=val;
+ break;
+ case 4:
+
+ /* Dave Taylor <taylor@think.com> says: Note: The reason the
+ lower limit is -0x1f000000 and not -0x20000000 is that,
+ according to Nat'l Semi's data sheet on the ns32532, ``the
+ pattern 11100000 for the most significant byte of the
+ displacement is reserved by National for future
+ enhancements''. */
+
+ if (val < -0x1f000000 || val >= 0x20000000)
+ as_warn("Double word displacement out of range");
+ val|=0xc0000000;
+#ifdef SHOW_NUM
+ printf("%x ",val>>24 & 0xff);
+#endif
+ *buf++=(val>>24);
+#ifdef SHOW_NUM
+ printf("%x ",val>>16 & 0xff);
+#endif
+ *buf++=(val>>16);
+#ifdef SHOW_NUM
+ printf("%x ",val>>8 & 0xff);
+#endif
+ *buf++=(val>>8);
+#ifdef SHOW_NUM
+ printf("%x ",val & 0xff);
+#endif
+ *buf++=val;
+ break;
+ default:
+ as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
+ }
+}
+
+static void md_number_to_imm(buf,val,n)
+char *buf;
+long val;
+char n;
+{
+ switch (n) {
+ case 1:
+#ifdef SHOW_NUM
+ printf("%x ",val & 0xff);
+#endif
+ *buf++=val;
+ break;
+ case 2:
+#ifdef SHOW_NUM
+ printf("%x ",val>>8 & 0xff);
+#endif
+ *buf++=(val>>8);
+#ifdef SHOW_NUM
+ printf("%x ",val & 0xff);
+#endif
+ *buf++=val;
+ break;
+ case 4:
+#ifdef SHOW_NUM
+ printf("%x ",val>>24 & 0xff);
+#endif
+ *buf++=(val>>24);
+#ifdef SHOW_NUM
+ printf("%x ",val>>16 & 0xff);
+#endif
+ *buf++=(val>>16);
+#ifdef SHOW_NUM
+ printf("%x ",val>>8 & 0xff);
+#endif
+ *buf++=(val>>8);
+#ifdef SHOW_NUM
+ printf("%x ",val & 0xff);
+#endif
+ *buf++=val;
+ break;
+ default:
+ as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
+ }
+}
+
+/* Translate internal representation of relocation info into target format.
+
+ OVE: on a ns32k the twiddling continues at an even deeper level
+ here we have to distinguish between displacements and immediates.
+
+ The sequent has a bit for this. It also has a bit for relocobjects that
+ points at the target for a bsr (BranchSubRoutine) !?!?!?!
+
+ This md_ri.... is tailored for sequent.
+ */
+
+#ifdef comment
+void
+ md_ri_to_chars(the_bytes, ri)
+char *the_bytes;
+struct reloc_info_generic *ri;
+{
+ if (ri->r_bsr) { ri->r_pcrel = 0; } /* sequent seems to want this */
+ md_number_to_chars(the_bytes, ri->r_address, sizeof(ri->r_address));
+ md_number_to_chars(the_bytes+4, ((long)(ri->r_symbolnum )
+ | (long)(ri->r_pcrel << 24 )
+ | (long)(ri->r_length << 25 )
+ | (long)(ri->r_extern << 27 )
+ | (long)(ri->r_bsr << 28 )
+ | (long)(ri->r_disp << 29 )),
+ 4);
+ /* the first and second md_number_to_chars never overlaps (32bit cpu case) */
+}
+#endif /* comment */
+
+#ifdef OBJ_AOUT
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };
+ long r_symbolnum;
+ int r_flags;
+
+ know(fixP->fx_addsy != NULL);
+
+ md_number_to_chars(where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy)
+ ? S_GET_TYPE(fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+ r_flags = (fixP->fx_pcrel ? 1 : 0)
+ | ((nbytes_r_length[fixP->fx_size] & 3) << 1)
+ | (!S_IS_DEFINED(fixP->fx_addsy) ? 8 : 0)
+#if defined(TE_SEQUENT)
+ | (fixP->fx_bsr ? 0x10 : 0)
+#elif defined(PIC)
+ /* Undefined pc-relative relocations are of type jmpslot */
+ | ((!S_IS_DEFINED(fixP->fx_addsy)
+ && fixP->fx_pcrel
+ && fixP->fx_addsy != got_symbol
+ && picmode) ? 0x10 : 0)
+#endif
+ | (fixP->fx_im_disp & 3) << 5;
+
+#ifdef PIC
+ switch (fixP->fx_r_type) {
+ case NO_RELOC:
+ break;
+ case RELOC_32:
+ if (picmode && S_IS_EXTERNAL(fixP->fx_addsy)) {
+ r_symbolnum = fixP->fx_addsy->sy_number;
+ r_flags |= 8; /* set extern bit */
+ }
+ break;
+ case RELOC_GLOB_DAT:
+ if (!fixP->fx_pcrel) {
+ r_flags |= 0x80; /* set baserel bit */
+ r_symbolnum = fixP->fx_addsy->sy_number;
+ if (S_IS_EXTERNAL(fixP->fx_addsy))
+ r_flags |= 8;
+ }
+ break;
+ case RELOC_RELATIVE:
+ /* should never happen */
+ as_fatal("relocation botch");
+ break;
+ }
+#endif /* PIC */
+
+ where[4] = r_symbolnum & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[6] = (r_symbolnum >> 16) & 0x0ff;
+ where[7] = r_flags;
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+
+#endif /* OBJ_AOUT */
+
+/* fast bitfiddling support */
+/* mask used to zero bitfield before oring in the true field */
+
+static unsigned long l_mask[] = {
+ 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
+ 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
+ 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
+ 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
+ 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
+ 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
+ 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
+ 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
+};
+static unsigned long r_mask[] = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
+ 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+ 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+ 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+ 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
+ 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+ 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
+ 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+};
+#define MASK_BITS 31
+/* Insert bitfield described by field_ptr and val at buf
+ This routine is written for modification of the first 4 bytes pointed
+ to by buf, to yield speed.
+ The ifdef stuff is for selection between a ns32k-dependent routine
+ and a general version. (My advice: use the general version!)
+ */
+
+static void
+ md_number_to_field(buf,val,field_ptr)
+register char *buf;
+register long val;
+register bit_fixS *field_ptr;
+{
+ register unsigned long object;
+ register unsigned long mask;
+ /* define ENDIAN on a ns32k machine */
+#ifdef ENDIAN
+ register unsigned long *mem_ptr;
+#else
+ register char *mem_ptr;
+#endif
+ if (field_ptr->fx_bit_min <= val && val <= field_ptr->fx_bit_max) {
+#ifdef ENDIAN
+ if (field_ptr->fx_bit_base) { /* override buf */
+ mem_ptr=(unsigned long*)field_ptr->fx_bit_base;
+ } else {
+ mem_ptr=(unsigned long*)buf;
+ }
+#else
+ if (field_ptr->fx_bit_base) { /* override buf */
+ mem_ptr=(char*)field_ptr->fx_bit_base;
+ } else {
+ mem_ptr=buf;
+ }
+#endif
+ mem_ptr+=field_ptr->fx_bit_base_adj;
+#ifdef ENDIAN /* we have a nice ns32k machine with lowbyte at low-physical mem */
+ object = *mem_ptr; /* get some bytes */
+#else /* OVE Goof! the machine is a m68k or dito */
+ /* That takes more byte fiddling */
+ object=0;
+ object|=mem_ptr[3] & 0xff;
+ object<<=8;
+ object|=mem_ptr[2] & 0xff;
+ object<<=8;
+ object|=mem_ptr[1] & 0xff;
+ object<<=8;
+ object|=mem_ptr[0] & 0xff;
+#endif
+ mask=0;
+ mask|=(r_mask[field_ptr->fx_bit_offset]);
+ mask|=(l_mask[field_ptr->fx_bit_offset+field_ptr->fx_bit_size]);
+ object&=mask;
+ val+=field_ptr->fx_bit_add;
+ object|=((val<<field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));
+#ifdef ENDIAN
+ *mem_ptr=object;
+#else
+ mem_ptr[0]=(char)object;
+ object>>=8;
+ mem_ptr[1]=(char)object;
+ object>>=8;
+ mem_ptr[2]=(char)object;
+ object>>=8;
+ mem_ptr[3]=(char)object;
+#endif
+ } else {
+ as_warn("Bit field out of range");
+ }
+}
+
+/* Apply a fixS (fixup of an instruction or data that we didn't have
+ enough info to complete immediately) to the data in a frag.
+
+ On the ns32k, everything is in a different format, so we have broken
+ out separate functions for each kind of thing we could be fixing.
+ They all get called from here. */
+
+void
+ md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+
+ if (fixP->fx_bit_fixP) { /* Bitfields to fix, sigh */
+ md_number_to_field (buf, val, fixP->fx_bit_fixP);
+ } else switch (fixP->fx_im_disp) {
+
+ case 0: /* Immediate field */
+ md_number_to_imm (buf, val, fixP->fx_size);
+ break;
+
+ case 1: /* Displacement field */
+ md_number_to_disp (buf,
+ fixP->fx_pcrel? val + fixP->fx_pcrel_adjust: val,
+ fixP->fx_size);
+ break;
+
+ case 2: /* Pointer in a data object */
+ md_number_to_chars (buf, val, fixP->fx_size);
+ break;
+ }
+}
+
+/* Convert a relaxed displacement to ditto in final output */
+
+void
+ md_convert_frag(headers, fragP)
+object_headers *headers;
+register fragS *fragP;
+{
+ long disp;
+ long ext = 0;
+
+ /* Address in gas core of the place to store the displacement. */
+ register char *buffer_address = fragP->fr_fix + fragP->fr_literal;
+ /* Address in object code of the displacement. */
+ register int object_address = fragP->fr_fix + fragP->fr_address;
+
+ know(fragP->fr_symbol);
+
+ /* The displacement of the address, from current location. */
+ disp = (S_GET_VALUE(fragP->fr_symbol) + fragP->fr_offset) - object_address;
+ disp += fragP->fr_pcrel_adjust;
+
+ switch (fragP->fr_subtype) {
+ case IND(BRANCH,BYTE):
+ ext = 1;
+ break;
+ case IND(BRANCH,WORD):
+ ext = 2;
+ break;
+ case IND(BRANCH,DOUBLE):
+ ext = 4;
+ break;
+ }
+ if (ext) {
+ md_number_to_disp(buffer_address, (long)disp, (int)ext);
+ fragP->fr_fix += ext;
+ }
+} /* md_convert_frag() */
+
+
+
+/* This function returns the estimated size a variable object will occupy,
+ one can say that we tries to guess the size of the objects before we
+ actually know it */
+
+int md_estimate_size_before_relax(fragP, segment)
+register fragS *fragP;
+segT segment;
+{
+ int old_fix;
+ old_fix = fragP->fr_fix;
+ switch (fragP->fr_subtype) {
+ case IND(BRANCH,UNDEF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ /* the symbol has been assigned a value */
+ fragP->fr_subtype = IND(BRANCH,BYTE);
+ } else {
+ /* we don't relax symbols defined in an other segment
+ the thing to do is to assume the object will occupy 4 bytes */
+ fix_new_ns32k(fragP,
+ (int)(fragP->fr_fix),
+ 4,
+ fragP->fr_symbol,
+ (symbolS *)0,
+ fragP->fr_offset,
+ 1,
+ fragP->fr_pcrel_adjust,
+ 1,
+ 0,
+ fragP->fr_bsr, /*sequent hack */
+ NO_RELOC);
+ fragP->fr_fix+=4;
+ /* fragP->fr_opcode[1]=0xff; */
+ frag_wane(fragP);
+ break;
+ }
+ case IND(BRANCH,BYTE):
+ fragP->fr_var+=1;
+ break;
+ default:
+ break;
+ }
+ return fragP->fr_var + fragP->fr_fix - old_fix;
+}
+
+int md_short_jump_size = 3;
+int md_long_jump_size = 5;
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void
+ md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol)
+char *ptr;
+long from_addr,
+ to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - from_addr;
+ md_number_to_chars(ptr, (long)0xEA ,1);
+ md_number_to_disp(ptr+1,(long)offset,2);
+}
+
+void
+ md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)
+char *ptr;
+long from_addr,
+ to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ offset= to_addr - from_addr;
+ md_number_to_chars(ptr, (long)0xEA, 2);
+ md_number_to_disp(ptr+2,(long)offset,4);
+}
+
+/* JF this is a new function to parse machine-dep options */
+int
+ md_parse_option(argP,cntP,vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ switch (**argP) {
+ case 'm':
+ (*argP)++;
+
+ if (!strcmp(*argP,"32032")) {
+ cpureg = cpureg_032;
+ mmureg = mmureg_032;
+ } else if (!strcmp(*argP, "32532")) {
+ cpureg = cpureg_532;
+ mmureg = mmureg_532;
+ } else
+ as_warn("Unknown -m option ignored");
+
+ while (**argP)
+ (*argP)++;
+ break;
+
+#ifdef PIC
+ case 'K':
+ got_offset_size = 4;
+ /*FALLTHROUGH*/
+ case 'k':
+ got_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
+ break;
+#endif
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * bit_fix_new()
+ *
+ * Create a bit_fixS in obstack 'notes'.
+ * This struct is used to profile the normal fix. If the bit_fixP is a
+ * valid pointer (not NULL) the bit_fix data will be used to format the fix.
+ */
+bit_fixS *bit_fix_new(size, offset, min, max, add, base_type, base_adj)
+char size; /* Length of bitfield */
+char offset; /* Bit offset to bitfield */
+long base_type; /* 0 or 1, if 1 it's exploded to opcode ptr */
+long base_adj;
+long min; /* Signextended min for bitfield */
+long max; /* Signextended max for bitfield */
+long add; /* Add mask, used for huffman prefix */
+{
+ register bit_fixS * bit_fixP;
+
+ bit_fixP = (bit_fixS *)obstack_alloc(&notes,sizeof(bit_fixS));
+
+ bit_fixP->fx_bit_size = size;
+ bit_fixP->fx_bit_offset = offset;
+ bit_fixP->fx_bit_base = base_type;
+ bit_fixP->fx_bit_base_adj = base_adj;
+ bit_fixP->fx_bit_max = max;
+ bit_fixP->fx_bit_min = min;
+ bit_fixP->fx_bit_add = add;
+
+ return(bit_fixP);
+}
+
+void
+ fix_new_ns32k(frag, where, size, add_symbol, sub_symbol, offset, pcrel,
+ pcrel_adjust, im_disp, bit_fixP, bsr, r_type)
+fragS *frag; /* Which frag? */
+int where; /* Where in that frag? */
+int size; /* 1, 2 or 4 usually. */
+symbolS *add_symbol; /* X_add_symbol. */
+symbolS *sub_symbol; /* X_subtract_symbol. */
+long offset; /* X_add_number. */
+int pcrel; /* TRUE if PC-relative relocation. */
+char pcrel_adjust; /* not zero if adjustment of pcrel offset is needed */
+char im_disp; /* true if the value to write is a displacement */
+bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if NULL */
+char bsr; /* sequent-linker-hack: 1 when relocobject is a bsr */
+int r_type; /* Relocation type */
+
+{
+#ifdef PIC
+ fixS *fixP = fix_new(frag, where, size, add_symbol, sub_symbol,
+ offset, pcrel, r_type, NULL);
+#else
+ fixS *fixP = fix_new(frag, where, size, add_symbol, sub_symbol,
+ offset, pcrel, r_type);
+#endif /* PIC */
+ fixP->fx_pcrel_adjust = pcrel_adjust;
+ fixP->fx_im_disp = im_disp;
+ fixP->fx_bit_fixP = bit_fixP;
+ fixP->fx_bsr = bsr;
+#ifdef PIC
+ if (r_type == RELOC_GLOB_DAT)
+ add_symbol->sy_forceout = 1;
+#endif /* PIC */
+} /* fix_new_ns32k() */
+
+/* We have no need to default values of symbols. */
+
+symbolS *
+ md_undefined_symbol (name)
+char *name;
+{
+ return 0;
+}
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void
+ md_operand (expressionP)
+expressionS *expressionP;
+{
+}
+
+/* Round up a section size to the appropriate boundary. */
+long
+ md_section_align (segment, size)
+segT segment;
+long size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the National warts, they're relative to the address of the offset,
+ with some funny adjustments in some circumstances during blue moons.
+ (??? Is this right? FIXME-SOON) */
+long
+ md_pcrel_from (fixP)
+fixS *fixP;
+{
+ long res;
+ res = fixP->fx_where + fixP->fx_frag->fr_address;
+#ifdef TE_SEQUENT
+ if (fixP->fx_frag->fr_bsr)
+ res += 0x12; /* FOO Kludge alert! */
+#endif
+ return(res);
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * End:
+ */
+
+/* end of tc-ns32k.c */
diff --git a/gnu/usr.bin/as/config/tc-ns32k.h b/gnu/usr.bin/as/config/tc-ns32k.h
new file mode 100644
index 0000000..8f97304
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-ns32k.h
@@ -0,0 +1,66 @@
+/* tc-ns32k.h -- Opcode table for National Semi 32k processor
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef TC_NS32K
+#define TC_NS32K 1
+#include "bit_fix.h"
+
+#define LOCAL_LABELS_FB
+
+#define AOUT_MACHTYPE 137
+
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+
+#ifndef DEF_MODEC
+#define DEF_MODEC 20
+#endif
+
+#ifndef DEF_MODEL
+#define DEF_MODEL 20
+#endif
+
+#define MAX_ARGS 4
+#define ARG_LEN 50
+
+#if __STDC__ == 1
+
+void fix_new_ns32k(fragS *frag,
+ int where,
+ int size,
+ struct symbol *add_symbol,
+ struct symbol *sub_symbol,
+ long offset,
+ int pcrel,
+ int pcrel_adjust,
+ int im_disp,
+ bit_fixS *bit_fixP, /* really bit_fixS */
+ int bsr,
+ int r_type);
+
+#else /* not __STDC__ */
+
+void fix_new_ns32k();
+
+#endif /* not __STDC__ */
+
+#endif /* TC_NS32K */
+
+/* end of tc-ns32k.h */
diff --git a/gnu/usr.bin/as/config/tc-rs6000.c b/gnu/usr.bin/as/config/tc-rs6000.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-rs6000.c
diff --git a/gnu/usr.bin/as/config/tc-rs6000.h b/gnu/usr.bin/as/config/tc-rs6000.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-rs6000.h
diff --git a/gnu/usr.bin/as/config/tc-sparc.c b/gnu/usr.bin/as/config/tc-sparc.c
new file mode 100644
index 0000000..7a14efd
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-sparc.c
@@ -0,0 +1,1803 @@
+/* tc-sparc.c -- Assemble for the SPARC
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#define cypress 1234
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "as.h"
+
+/* careful, this file includes data *declarations* */
+#include "opcode/sparc.h"
+
+#define DEBUG_SPARC 1
+void md_begin();
+void md_end();
+void md_number_to_chars();
+void md_assemble();
+char *md_atof();
+void md_convert_frag();
+void md_create_short_jump();
+void md_create_long_jump();
+int md_estimate_size_before_relax();
+void md_ri_to_chars();
+symbolS *md_undefined_symbol();
+static void sparc_ip();
+
+static enum sparc_architecture current_architecture = v6;
+static int architecture_requested = 0;
+static int warn_on_bump = 0;
+
+const relax_typeS md_relax_table[] = {
+ 0 };
+
+/* handle of the OPCODE hash table */
+static struct hash_control *op_hash = NULL;
+
+static void s_seg(), s_proc(), s_data1(), s_reserve(), s_common(), s_empty();
+extern void s_globl(), s_long(), s_short(), s_space(), cons();
+extern void s_align_bytes(), s_ignore();
+
+const pseudo_typeS md_pseudo_table[] = {
+ { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0) */
+ { "empty", s_empty, 0 },
+ { "common", s_common, 0 },
+ { "global", s_globl, 0 },
+ { "half", cons, 2 },
+ { "optim", s_ignore, 0 },
+ { "proc", s_proc, 0 },
+ { "reserve", s_reserve, 0 },
+ { "seg", s_seg, 0 },
+ { "skip", s_space, 0 },
+ { "word", cons, 4 },
+ { NULL, 0, 0 },
+};
+
+const int md_short_jump_size = 4;
+const int md_long_jump_size = 4;
+const int md_reloc_size = 12; /* Size of relocation record */
+
+/* This array holds the chars that always start a comment. If the
+ pre-processor is disabled, these aren't very useful */
+const char comment_chars[] = "!"; /* JF removed '|' from comment_chars */
+
+/* This array holds the chars that only start a comment at the beginning of
+ a line. If the line seems to have the form '# 123 filename'
+ .line and .file directives will appear in the pre-processed output */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+ first line of the input file. This is because the compiler outputs
+ #NO_APP at the beginning of its output. */
+/* Also note that comments started like this one will always
+ work if '/' isn't otherwise defined. */
+const char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* As in 0f12.456 */
+/* or 0d1.2345e12 */
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ */
+
+static unsigned char octal[256];
+#define isoctal(c) octal[c]
+ static unsigned char toHex[256];
+
+struct sparc_it {
+ char *error;
+ unsigned long opcode;
+ struct nlist *nlistp;
+ expressionS exp;
+ int pcrel;
+ enum reloc_type reloc;
+} the_insn, set_insn;
+
+#if __STDC__ == 1
+#if DEBUG_SPARC
+static void print_insn(struct sparc_it *insn);
+#endif
+static int getExpression(char *str);
+#else /* not __STDC__ */
+#if DEBUG_SPARC
+static void print_insn();
+#endif
+static int getExpression();
+#endif /* not __STDC__ */
+
+static char *Reloc[] = {
+ "RELOC_8",
+ "RELOC_16",
+ "RELOC_32",
+ "RELOC_DISP8",
+ "RELOC_DISP16",
+ "RELOC_DISP32",
+ "RELOC_WDISP30",
+ "RELOC_WDISP22",
+ "RELOC_HI22",
+ "RELOC_22",
+ "RELOC_13",
+ "RELOC_LO10",
+ "RELOC_SFA_BASE",
+ "RELOC_SFA_OFF13",
+ "RELOC_BASE10",
+ "RELOC_BASE13",
+ "RELOC_BASE22",
+ "RELOC_PC10",
+ "RELOC_PC22",
+ "RELOC_JMP_TBL",
+ "RELOC_SEGOFF16",
+ "RELOC_GLOB_DAT",
+ "RELOC_JMP_SLOT",
+ "RELOC_RELATIVE",
+ "NO_RELOC"
+};
+
+static char *expr_end;
+static int special_case;
+
+/*
+ * Instructions that require wierd handling because they're longer than
+ * 4 bytes.
+ */
+#define SPECIAL_CASE_SET 1
+#define SPECIAL_CASE_FDIV 2
+
+/*
+ * sort of like s_lcomm
+ *
+ */
+static int max_alignment = 15;
+
+static void s_reserve() {
+ char *name;
+ char *p;
+ char c;
+ int align;
+ int size;
+ int temp;
+ symbolS *symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after name");
+ ignore_rest_of_line();
+ return;
+ }
+
+ ++input_line_pointer;
+
+ if ((size = get_absolute_expression()) < 0) {
+ as_bad("BSS length (%d.) <0! Ignored.", size);
+ ignore_rest_of_line();
+ return;
+ } /* bad length */
+
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+
+ if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) {
+ as_bad("bad .reserve segment: `%s'", input_line_pointer);
+ return;
+ } /* if not bss */
+
+ input_line_pointer += 6;
+ SKIP_WHITESPACE();
+
+ if (*input_line_pointer == ',') {
+ ++input_line_pointer;
+
+ SKIP_WHITESPACE();
+ if (*input_line_pointer == '\n') {
+ as_bad("Missing alignment");
+ return;
+ }
+
+ align = get_absolute_expression();
+ if (align > max_alignment){
+ align = max_alignment;
+ as_warn("Alignment too large: %d. assumed.", align);
+ } else if (align < 0) {
+ align = 0;
+ as_warn("Alignment negative. 0 assumed.");
+ }
+#ifdef MANY_SEGMENTS
+#define SEG_BSS SEG_E2
+ record_alignment(SEG_E2, align);
+#else
+ record_alignment(SEG_BSS, align);
+#endif
+
+ /* convert to a power of 2 alignment */
+ for (temp = 0; (align & 1) == 0; align >>= 1, ++temp) ;;
+
+ if (align != 1) {
+ as_bad("Alignment not a power of 2");
+ ignore_rest_of_line();
+ return;
+ } /* not a power of two */
+
+ align = temp;
+
+ /* Align */
+ align = ~((~0) << align); /* Convert to a mask */
+ local_bss_counter = (local_bss_counter + align) & (~align);
+ } /* if has optional alignment */
+
+ if (S_GET_OTHER(symbolP) == 0
+ && S_GET_DESC(symbolP) == 0
+ && ((S_GET_SEGMENT(symbolP) == SEG_BSS
+ && S_GET_VALUE(symbolP) == local_bss_counter)
+ || !S_IS_DEFINED(symbolP))) {
+ S_SET_VALUE(symbolP, local_bss_counter);
+ S_SET_SEGMENT(symbolP, SEG_BSS);
+ symbolP->sy_frag = &bss_address_frag;
+ local_bss_counter += size;
+ } else {
+ as_warn("Ignoring attempt to re-define symbol from %d. to %d.",
+ S_GET_VALUE(symbolP), local_bss_counter);
+ } /* if not redefining */
+
+ demand_empty_rest_of_line();
+ return;
+} /* s_reserve() */
+
+static void s_common() {
+ register char *name;
+ register char c;
+ register char *p;
+ register int temp;
+ register symbolS * symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (* input_line_pointer != ',') {
+ as_bad("Expected comma after symbol-name");
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer ++; /* skip ',' */
+ if ((temp = get_absolute_expression ()) < 0) {
+ as_bad(".COMMon length (%d.) <0! Ignored.", temp);
+ ignore_rest_of_line();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+ if (S_IS_DEFINED(symbolP)) {
+ as_bad("Ignoring attempt to re-define symbol");
+ ignore_rest_of_line();
+ return;
+ }
+ if (S_GET_VALUE(symbolP) != 0) {
+ if (S_GET_VALUE(symbolP) != temp) {
+ as_warn("Length of .comm \"%s\" is already %d. Not changed to %d.",
+ S_GET_NAME(symbolP), S_GET_VALUE(symbolP), temp);
+ }
+ } else {
+ S_SET_VALUE(symbolP, temp);
+ S_SET_EXTERNAL(symbolP);
+ }
+ know(symbolP->sy_frag == &zero_address_frag);
+ if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0
+ && strncmp(input_line_pointer, ",\"data\"", 7) != 0) {
+ p=input_line_pointer;
+ while (*p && *p != '\n')
+ p++;
+ c= *p;
+ *p='\0';
+ as_bad("bad .common segment: `%s'", input_line_pointer);
+ *p=c;
+ return;
+ }
+ input_line_pointer += 6 + (input_line_pointer[2] == 'd'); /* Skip either */
+ demand_empty_rest_of_line();
+ return;
+} /* s_common() */
+
+static void s_seg() {
+
+ if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
+ input_line_pointer += 6;
+ s_text();
+ return;
+ }
+ if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
+ input_line_pointer += 6;
+ s_data();
+ return;
+ }
+ if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
+ input_line_pointer += 7;
+ s_data1();
+ return;
+ }
+ if (strncmp(input_line_pointer, "\"bss\"", 5) == 0) {
+ input_line_pointer += 5;
+ /* We only support 2 segments -- text and data -- for now, so
+ things in the "bss segment" will have to go into data for now.
+ You can still allocate SEG_BSS stuff with .lcomm or .reserve. */
+ subseg_new(SEG_DATA, 255); /* FIXME-SOMEDAY */
+ return;
+ }
+ as_bad("Unknown segment type");
+ demand_empty_rest_of_line();
+ return;
+} /* s_seg() */
+
+static void s_data1() {
+ subseg_new(SEG_DATA, 1);
+ demand_empty_rest_of_line();
+ return;
+} /* s_data1() */
+
+static void s_proc() {
+ extern char is_end_of_line[];
+
+ while (!is_end_of_line[*input_line_pointer]) {
+ ++input_line_pointer;
+ }
+ ++input_line_pointer;
+ return;
+} /* s_proc() */
+
+/*
+ * GI: This is needed for compatability with Sun's assembler - which
+ * otherwise generates a warning when certain "suspect" instructions
+ * appear in the delay slot of a branch. And more seriously without
+ * this directive in certain cases Sun's assembler will rearrange
+ * code thinking it knows how to alter things when it doesn't.
+ */
+static void
+s_empty()
+{
+ demand_empty_rest_of_line();
+ return;
+} /* s_empty() */
+
+/* This function is called once, at assembler startup time. It should
+ set up all the tables, etc. that the MD part of the assembler will need. */
+void md_begin() {
+ register char *retval = NULL;
+ int lose = 0;
+ register unsigned int i = 0;
+
+ op_hash = hash_new();
+ if (op_hash == NULL)
+ as_fatal("Virtual memory exhausted");
+
+ while (i < NUMOPCODES) {
+ const char *name = sparc_opcodes[i].name;
+ retval = hash_insert(op_hash, name, &sparc_opcodes[i]);
+ if (retval != NULL && *retval != '\0') {
+ fprintf (stderr, "internal error: can't hash `%s': %s\n",
+ sparc_opcodes[i].name, retval);
+ lose = 1;
+ }
+ do
+ {
+ if (sparc_opcodes[i].match & sparc_opcodes[i].lose) {
+ fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
+ sparc_opcodes[i].name, sparc_opcodes[i].args);
+ lose = 1;
+ }
+ ++i;
+ } while (i < NUMOPCODES
+ && !strcmp(sparc_opcodes[i].name, name));
+ }
+
+ if (lose)
+ as_fatal("Broken assembler. No assembly attempted.");
+
+ for (i = '0'; i < '8'; ++i)
+ octal[i] = 1;
+ for (i = '0'; i <= '9'; ++i)
+ toHex[i] = i - '0';
+ for (i = 'a'; i <= 'f'; ++i)
+ toHex[i] = i + 10 - 'a';
+ for (i = 'A'; i <= 'F'; ++i)
+ toHex[i] = i + 10 - 'A';
+
+#if 0
+ if (picmode)
+ GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
+#endif
+} /* md_begin() */
+
+void md_end() {
+ return;
+} /* md_end() */
+
+void md_assemble(str)
+char *str;
+{
+ char *toP;
+ int rsd;
+
+ know(str);
+ sparc_ip(str);
+
+ /* See if "set" operand is absolute and small; skip sethi if so. */
+ if (special_case == SPECIAL_CASE_SET && the_insn.exp.X_seg == SEG_ABSOLUTE) {
+ if (the_insn.exp.X_add_number >= -(1<<12)
+ && the_insn.exp.X_add_number < (1<<12)) {
+ the_insn.opcode = 0x80102000 /* or %g0,imm,... */
+ | (the_insn.opcode & 0x3E000000) /* dest reg */
+ | (the_insn.exp.X_add_number & 0x1FFF); /* imm */
+ special_case = 0; /* No longer special */
+ the_insn.reloc = NO_RELOC; /* No longer relocated */
+ }
+ }
+
+ toP = frag_more(4);
+ /* put out the opcode */
+ md_number_to_chars(toP, the_insn.opcode, 4);
+
+ /* put out the symbol-dependent stuff */
+ if (the_insn.reloc != NO_RELOC) {
+ fix_new(frag_now, /* which frag */
+ (toP - frag_now->fr_literal), /* where */
+ 4, /* size */
+ the_insn.exp.X_add_symbol,
+ the_insn.exp.X_subtract_symbol,
+ the_insn.exp.X_add_number,
+ the_insn.pcrel,
+ the_insn.reloc,
+ the_insn.exp.X_got_symbol);
+ }
+ switch (special_case) {
+
+ case SPECIAL_CASE_SET:
+ special_case = 0;
+ know(the_insn.reloc == RELOC_HI22 ||
+ the_insn.reloc == RELOC_BASE22);
+ /* See if "set" operand has no low-order bits; skip OR if so. */
+ if (the_insn.exp.X_seg == SEG_ABSOLUTE
+ && ((the_insn.exp.X_add_number & 0x3FF) == 0))
+ return;
+ toP = frag_more(4);
+ rsd = (the_insn.opcode >> 25) & 0x1f;
+ the_insn.opcode = 0x80102000 | (rsd << 25) | (rsd << 14);
+ md_number_to_chars(toP, the_insn.opcode, 4);
+ fix_new(frag_now, /* which frag */
+ (toP - frag_now->fr_literal), /* where */
+ 4, /* size */
+ the_insn.exp.X_add_symbol,
+ the_insn.exp.X_subtract_symbol,
+ the_insn.exp.X_add_number,
+ the_insn.pcrel,
+ the_insn.reloc==RELOC_BASE22?RELOC_BASE10:RELOC_LO10,
+ the_insn.exp.X_got_symbol);
+ return;
+
+ case SPECIAL_CASE_FDIV:
+ /* According to information leaked from Sun, the "fdiv" instructions
+ on early SPARC machines would produce incorrect results sometimes.
+ The workaround is to add an fmovs of the destination register to
+ itself just after the instruction. This was true on machines
+ with Weitek 1165 float chips, such as the Sun-4/260 and /280. */
+ special_case = 0;
+ assert(the_insn.reloc == NO_RELOC);
+ toP = frag_more(4);
+ rsd = (the_insn.opcode >> 25) & 0x1f;
+ the_insn.opcode = 0x81A00020 | (rsd << 25) | rsd; /* fmovs dest,dest */
+ md_number_to_chars(toP, the_insn.opcode, 4);
+ return;
+
+ case 0:
+ return;
+
+ default:
+ as_fatal("md_assemble: failed sanity check.");
+ }
+} /* md_assemble() */
+
+static void sparc_ip(str)
+char *str;
+{
+ char *error_message = "";
+ char *s;
+ const char *args;
+ char c;
+ struct sparc_opcode *insn;
+ char *argsStart;
+ unsigned long opcode;
+ unsigned int mask = 0;
+ int match = 0;
+ int comma = 0;
+
+ for (s = str; islower(*s) || (*s >= '0' && *s <= '3'); ++s)
+ ;
+ switch (*s) {
+
+ case '\0':
+ break;
+
+ case ',':
+ comma = 1;
+
+ /*FALLTHROUGH */
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ default:
+ as_bad("Unknown opcode: `%s'", str);
+ exit(1);
+ }
+ if ((insn = (struct sparc_opcode *) hash_find(op_hash, str)) == NULL) {
+ as_bad("Unknown opcode: `%s'", str);
+ return;
+ }
+ if (comma) {
+ *--s = ',';
+ }
+ argsStart = s;
+ for (;;) {
+ opcode = insn->match;
+ memset(&the_insn, '\0', sizeof(the_insn));
+ the_insn.reloc = NO_RELOC;
+
+ /*
+ * Build the opcode, checking as we go to make
+ * sure that the operands match
+ */
+ for (args = insn->args; ; ++args) {
+ switch (*args) {
+
+ case 'M':
+ case 'm':
+ if (strncmp(s, "%asr", 4) == 0) {
+ s += 4;
+
+ if (isdigit(*s)) {
+ long num = 0;
+
+ while (isdigit(*s)) {
+ num = num*10 + *s-'0';
+ ++s;
+ }
+
+ if (num < 16 || 31 < num) {
+ error_message = ": asr number must be between 15 and 31";
+ goto error;
+ } /* out of range */
+
+ opcode |= (*args == 'M' ? RS1(num) : RD(num));
+ continue;
+ } else {
+ error_message = ": expecting %asrN";
+ goto error;
+ } /* if %asr followed by a number. */
+
+ } /* if %asr */
+ break;
+
+
+ case '\0': /* end of args */
+ if (*s == '\0') {
+ match = 1;
+ }
+ break;
+
+ case '+':
+ if (*s == '+') {
+ ++s;
+ continue;
+ }
+ if (*s == '-') {
+ continue;
+ }
+ break;
+
+ case '[': /* these must match exactly */
+ case ']':
+ case ',':
+ case ' ':
+ if (*s++ == *args)
+ continue;
+ break;
+
+ case '#': /* must be at least one digit */
+ if (isdigit(*s++)) {
+ while (isdigit(*s)) {
+ ++s;
+ }
+ continue;
+ }
+ break;
+
+ case 'C': /* coprocessor state register */
+ if (strncmp(s, "%csr", 4) == 0) {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case 'b': /* next operand is a coprocessor register */
+ case 'c':
+ case 'D':
+ if (*s++ == '%' && *s++ == 'c' && isdigit(*s)) {
+ mask = *s++;
+ if (isdigit(*s)) {
+ mask = 10 * (mask - '0') + (*s++ - '0');
+ if (mask >= 32) {
+ break;
+ }
+ } else {
+ mask -= '0';
+ }
+ switch (*args) {
+
+ case 'b':
+ opcode |= mask << 14;
+ continue;
+
+ case 'c':
+ opcode |= mask;
+ continue;
+
+ case 'D':
+ opcode |= mask << 25;
+ continue;
+ }
+ }
+ break;
+
+ case 'r': /* next operand must be a register */
+ case 's':
+ case '1':
+ case '2':
+ case 'd':
+ case 'x':
+ if (*s++ == '%') {
+ switch (c = *s++) {
+
+ case 'f': /* frame pointer */
+ if (*s++ == 'p') {
+ mask = 0x1e;
+ break;
+ }
+ goto error;
+
+ case 'g': /* global register */
+ if (isoctal(c = *s++)) {
+ mask = c - '0';
+ break;
+ }
+ goto error;
+
+ case 'i': /* in register */
+ if (isoctal(c = *s++)) {
+ mask = c - '0' + 24;
+ break;
+ }
+ goto error;
+
+ case 'l': /* local register */
+ if (isoctal(c = *s++)) {
+ mask= (c - '0' + 16) ;
+ break;
+ }
+ goto error;
+
+ case 'o': /* out register */
+ if (isoctal(c = *s++)) {
+ mask= (c - '0' + 8) ;
+ break;
+ }
+ goto error;
+
+ case 's': /* stack pointer */
+ if (*s++ == 'p') {
+ mask= 0xe;
+ break;
+ }
+ goto error;
+
+ case 'r': /* any register */
+ if (!isdigit(c = *s++)) {
+ goto error;
+ }
+ /* FALLTHROUGH */
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (isdigit(*s)) {
+ if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
+ goto error;
+ }
+ } else {
+ c -= '0';
+ }
+ mask= c;
+ break;
+
+ case 'x':
+ opcode |= (mask << 25) | mask;
+ continue;
+
+ default:
+ goto error;
+ }
+ /*
+ * Got the register, now figure out where
+ * it goes in the opcode.
+ */
+ switch (*args) {
+
+ case '1':
+ opcode |= mask << 14;
+ continue;
+
+ case '2':
+ opcode |= mask;
+ continue;
+
+ case 'd':
+ opcode |= mask << 25;
+ continue;
+
+ case 'r':
+ opcode |= (mask << 25) | (mask << 14);
+ continue;
+ case 'x':
+ opcode |= (mask << 25) | mask;
+ continue;
+ }
+ }
+ break;
+
+ case 'e': /* next operand is a floating point register */
+ case 'v':
+ case 'V':
+
+ case 'f':
+ case 'B':
+ case 'R':
+
+ case 'g':
+ case 'H':
+ case 'J': {
+ char format;
+
+ if (*s++ == '%'
+
+ && ((format = *s) == 'f')
+
+ && isdigit(*++s)) {
+
+
+
+ for (mask = 0; isdigit(*s); ++s) {
+ mask = 10 * mask + (*s - '0');
+ } /* read the number */
+
+ if ((*args == 'u'
+ || *args == 'v'
+ || *args == 'B'
+ || *args == 'H')
+ && (mask & 1)) {
+ break;
+ } /* register must be even numbered */
+
+ if ((*args == 'U'
+ || *args == 'V'
+ || *args == 'R'
+ || *args == 'J')
+ && (mask & 3)) {
+ break;
+ } /* register must be multiple of 4 */
+
+ if (format == 'f') {
+ if (mask >= 32) {
+ error_message = ": There are only 32 f registers; [0-31]";
+ goto error;
+ } /* on error */
+ } /* if not an 'f' register. */
+ } /* on error */
+
+ switch (*args) {
+
+ case 'v':
+ case 'V':
+ case 'e':
+ opcode |= RS1(mask);
+ continue;
+
+
+ case 'f':
+ case 'B':
+ case 'R':
+ opcode |= RS2(mask);
+ continue;
+
+ case 'g':
+ case 'H':
+ case 'J':
+ opcode |= RD(mask);
+ continue;
+ } /* pack it in. */
+
+ know(0);
+ break;
+ } /* float arg */
+
+ case 'F':
+ if (strncmp(s, "%fsr", 4) == 0) {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case 'h': /* high 22 bits */
+ /*
+ * In the case of a `set' pseudo instruction
+ * we have an implied `%hi' operator.
+ */
+ if (special_case == SPECIAL_CASE_SET)
+ the_insn.reloc = RELOC_HI22;
+ else
+ the_insn.reloc = RELOC_22;
+ goto immediate;
+
+ case 'l': /* 22 bit PC relative immediate */
+ the_insn.reloc = RELOC_WDISP22;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 'L': /* 30 bit immediate */
+ the_insn.reloc =
+#ifdef PIC
+ picmode?RELOC_JMP_TBL:
+#endif
+ RELOC_WDISP30;
+ the_insn.pcrel = 1;
+ goto immediate;
+
+ case 'n': /* 22 bit immediate */
+ the_insn.reloc = RELOC_22;
+ goto immediate;
+
+ case 'i': /* 13 bit immediate */
+ the_insn.reloc = RELOC_13;
+
+ /*FALLTHROUGH */
+
+ immediate:
+ if (*s == ' ')
+ s++;
+ if (*s == '%') {
+ if ((c = s[1]) == 'h' && s[2] == 'i') {
+ if (the_insn.reloc != RELOC_22)
+ as_bad(
+ "`%hi' in improper context");
+ the_insn.reloc = RELOC_HI22;
+ s+=3;
+ } else if (c == 'l' && s[2] == 'o') {
+ the_insn.reloc = RELOC_LO10;
+ s+=3;
+ } else
+ break;
+ }
+ /* Note that if the getExpression() fails, we
+ will still have created U entries in the
+ symbol table for the 'symbols' in the input
+ string. Try not to create U symbols for
+ registers, etc. */
+ {
+ /* This stuff checks to see if the
+ expression ends in +%reg If it does,
+ it removes the register from the
+ expression, and re-sets 's' to point
+ to the right place */
+
+ char *s1;
+
+ for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++) ;;
+
+ if (s1 != s && isdigit(s1[-1])) {
+ if (s1[-2] == '%' && s1[-3] == '+') {
+ s1 -= 3;
+ *s1 = '\0';
+ (void) getExpression(s);
+ *s1 = '+';
+ s = s1;
+ continue;
+ } else if (strchr("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+') {
+ s1 -= 4;
+ *s1 = '\0';
+ (void) getExpression(s);
+ *s1 = '+';
+ s = s1;
+ continue;
+ }
+ }
+ }
+ (void)getExpression(s);
+#ifdef PIC
+ /*
+ * Handle refs to __GLOBAL_OFFSET_TABLE_
+ */
+ if (the_insn.exp.X_got_symbol) {
+ switch(the_insn.reloc) {
+ case RELOC_22:
+ case RELOC_HI22:
+ the_insn.reloc = RELOC_PC22;
+ the_insn.pcrel = 1;
+ break;
+ case RELOC_LO10:
+ the_insn.reloc = RELOC_PC10;
+ the_insn.pcrel = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (picmode && the_insn.exp.X_add_symbol) {
+ switch (the_insn.reloc) {
+ case RELOC_LO10:
+ the_insn.reloc = RELOC_BASE10;
+ the_insn.exp.X_add_symbol->sy_forceout = 1;
+ break;
+ case RELOC_HI22:
+ the_insn.reloc = RELOC_BASE22;
+ the_insn.exp.X_add_symbol->sy_forceout = 1;
+ break;
+ case RELOC_13:
+ the_insn.reloc = RELOC_BASE13;
+ the_insn.exp.X_add_symbol->sy_forceout = 1;
+ break;
+ }
+ }
+#endif
+ s = expr_end;
+ continue;
+
+ case 'a':
+ if (*s++ == 'a') {
+ opcode |= ANNUL;
+ continue;
+ }
+ break;
+
+ case 'A': {
+ char *push = input_line_pointer;
+ expressionS e;
+
+ input_line_pointer = s;
+
+ if (expression(&e) == SEG_ABSOLUTE) {
+ opcode |= e.X_add_number << 5;
+ s = input_line_pointer;
+ input_line_pointer = push;
+ continue;
+ } /* if absolute */
+
+ break;
+ } /* alternate space */
+
+ case 'p':
+ if (strncmp(s, "%psr", 4) == 0) {
+ s += 4;
+ continue;
+ }
+ break;
+
+ case 'q': /* floating point queue */
+ if (strncmp(s, "%fq", 3) == 0) {
+ s += 3;
+ continue;
+ }
+ break;
+
+ case 'Q': /* coprocessor queue */
+ if (strncmp(s, "%cq", 3) == 0) {
+ s += 3;
+ continue;
+ }
+ break;
+
+ case 'S':
+ if (strcmp(str, "set") == 0) {
+ special_case = SPECIAL_CASE_SET;
+ continue;
+ } else if (strncmp(str, "fdiv", 4) == 0) {
+ special_case = SPECIAL_CASE_FDIV;
+ continue;
+ }
+ break;
+
+ case 't':
+ if (strncmp(s, "%tbr", 4) != 0)
+ break;
+ s += 4;
+ continue;
+
+ case 'w':
+ if (strncmp(s, "%wim", 4) != 0)
+ break;
+ s += 4;
+ continue;
+
+ case 'y':
+ if (strncmp(s, "%y", 2) != 0)
+ break;
+ s += 2;
+ continue;
+
+ default:
+ as_fatal("sparc_ip: failed sanity check.");
+ } /* switch on arg code */
+ break;
+ } /* for each arg that we expect */
+ error:
+ if (match == 0) {
+ /* Args don't match. */
+ if (((unsigned) (&insn[1] - sparc_opcodes)) < NUMOPCODES
+ && !strcmp(insn->name, insn[1].name)) {
+ ++insn;
+ s = argsStart;
+ continue;
+ } else {
+ as_bad("Illegal operands%s", error_message);
+ return;
+ }
+ } else {
+ if (insn->architecture > current_architecture) {
+ if (!architecture_requested || warn_on_bump) {
+
+ if (warn_on_bump) {
+ as_warn("architecture bumped from \"%s\" to \"%s\" on \"%s\"",
+ architecture_pname[current_architecture],
+ architecture_pname[insn->architecture],
+ str);
+ } /* if warning */
+
+ current_architecture = insn->architecture;
+ } else {
+ as_bad("architecture mismatch on \"%s\" (\"%s\"). current architecture is \"%s\"",
+ str,
+ architecture_pname[insn->architecture],
+ architecture_pname[current_architecture]);
+ return;
+ } /* if bump ok else error */
+ } /* if architecture higher */
+ } /* if no match */
+
+ break;
+ } /* forever looking for a match */
+
+ the_insn.opcode = opcode;
+#if DEBUG_SPARC
+ if (flagseen['D'])
+ print_insn(&the_insn);
+#endif
+ return;
+} /* sparc_ip() */
+
+static int getExpression(str)
+char *str;
+{
+ char *save_in;
+ segT seg;
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ switch (seg = expression(&the_insn.exp)) {
+
+ case SEG_ABSOLUTE:
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_UNKNOWN:
+ case SEG_DIFFERENCE:
+ case SEG_BIG:
+ case SEG_ABSENT:
+ break;
+
+ default:
+ the_insn.error = "bad segment";
+ expr_end = input_line_pointer;
+ input_line_pointer=save_in;
+ return 1;
+ }
+
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+} /* getExpression() */
+
+
+/*
+ This is identical to the md_atof in m68k.c. I think this is right,
+ but I'm not sure.
+
+ Turn a string in input_line_pointer into a floating point constant of type
+ type, and store the appropriate bytes in *litP. The number of LITTLENUMS
+ emitted is stored in *sizeP. An error message is returned, or NULL on OK.
+ */
+
+/* Equal to MAX_PRECISION in atof-ieee.c */
+#define MAX_LITTLENUMS 6
+
+char *md_atof(type,litP,sizeP)
+char type;
+char *litP;
+int *sizeP;
+{
+ int prec;
+ LITTLENUM_TYPE words[MAX_LITTLENUMS];
+ LITTLENUM_TYPE *wordP;
+ char *t;
+ char *atof_ieee();
+
+ switch (type) {
+
+ case 'f':
+ case 'F':
+ case 's':
+ case 'S':
+ prec = 2;
+ break;
+
+ case 'd':
+ case 'D':
+ case 'r':
+ case 'R':
+ prec = 4;
+ break;
+
+ case 'x':
+ case 'X':
+ prec = 6;
+ break;
+
+ case 'p':
+ case 'P':
+ prec = 6;
+ break;
+
+ default:
+ *sizeP=0;
+ return "Bad call to MD_ATOF()";
+ }
+ t=atof_ieee(input_line_pointer,type,words);
+ if (t)
+ input_line_pointer=t;
+ *sizeP=prec * sizeof(LITTLENUM_TYPE);
+ for (wordP=words;prec--;) {
+ md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
+ litP+=sizeof(LITTLENUM_TYPE);
+ }
+ return ""; /* Someone should teach Dean about null pointers */
+} /* md_atof() */
+
+/*
+ * Write out big-endian.
+ */
+void md_number_to_chars(buf,val,n)
+char *buf;
+long val;
+int n;
+{
+
+ switch (n) {
+
+ case 4:
+ *buf++ = val >> 24;
+ *buf++ = val >> 16;
+ case 2:
+ *buf++ = val >> 8;
+ case 1:
+ *buf = val;
+ break;
+
+ default:
+ as_fatal("md_number_to_chars: failed sanity check.");
+ }
+ return;
+} /* md_number_to_chars() */
+
+static int reloc_check(val, bits, fixP)
+long val;
+int bits;
+fixS *fixP /* For reporting errors */;
+{
+ if (((val & (-1 << bits)) != 0)
+ && ((val & (-1 << bits)) != (-1 << (bits - 0)))) {
+
+ long addr = fixP->fx_where + fixP->fx_frag->fr_address;
+ int ln;
+ char *fname;
+
+ if (fixP->fx_frag->line) {
+ fname = fixP->fx_frag->line->file->filename;
+ ln = fixP->fx_frag->line->line;
+ } else {
+ fname = "";
+ ln = -1;
+ }
+
+ as_warn_where(fname, ln,
+ "Relocation (%s) overflow at %#x, value truncated.",
+ Reloc[fixP->fx_r_type], addr);
+ } /* on overflow */
+
+} /* reloc_check() */
+
+
+/* Apply a fixS to the frags, now that we know the value it ought to
+ hold. */
+
+void md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ long addr = fixP->fx_where + fixP->fx_frag->fr_address;
+
+#if DEBUG_SPARC
+ if (flagseen['D'])
+ fprintf(stderr, "md_apply_fix: \"%s\" \"%s\", val %d -- %s\n",
+ ((fixP->fx_addsy != NULL)
+ ? ((S_GET_NAME(fixP->fx_addsy) != NULL)
+ ? S_GET_NAME(fixP->fx_addsy)
+ : "???")
+ : "0"),
+ ((fixP->fx_subsy != NULL)
+ ? ((S_GET_NAME(fixP->fx_subsy) != NULL)
+ ? S_GET_NAME(fixP->fx_subsy)
+ : "???")
+ : "0"),
+ val, Reloc[fixP->fx_r_type]);
+#endif
+
+ assert(fixP->fx_size == 4);
+ assert(fixP->fx_r_type < NO_RELOC);
+
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc */
+
+ /*
+ * This is a hack. There should be a better way to
+ * handle this.
+ */
+ if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) {
+ val += fixP->fx_where + fixP->fx_frag->fr_address;
+ }
+
+ switch (fixP->fx_r_type) {
+
+ /* Michael Bloom <mb@ttidca.tti.com> says... [This] change was
+ made to match the behavior of Sun's assembler. Some broken
+ loaders depend on that. At least one such loader actually
+ adds the section data to what it finds in the addend. (It
+ should only be using the addend like Sun's loader seems to).
+ This caused incorrect relocation: (addend + adjustment)
+ became ( ( 2 * addend ) + adjustment ). [and there should
+ be no cases that reach here anyway. */
+ case RELOC_32:
+ if (fixP->fx_addsy == NULL) {
+ /*
+ * Ok, the remarks above do not hold if the
+ * expression has been reduced to a number.
+ */
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ } else {
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ }
+ break;
+
+ case RELOC_JMP_TBL:
+ if (!fixP->fx_addsy) {
+ val = (val >>= 2) + 1;
+ reloc_check(val, 30, fixP);
+
+ buf[0] |= (val >> 24) & 0x3f;
+ buf[1]= (val >> 16);
+ buf[2] = val >> 8;
+ buf[3] = val;
+ }
+ break;
+
+ case RELOC_WDISP30:
+ val = (val >>= 2) + 1;
+ reloc_check(val, 30, fixP);
+
+ buf[0] |= (val >> 24) & 0x3f;
+ buf[1]= (val >> 16);
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ case RELOC_WDISP22:
+ val = (val >>= 2) + 1;
+ reloc_check(val, 22, fixP);
+
+ buf[1] |= (val >> 16) & 0x3f;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ break;
+
+ /*
+ * We should only use the RELOC_HI22 type as a result of the %hi
+ * operator (which is implicit in the case of the `set' pseudo op),
+ * This is NOT the same as using the `sethi' instruction, which merely
+ * puts the 22 bit operand into the high 22 bits of the destination
+ * register.
+ */
+ case RELOC_22:
+ if (!fixP->fx_addsy) {
+ reloc_check(val, 22, fixP);
+
+ buf[1] |= (val >> 16) & 0x3f;
+ buf[2] = val >> 8;
+ buf[3] = val;
+ }
+ break;
+
+ case RELOC_HI22:
+ case RELOC_BASE22:
+ if (!fixP->fx_addsy) {
+ buf[1] |= (val >> 26) & 0x3f;
+ buf[2] = val >> 18;
+ buf[3] = val >> 10;
+ } else {
+ if (picmode && fixP->fx_r_type == RELOC_HI22)
+ as_warn("non-PIC access to %s",
+ S_GET_NAME(fixP->fx_addsy));
+ buf[2]=0;
+ buf[3]=0;
+ }
+ break;
+
+ case RELOC_13:
+ case RELOC_BASE13:
+ if (!fixP->fx_addsy) {
+ reloc_check(val, 13, fixP);
+ buf[2] |= (val >> 8) & 0x1f;
+ buf[3] = val;
+ } else {
+ buf[3]=0;
+ }
+ break;
+
+ case RELOC_LO10:
+ case RELOC_BASE10:
+ if (!fixP->fx_addsy) {
+ buf[2] |= (val >> 8) & 0x03;
+ buf[3] = val & 0xff;
+ } else {
+ if (picmode && fixP->fx_r_type == RELOC_LO10)
+ as_warn("non-PIC access to %s",
+ S_GET_NAME(fixP->fx_addsy));
+ buf[3]=0;
+ }
+ break;
+
+ case RELOC_PC10:
+ case RELOC_PC22:
+ if (fixP->fx_addsy != GOT_symbol) {
+ as_fatal("GOT");
+ }
+ break;
+
+#if 0
+ case RELOC_8: /* These don't seem to ever be needed. */
+ case RELOC_16:
+ case RELOC_DISP8:
+ case RELOC_DISP16:
+ case RELOC_DISP32:
+ case RELOC_SEGOFF16:
+ case RELOC_SFA_BASE:
+ case RELOC_SFA_OFF13:
+
+ case RELOC_GLOB_DAT: /* These are output by linker only */
+ case RELOC_JMP_SLOT:
+ case RELOC_RELATIVE:
+#endif
+
+ case NO_RELOC:
+ default:
+ as_bad("bad relocation type: 0x%02x", fixP->fx_r_type);
+ break;
+ }
+} /* md_apply_fix() */
+
+/* should never be called for sparc */
+void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr;
+long to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("sparc_create_short_jmp\n");
+} /* md_create_short_jump() */
+
+/* Translate internal representation of relocation info to target format.
+
+ On sparc: first 4 bytes are normal unsigned long address, next three
+ bytes are index, most sig. byte first. Byte 7 is broken up with
+ bit 7 as external, bits 6 & 5 unused, and the lower
+ five bits as relocation type. Next 4 bytes are long addend. */
+/* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ long r_index;
+ long r_extern;
+ long r_addend = 0;
+ long r_address;
+#ifdef PIC
+ int kflag = 0;
+#endif
+
+ know(fixP->fx_addsy);
+
+ if (!S_IS_DEFINED(fixP->fx_addsy)) {
+ r_extern = 1;
+ r_index = fixP->fx_addsy->sy_number;
+ } else {
+ r_extern = 0;
+ r_index = S_GET_TYPE(fixP->fx_addsy);
+#ifdef PIC
+ if (picmode) {
+ switch (fixP->fx_r_type) {
+ case RELOC_BASE10:
+ case RELOC_BASE13:
+ case RELOC_BASE22:
+ r_index = fixP->fx_addsy->sy_number;
+ if (S_IS_EXTERNAL(fixP->fx_addsy))
+ r_extern = 1;
+ kflag = 1;
+ break;
+
+ case RELOC_32:
+ if (!S_IS_EXTERNAL(fixP->fx_addsy))
+ break;
+ r_extern = 1;
+ r_index = fixP->fx_addsy->sy_number;
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+ }
+
+ /* this is easy */
+ md_number_to_chars(where,
+ r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ /* now the fun stuff */
+ where[4] = (r_index >> 16) & 0x0ff;
+ where[5] = (r_index >> 8) & 0x0ff;
+ where[6] = r_index & 0x0ff;
+ where[7] = ((r_extern << 7) & 0x80) | (0 & 0x60) | (fixP->fx_r_type & 0x1F);
+
+ /* Also easy */
+ if (fixP->fx_addsy->sy_frag) {
+ r_addend = fixP->fx_addsy->sy_frag->fr_address;
+ }
+
+ if (fixP->fx_pcrel) {
+#ifdef PIC
+ if (fixP->fx_gotsy) {
+ r_addend = r_address;
+ r_addend += fixP->fx_addnumber;
+ } else
+#endif
+ r_addend -= r_address;
+ } else {
+#ifdef PIC
+ if (kflag)
+ r_addend = 0;
+ else
+#endif
+ r_addend = fixP->fx_addnumber;
+ }
+
+ md_number_to_chars(&where[8], r_addend, 4);
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+/* should never be called for sparc */
+void md_convert_frag(headers, fragP)
+object_headers *headers;
+register fragS *fragP;
+{
+ as_fatal("sparc_convert_frag\n");
+} /* md_convert_frag() */
+
+/* should never be called for sparc */
+void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ as_fatal("sparc_create_long_jump\n");
+} /* md_create_long_jump() */
+
+/* should never be called for sparc */
+int md_estimate_size_before_relax(fragP, segtype)
+fragS *fragP;
+segT segtype;
+{
+ as_fatal("sparc_estimate_size_before_relax\n");
+ return(1);
+} /* md_estimate_size_before_relax() */
+
+#if DEBUG_SPARC
+/* for debugging only */
+static void print_insn(insn)
+struct sparc_it *insn;
+{
+
+ if (insn->error) {
+ fprintf(stderr, "ERROR: %s\n", insn->error);
+ }
+ fprintf(stderr, "opcode=0x%08x\n", insn->opcode);
+ fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]);
+ fprintf(stderr, "exp = {\n");
+ fprintf(stderr, "\t\tX_add_symbol = %s\n",
+ ((insn->exp.X_add_symbol != NULL)
+ ? ((S_GET_NAME(insn->exp.X_add_symbol) != NULL)
+ ? S_GET_NAME(insn->exp.X_add_symbol)
+ : "???")
+ : "0"));
+ fprintf(stderr, "\t\tX_sub_symbol = %s\n",
+ ((insn->exp.X_subtract_symbol != NULL)
+ ? (S_GET_NAME(insn->exp.X_subtract_symbol)
+ ? S_GET_NAME(insn->exp.X_subtract_symbol)
+ : "???")
+ : "0"));
+ fprintf(stderr, "\t\tX_got_symbol = %s\n",
+ ((insn->exp.X_got_symbol != NULL)
+ ? (S_GET_NAME(insn->exp.X_got_symbol)
+ ? S_GET_NAME(insn->exp.X_got_symbol)
+ : "???")
+ : "0"));
+ fprintf(stderr, "\t\tX_add_number = %d\n",
+ insn->exp.X_add_number);
+ fprintf(stderr, "}\n");
+ return;
+} /* print_insn() */
+#endif
+
+/* Set the hook... */
+
+/* void emit_sparc_reloc();
+ void (*md_emit_relocations)() = emit_sparc_reloc; */
+
+#ifdef comment
+
+/*
+ * Sparc/AM29K relocations are completely different, so it needs
+ * this machine dependent routine to emit them.
+ */
+#if defined(OBJ_AOUT) || defined(OBJ_BOUT)
+void emit_sparc_reloc(fixP, segment_address_in_file)
+register fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ struct reloc_info_generic ri;
+ register symbolS *symbolP;
+ extern char *next_object_file_charP;
+ /* long add_number; */
+
+ memset((char *) &ri, '\0', sizeof(ri));
+ for (; fixP; fixP = fixP->fx_next) {
+
+ if (fixP->fx_r_type >= NO_RELOC) {
+ as_fatal("fixP->fx_r_type = %d\n", fixP->fx_r_type);
+ }
+
+ if ((symbolP = fixP->fx_addsy) != NULL) {
+ ri.r_address = fixP->fx_frag->fr_address +
+ fixP->fx_where - segment_address_in_file;
+ if ((S_GET_TYPE(symbolP)) == N_UNDF) {
+ ri.r_extern = 1;
+ ri.r_index = symbolP->sy_number;
+ } else {
+ ri.r_extern = 0;
+ ri.r_index = S_GET_TYPE(symbolP);
+ }
+ if (symbolP && symbolP->sy_frag) {
+ ri.r_addend = symbolP->sy_frag->fr_address;
+ }
+ ri.r_type = fixP->fx_r_type;
+ if (fixP->fx_pcrel) {
+ /* ri.r_addend -= fixP->fx_where; */
+ ri.r_addend -= ri.r_address;
+ } else {
+ ri.r_addend = fixP->fx_addnumber;
+ }
+
+ md_ri_to_chars(next_object_file_charP, &ri);
+ next_object_file_charP += md_reloc_size;
+ }
+ }
+ return;
+} /* emit_sparc_reloc() */
+#endif /* aout or bout */
+#endif /* comment */
+
+/*
+ * md_parse_option
+ * Invocation line includes a switch not recognized by the base assembler.
+ * See if it's a processor-specific option. These are:
+ *
+ * -bump
+ * Warn on architecture bumps. See also -A.
+ *
+ * -Av6, -Av7, -Av8
+ * Select the architecture. Instructions or features not
+ * supported by the selected architecture cause fatal errors.
+ *
+ * The default is to start at v6, and bump the architecture up
+ * whenever an instruction is seen at a higher level.
+ *
+ * If -bump is specified, a warning is printing when bumping to
+ * higher levels.
+ *
+ * If an architecture is specified, all instructions must match
+ * that architecture. Any higher level instructions are flagged
+ * as errors.
+ *
+ * if both an architecture and -bump are specified, the
+ * architecture starts at the specified level, but bumps are
+ * warnings.
+ *
+ */
+int md_parse_option(argP, cntP, vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ char *p;
+ const char **arch;
+
+ if (!strcmp(*argP,"bump")){
+ warn_on_bump = 1;
+
+ } else if (**argP == 'A'){
+ p = (*argP) + 1;
+
+ for (arch = architecture_pname; *arch != NULL; ++arch){
+ if (strcmp(p, *arch) == 0){
+ break;
+ } /* found a match */
+ } /* walk the pname table */
+
+ if (*arch == NULL){
+ as_bad("unknown architecture: %s", p);
+ } else {
+ current_architecture = (enum sparc_architecture) (arch - architecture_pname);
+ architecture_requested = 1;
+ }
+#ifdef PIC
+ } else if (**argP == 'k' || **argP == 'K') {
+ /* Predefine GOT symbol */
+ GOT_symbol = symbol_find_or_make("__GLOBAL_OFFSET_TABLE_");
+#endif
+ } else {
+ /* Unknown option */
+ (*argP)++;
+ return 0;
+ }
+ **argP = '\0'; /* Done parsing this switch */
+ return 1;
+} /* md_parse_option() */
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *md_undefined_symbol(name)
+char *name;
+{
+ return 0;
+} /* md_undefined_symbol() */
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void md_operand(expressionP)
+expressionS *expressionP;
+{
+} /* md_operand() */
+
+/* Round up a section size to the appropriate boundary. */
+long md_section_align(segment, size)
+segT segment;
+long size;
+{
+ return((size + 7) & ~7); /* Round all sects to multiple of 8 */
+} /* md_section_align() */
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the sparc, they're relative to the address of the offset, plus
+ its size. This gets us to the following instruction.
+ (??? Is this right? FIXME-SOON) */
+long md_pcrel_from(fixP)
+fixS *fixP;
+{
+#ifdef PIC
+ /*
+ * _GLOBAL_OFFSET_TABLE_ refs are relative to the offset of the
+ * current instruction. We omit fx_size from the computation (which
+ * is always 4 anyway).
+ */
+ if (fixP->fx_gotsy)
+ return fixP->fx_where + fixP->fx_frag->fr_address;
+ else
+#endif
+ return(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address);
+} /* md_pcrel_from() */
+
+void tc_aout_pre_write_hook(headers)
+object_headers *headers;
+{
+ H_SET_VERSION(headers, 1);
+ return;
+} /* tc_aout_pre_write_hook() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-sparc.c */
diff --git a/gnu/usr.bin/as/config/tc-sparc.h b/gnu/usr.bin/as/config/tc-sparc.h
new file mode 100644
index 0000000..5dcb72b
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-sparc.h
@@ -0,0 +1,52 @@
+/* tc-sparc.h - Macros and type defines for the sparc.
+ Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2,
+ or (at your option) any later version.
+
+ GAS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+#define TC_SPARC 1
+
+#define LOCAL_LABELS_FB
+#define WORKING_DOT_WORD
+
+#ifdef __NetBSD__
+#define AOUT_MACHTYPE 138
+#endif
+
+#ifdef sun
+#define AOUT_MACHTYPE 3
+#define AOUT_VERSION 1
+#endif
+
+#define tc_headers_hook(a) {;} /* don't need it. */
+#define tc_crawl_symbol_chain(a) {;} /* don't need it. */
+
+void tc_aout_pre_write_hook();
+
+#define LISTING_HEADER "SPARC GAS "
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-sparc.h */
diff --git a/gnu/usr.bin/as/config/tc-tahoe.c b/gnu/usr.bin/as/config/tc-tahoe.c
new file mode 100644
index 0000000..4cd1a82
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-tahoe.c
@@ -0,0 +1,1924 @@
+/* tc-tahoe.c
+ Not part of GAS yet. */
+
+#include "as.h"
+#include "obstack.h"
+
+ /* this bit glommed from tahoe-inst.h */
+
+typedef unsigned char byte;
+typedef byte tahoe_opcodeT;
+
+/*
+ * This is part of tahoe-ins-parse.c & friends.
+ * We want to parse a tahoe instruction text into a tree defined here.
+ */
+
+#define TIT_MAX_OPERANDS (4) /* maximum number of operands in one
+ single tahoe instruction */
+
+struct top /* tahoe instruction operand */
+{
+ int top_ndx; /* -1, or index register. eg 7=[R7] */
+ int top_reg; /* -1, or register number. eg 7 = R7 or (R7) */
+ byte top_mode; /* Addressing mode byte. This byte, defines
+ which of the 11 modes opcode is. */
+
+ char top_access; /* Access type wanted for this opperand
+ 'b'branch ' 'no-instruction 'amrvw' */
+ char top_width; /* Operand width expected, one of "bwlq?-:!" */
+
+ char *top_error; /* Say if operand is inappropriate */
+
+ expressionS exp_of_operand; /* The expression as parsed by expression()*/
+
+ byte top_dispsize; /* Number of bytes in the displacement if we
+ can figure it out */
+};
+
+/* The addressing modes for an operand. These numbers are the acutal values
+ for certain modes, so be carefull if you screw with them. */
+#define TAHOE_DIRECT_REG (0x50)
+#define TAHOE_REG_DEFERRED (0x60)
+
+#define TAHOE_REG_DISP (0xE0)
+#define TAHOE_REG_DISP_DEFERRED (0xF0)
+
+#define TAHOE_IMMEDIATE (0x8F)
+#define TAHOE_IMMEDIATE_BYTE (0x88)
+#define TAHOE_IMMEDIATE_WORD (0x89)
+#define TAHOE_IMMEDIATE_LONGWORD (0x8F)
+#define TAHOE_ABSOLUTE_ADDR (0x9F)
+
+#define TAHOE_DISPLACED_RELATIVE (0xEF)
+#define TAHOE_DISP_REL_DEFERRED (0xFF)
+
+#define TAHOE_AUTO_DEC (0x7E)
+#define TAHOE_AUTO_INC (0x8E)
+#define TAHOE_AUTO_INC_DEFERRED (0x9E)
+/* INDEXED_REG is decided by the existance or lack of a [reg] */
+
+/* These are encoded into top_width when top_access=='b'
+ and it's a psuedo op.*/
+#define TAHOE_WIDTH_ALWAYS_JUMP '-'
+#define TAHOE_WIDTH_CONDITIONAL_JUMP '?'
+#define TAHOE_WIDTH_BIG_REV_JUMP '!'
+#define TAHOE_WIDTH_BIG_NON_REV_JUMP ':'
+
+/* The hex code for certain tahoe commands and modes.
+ This is just for readability. */
+#define TAHOE_JMP (0x71)
+#define TAHOE_PC_REL_LONG (0xEF)
+#define TAHOE_BRB (0x11)
+#define TAHOE_BRW (0x13)
+/* These, when 'ored' with, or added to, a register number,
+ set up the number for the displacement mode. */
+#define TAHOE_PC_OR_BYTE (0xA0)
+#define TAHOE_PC_OR_WORD (0xC0)
+#define TAHOE_PC_OR_LONG (0xE0)
+
+struct tit /* get it out of the sewer, it stands for
+ tahoe instruction tree (Geeze!) */
+{
+ tahoe_opcodeT tit_opcode; /* The opcode. */
+ byte tit_operands; /* How many operands are here. */
+ struct top tit_operand[TIT_MAX_OPERANDS]; /* Operands */
+ char *tit_error; /* "" or fatal error text */
+};
+
+/* end: tahoe-inst.h */
+
+/* tahoe.c - tahoe-specific -
+ Not part of gas yet.
+ */
+
+#include "opcode/tahoe.h"
+
+/* This is the number to put at the beginning of the a.out file */
+long omagic = OMAGIC;
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment or a quoted string. */
+const char comment_chars[] = "#;";
+
+/* These chars only start a comment at the beginning of a line. */
+const char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant
+ as in 0f123.456
+ or 0d1.234E-12 (see exp chars above)
+ Note: The Tahoe port doesn't support floating point constants. This is
+ consistant with 'as' If it's needed, I can always add it later. */
+const char FLT_CHARS[] = "df";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c . Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ (The tahoe has plenty of room, so the change currently isn't needed.)
+ */
+
+static struct tit t; /* A tahoe instruction after decoding. */
+
+void float_cons ();
+/* A table of pseudo ops (sans .), the function called, and an integer op
+ that the function is called with. */
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"dfloat", float_cons, 'd'},
+ {"ffloat", float_cons, 'f'},
+ {0}
+};
+
+/*
+ * For Tahoe, relative addresses of "just the right length" are pretty easy.
+ * The branch displacement is always the last operand, even in
+ * synthetic instructions.
+ * For Tahoe, we encode the relax_substateTs (in e.g. fr_substate) as:
+ *
+ * 4 3 2 1 0 bit number
+ * ---/ /--+-------+-------+-------+-------+-------+
+ * | what state ? | how long ? |
+ * ---/ /--+-------+-------+-------+-------+-------+
+ *
+ * The "how long" bits are 00=byte, 01=word, 10=long.
+ * This is a Un*x convention.
+ * Not all lengths are legit for a given value of (what state).
+ * The four states are listed below.
+ * The "how long" refers merely to the displacement length.
+ * The address usually has some constant bytes in it as well.
+ *
+
+States for Tahoe address relaxing.
+1. TAHOE_WIDTH_ALWAYS_JUMP (-)
+ Format: "b-"
+ Tahoe opcodes are: (Hex)
+ jr 11
+ jbr 11
+ Simple branch.
+ Always, 1 byte opcode, then displacement/absolute.
+ If word or longword, change opcode to brw or jmp.
+
+
+2. TAHOE_WIDTH_CONDITIONAL_JUMP (?)
+ J<cond> where <cond> is a simple flag test.
+ Format: "b?"
+ Tahoe opcodes are: (Hex)
+ jneq/jnequ 21
+ jeql/jeqlu 31
+ jgtr 41
+ jleq 51
+ jgeq 81
+ jlss 91
+ jgtru a1
+ jlequ b1
+ jvc c1
+ jvs d1
+ jlssu/jcs e1
+ jgequ/jcc f1
+ Always, you complement 4th bit to reverse the condition.
+ Always, 1-byte opcode, then 1-byte displacement.
+
+3. TAHOE_WIDTH_BIG_REV_JUMP (!)
+ Jbc/Jbs where cond tests a memory bit.
+ Format: "rlvlb!"
+ Tahoe opcodes are: (Hex)
+ jbs 0e
+ jbc 1e
+ Always, you complement 4th bit to reverse the condition.
+ Always, 1-byte opcde, longword, longword-address, 1-word-displacement
+
+4. TAHOE_WIDTH_BIG_NON_REV_JUMP (:)
+ JaoblXX/Jbssi
+ Format: "rlmlb:"
+ Tahoe opcodes are: (Hex)
+ aojlss 2f
+ jaoblss 2f
+ aojleq 3f
+ jaobleq 3f
+ jbssi 5f
+ Always, we cannot reverse the sense of the branch; we have a word
+ displacement.
+
+We need to modify the opcode is for class 1, 2 and 3 instructions.
+After relax() we may complement the 4th bit of 2 or 3 to reverse sense of
+branch.
+
+We sometimes store context in the operand literal. This way we can figure out
+after relax() what the original addressing mode was. (Was is pc_rel, or
+pc_rel_disp? That sort of thing.) */
+
+/* These displacements are relative to the START address of the
+ displacement which is at the start of the displacement, not the end of
+ the instruction. The hardware pc_rel is at the end of the instructions.
+ That's why all the displacements have the length of the displacement added
+ to them. (WF + length(word))
+
+ The first letter is Byte, Word.
+ 2nd letter is Forward, Backward. */
+#define BF (1+ 127)
+#define BB (1+-128)
+#define WF (2+ 32767)
+#define WB (2+-32768)
+/* Dont need LF, LB because they always reach. [They are coded as 0.] */
+
+#define C(a,b) ENCODE_RELAX(a,b)
+ /* This macro has no side-effects. */
+#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+#define RELAX_STATE(what) ((what) >> 2)
+#define RELAX_LENGTH(length) ((length) && 3)
+
+#define STATE_ALWAYS_BRANCH (1)
+#define STATE_CONDITIONAL_BRANCH (2)
+#define STATE_BIG_REV_BRANCH (3)
+#define STATE_BIG_NON_REV_BRANCH (4)
+#define STATE_PC_RELATIVE (5)
+
+#define STATE_BYTE (0)
+#define STATE_WORD (1)
+#define STATE_LONG (2)
+#define STATE_UNDF (3) /* Symbol undefined in pass1 */
+
+/* This is the table used by gas to figure out relaxing modes. The fields are
+ forward_branch reach, backward_branch reach, number of bytes it would take,
+ where the next biggest branch is. */
+const relax_typeS
+md_relax_table[] =
+{
+ {
+ 1, 1, 0, 0
+ }, /* error sentinel 0,0 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 0,1 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 0,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 0,3 */
+ /* Unconditional branch cases "jrb"
+ The relax part is the actual displacement */
+ {
+ BF, BB, 1, C (1, 1)
+ }, /* brb B`foo 1,0 */
+ {
+ WF, WB, 2, C (1, 2)
+ }, /* brw W`foo 1,1 */
+ {
+ 0, 0, 5, 0
+ }, /* Jmp L`foo 1,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 1,3 */
+ /* Reversible Conditional Branch. If the branch won't reach, reverse
+ it, and jump over a brw or a jmp that will reach. The relax part is the
+ actual address. */
+ {
+ BF, BB, 1, C (2, 1)
+ }, /* b<cond> B`foo 2,0 */
+ {
+ WF + 2, WB + 2, 4, C (2, 2)
+ }, /* brev over, brw W`foo, over: 2,1 */
+ {
+ 0, 0, 7, 0
+ }, /* brev over, jmp L`foo, over: 2,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 2,3 */
+ /* Another type of reversable branch. But this only has a word
+ displacement. */
+ {
+ 1, 1, 0, 0
+ }, /* unused 3,0 */
+ {
+ WF, WB, 2, C(3, 2)
+ }, /* jbX W`foo 3,1 */
+ {
+ 0, 0, 8, 0
+ }, /* jrevX over, jmp L`foo, over: 3,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 3,3 */
+ /* These are the non reversable branches, all of which have a word
+ displacement. If I can't reach, branch over a byte branch, to a
+ jump that will reach. The jumped branch jumps over the reaching
+ branch, to continue with the flow of the program. It's like playing
+ leap frog. */
+ {
+ 1, 1, 0, 0
+ }, /* unused 4,0 */
+ {
+ WF, WB, 2, C (4, 2)
+ }, /* aobl_ W`foo 4,1 */
+ {
+ 0, 0, 10, 0
+ }, /*aobl_ W`hop,br over,hop: jmp L^foo,over 4,2*/
+ {
+ 1, 1, 0, 0
+ }, /* unused 4,3 */
+ /* Normal displacement mode, no jumping or anything like that.
+ The relax points to one byte before the address, thats why all
+ the numbers are up by one. */
+ {
+ BF + 1, BB + 1, 2, C (5, 1)
+ }, /* B^"foo" 5,0 */
+ {
+ WF + 1, WB + 1, 3, C (5, 2)
+ }, /* W^"foo" 5,1 */
+ {
+ 0, 0, 5, 0
+ }, /* L^"foo" 5,2 */
+ {
+ 1, 1, 0, 0
+ }, /* unused 5,3 */
+};
+
+#undef C
+#undef BF
+#undef BB
+#undef WF
+#undef WB
+/* End relax stuff */
+
+static struct hash_control *op_hash = NULL; /* handle of the OPCODE hash table
+ NULL means any use before md_begin() will
+ crash */
+
+/* Init function. Build the hash table. */
+void
+md_begin()
+{
+ struct tot *tP;
+ char *errorval = "";
+ int synthetic_too = 1; /* If 0, just use real opcodes. */
+
+ if ((op_hash = hash_new())){
+ for (tP= totstrs; *tP->name && !*errorval; tP++){
+ errorval = hash_insert (op_hash, tP->name, &tP->detail);
+ }
+ if (synthetic_too){
+ for (tP = synthetic_totstrs; *tP->name && !*errorval; tP++){
+ errorval = hash_insert (op_hash, tP->name, &tP->detail);
+ }
+ }
+ }else{
+ errorval = "Virtual memory exceeded";
+ }
+ if (*errorval)
+ as_fatal(errorval);
+}/* md_begin */
+
+void
+md_end()
+{
+}/* md_end */
+
+int
+md_parse_option (argP, cntP, vecP)
+ char **argP;
+ int *cntP;
+ char ***vecP;
+{
+ char *temp_name; /* name for -t or -d options */
+ char opt;
+
+ switch (**argP){
+ case 'a':
+ as_warn("The -a option doesn't exits. (Dispite what the man page says!");
+
+ case 'J':
+ as_warn("JUMPIFY (-J) not implemented, use psuedo ops instead.");
+ break;
+
+ case 'S':
+ as_warn ("SYMBOL TABLE not implemented");
+ break; /* SYMBOL TABLE not implemented */
+
+ case 'T':
+ as_warn ("TOKEN TRACE not implemented");
+ break; /* TOKEN TRACE not implemented */
+
+ case 'd':
+ case 't':
+ opt= **argP;
+ if (**argP){ /* Rest of argument is filename. */
+ temp_name = *argP;
+ while (**argP)
+ (*argP)++;
+ }else if (*cntP){
+ while (**argP)
+ (*argP)++;
+ --(*cntP);
+ temp_name = *++(*vecP);
+ **vecP = NULL; /* Remember this is not a file-name. */
+ }else{
+ as_warn ("I expected a filename after -%c.",opt);
+ temp_name = "{absent}";
+ }
+
+ if(opt=='d')
+ as_warn ("Displacement length %s ignored!", temp_name);
+ else
+ as_warn ("I don't need or use temp. file \"%s\".", temp_name);
+ break;
+
+ case 'V':
+ as_warn ("I don't use an interpass file! -V ignored");
+ break;
+
+ default:
+ return 0;
+
+ }
+ return 1;
+}
+
+/* The functions in this section take numbers in the machine format, and
+ munges them into Tahoe byte order.
+ They exist primarily for cross assembly purpose. */
+void /* Knows about order of bytes in address. */
+md_number_to_chars (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ long int value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ int n = nbytes;
+ long int v = value;
+
+ con += nbytes - 1; /* Tahoes is (Bleah!) big endian */
+ while (nbytes--){
+ *con-- = value; /* Lint wants & MASK_CHAR. */
+ value >>= BITS_PER_CHAR;
+ }
+ /* XXX line number probably botched for this warning message. */
+ if (value != 0 && value != -1)
+ as_warn ("Displacement (%ld) long for instruction field length (%d).",v,n);
+}
+
+#ifdef comment
+void /* Knows about order of bytes in address. */
+md_number_to_imm (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ long int value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ md_number_to_chars(con, value, nbytes);
+}
+#endif /* comment */
+
+void
+ md_apply_fix(fixP, val)
+fixS *fixP;
+long val;
+{
+ char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
+ md_number_to_chars(place, val, fixP->fx_size);
+ return;
+} /* md_apply_fix() */
+
+void /* Knows about order of bytes in address. */
+md_number_to_disp (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ long int value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ md_number_to_chars(con, value, nbytes);
+}
+
+void /* Knows about order of bytes in address. */
+md_number_to_field (con, value, nbytes)
+ char con[]; /* Return 'nbytes' of chars here. */
+ long int value; /* The value of the bits. */
+ int nbytes; /* Number of bytes in the output. */
+{
+ md_number_to_chars(con, value, nbytes);
+}
+
+/* Put the bits in an order that a tahoe will understand, despite the ordering
+ of the native machine.
+ On Tahoe: first 4 bytes are normal unsigned big endian long,
+ next three bytes are symbolnum, in kind of 3 byte big endian (least sig. byte last).
+ The last byte is broken up with bit 7 as pcrel,
+ bits 6 & 5 as length,
+ bit 4 as extern and the last nibble as 'undefined'. */
+
+#if comment
+void
+md_ri_to_chars (ri_p, ri)
+ struct relocation_info *ri_p, ri;
+{
+ byte the_bytes[sizeof(struct relocation_info)];
+ /* The reason I can't just encode these directly into ri_p is that
+ ri_p may point to ri. */
+
+ /* This is easy */
+ md_number_to_chars (the_bytes, ri.r_address, sizeof(ri.r_address));
+
+ /* now the fun stuff */
+ the_bytes[4] = (ri.r_symbolnum >> 16) & 0x0ff;
+ the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff;
+ the_bytes[6] = ri.r_symbolnum & 0x0ff;
+ the_bytes[7] = (((ri.r_extern << 4) & 0x10) | ((ri.r_length << 5) & 0x60) |
+ ((ri.r_pcrel << 7) & 0x80)) & 0xf0;
+
+ bcopy (the_bytes, (char *) ri_p, sizeof (struct relocation_info));
+}
+#endif /* comment */
+
+/* Put the bits in an order that a tahoe will understand, despite the ordering
+ of the native machine.
+ On Tahoe: first 4 bytes are normal unsigned big endian long,
+ next three bytes are symbolnum, in kind of 3 byte big endian (least sig. byte last).
+ The last byte is broken up with bit 7 as pcrel,
+ bits 6 & 5 as length,
+ bit 4 as extern and the last nibble as 'undefined'. */
+
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };
+ long r_symbolnum;
+
+ know(fixP->fx_addsy != NULL);
+
+ md_number_to_chars(where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy)
+ ? S_GET_TYPE(fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[4] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[6] = r_symbolnum & 0x0ff;
+ where[7] = (((fixP->fx_pcrel << 7) & 0x80)
+ | ((nbytes_r_length[fixP->fx_size] << 5) & 0x60)
+ | ((!S_IS_DEFINED(fixP->fx_addsy) << 4) & 0x10));
+
+ return;
+} /* tc_aout_fix_to_chars() */
+
+/* Relocate byte stuff */
+
+/* This is for broken word. */
+const int md_short_jump_size = 3;
+
+void
+md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ long from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - (from_addr + 1);
+ *ptr++ = TAHOE_BRW;
+ md_number_to_chars (ptr, offset, 2);
+}
+
+const int md_long_jump_size = 6;
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void
+md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+ char *ptr;
+ long from_addr, to_addr;
+ fragS *frag;
+ symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - (from_addr + 4);
+ *ptr++ = TAHOE_JMP;
+ *ptr++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (ptr, offset, 4);
+}
+
+/*
+ * md_estimate_size_before_relax()
+ *
+ * Called just before relax().
+ * Any symbol that is now undefined will not become defined, so we assumed
+ * that it will be resolved by the linker.
+ * Return the correct fr_subtype in the frag, for relax()
+ * Return the initial "guess for fr_var" to caller. (How big I think this
+ * will be.)
+ * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ * Although it may not be explicit in the frag, pretend fr_var starts with a
+ * 0 value.
+ */
+int
+md_estimate_size_before_relax (fragP, segment_type)
+ register fragS *fragP;
+ segT segment_type; /* N_DATA or N_TEXT. */
+{
+ register char *p;
+ register int old_fr_fix;
+/* int pc_rel; FIXME: remove this */
+
+ old_fr_fix = fragP->fr_fix;
+ switch (fragP->fr_subtype){
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment_type) {
+ /* The symbol was in the same segment as the opcode, and it's
+ a real pc_rel case so it's a relaxable case. */
+ fragP->fr_subtype = ENCODE_RELAX(STATE_PC_RELATIVE, STATE_BYTE);
+ }else{
+ /* This case is still undefined, so asume it's a long word for the
+ linker to fix. */
+ p = fragP->fr_literal + old_fr_fix;
+ *p |= TAHOE_PC_OR_LONG;
+ /* We now know how big it will be, one long word. */
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment_type){
+ fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
+ }else{
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode ^= 0x10; /* Reverse sense of branch. */
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 1 + 1 + 1 + 4;
+ fix_new (fragP, old_fr_fix + 3, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment_type){
+ fragP->fr_subtype =
+ ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_WORD);
+ }else{
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode ^= 0x10; /* Reverse sense of branch. */
+ *p++ = 0;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 2 + 2 + 4;
+ fix_new (fragP, old_fr_fix + 4, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment_type){
+ fragP->fr_subtype = ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_WORD);
+ }else{
+ p = fragP->fr_literal + old_fr_fix;
+ *p++ = 2;
+ *p++ = 0;
+ *p++ = TAHOE_BRB;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 2 + 2 + 2 + 4;
+ fix_new (fragP, old_fr_fix + 6, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment_type){
+ fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE);
+ }else{
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode = TAHOE_JMP;
+ *p++ = TAHOE_PC_REL_LONG;
+ fragP->fr_fix += 1 + 4;
+ fix_new (fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane (fragP);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+} /* md_estimate_size_before_relax() */
+
+/*
+ * md_convert_frag();
+ *
+ * Called after relax() is finished.
+ * In: Address of frag.
+ * fr_type == rs_machine_dependent.
+ * fr_subtype is what the address relaxed to.
+ *
+ * Out: Any fixSs and constants are set up.
+ * Caller will turn frag into a ".space 0".
+ */
+void
+md_convert_frag (headers, fragP)
+object_headers *headers;
+ register fragS *fragP;
+{
+ register char *addressP; /* -> _var to change. */
+ register char *opcodeP; /* -> opcode char(s) to change. */
+ register short int length_code; /* 2=long 1=word 0=byte */
+ register short int extension = 0; /* Size of relaxed address.
+ Added to fr_fix: incl. ALL var chars. */
+ register symbolS *symbolP;
+ register long int where;
+ register long int address_of_var;
+ /* Where, in file space, is _var of *fragP? */
+ register long int target_address;
+ /* Where, in file space, does addr point? */
+
+ know (fragP->fr_type == rs_machine_dependent);
+ length_code = RELAX_LENGTH(fragP->fr_subtype);
+ know (length_code >= 0 && length_code < 3);
+ where = fragP->fr_fix;
+ addressP = fragP->fr_literal + where;
+ opcodeP = fragP->fr_opcode;
+ symbolP = fragP->fr_symbol;
+ know(symbolP);
+ target_address = S_GET_VALUE(symbolP) + fragP->fr_offset;
+ address_of_var = fragP->fr_address + where;
+ switch (fragP->fr_subtype){
+ case ENCODE_RELAX(STATE_PC_RELATIVE, STATE_BYTE):
+ /* *addressP holds the registers number, plus 0x10, if it's deferred
+ mode. To set up the right mode, just OR the size of this displacement */
+ /* Byte displacement. */
+ *addressP++ |= TAHOE_PC_OR_BYTE;
+ *addressP = target_address - (address_of_var + 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX(STATE_PC_RELATIVE, STATE_WORD):
+ /* Word displacement. */
+ *addressP++ |= TAHOE_PC_OR_WORD;
+ md_number_to_chars(addressP, target_address - (address_of_var + 3), 2);
+ extension = 3;
+ break;
+
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_LONG):
+ /* Long word displacement. */
+ *addressP++ |= TAHOE_PC_OR_LONG;
+ md_number_to_chars(addressP, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):
+ *addressP = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
+ *opcodeP ^= 0x10; /* Reverse sense of test. */
+ *addressP++ = 3; /* Jump over word branch */
+ *addressP++ = TAHOE_BRW;
+ md_number_to_chars (addressP, target_address - (address_of_var + 4), 2);
+ extension = 4;
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_LONG):
+ *opcodeP ^= 0x10; /* Reverse sense of test. */
+ *addressP++ = 6;
+ *addressP++ = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (addressP, target_address, 4);
+ extension = 7;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE):
+ *addressP = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_WORD):
+ *opcodeP = TAHOE_BRW;
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_LONG):
+ *opcodeP = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars(addressP, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_WORD):
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_REV_BRANCH, STATE_LONG):
+ *opcodeP ^= 0x10;
+ *addressP++ = 0;
+ *addressP++ = 6;
+ *addressP++ = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (addressP, target_address, 4);
+ extension = 8;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_WORD):
+ md_number_to_chars (addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH, STATE_LONG):
+ *addressP++ = 0;
+ *addressP++ = 2;
+ *addressP++ = TAHOE_BRB;
+ *addressP++ = 6;
+ *addressP++ = TAHOE_JMP;
+ *addressP++ = TAHOE_PC_REL_LONG;
+ md_number_to_chars (addressP, target_address, 4);
+ extension = 10;
+ break;
+
+ default:
+ BAD_CASE (fragP->fr_subtype);
+ break;
+ }
+ fragP->fr_fix += extension;
+} /* md_convert_frag */
+
+
+/* This is the stuff for md_assemble. */
+#define FP_REG 13
+#define SP_REG 14
+#define PC_REG 15
+#define BIGGESTREG PC_REG
+
+/*
+ * Parse the string pointed to by START
+ * If it represents a valid register, point START to the character after
+ * the last valid register char, and return the register number (0-15).
+ * If invalid, leave START alone, return -1.
+ * The format has to be exact. I don't do things like eat leading zeros
+ * or the like.
+ * Note: This doesn't check for the next character in the string making
+ * this invalid. Ex: R123 would return 12, it's the callers job to check
+ * what start is point to apon return.
+ *
+ * Valid registers are R1-R15, %1-%15, FP (13), SP (14), PC (15)
+ * Case doesn't matter.
+ */
+int
+tahoe_reg_parse(start)
+ char **start; /* A pointer to the string to parse. */
+{
+ register char *regpoint = *start;
+ register int regnum = -1;
+
+ switch(*regpoint++){
+ case '%': /* Registers can start with a %,
+ R or r, and then a number. */
+ case 'R':
+ case 'r':
+ if (isdigit(*regpoint)){
+ /* Got the first digit. */
+ regnum = *regpoint++ - '0';
+ if ((regnum == 1) && isdigit(*regpoint)){
+ /* Its a two digit number. */
+ regnum = 10 + (*regpoint++ - '0');
+ if (regnum > BIGGESTREG){ /* Number too big? */
+ regnum = -1;
+ }
+ }
+ }
+ break;
+ case 'F': /* Is it the FP */
+ case 'f':
+ switch(*regpoint++){
+ case 'p':
+ case 'P':
+ regnum = FP_REG;
+ }
+ break;
+ case 's': /* How about the SP */
+ case 'S':
+ switch(*regpoint++){
+ case 'p':
+ case 'P':
+ regnum = SP_REG;
+ }
+ break;
+ case 'p': /* OR the PC even */
+ case 'P':
+ switch(*regpoint++){
+ case 'c':
+ case 'C':
+ regnum = PC_REG;
+ }
+ break;
+ }
+
+ if (regnum != -1){ /* No error, so move string pointer */
+ *start = regpoint;
+ }
+ return regnum; /* Return results */
+} /* tahoe_reg_parse */
+
+/*
+ * This chops up an operand and figures out its modes and stuff.
+ * It's a little touchy about extra characters.
+ * Optex to start with one extra character so it can be overwritten for
+ * the backward part of the parsing.
+ * You can't put a bunch of extra characters in side to
+ * make the command look cute. ie: * foo ( r1 ) [ r0 ]
+ * If you like doing a lot of typing, try COBOL!
+ * Actually, this parser is a little weak all around. It's designed to be
+ * used with compliers, so I emphisise correct decoding of valid code quickly
+ * rather that catching every possable error.
+ * Note: This uses the expression function, so save input_line_pointer before
+ * calling.
+ *
+ * Sperry defines the semantics of address modes (and values)
+ * by a two-letter code, explained here.
+ *
+ * letter 1: access type
+ *
+ * a address calculation - no data access, registers forbidden
+ * b branch displacement
+ * m read - let go of bus - write back "modify"
+ * r read
+ * w write
+ * v bit field address: like 'a' but registers are OK
+ *
+ * letter 2: data type (i.e. width, alignment)
+ *
+ * b byte
+ * w word
+ * l longword
+ * q quadword (Even regs < 14 allowed) (if 12, you get a warning)
+ * - unconditional synthetic jbr operand
+ * ? simple synthetic reversable branch operand
+ * ! complex synthetic reversable branch operand
+ * : complex synthetic non-reversable branch operand
+ *
+ * The '-?!:' letter 2's are not for external consumption. They are used
+ * by GAS for psuedo ops relaxing code.
+ *
+ * After parsing topP has:
+ *
+ * top_ndx: -1, or the index register. eg 7=[R7]
+ * top_reg: -1, or register number. eg 7 = R7 or (R7)
+ * top_mode: The addressing mode byte. This byte, defines which of
+ * the 11 modes opcode is.
+ * top_access: Access type wanted for this opperand 'b'branch ' '
+ * no-instruction 'amrvw'
+ * top_width: Operand width expected, one of "bwlq?-:!"
+ * exp_of_operand: The expression as parsed by expression()
+ * top_dispsize: Number of bytes in the displacement if we can figure it
+ * out and it's relavent.
+ *
+ * Need syntax checks built.
+ */
+
+void
+tip_op (optex,topP)
+ char *optex; /* The users text input, with one leading character */
+ struct top *topP;/* The tahoe instruction with some fields already set:
+ in: access, width
+ out: ndx, reg, mode, error, dispsize */
+
+{
+ int mode = 0; /* This operand's mode. */
+ char segfault = *optex; /* To keep the back parsing from freaking. */
+ char *point = optex+1; /* Parsing from front to back. */
+ char *end; /* Parsing from back to front. */
+ int reg = -1; /* major register, -1 means absent */
+ int imreg = -1; /* Major register in immediate mode */
+ int ndx = -1; /* index register number, -1 means absent */
+ char dec_inc = ' '; /* Is the SP auto-incremented '+' or
+ auto-decremented '-' or neither ' '. */
+ int immediate = 0; /* 1 if '$' immediate mode */
+ int call_width = 0; /* If the caller casts the displacement */
+ int abs_width = 0; /* The width of the absolute displacment */
+ int com_width = 0; /* Displacement width required by branch */
+ int deferred = 0; /* 1 if '*' deferral is used */
+ byte disp_size = 0; /* How big is this operand. 0 == don't know */
+ char *op_bad = ""; /* Bad operand error */
+
+ char *tp, *temp, c; /* Temporary holders */
+
+ char access = topP->top_access; /* Save on a deref. */
+ char width = topP->top_width;
+
+ int really_none = 0; /* Empty expressions evaluate to 0
+ but I need to know if it's there or not */
+ expressionS *expP; /* -> expression values for this operand */
+
+ /* Does this command restrict the displacement size. */
+ if (access == 'b')
+ com_width = (width == 'b' ? 1 :
+ (width == 'w' ? 2 :
+ (width == 'l' ? 4 : 0)));
+
+ *optex = '\0'; /* This is kind of a back stop for all
+ the searches to fail on if needed.*/
+ if (*point == '*') { /* A dereference? */
+ deferred = 1;
+ point++;
+ }
+
+ /* Force words into a certain mode */
+ /* Bitch, Bitch, Bitch! */
+ /*
+ * Using the ^ operator is ambigous. If I have an absolute label
+ * called 'w' set to, say 2, and I have the expression 'w^1', do I get
+ * 1, forced to be in word displacement mode, or do I get the value of
+ * 'w' or'ed with 1 (3 in this case).
+ * The default is 'w' as an offset, so that's what I use.
+ * Stick with `, it does the same, and isn't ambig.
+ */
+
+ if (*point != '\0' && ((point[1] == '^') || (point[1] == '`')))
+ switch(*point){
+ case 'b':
+ case 'B':
+ case 'w':
+ case 'W':
+ case 'l':
+ case 'L':
+ if (com_width)
+ as_warn("Casting a branch displacement is bad form, and is ignored.");
+ else{
+ c = (isupper(*point) ? tolower(*point) : *point);
+ call_width = ((c == 'b') ? 1 :
+ ((c == 'w') ? 2 : 4));
+ }
+ point += 2;
+ break;
+ }
+
+ /* Setting immediate mode */
+ if (*point == '$'){
+ immediate = 1;
+ point++;
+ }
+
+ /*
+ * I've pulled off all the easy stuff off the front, move to the end and
+ * yank.
+ */
+
+ for(end = point;*end != '\0';end++) /* Move to the end. */
+ ;
+
+ if(end != point) /* Null string? */
+ end--;
+
+ if (end > point && *end == ' ' && end[-1] != '\'')
+ end--; /* Hop white space */
+
+ /* Is this an index reg. */
+ if ((*end == ']') && (end[-1] != '\'')){
+ temp = end;
+
+ /* Find opening brace. */
+ for(--end;(*end != '[' && end != point);end--)
+ ;
+
+ /* If I found the opening brace, get the index register number. */
+ if (*end == '['){
+ tp = end + 1; /* tp should point to the start of a reg. */
+ ndx = tahoe_reg_parse(&tp);
+ if (tp != temp){ /* Reg. parse error. */
+ ndx = -1;
+ } else {
+ end--; /* Found it, move past brace. */
+ }
+ if (ndx == -1){
+ op_bad = "Couldn't parse the [index] in this operand.";
+ end = point; /* Force all the rest of the tests to fail. */
+ }
+ }else{
+ op_bad = "Couldn't find the opening '[' for the index of this operand.";
+ end = point; /* Force all the rest of the tests to fail. */
+ }
+ }
+
+ /* Post increment? */
+ if (*end == '+'){
+ dec_inc = '+';
+/* was: *end--; */
+ end--;
+ }
+
+ /* register in parens? */
+ if ((*end == ')') && (end[-1] != '\'')){
+ temp = end;
+
+ /* Find opening paren. */
+ for(--end;(*end != '(' && end != point);end--)
+ ;
+
+ /* If I found the opening paren, get the register number. */
+ if (*end == '('){
+ tp = end + 1;
+ reg = tahoe_reg_parse(&tp);
+ if (tp != temp){
+ /* Not a register, but could be part of the expression. */
+ reg = -1;
+ end = temp; /* Rest the pointer back */
+ } else {
+ end--; /* Found the reg. move before opening paren. */
+ }
+ }else{
+ op_bad = "Couldn't find the opening '(' for the deref of this operand.";
+ end = point; /* Force all the rest of the tests to fail. */
+ }
+ }
+
+ /* Pre decrement? */
+ if (*end == '-'){
+ if (dec_inc != ' '){
+ op_bad = "Operand can't be both pre-inc and post-dec.";
+ end = point;
+ }else{
+ dec_inc = '-';
+/* was: *end--; */
+ end--;
+ }
+ }
+
+ /*
+ * Everything between point and end is the 'expression', unless it's
+ * a register name.
+ */
+
+ c = end[1];
+ end[1] = '\0';
+
+ tp = point;
+ imreg = tahoe_reg_parse(&point); /* Get the immediate register
+ if it is there.*/
+ if (*point != '\0'){
+ /* If there is junk after point, then the it's not immediate reg. */
+ point = tp;
+ imreg = -1;
+ }
+
+ if (imreg != -1 && reg != -1)
+ op_bad = "I parsed 2 registers in this operand.";
+
+ /*
+ * Evaluate whats left of the expression to see if it's valid.
+ * Note again: This assumes that the calling expression has saved
+ * input_line_pointer. (Nag, nag, nag!)
+ */
+
+ if (*op_bad == '\0'){
+ /* statement has no syntax goofs yet: lets sniff the expression */
+ input_line_pointer = point;
+ expP = &(topP->exp_of_operand);
+ switch (expression (expP)){
+ /* If expression == SEG_PASS1, expression() will have set
+ need_pass_2 = 1. */
+ case SEG_ABSENT:
+ /* No expression. For BSD4.2 compatibility, missing expression is
+ absolute 0 */
+ expP->X_seg = SEG_ABSOLUTE;
+ expP->X_add_number = 0;
+ really_none = 1;
+ case SEG_ABSOLUTE:
+ /* for SEG_ABSOLUTE, we shouldnt need to set X_subtract_symbol,
+ X_add_symbol to any particular value. */
+ /* But, we will program defensively. Since this situation occurs
+ rarely so it costs us little to do so. */
+ expP->X_add_symbol = NULL;
+ expP->X_subtract_symbol = NULL;
+ /* How many bytes are needed to express this abs value? */
+ abs_width =
+ ((((expP->X_add_number & 0xFFFFFF80) == 0) ||
+ ((expP->X_add_number & 0xFFFFFF80) == 0xFFFFFF80)) ? 1 :
+ (((expP->X_add_number & 0xFFFF8000) == 0) ||
+ ((expP->X_add_number & 0xFFFF8000) == 0xFFFF8000)) ? 2 : 4);
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_UNKNOWN:
+ break;
+
+ case SEG_DIFFERENCE:
+ /*
+ * Major bug. We can't handle the case of a
+ * SEG_DIFFERENCE expression in a synthetic opcode
+ * variable-length instruction.
+ * We don't have a frag type that is smart enough to
+ * relax a SEG_DIFFERENCE, and so we just force all
+ * SEG_DIFFERENCEs to behave like SEG_PASS1s.
+ * Clearly, if there is a demand we can invent a new or
+ * modified frag type and then coding up a frag for this
+ * case will be easy. SEG_DIFFERENCE was invented for the
+ * .words after a CASE opcode, and was never intended for
+ * instruction operands.
+ */
+ need_pass_2 = 1;
+ case SEG_PASS1:
+ op_bad = "Can't relocate expression error.";
+ break;
+
+ case SEG_BIG:
+ /* This is an error. Tahoe doesn't allow any expressions
+ bigger that a 32 bit long word. Any bigger has to be referenced
+ by address. */
+ op_bad = "Expression is too large for a 32 bits.";
+ break;
+
+ default:
+ as_fatal("Complier Bug: I got segment %d in tip_op.",expP->X_seg);
+ break;
+ }
+ if (*input_line_pointer != '\0'){
+ op_bad = "Junk at end of expression.";
+ }
+ }
+
+ end[1] = c;
+
+ /* I'm done, so restore optex */
+ *optex = segfault;
+
+
+ /*
+ * At this point in the game, we (in theory) have all the components of
+ * the operand at least parsed. Now it's time to check for syntax/semantic
+ * errors, and build the mode.
+ * This is what I have:
+ * deferred = 1 if '*'
+ * call_width = 0,1,2,4
+ * abs_width = 0,1,2,4
+ * com_width = 0,1,2,4
+ * immediate = 1 if '$'
+ * ndx = -1 or reg num
+ * dec_inc = '-' or '+' or ' '
+ * reg = -1 or reg num
+ * imreg = -1 or reg num
+ * topP->exp_of_operand
+ * really_none
+ */
+ /* Is there a displacement size? */
+ disp_size = (call_width ? call_width :
+ (com_width ? com_width :
+ abs_width ? abs_width : 0));
+
+ if (*op_bad == '\0'){
+ if (imreg != -1){
+ /* Rn */
+ mode = TAHOE_DIRECT_REG;
+ if (deferred || immediate || (dec_inc != ' ') ||
+ (reg != -1) || !really_none)
+ op_bad = "Syntax error in direct register mode.";
+ else if (ndx != -1)
+ op_bad = "You can't index a register in direct register mode.";
+ else if (imreg == SP_REG && access == 'r')
+ op_bad =
+ "SP can't be the source operand with direct register addressing.";
+ else if (access == 'a')
+ op_bad = "Can't take the address of a register.";
+ else if (access == 'b')
+ op_bad = "Direct Register can't be used in a branch.";
+ else if (width == 'q' && ((imreg % 2) || (imreg > 13)))
+ op_bad = "For quad access, the register must be even and < 14.";
+ else if (call_width)
+ op_bad = "You can't cast a direct register.";
+
+ if (*op_bad == '\0'){
+ /* No errors, check for warnings */
+ if (width == 'q' && imreg == 12)
+ as_warn("Using reg 14 for quadwords can tromp the FP register.");
+
+ reg = imreg;
+ }
+
+ /* We know: imm = -1 */
+ }else if (dec_inc == '-'){
+ /* -(SP) */
+ mode = TAHOE_AUTO_DEC;
+ if (deferred || immediate || !really_none)
+ op_bad = "Syntax error in auto-dec mode.";
+ else if (ndx != -1)
+ op_bad = "You can't have an index auto dec mode.";
+ else if (access == 'r')
+ op_bad = "Auto dec mode cant be used for reading.";
+ else if (reg != SP_REG)
+ op_bad = "Auto dec only works of the SP register.";
+ else if (access == 'b')
+ op_bad = "Auto dec can't be used in a branch.";
+ else if (width == 'q')
+ op_bad = "Auto dec won't work with quadwords.";
+
+ /* We know: imm = -1, dec_inc != '-' */
+ }else if (dec_inc == '+'){
+ if (immediate || !really_none)
+ op_bad = "Syntax error in one of the auto-inc modes.";
+ else if (deferred){
+ /* *(SP)+ */
+ mode = TAHOE_AUTO_INC_DEFERRED;
+ if (reg != SP_REG)
+ op_bad = "Auto inc deferred only works of the SP register.";
+ else if (ndx != -1)
+ op_bad = "You can't have an index auto inc deferred mode.";
+ else if (access == 'b')
+ op_bad = "Auto inc can't be used in a branch.";
+ }else{
+ /* (SP)+ */
+ mode = TAHOE_AUTO_INC;
+ if (access == 'm' || access == 'w')
+ op_bad = "You can't write to an auto inc register.";
+ else if (reg != SP_REG)
+ op_bad = "Auto inc only works of the SP register.";
+ else if (access == 'b')
+ op_bad = "Auto inc can't be used in a branch.";
+ else if (width == 'q')
+ op_bad = "Auto inc won't work with quadwords.";
+ else if (ndx != -1)
+ op_bad = "You can't have an index in auto inc mode.";
+ }
+
+ /* We know: imm = -1, dec_inc == ' ' */
+ }else if (reg != -1){
+ if ((ndx != -1) && (reg == SP_REG))
+ op_bad = "You can't index the sp register.";
+ if (deferred){
+ /* *<disp>(Rn) */
+ mode = TAHOE_REG_DISP_DEFERRED;
+ if (immediate)
+ op_bad = "Syntax error in register displaced mode.";
+ }else if (really_none){
+ /* (Rn) */
+ mode = TAHOE_REG_DEFERRED;
+ /* if reg = SP then cant be indexed */
+ }else{
+ /* <disp>(Rn) */
+ mode = TAHOE_REG_DISP;
+ }
+
+ /* We know: imm = -1, dec_inc == ' ', Reg = -1 */
+ }else{
+ if (really_none)
+ op_bad = "An offest is needed for this operand.";
+ if (deferred && immediate){
+ /* *$<ADDR> */
+ mode = TAHOE_ABSOLUTE_ADDR;
+ disp_size = 4;
+ }else if (immediate){
+ /* $<disp> */
+ mode = TAHOE_IMMEDIATE;
+ if (ndx != -1)
+ op_bad = "You can't index a register in immediate mode.";
+ if (access == 'a')
+ op_bad = "Immediate access can't be used as an address.";
+ /* ponder the wisdom of a cast because it doesn't do any good. */
+ }else if (deferred){
+ /* *<disp> */
+ mode = TAHOE_DISP_REL_DEFERRED;
+ }else{
+ /* <disp> */
+ mode = TAHOE_DISPLACED_RELATIVE;
+ }
+ }
+ }
+
+ /*
+ * At this point, all the errors we can do have be checked for.
+ * We can build the 'top'. */
+
+ topP->top_ndx = ndx;
+ topP->top_reg = reg;
+ topP->top_mode = mode;
+ topP->top_error = op_bad;
+ topP->top_dispsize = disp_size;
+} /* tip_op */
+
+/*
+ * t i p ( )
+ *
+ * This converts a string into a tahoe instruction.
+ * The string must be a bare single instruction in tahoe (with BSD4 frobs)
+ * format.
+ * It provides at most one fatal error message (which stops the scan)
+ * some warning messages as it finds them.
+ * The tahoe instruction is returned in exploded form.
+ *
+ * The exploded instruction is returned to a struct tit of your choice.
+ * #include "tahoe-inst.h" to know what a struct tit is.
+ *
+ */
+
+static void
+tip (titP, instring)
+ struct tit *titP; /* We build an exploded instruction here. */
+ char *instring; /* Text of a vax instruction: we modify. */
+{
+ register struct tot_wot *twP = NULL; /* How to bit-encode this opcode. */
+ register char *p; /* 1/skip whitespace.2/scan vot_how */
+ register char *q; /* */
+ register unsigned char count; /* counts number of operands seen */
+ register struct top *operandp;/* scan operands in struct tit */
+ register char *alloperr = ""; /* error over all operands */
+ register char c; /* Remember char, (we clobber it
+ with '\0' temporarily). */
+ char *save_input_line_pointer;
+
+ if (*instring == ' ')
+ ++instring; /* Skip leading whitespace. */
+ for (p = instring; *p && *p != ' '; p++)
+ ; /* MUST end in end-of-string or
+ exactly 1 space. */
+ /* Scanned up to end of operation-code. */
+ /* Operation-code is ended with whitespace. */
+ if (p == instring){
+ titP->tit_error = "No operator";
+ count = 0;
+ titP->tit_opcode = 0;
+ } else {
+ c = *p;
+ *p = '\0';
+ /*
+ * Here with instring pointing to what better be an op-name, and p
+ * pointing to character just past that.
+ * We trust instring points to an op-name, with no whitespace.
+ */
+ twP = (struct tot_wot *) hash_find(op_hash, instring);
+ *p = c; /* Restore char after op-code. */
+ if (twP == 0){
+ titP->tit_error = "Unknown operator";
+ count = 0;
+ titP->tit_opcode = 0;
+ }else{
+ /*
+ * We found a match! So lets pick up as many operands as the
+ * instruction wants, and even gripe if there are too many.
+ * We expect comma to seperate each operand.
+ * We let instring track the text, while p tracks a part of the
+ * struct tot.
+ */
+
+ count = 0; /* no operands seen yet */
+ instring = p+(*p!='\0'); /* point past the operation code */
+ /* tip_op() screws with the input_line_pointer, so save it before
+ I jump in */
+ save_input_line_pointer = input_line_pointer;
+ for (p = twP->args, operandp = titP->tit_operand;
+ !*alloperr && *p;
+ operandp++, p += 2){
+ /*
+ * Here to parse one operand. Leave instring pointing just
+ * past any one ',' that marks the end of this operand.
+ */
+ if (!p[1])
+ as_fatal("Compiler bug: ODD number of bytes in arg structure %s.",
+ twP->args);
+ else if (*instring){
+ for (q = instring; (*q != ',' && *q != '\0'); q++){
+ if (*q == '\'' && q[1] != '\0') /* Jump quoted characters */
+ q++;
+ }
+ c = *q;
+ /*
+ * Q points to ',' or '\0' that ends argument. C is that
+ * character.
+ */
+ *q = '\0';
+ operandp->top_access = p[0];
+ operandp->top_width = p[1];
+ tip_op(instring-1, operandp);
+ *q = c; /* Restore input text. */
+ if (*(operandp->top_error)){
+ alloperr = operandp->top_error;
+ }
+ instring = q + (c ? 1 : 0); /* next operand (if any) */
+ count++; /* won another argument, may have an operr */
+ }else
+ alloperr = "Not enough operands";
+ }
+ /* Restore the pointer. */
+ input_line_pointer = save_input_line_pointer;
+
+ if (!*alloperr){
+ if (*instring == ' ')
+ instring++; /* Skip whitespace. */
+ if (*instring)
+ alloperr = "Too many operands";
+ }
+ titP->tit_error = alloperr;
+ }
+ }
+
+ titP->tit_opcode = twP->code; /* The op-code. */
+ titP->tit_operands = count;
+} /* tip */
+
+/* md_assemble() emit frags for 1 instruction */
+void
+md_assemble (instruction_string)
+ char *instruction_string; /* A string: assemble 1 instruction. */
+{
+ char *p;
+ register struct top *operandP; /* An operand. Scans all operands. */
+/* char c_save; fixme: remove this line */ /* What used to live after an expression. */
+/* struct frag *fragP; fixme: remove this line */ /* Fragment of code we just made. */
+/* register struct top *end_operandP; fixme: remove this line */ /* -> slot just after last operand
+ Limit of the for (each operand). */
+ register expressionS *expP; /* -> expression values for this operand */
+
+ /* These refer to an instruction operand expression. */
+ segT to_seg; /* Target segment of the address. */
+
+ register valueT this_add_number;
+ register struct symbol *this_add_symbol; /* +ve (minuend) symbol. */
+
+/* tahoe_opcodeT opcode_as_number; fixme: remove this line */ /* The opcode as a number. */
+ char *opcodeP; /* Where it is in a frag. */
+/* char *opmodeP; fixme: remove this line */ /* Where opcode type is, in a frag. */
+
+ int dispsize; /* From top_dispsize: tahoe_operand_width
+ (in bytes) */
+ int is_undefined; /* 1 if operand expression's
+ segment not known yet. */
+ int pc_rel; /* Is this operand pc relative? */
+
+ /* Decode the operand. */
+ tip(&t, instruction_string);
+
+ /*
+ * Check to see if this operand decode properly.
+ * Notice that we haven't made any frags yet.
+ * If it goofed, then this instruction will wedge in any pass,
+ * and we can safely flush it, without causing interpass symbol phase
+ * errors. That is, without changing label values in different passes.
+ */
+ if (*t.tit_error){
+ as_warn("Ignoring statement due to \"%s\"", t.tit_error);
+ }else{
+ /* We saw no errors in any operands - try to make frag(s) */
+ /* Emit op-code. */
+ /* Remember where it is, in case we want to modify the op-code later. */
+ opcodeP = frag_more(1);
+ *opcodeP = t.tit_opcode;
+ /* Now do each operand. */
+ for (operandP = t.tit_operand;
+ operandP < t.tit_operand + t.tit_operands;
+ operandP++){ /* for each operand */
+ expP = &(operandP->exp_of_operand);
+ if (operandP->top_ndx >= 0){
+ /* Indexed addressing byte
+ Legality of indexed mode already checked: it is OK */
+ FRAG_APPEND_1_CHAR(0x40 + operandP->top_ndx);
+ } /* if(top_ndx>=0) */
+
+ /* Here to make main operand frag(s). */
+ this_add_number = expP->X_add_number;
+ this_add_symbol = expP->X_add_symbol;
+ to_seg = expP->X_seg;
+ know (to_seg == SEG_UNKNOWN||\
+ to_seg == SEG_ABSOLUTE||\
+ to_seg == SEG_DATA||\
+ to_seg == SEG_TEXT||\
+ to_seg == SEG_BSS);
+ is_undefined = (to_seg == SEG_UNKNOWN);
+ /* Do we know how big this opperand is? */
+ dispsize = operandP->top_dispsize;
+ pc_rel = 0;
+ /* Deal with the branch possabilities. (Note, this doesn't include
+ jumps.)*/
+ if (operandP->top_access == 'b'){
+ /* Branches must be expressions. A psuedo branch can also jump to
+ an absolute address. */
+ if (to_seg == now_seg || is_undefined){
+ /* If is_undefined, then it might BECOME now_seg by relax time. */
+ if (dispsize){
+ /* I know how big the branch is supposed to be (it's a normal
+ branch), so I set up the frag, and let GAS do the rest. */
+ p = frag_more (dispsize);
+ fix_new (frag_now, p - frag_now->fr_literal, dispsize,
+ this_add_symbol, 0, this_add_number, 1, NO_RELOC);
+ } else {
+ /* (to_seg==now_seg || to_seg == SEG_UNKNOWN) && dispsize==0 */
+ /* If we don't know how big it is, then its a synthetic branch,
+ so we set up a simple relax state. */
+ switch (operandP->top_width){
+ case TAHOE_WIDTH_CONDITIONAL_JUMP:
+ /* Simple (conditional) jump. I may have to reverse the
+ condition of opcodeP, and then jump to my destination.
+ I set 1 byte aside for the branch off set, and could need 6
+ more bytes for the pc_rel jump */
+ frag_var (rs_machine_dependent, 7, 1,
+ ENCODE_RELAX (STATE_CONDITIONAL_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_BYTE),
+ this_add_symbol, this_add_number, opcodeP);
+ break;
+ case TAHOE_WIDTH_ALWAYS_JUMP:
+ /* Simple (unconditional) jump. I may have to convert this to
+ a word branch, or an absolute jump. */
+ frag_var (rs_machine_dependent, 5, 1,
+ ENCODE_RELAX (STATE_ALWAYS_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_BYTE),
+ this_add_symbol, this_add_number, opcodeP);
+ break;
+ /* The smallest size for the next 2 cases is word. */
+ case TAHOE_WIDTH_BIG_REV_JUMP:
+ frag_var (rs_machine_dependent, 8, 2,
+ ENCODE_RELAX (STATE_BIG_REV_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_WORD),
+ this_add_symbol, this_add_number,
+ opcodeP);
+ break;
+ case TAHOE_WIDTH_BIG_NON_REV_JUMP:
+ frag_var (rs_machine_dependent, 10, 2,
+ ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH,
+ is_undefined ? STATE_UNDF : STATE_WORD),
+ this_add_symbol, this_add_number,
+ opcodeP);
+ break;
+ default:
+ as_fatal("Compliler bug: Got a case (%d) I wasn't expecting.",
+ operandP->top_width);
+ }
+ }
+ }else{
+ /* to_seg != now_seg && to_seg != seg_unknown (still in branch)
+ In other words, I'm jumping out of my segment so extend the
+ branches to jumps, and let GAS fix them. */
+
+ /* These are "branches" what will always be branches around a jump
+ to the correct addresss in real life.
+ If to_seg is SEG_ABSOLUTE, just encode the branch in,
+ else let GAS fix the address. */
+
+ switch (operandP->top_width){
+ /* The theory:
+ For SEG_ABSOLUTE, then mode is ABSOLUTE_ADDR, jump
+ to that addresss (not pc_rel).
+ For other segs, address is a long word PC rel jump. */
+ case TAHOE_WIDTH_CONDITIONAL_JUMP:
+ /* b<cond> */
+ /* To reverse the condition in a TAHOE branch,
+ complement bit 4 */
+ *opcodeP ^= 0x10;
+ p = frag_more (7);
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal, 4,
+ this_add_symbol, 0, this_add_number,
+ (to_seg != SEG_ABSOLUTE), NO_RELOC);
+ /*
+ * Now (eg) BLEQ 1f
+ * JMP foo
+ * 1:
+ */
+ break;
+ case TAHOE_WIDTH_ALWAYS_JUMP:
+ /* br, just turn it into a jump */
+ *opcodeP = TAHOE_JMP;
+ p = frag_more (5);
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal, 4,
+ this_add_symbol, 0, this_add_number,
+ (to_seg != SEG_ABSOLUTE), NO_RELOC);
+ /* Now (eg) JMP foo */
+ break;
+ case TAHOE_WIDTH_BIG_REV_JUMP:
+ p = frag_more (8);
+ *opcodeP ^= 0x10;
+ *p++ = 0;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal, 4,
+ this_add_symbol, 0, this_add_number,
+ (to_seg != SEG_ABSOLUTE), NO_RELOC);
+ /*
+ * Now (eg) ACBx 1f
+ * JMP foo
+ * 1:
+ */
+ break;
+ case TAHOE_WIDTH_BIG_NON_REV_JUMP:
+ p = frag_more (10);
+ *p++ = 0;
+ *p++ = 2;
+ *p++ = TAHOE_BRB;
+ *p++ = 6;
+ *p++ = TAHOE_JMP;
+ *p++ = (operandP->top_mode ==
+ TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :
+ TAHOE_PC_REL_LONG);
+ fix_new (frag_now, p - frag_now->fr_literal, 4,
+ this_add_symbol, 0, this_add_number,
+ (to_seg != SEG_ABSOLUTE), NO_RELOC);
+ /*
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
+ break;
+ case 'b':
+ case 'w':
+ as_warn("Real branch displacements must be expressions.");
+ break;
+ default:
+ as_fatal("Complier error: I got an unknown synthetic branch :%c",
+ operandP->top_width);
+ break;
+ }
+ }
+ }else{
+ /* It ain't a branch operand. */
+ switch (operandP->top_mode){
+ /* Auto-foo access, only works for one reg (SP)
+ so the only thing needed is the mode. */
+ case TAHOE_AUTO_DEC:
+ case TAHOE_AUTO_INC:
+ case TAHOE_AUTO_INC_DEFERRED:
+ FRAG_APPEND_1_CHAR(operandP->top_mode);
+ break;
+
+ /* Numbered Register only access. Only thing needed is the
+ mode + Register number */
+ case TAHOE_DIRECT_REG:
+ case TAHOE_REG_DEFERRED:
+ FRAG_APPEND_1_CHAR(operandP->top_mode + operandP->top_reg);
+ break;
+
+ /* An absolute address. It's size is always 5 bytes.
+ (mode_type + 4 byte address). */
+ case TAHOE_ABSOLUTE_ADDR:
+ know((this_add_symbol == NULL));
+ p = frag_more(5);
+ *p = TAHOE_ABSOLUTE_ADDR;
+ md_number_to_chars(p+1,this_add_number,4);
+ break;
+
+ /* Immediate data. If the size isn't known, then it's an address
+ + and offset, which is 4 bytes big. */
+ case TAHOE_IMMEDIATE:
+ if (this_add_symbol != NULL){
+ p = frag_more (5);
+ *p++ = TAHOE_IMMEDIATE_LONGWORD;
+ fix_new (frag_now, p - frag_now->fr_literal,
+ 4, this_add_symbol,0,this_add_number,
+ 0, NO_RELOC);
+ }else{
+ /* It's a integer, and I know it's size. */
+ if ((unsigned) this_add_number < 0x40){
+ /* Will it fit in a literal? */
+ FRAG_APPEND_1_CHAR((byte) this_add_number);
+ }else{
+ p = frag_more(dispsize+1);
+ switch(dispsize){
+ case 1:
+ *p++ = TAHOE_IMMEDIATE_BYTE;
+ *p = (byte) this_add_number;
+ break;
+ case 2:
+ *p++ = TAHOE_IMMEDIATE_WORD;
+ md_number_to_chars(p,this_add_number,2);
+ break;
+ case 4:
+ *p++ = TAHOE_IMMEDIATE_LONGWORD;
+ md_number_to_chars(p,this_add_number,4);
+ break;
+ }
+ }
+ }
+ break;
+
+ /* Distance from the PC. If the size isn't known, we have to relax
+ into it. The difference between this and disp(sp) is that
+ this offset is pc_rel, and disp(sp) isn't.
+ Note the drop through code. */
+
+ case TAHOE_DISPLACED_RELATIVE:
+ case TAHOE_DISP_REL_DEFERRED:
+ operandP->top_reg = PC_REG;
+ pc_rel = 1;
+
+ /* Register, plus a displacement mode. Save the register number,
+ and weather its deffered or not, and relax the size if it isn't
+ known. */
+ case TAHOE_REG_DISP:
+ case TAHOE_REG_DISP_DEFERRED:
+ if (operandP->top_mode == TAHOE_DISP_REL_DEFERRED ||
+ operandP->top_mode == TAHOE_REG_DISP_DEFERRED)
+ operandP->top_reg += 0x10; /* deffered mode is always 0x10 higher
+ than it's non-deffered sibling. */
+
+ /* Is this a value out of this segment?
+ The first part of this conditional is a cludge to make gas
+ produce the same output as 'as' when there is a lable, in
+ the current segment, displaceing a register. It's strange,
+ and no one in their right mind would do it, but it's easy
+ to cludge. */
+ if ((dispsize == 0 && !pc_rel) ||
+ (to_seg != now_seg && !is_undefined && to_seg != SEG_ABSOLUTE))
+ dispsize = 4;
+
+ if (dispsize == 0){
+ /*
+ * We have a SEG_UNKNOWN symbol, or the size isn't cast.
+ * It might turn out to be in the same segment as
+ * the instruction, permitting relaxation.
+ */
+ p = frag_var(rs_machine_dependent, 5, 2,
+ ENCODE_RELAX(STATE_PC_RELATIVE,
+ is_undefined ? STATE_UNDF:STATE_BYTE),
+ this_add_symbol, this_add_number,0);
+ *p = operandP->top_reg;
+ }else{
+ /* Either this is an abs, or a cast. */
+ p = frag_more (dispsize + 1);
+ switch(dispsize){
+ case 1:
+ *p = TAHOE_PC_OR_BYTE + operandP->top_reg;
+ break;
+ case 2:
+ *p = TAHOE_PC_OR_WORD + operandP->top_reg;
+ break;
+ case 4:
+ *p = TAHOE_PC_OR_LONG + operandP->top_reg;
+ break;
+ };
+ fix_new (frag_now, p + 1 - frag_now->fr_literal,
+ dispsize, this_add_symbol,0,this_add_number,
+ pc_rel, NO_RELOC);
+ }
+ break;
+ default:
+ as_fatal("Barf, bad mode %x\n",operandP->top_mode);
+ }
+ }
+ } /* for(operandP) */
+ } /* if(!need_pass_2 && !goofed) */
+} /* tahoe_assemble() */
+
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *md_undefined_symbol(name)
+char *name;
+{
+ return 0;
+} /* md_undefined_symbol() */
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void md_operand(expressionP)
+expressionS *expressionP;
+{
+} /* md_operand() */
+
+/* Round up a section size to the appropriate boundary. */
+long md_section_align(segment, size)
+segT segment;
+long size;
+{
+ return((size + 7) & ~7); /* Round all sects to multiple of 8 */
+} /* md_section_align() */
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the sparc, they're relative to the address of the offset, plus
+ its size. This gets us to the following instruction.
+ (??? Is this right? FIXME-SOON) */
+long md_pcrel_from(fixP)
+fixS *fixP;
+{
+ return(fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address);
+} /* md_pcrel_from() */
+
+/* end of tc-tahoe.c */
diff --git a/gnu/usr.bin/as/config/tc-tahoe.h b/gnu/usr.bin/as/config/tc-tahoe.h
new file mode 100644
index 0000000..4593a76
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-tahoe.h
@@ -0,0 +1,36 @@
+/* This file is tc-tahoe.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TC_TAHOE 1
+
+#define NO_LISTING
+
+#define tc_headers_hook(a) {;} /* don't need it. */
+#define tc_crawl_symbol_chain(a) {;} /* don't need it. */
+#define tc_aout_pre_write_hook(a) {;}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-tahoe.h */
diff --git a/gnu/usr.bin/as/config/tc-vax.c b/gnu/usr.bin/as/config/tc-vax.c
new file mode 100644
index 0000000..2b1970a
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-vax.c
@@ -0,0 +1,3073 @@
+/* tc-vax.c - vax-specific -
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* JF I moved almost all the vax specific stuff into this one file 'cuz RMS
+ seems to think its a good idea. I hope I managed to get all the VAX-isms */
+
+
+#include "as.h"
+
+#include "read.h"
+#include "vax-inst.h"
+#include "obstack.h" /* For FRAG_APPEND_1_CHAR macro in "frags.h" */
+
+/* These chars start a comment anywhere in a source file (except inside
+ another comment */
+const char comment_chars[] = "#";
+
+/* These chars only start a comment at the beginning of a line. */
+/* Note that for the VAX the are the same as comment_chars above. */
+const char line_comment_chars[] = "#";
+
+/* Chars that can be used to separate mant from exp in floating point nums */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant */
+/* as in 0f123.456 */
+/* or 0H1.234E-12 (see exp chars above) */
+const char FLT_CHARS[] = "dDfFgGhH";
+
+/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
+ changed in read.c. Ideally it shouldn't have to know about it at all,
+ but nothing is ideal around here.
+ */
+
+static expressionS /* Hold details of an operand expression */
+ exp_of_operand[VIT_MAX_OPERANDS];
+
+static struct vit
+ v; /* A vax instruction after decoding. */
+
+LITTLENUM_TYPE big_operand_bits[VIT_MAX_OPERANDS][SIZE_OF_LARGE_NUMBER];
+/* Hold details of big operands. */
+FLONUM_TYPE float_operand[VIT_MAX_OPERANDS];
+/* Above is made to point into */
+/* big_operand_bits by md_begin(). */
+
+/*
+ * For VAX, relative addresses of "just the right length" are easy.
+ * The branch displacement is always the last operand, even in
+ * synthetic instructions.
+ * For VAX, we encode the relax_substateTs (in e.g. fr_substate) as:
+ *
+ * 4 3 2 1 0 bit number
+ * ---/ /--+-------+-------+-------+-------+-------+
+ * | what state ? | how long ? |
+ * ---/ /--+-------+-------+-------+-------+-------+
+ *
+ * The "how long" bits are 00=byte, 01=word, 10=long.
+ * This is a Un*x convention.
+ * Not all lengths are legit for a given value of (what state).
+ * The "how long" refers merely to the displacement length.
+ * The address usually has some constant bytes in it as well.
+ *
+
+ groups for VAX address relaxing.
+
+ 1. "foo" pc-relative.
+ length of byte, word, long
+
+ 2a. J<cond> where <cond> is a simple flag test.
+ length of byte, word, long.
+ VAX opcodes are: (Hex)
+ bneq/bnequ 12
+ beql/beqlu 13
+ bgtr 14
+ bleq 15
+ bgeq 18
+ blss 19
+ bgtru 1a
+ blequ 1b
+ bvc 1c
+ bvs 1d
+ bgequ/bcc 1e
+ blssu/bcs 1f
+ Always, you complement 0th bit to reverse condition.
+ Always, 1-byte opcode, then 1-byte displacement.
+
+ 2b. J<cond> where cond tests a memory bit.
+ length of byte, word, long.
+ Vax opcodes are: (Hex)
+ bbs e0
+ bbc e1
+ bbss e2
+ bbcs e3
+ bbsc e4
+ bbcc e5
+ bbssi e6
+ bbcci e7
+ Always, you complement 0th bit to reverse condition.
+ Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement
+
+ 2c. J<cond> where cond tests low-order memory bit
+ length of byte,word,long.
+ Vax opcodes are: (Hex)
+ blbs e8
+ blbc e9
+ Always, you complement 0th bit to reverse condition.
+ Always, 1-byte opcode, longword-address, 1-byte displacement.
+
+ 3. Jbs/Jbr.
+ length of byte,word,long.
+ Vax opcodes are: (Hex)
+ bsbb 10
+ brb 11
+ These are like (2) but there is no condition to reverse.
+ Always, 1 byte opcode, then displacement/absolute.
+
+ 4a. JacbX
+ length of word, long.
+ Vax opcodes are: (Hex)
+ acbw 3d
+ acbf 4f
+ acbd 6f
+ abcb 9d
+ acbl f1
+ acbg 4ffd
+ acbh 6ffd
+ Always, we cannot reverse the sense of the branch; we have a word
+ displacement.
+ The double-byte op-codes don't hurt: we never want to modify the
+ opcode, so we don't care how many bytes are between the opcode and
+ the operand.
+
+ 4b. JXobXXX
+ length of long, long, byte.
+ Vax opcodes are: (Hex)
+ aoblss f2
+ aobleq f3
+ sobgeq f4
+ sobgtr f5
+ Always, we cannot reverse the sense of the branch; we have a byte
+ displacement.
+
+ The only time we need to modify the opcode is for class 2 instructions.
+ After relax() we may complement the lowest order bit of such instruction
+ to reverse sense of branch.
+
+ For class 2 instructions, we store context of "where is the opcode literal".
+ We can change an opcode's lowest order bit without breaking anything else.
+
+ We sometimes store context in the operand literal. This way we can figure out
+ after relax() what the original addressing mode was.
+ */
+
+/* These displacements are relative to */
+/* the start address of the displacement. */
+/* The first letter is Byte, Word. */
+/* 2nd letter is Forward, Backward. */
+#define BF (1+ 127)
+#define BB (1+-128)
+#define WF (2+ 32767)
+#define WB (2+-32768)
+/* Dont need LF, LB because they always */
+/* reach. [They are coded as 0.] */
+
+
+#define C(a,b) ENCODE_RELAX(a,b)
+/* This macro has no side-effects. */
+#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
+
+const relax_typeS
+ md_relax_table[] =
+{
+ { 1, 1, 0, 0 }, /* error sentinel 0,0 */
+ { 1, 1, 0, 0 }, /* unused 0,1 */
+ { 1, 1, 0, 0 }, /* unused 0,2 */
+ { 1, 1, 0, 0 }, /* unused 0,3 */
+ { BF + 1, BB + 1, 2, C(1, 1) }, /* B^"foo" 1,0 */
+ { WF + 1, WB + 1, 3, C (1, 2) }, /* W^"foo" 1,1 */
+ { 0, 0, 5, 0 }, /* L^"foo" 1,2 */
+ { 1, 1, 0, 0 }, /* unused 1,3 */
+ { BF, BB, 1, C(2, 1) }, /* b<cond> B^"foo" 2,0 */
+ { WF + 2, WB + 2, 4, C (2, 2) }, /* br.+? brw X 2,1 */
+ { 0, 0, 7, 0 }, /* br.+? jmp X 2,2 */
+ { 1, 1, 0, 0 }, /* unused 2,3 */
+ { BF, BB, 1, C (3, 1) }, /* brb B^foo 3,0 */
+ { WF, WB, 2, C (3, 2) }, /* brw W^foo 3,1 */
+ { 0, 0, 5, 0 }, /* Jmp L^foo 3,2 */
+ { 1, 1, 0, 0 }, /* unused 3,3 */
+ { 1, 1, 0, 0 }, /* unused 4,0 */
+ { WF, WB, 2, C (4, 2) }, /* acb_ ^Wfoo 4,1 */
+ { 0, 0, 10, 0 }, /* acb_,br,jmp L^foo4,2 */
+ { 1, 1, 0, 0 }, /* unused 4,3 */
+ { BF, BB, 1, C (5, 1) }, /* Xob___,,foo 5,0 */
+ { WF + 4, WB + 4, 6, C (5, 2) }, /* Xob.+2,brb.+3,brw5,1 */
+ { 0, 0, 9, 0 }, /* Xob.+2,brb.+6,jmp5,2 */
+};
+
+#undef C
+#undef BF
+#undef BB
+#undef WF
+#undef WB
+
+void float_cons ();
+
+const pseudo_typeS md_pseudo_table[] = {
+ {"dfloat", float_cons, 'd'},
+ {"ffloat", float_cons, 'f'},
+ {"gfloat", float_cons, 'g'},
+ {"hfloat", float_cons, 'h'},
+ {0},
+};
+
+#define STATE_PC_RELATIVE (1)
+#define STATE_CONDITIONAL_BRANCH (2)
+#define STATE_ALWAYS_BRANCH (3) /* includes BSB... */
+#define STATE_COMPLEX_BRANCH (4)
+#define STATE_COMPLEX_HOP (5)
+
+#define STATE_BYTE (0)
+#define STATE_WORD (1)
+#define STATE_LONG (2)
+#define STATE_UNDF (3) /* Symbol undefined in pass1 */
+
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#if __STDC__ == 1
+
+int flonum_gen2vax(char format_letter, FLONUM_TYPE *f, LITTLENUM_TYPE *words);
+static void vip_end(void);
+static void vip_op_defaults(char *immediate, char *indirect, char *displen);
+
+#else /* not __STDC__ */
+
+int flonum_gen2vax();
+static void vip_end();
+static void vip_op_defaults();
+
+#endif /* not __STDC__ */
+
+void
+ md_begin ()
+{
+ char *vip_begin ();
+ char *errtxt;
+ FLONUM_TYPE *fP;
+ int i;
+
+ if (*(errtxt = vip_begin (1, "$", "*", "`"))) {
+ as_fatal("VIP_BEGIN error:%s", errtxt);
+ }
+
+ for (i = 0, fP = float_operand;
+ fP < float_operand + VIT_MAX_OPERANDS;
+ i++, fP++) {
+ fP->low = &big_operand_bits[i][0];
+ fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];
+ }
+}
+
+void
+ md_end ()
+{
+ vip_end ();
+}
+
+void /* Knows about order of bytes in address. */
+ md_number_to_chars(con, value, nbytes)
+char con[]; /* Return 'nbytes' of chars here. */
+long value; /* The value of the bits. */
+int nbytes; /* Number of bytes in the output. */
+{
+ int n;
+ long v;
+
+ n = nbytes;
+ v = value;
+ while (nbytes--) {
+ *con++ = value; /* Lint wants & MASK_CHAR. */
+ value >>= BITS_PER_CHAR;
+ }
+ /* XXX line number probably botched for this warning message. */
+ if (value != 0 && value != -1)
+ as_bad("Displacement (%ld) long for instruction field length (%d).", v, n);
+}
+
+/* Fix up some data or instructions after we find out the value of a symbol
+ that they reference. */
+
+void /* Knows about order of bytes in address. */
+ md_apply_fix(fixP, value)
+fixS *fixP; /* Fixup struct pointer */
+long value; /* The value of the bits. */
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ int nbytes; /* Number of bytes in the output. */
+
+ nbytes = fixP->fx_size;
+ while (nbytes--) {
+ *buf++ = value; /* Lint wants & MASK_CHAR. */
+ value >>= BITS_PER_CHAR;
+ }
+}
+
+long /* Knows about the byte order in a word. */
+ md_chars_to_number (con, nbytes)
+unsigned char con[]; /* Low order byte 1st. */
+int nbytes; /* Number of bytes in the input. */
+{
+ long retval;
+ for (retval = 0, con += nbytes - 1; nbytes--; con--) {
+ retval <<= BITS_PER_CHAR;
+ retval |= *con;
+ }
+ return retval;
+}
+
+/* vax:md_assemble() emit frags for 1 instruction */
+
+void
+ md_assemble (instruction_string)
+char *instruction_string; /* A string: assemble 1 instruction. */
+{
+ /* We saw no errors in any operands - try to make frag(s) */
+ int is_undefined; /* 1 if operand expression's */
+ /* segment not known yet. */
+ int length_code;
+
+ char *p;
+ register struct vop *operandP;/* An operand. Scans all operands. */
+ char *save_input_line_pointer;
+ char c_save; /* What used to live after an expression. */
+ /* fixme: unused? */
+/* struct frag *fragP; */ /* Fragment of code we just made. */
+ register int goofed; /* 1: instruction_string bad for all passes. */
+ register struct vop *end_operandP; /* -> slot just after last operand */
+ /* Limit of the for (each operand). */
+ register expressionS *expP; /* -> expression values for this operand */
+
+ /* These refer to an instruction operand expression. */
+ segT to_seg; /* Target segment of the address. */
+ register valueT this_add_number;
+ register struct symbol *this_add_symbol; /* +ve (minuend) symbol. */
+ register struct symbol *this_subtract_symbol; /* -ve(subtrahend) symbol. */
+
+ long opcode_as_number; /* As a number. */
+ char *opcode_as_chars; /* Least significant byte 1st. */
+ /* As an array of characters. */
+ char *opcode_low_byteP; /* Least significant byte 1st */
+ /* richfix: unused? */
+/* struct details *detP; */ /* The details of an ADxxx frag. */
+ int length; /* length (bytes) meant by vop_short. */
+ int at; /* 0, or 1 if '@' is in addressing mode. */
+ int nbytes; /* From vop_nbytes: vax_operand_width (in bytes) */
+ FLONUM_TYPE *floatP;
+ char *vip ();
+ LITTLENUM_TYPE literal_float[8];
+ /* Big enough for any floating point literal. */
+
+ if (*(p = vip (&v, instruction_string))) {
+ as_fatal("vax_assemble\"%s\" in=\"%s\"", p, instruction_string);
+ }
+ /*
+ * Now we try to find as many as_warn()s as we can. If we do any as_warn()s
+ * then goofed=1. Notice that we don't make any frags yet.
+ * Should goofed be 1, then this instruction will wedge in any pass,
+ * and we can safely flush it, without causing interpass symbol phase
+ * errors. That is, without changing label values in different passes.
+ */
+ if (goofed = (*v.vit_error)) {
+ as_warn ("Ignoring statement due to \"%s\"", v.vit_error);
+ }
+ /*
+ * We need to use expression() and friends, which require us to diddle
+ * input_line_pointer. So we save it and restore it later.
+ */
+ save_input_line_pointer = input_line_pointer;
+ for (operandP = v.vit_operand,
+ expP = exp_of_operand,
+ floatP = float_operand,
+ end_operandP = v.vit_operand + v.vit_operands;
+
+ operandP < end_operandP;
+
+ operandP++, expP++, floatP++) { /* for each operand */
+ if (*(operandP->vop_error)) {
+ as_warn ("Ignoring statement because \"%s\"", (operandP->vop_error));
+ goofed = 1;
+ } else { /* statement has no syntax goofs: lets sniff the expression */
+ int can_be_short = 0; /* 1 if a bignum can be reduced to a short literal. */
+
+ input_line_pointer = operandP->vop_expr_begin;
+ c_save = operandP->vop_expr_end[1];
+ operandP->vop_expr_end[1] = '\0';
+ /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = 1. */
+ switch (to_seg = expression (expP)) {
+ case SEG_ABSENT:
+ /* for BSD4.2 compatibility, missing expression is absolute 0 */
+ to_seg = expP->X_seg = SEG_ABSOLUTE;
+ expP->X_add_number = 0;
+ /* for SEG_ABSOLUTE, we shouldnt need to set X_subtract_symbol, X_add_symbol to any
+ particular value. But, we will program defensively. Since this situation occurs rarely
+ so it costs us little to do, and stops Dean worrying about the origin of random bits in
+ expressionS's. */
+ expP->X_add_symbol = NULL;
+ expP->X_subtract_symbol = NULL;
+ case SEG_TEXT:
+ case SEG_DATA:
+ case SEG_BSS:
+ case SEG_ABSOLUTE:
+ case SEG_UNKNOWN:
+ break;
+
+ case SEG_DIFFERENCE:
+ case SEG_PASS1:
+ /*
+ * Major bug. We can't handle the case of a
+ * SEG_DIFFERENCE expression in a VIT_OPCODE_SYNTHETIC
+ * variable-length instruction.
+ * We don't have a frag type that is smart enough to
+ * relax a SEG_DIFFERENCE, and so we just force all
+ * SEG_DIFFERENCEs to behave like SEG_PASS1s.
+ * Clearly, if there is a demand we can invent a new or
+ * modified frag type and then coding up a frag for this
+ * case will be easy. SEG_DIFFERENCE was invented for the
+ * .words after a CASE opcode, and was never intended for
+ * instruction operands.
+ */
+ need_pass_2 = 1;
+ as_warn("Can't relocate expression");
+ break;
+
+ case SEG_BIG:
+ /* Preserve the bits. */
+ if (expP->X_add_number > 0) {
+ bignum_copy(generic_bignum, expP->X_add_number,
+ floatP->low, SIZE_OF_LARGE_NUMBER);
+ } else {
+ know(expP->X_add_number < 0);
+ flonum_copy (&generic_floating_point_number,
+ floatP);
+ if (strchr("s i", operandP->vop_short)) { /* Could possibly become S^# */
+ flonum_gen2vax(-expP->X_add_number, floatP, literal_float);
+ switch (-expP->X_add_number) {
+ case 'f':
+ can_be_short =
+ (literal_float[0] & 0xFC0F) == 0x4000
+ && literal_float[1] == 0;
+ break;
+
+ case 'd':
+ can_be_short =
+ (literal_float[0] & 0xFC0F) == 0x4000
+ && literal_float[1] == 0
+ && literal_float[2] == 0
+ && literal_float[3] == 0;
+ break;
+
+ case 'g':
+ can_be_short =
+ (literal_float[0] & 0xFF81) == 0x4000
+ && literal_float[1] == 0
+ && literal_float[2] == 0
+ && literal_float[3] == 0;
+ break;
+
+ case 'h':
+ can_be_short = ((literal_float[0] & 0xFFF8) == 0x4000
+ && (literal_float[1] & 0xE000) == 0
+ && literal_float[2] == 0
+ && literal_float[3] == 0
+ && literal_float[4] == 0
+ && literal_float[5] == 0
+ && literal_float[6] == 0
+ && literal_float[7] == 0);
+ break;
+
+ default:
+ BAD_CASE(-expP->X_add_number);
+ break;
+ } /* switch (float type) */
+ } /* if (could want to become S^#...) */
+ } /* bignum or flonum ? */
+
+ if (operandP->vop_short == 's'
+ || operandP->vop_short == 'i'
+ || (operandP->vop_short == ' '
+ && operandP->vop_reg == 0xF
+ && (operandP->vop_mode & 0xE) == 0x8)) {
+ /* Saw a '#'. */
+ if (operandP->vop_short == ' ') { /* We must chose S^ or I^. */
+ if (expP->X_add_number > 0) { /* Bignum: Short literal impossible. */
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC. */
+ } else { /* Flonum: Try to do it. */
+ if (can_be_short)
+ {
+ operandP->vop_short = 's';
+ operandP->vop_mode = 0;
+ operandP->vop_ndx = -1;
+ operandP->vop_reg = -1;
+ /* JF hope this is the right thing */
+ expP->X_seg = SEG_ABSOLUTE;
+ } else {
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC */
+ }
+ } /* bignum or flonum ? */
+ } /* if #, but no S^ or I^ seen. */
+ /* No more ' ' case: either 's' or 'i'. */
+ if (operandP->vop_short == 's') {
+ /* Wants to be a short literal. */
+ if (expP->X_add_number > 0) {
+ as_warn ("Bignum not permitted in short literal. Immediate mode assumed.");
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC. */
+ } else {
+ if (!can_be_short) {
+ as_warn ("Can't do flonum short literal: immediate mode used.");
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF; /* VAX PC. */
+ } else { /* Encode short literal now. */
+ int temp = 0;
+
+ switch (-expP->X_add_number) {
+ case 'f':
+ case 'd':
+ temp = literal_float[0] >> 4;
+ break;
+
+ case 'g':
+ temp = literal_float[0] >> 1;
+ break;
+
+ case 'h':
+ temp = ((literal_float[0] << 3) & 070)
+ | ((literal_float[1] >> 13) & 07);
+ break;
+
+ default:
+ BAD_CASE(-expP->X_add_number);
+ break;
+ }
+
+ floatP->low[0] = temp & 077;
+ floatP->low[1] = 0;
+ } /* if can be short literal float */
+ } /* flonum or bignum ? */
+ } else { /* I^# seen: set it up if float. */
+ if (expP->X_add_number < 0) {
+ memcpy(floatP->low, literal_float, sizeof(literal_float));
+ }
+ } /* if S^# seen. */
+ } else {
+ as_warn ("A bignum/flonum may not be a displacement: 0x%x used",
+ expP->X_add_number = 0x80000000);
+ /* Chosen so luser gets the most offset bits to patch later. */
+ }
+ expP->X_add_number = floatP->low[0]
+ | ((LITTLENUM_MASK & (floatP->low[1])) << LITTLENUM_NUMBER_OF_BITS);
+ /*
+ * For the SEG_BIG case we have:
+ * If vop_short == 's' then a short floating literal is in the
+ * lowest 6 bits of floatP->low [0], which is
+ * big_operand_bits [---] [0].
+ * If vop_short == 'i' then the appropriate number of elements
+ * of big_operand_bits [---] [...] are set up with the correct
+ * bits.
+ * Also, just in case width is byte word or long, we copy the lowest
+ * 32 bits of the number to X_add_number.
+ */
+ break;
+
+ default:
+ BAD_CASE (to_seg);
+ break;
+ }
+ if (input_line_pointer != operandP->vop_expr_end + 1) {
+ as_warn ("Junk at end of expression \"%s\"", input_line_pointer);
+ goofed = 1;
+ }
+ operandP->vop_expr_end[1] = c_save;
+ }
+ } /* for (each operand) */
+
+ input_line_pointer = save_input_line_pointer;
+
+ if (need_pass_2 || goofed) {
+ return;
+ }
+
+
+ /* Emit op-code. */
+ /* Remember where it is, in case we want to modify the op-code later. */
+ opcode_low_byteP = frag_more (v.vit_opcode_nbytes);
+ memcpy(opcode_low_byteP, v.vit_opcode, v.vit_opcode_nbytes);
+ opcode_as_number = md_chars_to_number (opcode_as_chars = v.vit_opcode, 4);
+ for (operandP = v.vit_operand,
+ expP = exp_of_operand,
+ floatP = float_operand,
+ end_operandP = v.vit_operand + v.vit_operands;
+
+ operandP < end_operandP;
+
+ operandP++,
+ floatP++,
+ expP++) { /* for each operand */
+ if (operandP->vop_ndx >= 0) {
+ /* indexed addressing byte */
+ /* Legality of indexed mode already checked: it is OK */
+ FRAG_APPEND_1_CHAR (0x40 + operandP->vop_ndx);
+ } /* if (vop_ndx >= 0) */
+
+ /* Here to make main operand frag(s). */
+ this_add_number = expP->X_add_number;
+ this_add_symbol = expP->X_add_symbol;
+ this_subtract_symbol = expP->X_subtract_symbol;
+ to_seg = expP->X_seg;
+ is_undefined = (to_seg == SEG_UNKNOWN);
+ know(to_seg == SEG_UNKNOWN
+ || to_seg == SEG_ABSOLUTE
+ || to_seg == SEG_DATA
+ || to_seg == SEG_TEXT
+ || to_seg == SEG_BSS
+ || to_seg == SEG_BIG);
+ at = operandP->vop_mode & 1;
+ length = (operandP->vop_short == 'b'
+ ? 1 : (operandP->vop_short == 'w'
+ ? 2 : (operandP->vop_short == 'l'
+ ? 4 : 0)));
+ nbytes = operandP->vop_nbytes;
+ if (operandP->vop_access == 'b') {
+ if (to_seg == now_seg || is_undefined) {
+ /* If is_undefined, then it might BECOME now_seg. */
+ if (nbytes) {
+ p = frag_more(nbytes);
+ fix_new(frag_now, p - frag_now->fr_literal, nbytes,
+ this_add_symbol, 0, this_add_number, 1, NO_RELOC);
+ } else { /* to_seg == now_seg || to_seg == SEG_UNKNOWN */
+ /* nbytes == 0 */
+ length_code = is_undefined ? STATE_UNDF : STATE_BYTE;
+ if (opcode_as_number & VIT_OPCODE_SPECIAL) {
+ if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) {
+ /* br or jsb */
+ frag_var(rs_machine_dependent, 5, 1,
+ ENCODE_RELAX (STATE_ALWAYS_BRANCH, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ } else {
+ if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) {
+ length_code = STATE_WORD;
+ /* JF: There is no state_byte for this one! */
+ frag_var(rs_machine_dependent, 10, 2,
+ ENCODE_RELAX (STATE_COMPLEX_BRANCH, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ } else {
+ know(operandP->vop_width == VAX_WIDTH_BYTE_JUMP);
+ frag_var(rs_machine_dependent, 9, 1,
+ ENCODE_RELAX (STATE_COMPLEX_HOP, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ }
+ }
+ } else {
+ know(operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP);
+ frag_var(rs_machine_dependent, 7, 1,
+ ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, length_code),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ }
+ }
+ } else { /* to_seg != now_seg && to_seg != SEG_UNKNOWN */
+ /*
+ * --- SEG FLOAT MAY APPEAR HERE ----
+ */
+ if (to_seg == SEG_ABSOLUTE) {
+ if (nbytes) {
+ know(!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
+ p = frag_more (nbytes);
+ /* Conventional relocation. */
+ fix_new(frag_now, p - frag_now->fr_literal,
+ nbytes, &abs_symbol, 0, this_add_number, 1, NO_RELOC);
+ } else {
+ know(opcode_as_number & VIT_OPCODE_SYNTHETIC);
+ if (opcode_as_number & VIT_OPCODE_SPECIAL) {
+ if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) {
+ /* br or jsb */
+ *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG;
+ know(opcode_as_chars[1] == 0);
+ p = frag_more (5);
+ p[0] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars(p + 1, this_add_number, 4);
+ /* Now (eg) JMP @#foo or JSB @#foo. */
+ } else {
+ if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) {
+ p = frag_more (10);
+ p[0] = 2;
+ p[1] = 0;
+ p[2] = VAX_BRB;
+ p[3] = 6;
+ p[4] = VAX_JMP;
+ p[5] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars(p + 6, this_add_number, 4);
+ /*
+ * Now (eg) ACBx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
+ } else {
+ know(operandP->vop_width == VAX_WIDTH_BYTE_JUMP);
+ p = frag_more (9);
+ p[0] = 2;
+ p[1] = VAX_BRB;
+ p[2] = 6;
+ p[3] = VAX_JMP;
+ p[4] = VAX_PC_RELATIVE_MODE + 1; /* @#... */
+ md_number_to_chars(p + 5, this_add_number, 4);
+ /*
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP @#foo
+ * 2:
+ */
+ }
+ }
+ } else {
+ /* b<cond> */
+ *opcode_low_byteP ^= 1;
+ /* To reverse the condition in a VAX branch, complement the lowest order
+ bit. */
+ p = frag_more (7);
+ p[0] = 6;
+ p[1] = VAX_JMP;
+ p[2] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars(p + 3, this_add_number, 4);
+ /*
+ * Now (eg) BLEQ 1f
+ * JMP @#foo
+ * 1:
+ */
+ }
+ }
+ } else { /* to_seg != now_seg && to_seg != SEG_UNKNOWN && to_Seg != SEG_ABSOLUTE */
+ if (nbytes > 0) {
+ /* Pc-relative. Conventional relocation. */
+ know(!(opcode_as_number & VIT_OPCODE_SYNTHETIC));
+ p = frag_more (nbytes);
+ fix_new(frag_now, p - frag_now->fr_literal,
+ nbytes, &abs_symbol, 0, this_add_number, 1, NO_RELOC);
+ } else {
+ know(opcode_as_number & VIT_OPCODE_SYNTHETIC);
+ if (opcode_as_number & VIT_OPCODE_SPECIAL) {
+ if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP) {
+ /* br or jsb */
+ know(opcode_as_chars[1] == 0);
+ *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG;
+ p = frag_more (5);
+ p[0] = VAX_PC_RELATIVE_MODE;
+ fix_new(frag_now,
+ p + 1 - frag_now->fr_literal, 4,
+ this_add_symbol, 0,
+ this_add_number, 1, NO_RELOC);
+ /* Now eg JMP foo or JSB foo. */
+ } else {
+ if (operandP->vop_width == VAX_WIDTH_WORD_JUMP) {
+ p = frag_more (10);
+ p[0] = 0;
+ p[1] = 2;
+ p[2] = VAX_BRB;
+ p[3] = 6;
+ p[4] = VAX_JMP;
+ p[5] = VAX_PC_RELATIVE_MODE;
+ fix_new(frag_now,
+ p + 6 - frag_now->fr_literal, 4,
+ this_add_symbol, 0,
+ this_add_number, 1, NO_RELOC);
+ /*
+ * Now (eg) ACBx 1f
+ * BRB 2f
+ * 1: JMP foo
+ * 2:
+ */
+ } else {
+ know(operandP->vop_width == VAX_WIDTH_BYTE_JUMP);
+ p = frag_more (10);
+ p[0] = 2;
+ p[1] = VAX_BRB;
+ p[2] = 6;
+ p[3] = VAX_JMP;
+ p[4] = VAX_PC_RELATIVE_MODE;
+ fix_new(frag_now,
+ p + 5 - frag_now->fr_literal,
+ 4, this_add_symbol, 0,
+ this_add_number, 1, NO_RELOC);
+ /*
+ * Now (eg) xOBxxx 1f
+ * BRB 2f
+ * 1: JMP foo
+ * 2:
+ */
+ }
+ }
+ } else {
+ know(operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP);
+ *opcode_low_byteP ^= 1; /* Reverse branch condition. */
+ p = frag_more (7);
+ p[0] = 6;
+ p[1] = VAX_JMP;
+ p[2] = VAX_PC_RELATIVE_MODE;
+ fix_new(frag_now, p + 3 - frag_now->fr_literal,
+ 4, this_add_symbol, 0,
+ this_add_number, 1, NO_RELOC);
+ }
+ }
+ }
+ }
+ } else {
+ know(operandP->vop_access != 'b'); /* So it is ordinary operand. */
+ know(operandP->vop_access != ' '); /* ' ' target-independent: elsewhere. */
+ know(operandP->vop_access == 'a'
+ || operandP->vop_access == 'm'
+ || operandP->vop_access == 'r'
+ || operandP->vop_access == 'v'
+ || operandP->vop_access == 'w');
+ if (operandP->vop_short == 's') {
+ if (to_seg == SEG_ABSOLUTE) {
+ if (this_add_number < 0 || this_add_number >= 64) {
+ as_warn("Short literal overflow(%d.), immediate mode assumed.", this_add_number);
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF;
+ }
+ } else {
+ as_warn ("Forced short literal to immediate mode. now_seg=%s to_seg=%s",
+ segment_name(now_seg), segment_name(to_seg));
+ operandP->vop_short = 'i';
+ operandP->vop_mode = 8;
+ operandP->vop_reg = 0xF;
+ }
+ }
+ if (operandP->vop_reg >= 0 && (operandP->vop_mode < 8
+ || (operandP->vop_reg != 0xF && operandP->vop_mode < 10))) {
+ /* One byte operand. */
+ know(operandP->vop_mode > 3);
+ FRAG_APPEND_1_CHAR (operandP->vop_mode << 4 | operandP->vop_reg);
+ /* All 1-bytes except S^# happen here. */
+ } else { /* {@}{q^}foo{(Rn)} or S^#foo */
+ if (operandP->vop_reg == -1 && operandP->vop_short != 's') {
+ /* "{@}{q^}foo" */
+ if (to_seg == now_seg) {
+ if (length == 0) {
+ know(operandP->vop_short == ' ');
+ p = frag_var(rs_machine_dependent, 10, 2,
+ ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE),
+ this_add_symbol, this_add_number,
+ opcode_low_byteP);
+ know(operandP->vop_mode == 10 + at);
+ *p = at << 4;
+ /* At is the only context we need to carry to */
+ /* other side of relax() process. */
+ /* Must be in the correct bit position of VAX */
+ /* operand spec. byte. */
+ } else {
+ know(length);
+ know(operandP->vop_short != ' ');
+ p = frag_more (length + 1);
+ /* JF is this array stuff really going to work? */
+ p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
+ fix_new(frag_now, p + 1 - frag_now->fr_literal,
+ length, this_add_symbol, 0,
+ this_add_number, 1, NO_RELOC);
+ }
+ } else { /* to_seg != now_seg */
+ if (this_add_symbol == NULL) {
+ know(to_seg == SEG_ABSOLUTE);
+ /* Do @#foo: simpler relocation than foo-.(pc) anyway. */
+ p = frag_more (5);
+ p[0] = VAX_ABSOLUTE_MODE; /* @#... */
+ md_number_to_chars(p + 1, this_add_number, 4);
+ if (length && length != 4)
+ {
+ as_warn ("Length specification ignored. Address mode 9F used");
+ }
+ } else {
+ /* {@}{q^}other_seg */
+ know((length == 0 && operandP->vop_short == ' ')
+ ||(length > 0 && operandP->vop_short != ' '));
+ if (is_undefined) {
+ /*
+ * We have a SEG_UNKNOWN symbol. It might
+ * turn out to be in the same segment as
+ * the instruction, permitting relaxation.
+ */
+ p = frag_var(rs_machine_dependent, 5, 2,
+ ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),
+ this_add_symbol, this_add_number,
+ 0);
+ p[0] = at << 4;
+ } else {
+ if (length == 0) {
+ know(operandP->vop_short == ' ');
+ length = 4; /* Longest possible. */
+ }
+ p = frag_more (length + 1);
+ p[0] = 0xF | ((at + "?\12\14?\16"[length]) << 4);
+ md_number_to_chars(p + 1, this_add_number, length);
+ fix_new(frag_now,
+ p + 1 - frag_now->fr_literal,
+ length, this_add_symbol, 0,
+ this_add_number, 1, NO_RELOC);
+ }
+ }
+ }
+ } else { /* {@}{q^}foo(Rn) or S^# or I^# or # */
+ if (operandP->vop_mode < 0xA) { /* # or S^# or I^# */
+ /* know( (length == 0 && operandP->vop_short == ' ')
+ || (length > 0 && operandP->vop_short != ' ')); */
+ if (length == 0
+ && to_seg == SEG_ABSOLUTE
+ && operandP->vop_mode == 8 /* No '@'. */
+ && this_add_number < 64
+ && this_add_number >= 0) {
+ operandP->vop_short = 's';
+ }
+ if (operandP->vop_short == 's') {
+ FRAG_APPEND_1_CHAR (this_add_number);
+ } else { /* I^#... */
+ know(nbytes);
+ p = frag_more (nbytes + 1);
+ know(operandP->vop_reg == 0xF);
+ p[0] = (operandP->vop_mode << 4) | 0xF;
+ if (to_seg == SEG_ABSOLUTE) {
+ /*
+ * If nbytes > 4, then we are scrod. We don't know if the
+ * high order bytes are to be 0xFF or 0x00.
+ * BSD4.2 & RMS say use 0x00. OK --- but this
+ * assembler needs ANOTHER rewrite to
+ * cope properly with this bug.
+ */
+ md_number_to_chars(p + 1, this_add_number, min (4, nbytes));
+ if (nbytes > 4)
+ {
+ memset(p + 5, '\0', nbytes - 4);
+ }
+ } else {
+ if (to_seg == SEG_BIG) {
+ /*
+ * Problem here is to get the bytes in the right order.
+ * We stored our constant as LITTLENUMs, not bytes.
+ */
+ LITTLENUM_TYPE *lP;
+
+ lP = floatP->low;
+ if (nbytes & 1) {
+ know(nbytes == 1);
+ p[1] = *lP;
+ } else {
+ for (p++; nbytes; nbytes -= 2, p += 2, lP++)
+ {
+ md_number_to_chars(p, *lP, 2);
+ }
+ }
+ } else {
+ fix_new(frag_now, p + 1 - frag_now->fr_literal,
+ nbytes, this_add_symbol, 0,
+ this_add_number, 0, NO_RELOC);
+ }
+ }
+ }
+ } else { /* {@}{q^}foo(Rn) */
+ know((length == 0 && operandP->vop_short == ' ')
+ ||(length > 0 && operandP->vop_short != ' '));
+ if (length == 0) {
+ if (to_seg == SEG_ABSOLUTE) {
+ register long test;
+
+ test = this_add_number;
+
+ if (test < 0)
+ test = ~test;
+
+ length = test & 0xffff8000 ? 4
+ : test & 0xffffff80 ? 2
+ : 1;
+ } else {
+ length = 4;
+ }
+ }
+ p = frag_more (1 + length);
+ know(operandP->vop_reg >= 0);
+ p[0] = operandP->vop_reg
+ | ((at | "?\12\14?\16"[length]) << 4);
+ if (to_seg == SEG_ABSOLUTE) {
+ md_number_to_chars(p + 1, this_add_number, length);
+ } else {
+ fix_new(frag_now, p + 1 - frag_now->fr_literal,
+ length, this_add_symbol, 0,
+ this_add_number, 0, NO_RELOC);
+ }
+ }
+ }
+ } /* if (single-byte-operand) */
+ }
+ } /* for (operandP) */
+} /* vax_assemble() */
+
+/*
+ * md_estimate_size_before_relax()
+ *
+ * Called just before relax().
+ * Any symbol that is now undefined will not become defined.
+ * Return the correct fr_subtype in the frag.
+ * Return the initial "guess for fr_var" to caller.
+ * The guess for fr_var is ACTUALLY the growth beyond fr_fix.
+ * Whatever we do to grow fr_fix or fr_var contributes to our returned value.
+ * Although it may not be explicit in the frag, pretend fr_var starts with a
+ * 0 value.
+ */
+int
+ md_estimate_size_before_relax (fragP, segment)
+register fragS *fragP;
+register segT segment;
+{
+ register char *p;
+ register int old_fr_fix;
+
+ old_fr_fix = fragP->fr_fix;
+ switch (fragP->fr_subtype) {
+ case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment) { /* A relaxable case. */
+ fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
+ } else {
+ p = fragP->fr_literal + old_fr_fix;
+ p[0] |= VAX_PC_RELATIVE_MODE; /* Preserve @ bit. */
+ fragP->fr_fix += 1 + 4;
+ fix_new(fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane(fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE);
+ } else {
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode ^= 1; /* Reverse sense of branch. */
+ p[0] = 6;
+ p[1] = VAX_JMP;
+ p[2] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
+ fragP->fr_fix += 1 + 1 + 1 + 4;
+ fix_new(fragP, old_fr_fix + 3, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane(fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_BRANCH, STATE_WORD);
+ } else {
+ p = fragP->fr_literal + old_fr_fix;
+ p[0] = 2;
+ p[1] = 0;
+ p[2] = VAX_BRB;
+ p[3] = 6;
+ p[4] = VAX_JMP;
+ p[5] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
+ fragP->fr_fix += 2 + 2 + 1 + 1 + 4;
+ fix_new(fragP, old_fr_fix + 6, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane(fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_COMPLEX_HOP, STATE_BYTE);
+ } else {
+ p = fragP->fr_literal + old_fr_fix;
+ p[0] = 2;
+ p[1] = VAX_BRB;
+ p[2] = 6;
+ p[3] = VAX_JMP;
+ p[4] = VAX_PC_RELATIVE_MODE; /* ...(pc) */
+ fragP->fr_fix += 1 + 2 + 1 + 1 + 4;
+ fix_new(fragP, old_fr_fix + 5, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane(fragP);
+ }
+ break;
+
+ case ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_UNDF):
+ if (S_GET_SEGMENT(fragP->fr_symbol) == segment) {
+ fragP->fr_subtype = ENCODE_RELAX (STATE_ALWAYS_BRANCH, STATE_BYTE);
+ } else {
+ p = fragP->fr_literal + old_fr_fix;
+ *fragP->fr_opcode += VAX_WIDEN_LONG;
+ p[0] = VAX_PC_RELATIVE_MODE; /* ...(PC) */
+ fragP->fr_fix += 1 + 4;
+ fix_new(fragP, old_fr_fix + 1, 4, fragP->fr_symbol, 0,
+ fragP->fr_offset, 1, NO_RELOC);
+ frag_wane(fragP);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return (fragP->fr_var + fragP->fr_fix - old_fr_fix);
+} /* md_estimate_size_before_relax() */
+
+/*
+ * md_convert_frag();
+ *
+ * Called after relax() is finished.
+ * In: Address of frag.
+ * fr_type == rs_machine_dependent.
+ * fr_subtype is what the address relaxed to.
+ *
+ * Out: Any fixSs and constants are set up.
+ * Caller will turn frag into a ".space 0".
+ */
+void
+ md_convert_frag (headers, fragP)
+object_headers *headers;
+register fragS *fragP;
+{
+ char *addressP; /* -> _var to change. */
+ char *opcodeP; /* -> opcode char(s) to change. */
+ short int length_code; /* 2=long 1=word 0=byte */
+ short int extension = 0; /* Size of relaxed address. */
+ /* Added to fr_fix: incl. ALL var chars. */
+ symbolS *symbolP;
+ long where;
+ long address_of_var;
+ /* Where, in file space, is _var of *fragP? */
+ long target_address = 0;
+ /* Where, in file space, does addr point? */
+
+ know(fragP->fr_type == rs_machine_dependent);
+ length_code = fragP->fr_subtype & 3; /* depends on ENCODE_RELAX() */
+ know(length_code >= 0 && length_code < 3);
+ where = fragP->fr_fix;
+ addressP = fragP->fr_literal + where;
+ opcodeP = fragP->fr_opcode;
+ symbolP = fragP->fr_symbol;
+ know(symbolP);
+ target_address = S_GET_VALUE(symbolP) + fragP->fr_offset;
+ address_of_var = fragP->fr_address + where;
+
+ switch (fragP->fr_subtype) {
+
+ case ENCODE_RELAX(STATE_PC_RELATIVE, STATE_BYTE):
+ know(*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ addressP[0] |= 0xAF; /* Byte displacement. */
+ addressP[1] = target_address - (address_of_var + 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX(STATE_PC_RELATIVE, STATE_WORD):
+ know(*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ addressP[0] |= 0xCF; /* Word displacement. */
+ md_number_to_chars(addressP + 1, target_address - (address_of_var + 3), 2);
+ extension = 3;
+ break;
+
+ case ENCODE_RELAX(STATE_PC_RELATIVE, STATE_LONG):
+ know(*addressP == 0 || *addressP == 0x10); /* '@' bit. */
+ addressP[0] |= 0xEF; /* Long word displacement. */
+ md_number_to_chars(addressP + 1, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX(STATE_CONDITIONAL_BRANCH, STATE_BYTE):
+ addressP[0] = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX(STATE_CONDITIONAL_BRANCH, STATE_WORD):
+ opcodeP[0] ^= 1; /* Reverse sense of test. */
+ addressP[0] = 3;
+ addressP[1] = VAX_BRB + VAX_WIDEN_WORD;
+ md_number_to_chars(addressP + 2, target_address - (address_of_var + 4), 2);
+ extension = 4;
+ break;
+
+ case ENCODE_RELAX(STATE_CONDITIONAL_BRANCH, STATE_LONG):
+ opcodeP[0] ^= 1; /* Reverse sense of test. */
+ addressP[0] = 6;
+ addressP[1] = VAX_JMP;
+ addressP[2] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars(addressP + 3, target_address, 4);
+ extension = 7;
+ break;
+
+ case ENCODE_RELAX(STATE_ALWAYS_BRANCH, STATE_BYTE):
+ addressP[0] = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX(STATE_ALWAYS_BRANCH, STATE_WORD):
+ opcodeP[0] += VAX_WIDEN_WORD; /* brb -> brw, bsbb -> bsbw */
+ md_number_to_chars(addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX(STATE_ALWAYS_BRANCH, STATE_LONG):
+ opcodeP[0] += VAX_WIDEN_LONG; /* brb -> jmp, bsbb -> jsb */
+ addressP[0] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars(addressP + 1, target_address - (address_of_var + 5), 4);
+ extension = 5;
+ break;
+
+ case ENCODE_RELAX(STATE_COMPLEX_BRANCH, STATE_WORD):
+ md_number_to_chars(addressP, target_address - (address_of_var + 2), 2);
+ extension = 2;
+ break;
+
+ case ENCODE_RELAX(STATE_COMPLEX_BRANCH, STATE_LONG):
+ addressP[0] = 2;
+ addressP[1] = 0;
+ addressP[2] = VAX_BRB;
+ addressP[3] = 6;
+ addressP[4] = VAX_JMP;
+ addressP[5] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars(addressP + 6, target_address, 4);
+ extension = 10;
+ break;
+
+ case ENCODE_RELAX(STATE_COMPLEX_HOP, STATE_BYTE):
+ addressP[0] = target_address - (address_of_var + 1);
+ extension = 1;
+ break;
+
+ case ENCODE_RELAX(STATE_COMPLEX_HOP, STATE_WORD):
+ addressP[0] = 2;
+ addressP[1] = VAX_BRB;
+ addressP[2] = 3;
+ addressP[3] = VAX_BRW;
+ md_number_to_chars(addressP + 4, target_address - (address_of_var + 6), 2);
+ extension = 6;
+ break;
+
+ case ENCODE_RELAX(STATE_COMPLEX_HOP, STATE_LONG):
+ addressP[0] = 2;
+ addressP[1] = VAX_BRB;
+ addressP[2] = 6;
+ addressP[3] = VAX_JMP;
+ addressP[4] = VAX_PC_RELATIVE_MODE;
+ md_number_to_chars(addressP + 5, target_address, 4);
+ extension = 9;
+ break;
+
+ default:
+ BAD_CASE(fragP->fr_subtype);
+ break;
+ }
+ fragP->fr_fix += extension;
+} /* md_convert_frag() */
+
+/* Translate internal format of relocation info into target format.
+
+ On vax: first 4 bytes are normal unsigned long, next three bytes
+ are symbolnum, least sig. byte first. Last byte is broken up with
+ the upper nibble as nuthin, bit 3 as extern, bits 2 & 1 as length, and
+ bit 0 as pcrel. */
+#ifdef comment
+void
+ md_ri_to_chars (the_bytes, ri)
+char *the_bytes;
+struct reloc_info_generic ri;
+{
+ /* this is easy */
+ md_number_to_chars(the_bytes, ri.r_address, sizeof (ri.r_address));
+ /* now the fun stuff */
+ the_bytes[6] = (ri.r_symbolnum >> 16) & 0x0ff;
+ the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff;
+ the_bytes[4] = ri.r_symbolnum & 0x0ff;
+ the_bytes[7] = (((ri.r_extern << 3) & 0x08) | ((ri.r_length << 1) & 0x06) |
+ ((ri.r_pcrel << 0) & 0x01)) & 0x0F;
+}
+#endif /* comment */
+
+void tc_aout_fix_to_chars(where, fixP, segment_address_in_file)
+char *where;
+fixS *fixP;
+relax_addressT segment_address_in_file;
+{
+ /*
+ * In: length of relocation (or of address) in chars: 1, 2 or 4.
+ * Out: GNU LD relocation length code: 0, 1, or 2.
+ */
+
+ static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };
+ long r_symbolnum;
+
+ know(fixP->fx_addsy != NULL);
+
+ md_number_to_chars(where,
+ fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
+ 4);
+
+ r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy)
+ ? S_GET_TYPE(fixP->fx_addsy)
+ : fixP->fx_addsy->sy_number);
+
+ where[6] = (r_symbolnum >> 16) & 0x0ff;
+ where[5] = (r_symbolnum >> 8) & 0x0ff;
+ where[4] = r_symbolnum & 0x0ff;
+ where[7] = ((((!S_IS_DEFINED(fixP->fx_addsy)) << 3) & 0x08)
+ | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06)
+ | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f));
+
+ return;
+} /* tc_aout_fix_to_chars() */
+/*
+ * BUGS, GRIPES, APOLOGIA, etc.
+ *
+ * The opcode table 'votstrs' needs to be sorted on opcode frequency.
+ * That is, AFTER we hash it with hash_...(), we want most-used opcodes
+ * to come out of the hash table faster.
+ *
+ * I am sorry to inflict
+ * yet another VAX assembler on the world, but RMS says we must
+ * do everything from scratch, to prevent pin-heads restricting
+ * this software.
+ */
+
+/*
+ * This is a vaguely modular set of routines in C to parse VAX
+ * assembly code using DEC mnemonics. It is NOT un*x specific.
+ *
+ * The idea here is that the assembler has taken care of all:
+ * labels
+ * macros
+ * listing
+ * pseudo-ops
+ * line continuation
+ * comments
+ * condensing any whitespace down to exactly one space
+ * and all we have to do is parse 1 line into a vax instruction
+ * partially formed. We will accept a line, and deliver:
+ * an error message (hopefully empty)
+ * a skeleton VAX instruction (tree structure)
+ * textual pointers to all the operand expressions
+ * a warning message that notes a silly operand (hopefully empty)
+ */
+
+/*
+ * E D I T H I S T O R Y
+ *
+ * 17may86 Dean Elsner. Bug if line ends immediately after opcode.
+ * 30apr86 Dean Elsner. New vip_op() uses arg block so change call.
+ * 6jan86 Dean Elsner. Crock vip_begin() to call vip_op_defaults().
+ * 2jan86 Dean Elsner. Invent synthetic opcodes.
+ * Widen vax_opcodeT to 32 bits. Use a bit for VIT_OPCODE_SYNTHETIC,
+ * which means this is not a real opcode, it is like a macro; it will
+ * be relax()ed into 1 or more instructions.
+ * Use another bit for VIT_OPCODE_SPECIAL if the op-code is not optimised
+ * like a regular branch instruction. Option added to vip_begin():
+ * exclude synthetic opcodes. Invent synthetic_votstrs[].
+ * 31dec85 Dean Elsner. Invent vit_opcode_nbytes.
+ * Also make vit_opcode into a char[]. We now have n-byte vax opcodes,
+ * so caller's don't have to know the difference between a 1-byte & a
+ * 2-byte op-code. Still need vax_opcodeT concept, so we know how
+ * big an object must be to hold an op.code.
+ * 30dec85 Dean Elsner. Widen typedef vax_opcodeT in "vax-inst.h"
+ * because vax opcodes may be 16 bits. Our crufty C compiler was
+ * happily initialising 8-bit vot_codes with 16-bit numbers!
+ * (Wouldn't the 'phone company like to compress data so easily!)
+ * 29dec85 Dean Elsner. New static table vax_operand_width_size[].
+ * Invented so we know hw many bytes a "I^#42" needs in its immediate
+ * operand. Revised struct vop in "vax-inst.h": explicitly include
+ * byte length of each operand, and it's letter-code datum type.
+ * 17nov85 Dean Elsner. Name Change.
+ * Due to ar(1) truncating names, we learned the hard way that
+ * "vax-inst-parse.c" -> "vax-inst-parse." dropping the "o" off
+ * the archived object name. SO... we shortened the name of this
+ * source file, and changed the makefile.
+ */
+
+static struct hash_control *op_hash = NULL; /* handle of the OPCODE hash table */
+/* NULL means any use before vip_begin() */
+/* will crash */
+
+/*
+ * In: 1 character, from "bdfghloqpw" being the data-type of an operand
+ * of a vax instruction.
+ *
+ * Out: the length of an operand of that type, in bytes.
+ * Special branch operands types "-?!" have length 0.
+ */
+
+static const short int vax_operand_width_size[256] =
+{
+
+#define _ 0
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */
+ _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */
+ _, _, 1, _, 8, _, 4, 8, 16, _, _, _, 4, _, _, 16, /* ..b.d.fgh...l..o */
+ _, 8, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, /* .q.....w........ */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _};
+#undef _
+
+/*
+ * This perversion encodes all the vax opcodes as a bunch of strings.
+ * RMS says we should build our hash-table at run-time. Hmm.
+ * Please would someone arrange these in decreasing frequency of opcode?
+ * Because of the way hash_...() works, the most frequently used opcode
+ * should be textually first and so on.
+ *
+ * Input for this table was 'vax.opcodes', awk(1)ed by 'vax.opcodes.c.awk' .
+ * So change 'vax.opcodes', then re-generate this table.
+ */
+
+#include "opcode/vax.h"
+
+/*
+ * This is a table of optional op-codes. All of them represent
+ * 'synthetic' instructions that seem popular.
+ *
+ * Here we make some pseudo op-codes. Every code has a bit set to say
+ * it is synthetic. This lets you catch them if you want to
+ * ban these opcodes. They are mnemonics for "elastic" instructions
+ * that are supposed to assemble into the fewest bytes needed to do a
+ * branch, or to do a conditional branch, or whatever.
+ *
+ * The opcode is in the usual place [low-order n*8 bits]. This means
+ * that if you mask off the bucky bits, the usual rules apply about
+ * how long the opcode is.
+ *
+ * All VAX branch displacements come at the end of the instruction.
+ * For simple branches (1-byte opcode + 1-byte displacement) the last
+ * operand is coded 'b?' where the "data type" '?' is a clue that we
+ * may reverse the sense of the branch (complement lowest order bit)
+ * and branch around a jump. This is by far the most common case.
+ * That is why the VIT_OPCODE_SYNTHETIC bit is set: it says this is
+ * a 0-byte op-code followed by 2 or more bytes of operand address.
+ *
+ * If the op-code has VIT_OPCODE_SPECIAL set, then we have a more unusual
+ * case.
+ *
+ * For JBSB & JBR the treatment is the similar, except (1) we have a 'bw'
+ * option before (2) we can directly JSB/JMP because there is no condition.
+ * These operands have 'b-' as their access/data type.
+ *
+ * That leaves a bunch of random opcodes: JACBx, JxOBxxx. In these
+ * cases, we do the same idea. JACBxxx are all marked with a 'b!'
+ * JAOBxxx & JSOBxxx are marked with a 'b:'.
+ *
+ */
+#if (VIT_OPCODE_SYNTHETIC != 0x80000000)
+You have just broken the encoding below, which assumes the sign bit
+ means 'I am an imaginary instruction'.
+#endif
+
+#if (VIT_OPCODE_SPECIAL != 0x40000000)
+You have just broken the encoding below, which assumes the 0x40 M bit means
+ 'I am not to be "optimised" the way normal branches are'.
+#endif
+
+ static const struct vot
+ synthetic_votstrs[] =
+{
+ {"jbsb", {"b-", 0xC0000010}}, /* BSD 4.2 */
+ /* jsb used already */
+ {"jbr", {"b-", 0xC0000011}}, /* BSD 4.2 */
+ {"jr", {"b-", 0xC0000011}}, /* consistent */
+ {"jneq", {"b?", 0x80000012}},
+ {"jnequ", {"b?", 0x80000012}},
+ {"jeql", {"b?", 0x80000013}},
+ {"jeqlu", {"b?", 0x80000013}},
+ {"jgtr", {"b?", 0x80000014}},
+ {"jleq", {"b?", 0x80000015}},
+ /* un-used opcodes here */
+ {"jgeq", {"b?", 0x80000018}},
+ {"jlss", {"b?", 0x80000019}},
+ {"jgtru", {"b?", 0x8000001a}},
+ {"jlequ", {"b?", 0x8000001b}},
+ {"jvc", {"b?", 0x8000001c}},
+ {"jvs", {"b?", 0x8000001d}},
+ {"jgequ", {"b?", 0x8000001e}},
+ {"jcc", {"b?", 0x8000001e}},
+ {"jlssu", {"b?", 0x8000001f}},
+ {"jcs", {"b?", 0x8000001f}},
+
+ {"jacbw", {"rwrwmwb!", 0xC000003d}},
+ {"jacbf", {"rfrfmfb!", 0xC000004f}},
+ {"jacbd", {"rdrdmdb!", 0xC000006f}},
+ {"jacbb", {"rbrbmbb!", 0xC000009d}},
+ {"jacbl", {"rlrlmlb!", 0xC00000f1}},
+ {"jacbg", {"rgrgmgb!", 0xC0004ffd}},
+ {"jacbh", {"rhrhmhb!", 0xC0006ffd}},
+
+ {"jbs", {"rlvbb?", 0x800000e0}},
+ {"jbc", {"rlvbb?", 0x800000e1}},
+ {"jbss", {"rlvbb?", 0x800000e2}},
+ {"jbcs", {"rlvbb?", 0x800000e3}},
+ {"jbsc", {"rlvbb?", 0x800000e4}},
+ {"jbcc", {"rlvbb?", 0x800000e5}},
+ {"jbssi", {"rlvbb?", 0x800000e6}},
+ {"jbcci", {"rlvbb?", 0x800000e7}},
+ {"jlbs", {"rlb?", 0x800000e8}}, /* JF changed from rlvbb? */
+ {"jlbc", {"rlb?", 0x800000e9}}, /* JF changed from rlvbb? */
+
+ {"jaoblss", {"rlmlb:", 0xC00000f2}},
+ {"jaobleq", {"rlmlb:", 0xC00000f3}},
+ {"jsobgeq", {"mlb:", 0xC00000f4}}, /* JF was rlmlb: */
+ {"jsobgtr", {"mlb:", 0xC00000f5}}, /* JF was rlmlb: */
+
+ /* CASEx has no branch addresses in our conception of it. */
+ /* You should use ".word ..." statements after the "case ...". */
+
+ {"", ""} /* empty is end sentinel */
+
+}; /* synthetic_votstrs */
+
+/*
+ * v i p _ b e g i n ( )
+ *
+ * Call me once before you decode any lines.
+ * I decode votstrs into a hash table at op_hash (which I create).
+ * I return an error text: hopefully "".
+ * If you want, I will include the 'synthetic' jXXX instructions in the
+ * instruction table.
+ * You must nominate metacharacters for eg DEC's "#", "@", "^".
+ */
+
+char *
+ vip_begin (synthetic_too, immediate, indirect, displen)
+int synthetic_too; /* 1 means include jXXX op-codes. */
+char *immediate, *indirect, *displen;
+{
+ const struct vot *vP; /* scan votstrs */
+ char *retval; /* error text */
+
+ if ((op_hash = hash_new())) {
+ retval = ""; /* OK so far */
+ for (vP = votstrs; *vP->vot_name && !*retval; vP++) {
+ retval = hash_insert(op_hash, vP->vot_name, &vP->vot_detail);
+ }
+ if (synthetic_too) {
+ for (vP = synthetic_votstrs; *vP->vot_name && !*retval; vP++) {
+ retval = hash_insert(op_hash, vP->vot_name, &vP->vot_detail);
+ }
+ }
+ } else {
+ retval = "virtual memory exceeded";
+ }
+#ifndef CONST_TABLE
+ vip_op_defaults(immediate, indirect, displen);
+#endif
+
+ return (retval);
+}
+
+
+/*
+ * v i p _ e n d ( )
+ *
+ * Call me once after you have decoded all lines.
+ * I do any cleaning-up needed.
+ *
+ * We don't have to do any cleanup ourselves: all of our operand
+ * symbol table is static, and free()ing it is naughty.
+ */
+static void vip_end () { }
+
+/*
+ * v i p ( )
+ *
+ * This converts a string into a vax instruction.
+ * The string must be a bare single instruction in dec-vax (with BSD4 frobs)
+ * format.
+ * It provides some error messages: at most one fatal error message (which
+ * stops the scan) and at most one warning message for each operand.
+ * The vax instruction is returned in exploded form, since we have no
+ * knowledge of how you parse (or evaluate) your expressions.
+ * We do however strip off and decode addressing modes and operation
+ * mnemonic.
+ *
+ * The exploded instruction is returned to a struct vit of your choice.
+ * #include "vax-inst.h" to know what a struct vit is.
+ *
+ * This function's value is a string. If it is not "" then an internal
+ * logic error was found: read this code to assign meaning to the string.
+ * No argument string should generate such an error string:
+ * it means a bug in our code, not in the user's text.
+ *
+ * You MUST have called vip_begin() once and vip_end() never before using
+ * this function.
+ */
+
+char * /* "" or bug string */
+ vip (vitP, instring)
+struct vit *vitP; /* We build an exploded instruction here. */
+char *instring; /* Text of a vax instruction: we modify. */
+{
+ register struct vot_wot *vwP; /* How to bit-encode this opcode. */
+ register char *p; /* 1/skip whitespace.2/scan vot_how */
+ register char *q; /* */
+ register char *bug; /* "" or program logic error */
+ register unsigned char count; /* counts number of operands seen */
+ register struct vop *operandp;/* scan operands in struct vit */
+ register char *alloperr; /* error over all operands */
+ register char c; /* Remember char, (we clobber it */
+ /* with '\0' temporarily). */
+ register vax_opcodeT oc; /* Op-code of this instruction. */
+
+ char *vip_op ();
+
+ bug = "";
+ if (*instring == ' ')
+ ++instring; /* Skip leading whitespace. */
+ for (p = instring; *p && *p != ' '; p++) ;; /* MUST end in end-of-string or exactly 1 space. */
+ /* Scanned up to end of operation-code. */
+ /* Operation-code is ended with whitespace. */
+ if (p - instring == 0) {
+ vitP->vit_error = "No operator";
+ count = 0;
+ memset(vitP->vit_opcode, '\0', sizeof(vitP->vit_opcode));
+ } else {
+ c = *p;
+ *p = '\0';
+ /*
+ * Here with instring pointing to what better be an op-name, and p
+ * pointing to character just past that.
+ * We trust instring points to an op-name, with no whitespace.
+ */
+ vwP = (struct vot_wot *) hash_find(op_hash, instring);
+ *p = c; /* Restore char after op-code. */
+ if (vwP == 0) {
+ vitP->vit_error = "Unknown operator";
+ count = 0;
+ memset(vitP->vit_opcode, '\0', sizeof(vitP->vit_opcode));
+ } else {
+ /*
+ * We found a match! So lets pick up as many operands as the
+ * instruction wants, and even gripe if there are too many.
+ * We expect comma to seperate each operand.
+ * We let instring track the text, while p tracks a part of the
+ * struct vot.
+ */
+ /*
+ * The lines below know about 2-byte opcodes starting FD,FE or FF.
+ * They also understand synthetic opcodes. Note:
+ * we return 32 bits of opcode, including bucky bits, BUT
+ * an opcode length is either 8 or 16 bits for vit_opcode_nbytes.
+ */
+ oc = vwP->vot_code; /* The op-code. */
+ vitP->vit_opcode_nbytes = (oc & 0xFF) >= 0xFD ? 2 : 1;
+ md_number_to_chars(vitP->vit_opcode, oc, 4);
+ count = 0; /* no operands seen yet */
+ instring = p; /* point just past operation code */
+ alloperr = "";
+ for (p = vwP->vot_how, operandp = vitP->vit_operand;
+ !*alloperr && !*bug && *p;
+ operandp++, p += 2
+ ) {
+ /*
+ * Here to parse one operand. Leave instring pointing just
+ * past any one ',' that marks the end of this operand.
+ */
+ if (!p[1])
+ bug = "p"; /* ODD(!!) number of bytes in vot_how?? */
+ else if (*instring) {
+ for (q = instring; (c = *q) && c != ','; q++)
+ ;
+ /*
+ * Q points to ',' or '\0' that ends argument. C is that
+ * character.
+ */
+ *q = 0;
+ operandp->vop_width = p[1];
+ operandp->vop_nbytes = vax_operand_width_size[p[1]];
+ operandp->vop_access = p[0];
+ bug = vip_op (instring, operandp);
+ *q = c; /* Restore input text. */
+ if (*(operandp->vop_error))
+ alloperr = "Bad operand";
+ instring = q + (c ? 1 : 0); /* next operand (if any) */
+ count++; /* won another argument, may have an operr */
+ } else
+ alloperr = "Not enough operands";
+ }
+ if (!*alloperr) {
+ if (*instring == ' ')
+ instring++; /* Skip whitespace. */
+ if (*instring)
+ alloperr = "Too many operands";
+ }
+ vitP->vit_error = alloperr;
+ }
+ }
+ vitP->vit_operands = count;
+ return (bug);
+}
+
+#ifdef test
+
+/*
+ * Test program for above.
+ */
+
+struct vit myvit; /* build an exploded vax instruction here */
+char answer[100]; /* human types a line of vax assembler here */
+char *mybug; /* "" or an internal logic diagnostic */
+int mycount; /* number of operands */
+struct vop *myvop; /* scan operands from myvit */
+int mysynth; /* 1 means want synthetic opcodes. */
+char my_immediate[200];
+char my_indirect[200];
+char my_displen[200];
+
+char *vip ();
+
+main ()
+{
+ char *p;
+ char *vip_begin ();
+
+ printf ("0 means no synthetic instructions. ");
+ printf ("Value for vip_begin? ");
+ gets (answer);
+ sscanf (answer, "%d", &mysynth);
+ printf ("Synthetic opcodes %s be included.\n", mysynth ? "will" : "will not");
+ printf ("enter immediate symbols eg enter # ");
+ gets (my_immediate);
+ printf ("enter indirect symbols eg enter @ ");
+ gets (my_indirect);
+ printf ("enter displen symbols eg enter ^ ");
+ gets (my_displen);
+ if (*(p = vip_begin (mysynth, my_immediate, my_indirect, my_displen))) {
+ error ("vip_begin=%s", p);
+ }
+ printf ("An empty input line will quit you from the vax instruction parser\n");
+ for (;;) {
+ printf ("vax instruction: ");
+ fflush (stdout);
+ gets (answer);
+ if (!*answer) {
+ break; /* out of for each input text loop */
+ }
+ mybug = vip (&myvit, answer);
+ if (*mybug) {
+ printf ("BUG:\"%s\"\n", mybug);
+ }
+ if (*myvit.vit_error) {
+ printf ("ERR:\"%s\"\n", myvit.vit_error);
+ }
+ printf ("opcode=");
+ for (mycount = myvit.vit_opcode_nbytes, p = myvit.vit_opcode;
+ mycount;
+ mycount--, p++
+ ) {
+ printf ("%02x ", *p & 0xFF);
+ }
+ printf (" operand count=%d.\n", mycount = myvit.vit_operands);
+ for (myvop = myvit.vit_operand; mycount; mycount--, myvop++) {
+ printf ("mode=%xx reg=%xx ndx=%xx len='%c'=%c%c%d. expr=\"",
+ myvop->vop_mode, myvop->vop_reg, myvop->vop_ndx,
+ myvop->vop_short, myvop->vop_access, myvop->vop_width,
+ myvop->vop_nbytes);
+ for (p = myvop->vop_expr_begin; p <= myvop->vop_expr_end; p++) {
+ putchar (*p);
+ }
+ printf ("\"\n");
+ if (*myvop->vop_error) {
+ printf (" err:\"%s\"\n", myvop->vop_error);
+ }
+ if (*myvop->vop_warn) {
+ printf (" wrn:\"%s\"\n", myvop->vop_warn);
+ }
+ }
+ }
+ vip_end ();
+ exit ();
+}
+
+#endif /* #ifdef test */
+
+/* end of vax_ins_parse.c */
+
+/* JF this used to be a separate file also */
+/* vax_reg_parse.c - convert a VAX register name to a number */
+
+/* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU. */
+
+/*
+ * v a x _ r e g _ p a r s e ( )
+ *
+ * Take 3 char.s, the last of which may be `\0` (non-existent)
+ * and return the VAX register number that they represent.
+ *
+ * Return -1 if they don't form a register name. Good names return
+ * a number from 0:15 inclusive.
+ *
+ * Case is not important in a name.
+ *
+ * Register names understood are:
+ *
+ * R0
+ * R1
+ * R2
+ * R3
+ * R4
+ * R5
+ * R6
+ * R7
+ * R8
+ * R9
+ * R10
+ * R11
+ * R12 AP
+ * R13 FP
+ * R14 SP
+ * R15 PC
+ *
+ */
+
+#include <ctype.h>
+#define AP (12)
+#define FP (13)
+#define SP (14)
+#define PC (15)
+
+int /* return -1 or 0:15 */
+ vax_reg_parse (c1, c2, c3) /* 3 chars of register name */
+char c1, c2, c3; /* c3 == 0 if 2-character reg name */
+{
+ register int retval; /* return -1:15 */
+
+ retval = -1;
+
+ if (isupper (c1))
+ c1 = tolower (c1);
+ if (isupper (c2))
+ c2 = tolower (c2);
+ if (isdigit (c2) && c1 == 'r') {
+ retval = c2 - '0';
+ if (isdigit (c3)) {
+ retval = retval * 10 + c3 - '0';
+ retval = (retval > 15) ? -1 : retval;
+ /* clamp the register value to 1 hex digit */
+ } else if (c3)
+ retval = -1; /* c3 must be '\0' or a digit */
+ } else if (c3) /* There are no three letter regs */
+ retval = -1;
+ else if (c2 == 'p') {
+ switch (c1) {
+ case 's':
+ retval = SP;
+ break;
+ case 'f':
+ retval = FP;
+ break;
+ case 'a':
+ retval = AP;
+ break;
+ default:
+ retval = -1;
+ }
+ } else if (c1 == 'p' && c2 == 'c')
+ retval = PC;
+ else
+ retval = -1;
+ return (retval);
+}
+
+/*
+ * v i p _ o p ( )
+ *
+ * Parse a vax operand in DEC assembler notation.
+ * For speed, expect a string of whitespace to be reduced to a single ' '.
+ * This is the case for GNU AS, and is easy for other DEC-compatible
+ * assemblers.
+ *
+ * Knowledge about DEC VAX assembler operand notation lives here.
+ * This doesn't even know what a register name is, except it believes
+ * all register names are 2 or 3 characters, and lets vax_reg_parse() say
+ * what number each name represents.
+ * It does, however, know that PC, SP etc are special registers so it can
+ * detect addressing modes that are silly for those registers.
+ *
+ * Where possible, it delivers 1 fatal or 1 warning message if the operand
+ * is suspect. Exactly what we test for is still evolving.
+ */
+
+/*
+ * B u g s
+ *
+ * Arg block.
+ *
+ * There were a number of 'mismatched argument type' bugs to vip_op.
+ * The most general solution is to typedef each (of many) arguments.
+ * We used instead a typedef'd argument block. This is less modular
+ * than using seperate return pointers for each result, but runs faster
+ * on most engines, and seems to keep programmers happy. It will have
+ * to be done properly if we ever want to use vip_op as a general-purpose
+ * module (it was designed to be).
+ *
+ * G^
+ *
+ * Doesn't support DEC "G^" format operands. These always take 5 bytes
+ * to express, and code as modes 8F or 9F. Reason: "G^" deprives you of
+ * optimising to (say) a "B^" if you are lucky in the way you link.
+ * When someone builds a linker smart enough to convert "G^" to "B^", "W^"
+ * whenever possible, then we should implement it.
+ * If there is some other use for "G^", feel free to code it in!
+ *
+ *
+ * speed
+ *
+ * If I nested if ()s more, I could avoid testing (*err) which would save
+ * time, space and page faults. I didn't nest all those if ()s for clarity
+ * and because I think the mode testing can be re-arranged 1st to test the
+ * commoner constructs 1st. Does anybody have statistics on this?
+ *
+ *
+ *
+ * error messages
+ *
+ * In future, we should be able to 'compose' error messages in a scratch area
+ * and give the user MUCH more informative error messages. Although this takes
+ * a little more code at run-time, it will make this module much more self-
+ * documenting. As an example of what sucks now: most error messages have
+ * hardwired into them the DEC VAX metacharacters "#^@" which are nothing like
+ * the Un*x characters "$`*", that most users will expect from this AS.
+ */
+
+/*
+ * The input is a string, ending with '\0'.
+ *
+ * We also require a 'hint' of what kind of operand is expected: so
+ * we can remind caller not to write into literals for instance.
+ *
+ * The output is a skeletal instruction.
+ *
+ * The algorithm has two parts.
+ * 1. extract the syntactic features (parse off all the @^#-()+[] mode crud);
+ * 2. express the @^#-()+[] as some parameters suited to further analysis.
+ *
+ * 2nd step is where we detect the googles of possible invalid combinations
+ * a human (or compiler) might write. Note that if we do a half-way
+ * decent assembler, we don't know how long to make (eg) displacement
+ * fields when we first meet them (because they may not have defined values).
+ * So we must wait until we know how many bits are needed for each address,
+ * then we can know both length and opcodes of instructions.
+ * For reason(s) above, we will pass to our caller a 'broken' instruction
+ * of these major components, from which our caller can generate instructions:
+ * - displacement length I^ S^ L^ B^ W^ unspecified
+ * - mode (many)
+ * - register R0-R15 or absent
+ * - index register R0-R15 or absent
+ * - expression text what we don't parse
+ * - error text(s) why we couldn't understand the operand
+ */
+
+/*
+ * To decode output of this, test errtxt. If errtxt[0] == '\0', then
+ * we had no errors that prevented parsing. Also, if we ever report
+ * an internal bug, errtxt[0] is set non-zero. So one test tells you
+ * if the other outputs are to be taken seriously.
+ */
+
+
+/* vax registers we need to know */
+/* JF #define SP (14) */
+/* JF for one big happy file #define PC (15) */
+
+/*
+ * Because this module is useful for both VMS and UN*X style assemblers
+ * and because of the variety of UN*X assemblers we must recognise
+ * the different conventions for assembler operand notation. For example
+ * VMS says "#42" for immediate mode, while most UN*X say "$42".
+ * We permit arbitrary sets of (single) characters to represent the
+ * 3 concepts that DEC writes '#', '@', '^'.
+ */
+
+/* character tests */
+#define VIP_IMMEDIATE 01 /* Character is like DEC # */
+#define VIP_INDIRECT 02 /* Char is like DEC @ */
+#define VIP_DISPLEN 04 /* Char is like DEC ^ */
+
+#define IMMEDIATEP(c) (vip_metacharacters[(c)&0xff]&VIP_IMMEDIATE)
+#define INDIRECTP(c) (vip_metacharacters[(c)&0xff]&VIP_INDIRECT)
+#define DISPLENP(c) (vip_metacharacters[(c)&0xff]&VIP_DISPLEN)
+
+/* We assume 8 bits per byte. Use vip_op_defaults() to set these up BEFORE we
+ * are ever called.
+ */
+
+#if defined(CONST_TABLE)
+#define _ 0,
+#define I VIP_IMMEDIATE,
+#define S VIP_INDIRECT,
+#define D VIP_DISPLEN,
+static const char
+ vip_metacharacters[256] = {
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/* ^@ ^A ^B ^C ^D ^E ^F ^G ^H ^I ^J ^K ^L ^M ^N ^O*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/* ^P ^Q ^R ^S ^T ^U ^V ^W ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
+ _ _ _ _ I _ _ _ _ _ S _ _ _ _ _/* sp ! " # $ % & ' ( ) * + , - . / */
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*0 1 2 3 4 5 6 7 8 9 : ; < = > ?*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*@ A B C D E F G H I J K L M N O*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*P Q R S T U V W X Y Z [ \ ] ^ _*/
+ D _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*` a b c d e f g h i j k l m n o*/
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _/*p q r s t u v w x y z { | } ~ ^?*/
+
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ };
+#undef _
+#undef I
+#undef S
+#undef D
+#else
+static char vip_metacharacters[256];
+
+/* Macro is faster under GCC; The constant table is faster yet, but only works with ASCII */
+#if 0
+static
+#ifdef __GNUC__
+ inline
+#endif
+ static void
+ vip_op_1(bit,syms)
+int bit;
+char *syms;
+{
+ unsigned char t;
+
+ while (t= *syms++)
+ vip_metacharacters[t]|=bit;
+}
+#else
+#define vip_op_1(bit,syms) { \
+ unsigned char t; \
+ char *table=vip_metacharacters; \
+ while (t= *syms++) \
+ table[t]|=bit; \
+ }
+#endif
+
+static void vip_op_defaults(immediate, indirect, displen) /* can be called any time */
+char *immediate; /* Strings of characters for each job. */
+char *indirect;
+char *displen; /* more arguments may appear in future! */
+{
+ vip_op_1 (VIP_IMMEDIATE, immediate);
+ vip_op_1 (VIP_INDIRECT, indirect);
+ vip_op_1 (VIP_DISPLEN, displen);
+
+ return;
+}
+#endif
+
+
+/*
+ * Dec defines the semantics of address modes (and values)
+ * by a two-letter code, explained here.
+ *
+ * letter 1: access type
+ *
+ * a address calculation - no data access, registers forbidden
+ * b branch displacement
+ * m read - let go of bus - write back "modify"
+ * r read
+ * v bit field address: like 'a' but registers are OK
+ * w write
+ * space no operator (eg ".long foo") [our convention]
+ *
+ * letter 2: data type (i.e. width, alignment)
+ *
+ * b byte
+ * d double precision floating point (D format)
+ * f single precision floating point (F format)
+ * g G format floating
+ * h H format floating
+ * l longword
+ * o octaword
+ * q quadword
+ * w word
+ * ? simple synthetic branch operand
+ * - unconditional synthetic JSB/JSR operand
+ * ! complex synthetic branch operand
+ *
+ * The '-?!' letter 2's are not for external consumption. They are used
+ * for various assemblers. Generally, all unknown widths are assumed 0.
+ * We don't limit your choice of width character.
+ *
+ * DEC operands are hard work to parse. For example, '@' as the first
+ * character means indirect (deferred) mode but elswhere it is a shift
+ * operator.
+ * The long-winded explanation of how this is supposed to work is
+ * cancelled. Read a DEC vax manual.
+ * We try hard not to parse anything that MIGHT be part of the expression
+ * buried in that syntax. For example if we see @...(Rn) we don't check
+ * for '-' before the '(' because mode @-(Rn) does not exist.
+ *
+ * After parsing we have:
+ *
+ * at 1 if leading '@' (or Un*x '*')
+ * len takes one value from " bilsw". eg B^ -> 'b'.
+ * hash 1 if leading '#' (or Un*x '$')
+ * expr_begin, expr_end the expression we did not parse
+ * even though we don't interpret it, we make use
+ * of its presence or absence.
+ * sign -1: -(Rn) 0: absent +1: (Rn)+
+ * paren 1 if () are around register
+ * reg major register number 0:15 -1 means absent
+ * ndx index register number 0:15 -1 means absent
+ *
+ * Again, I dare not explain it: just trace ALL the code!
+ */
+
+char * /* (code here) bug message, "" = OK */
+ /* our code bug, NOT bad assembly language */
+ vip_op (optext, vopP)
+char *optext; /* user's input string e.g.: */
+/* "@B^foo@bar(AP)[FP]:" */
+struct vop *vopP; /* In: vop_access, vop_width. */
+/* Out: _ndx, _reg, _mode, _short, _warn, */
+/* _error _expr_begin, _expr_end, _nbytes. */
+/* vop_nbytes : number of bytes in a datum. */
+{
+ char *p; /* track operand text forward */
+ char *q; /* track operand text backward */
+ int at; /* 1 if leading '@' ('*') seen */
+ char len; /* one of " bilsw" */
+ int hash; /* 1 if leading '#' ('$') seen */
+ int sign = 0; /* -1, 0 or +1 */
+ int paren = 0; /* 1 if () surround register */
+ int reg = 0; /* register number, -1:absent */
+ int ndx = 0; /* index register number -1:absent */
+ char *bug; /* report any logic error in here, "" == OK */
+ char *err; /* report illegal operand, "" == OK */
+ /* " " is a FAKE error: means we won */
+ /* ANY err that begins with ' ' is a fake. */
+ /* " " is converted to "" before return */
+ char *wrn; /* warn about weird modes pf address */
+ char *oldq = NULL; /* preserve q in case we backup */
+ int mode = 0; /* build up 4-bit operand mode here */
+ /* note: index mode is in ndx, this is */
+ /* the major mode of operand address */
+ /*
+ * Notice how we move wrong-arg-type bugs INSIDE this module: if we
+ * get the types wrong below, we lose at compile time rather than at
+ * lint or run time.
+ */
+ char access; /* vop_access. */
+ char width; /* vop_width. */
+
+ int vax_reg_parse (); /* returns 0:15 or -1 if not a register */
+
+ access = vopP->vop_access;
+ width = vopP->vop_width;
+ bug = /* none of our code bugs (yet) */
+ err = /* no user text errors */
+ wrn = ""; /* no warnings even */
+
+ p = optext;
+
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ p++; /* skip over whitespace */
+
+ if (at = INDIRECTP (*p)) { /* 1 if *p == '@'(or '*' for Un*x) */
+ p++; /* at is determined */
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ p++; /* skip over whitespace */
+ }
+
+ /*
+ * This code is subtle. It tries to detect all legal (letter)'^'
+ * but it doesn't waste time explicitly testing for premature '\0' because
+ * this case is rejected as a mismatch against either (letter) or '^'.
+ */
+ {
+ register char c;
+
+ c = *p;
+ if (isupper (c))
+ c = tolower (c);
+ if (DISPLENP (p[1]) && strchr ("bilws", len = c))
+ p += 2; /* skip (letter) '^' */
+ else /* no (letter) '^' seen */
+ len = ' '; /* len is determined */
+ }
+
+ if (*p == ' ') /* Expect all whitespace reduced to ' '. */
+ p++; /* skip over whitespace */
+
+ if (hash = IMMEDIATEP (*p)) /* 1 if *p == '#' ('$' for Un*x) */
+ p++; /* hash is determined */
+
+ /*
+ * p points to what may be the beginning of an expression.
+ * We have peeled off the front all that is peelable.
+ * We know at, len, hash.
+ *
+ * Lets point q at the end of the text and parse that (backwards).
+ */
+
+ for (q = p; *q; q++)
+ ;
+ q--; /* now q points at last char of text */
+
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ q--;
+ /* reverse over whitespace, but don't */
+ /* run back over *p */
+
+ /*
+ * As a matter of policy here, we look for [Rn], although both Rn and S^#
+ * forbid [Rn]. This is because it is easy, and because only a sick
+ * cyborg would have [...] trailing an expression in a VAX-like assembler.
+ * A meticulous parser would first check for Rn followed by '(' or '['
+ * and not parse a trailing ']' if it found another. We just ban expressions
+ * ending in ']'.
+ */
+ if (*q == ']') {
+ while (q >= p && *q != '[')
+ q--;
+ /* either q<p or we got matching '[' */
+ if (q < p)
+ err = "no '[' to match ']'";
+ else {
+ /*
+ * Confusers like "[]" will eventually lose with a bad register
+ * name error. So again we don't need to check for early '\0'.
+ */
+ if (q[3] == ']')
+ ndx = vax_reg_parse (q[1], q[2], 0);
+ else if (q[4] == ']')
+ ndx = vax_reg_parse (q[1], q[2], q[3]);
+ else
+ ndx = -1;
+ /*
+ * Since we saw a ']' we will demand a register name in the [].
+ * If luser hasn't given us one: be rude.
+ */
+ if (ndx < 0)
+ err = "bad register in []";
+ else if (ndx == PC)
+ err = "[PC] index banned";
+ else
+ q--; /* point q just before "[...]" */
+ }
+ } else
+ ndx = -1; /* no ']', so no iNDeX register */
+
+ /*
+ * If err = "..." then we lost: run away.
+ * Otherwise ndx == -1 if there was no "[...]".
+ * Otherwise, ndx is index register number, and q points before "[...]".
+ */
+
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ q--;
+ /* reverse over whitespace, but don't */
+ /* run back over *p */
+ if (!*err) {
+ sign = 0; /* no ()+ or -() seen yet */
+
+ if (q > p + 3 && *q == '+' && q[-1] == ')') {
+ sign = 1; /* we saw a ")+" */
+ q--; /* q points to ')' */
+ }
+
+ if (*q == ')' && q > p + 2) {
+ paren = 1; /* assume we have "(...)" */
+ while (q >= p && *q != '(')
+ q--;
+ /* either q<p or we got matching '(' */
+ if (q < p)
+ err = "no '(' to match ')'";
+ else {
+ /*
+ * Confusers like "()" will eventually lose with a bad register
+ * name error. So again we don't need to check for early '\0'.
+ */
+ if (q[3] == ')')
+ reg = vax_reg_parse (q[1], q[2], 0);
+ else if (q[4] == ')')
+ reg = vax_reg_parse (q[1], q[2], q[3]);
+ else
+ reg = -1;
+ /*
+ * Since we saw a ')' we will demand a register name in the ')'.
+ * This is nasty: why can't our hypothetical assembler permit
+ * parenthesised expressions? BECAUSE I AM LAZY! That is why.
+ * Abuse luser if we didn't spy a register name.
+ */
+ if (reg < 0) {
+ /* JF allow parenthasized expressions. I hope this works */
+ paren = 0;
+ while (*q != ')')
+ q++;
+ /* err = "unknown register in ()"; */
+ } else
+ q--; /* point just before '(' of "(...)" */
+ /*
+ * If err == "..." then we lost. Run away.
+ * Otherwise if reg >= 0 then we saw (Rn).
+ */
+ }
+ /*
+ * If err == "..." then we lost.
+ * Otherwise paren == 1 and reg = register in "()".
+ */
+ } else
+ paren = 0;
+ /*
+ * If err == "..." then we lost.
+ * Otherwise, q points just before "(Rn)", if any.
+ * If there was a "(...)" then paren == 1, and reg is the register.
+ */
+
+ /*
+ * We should only seek '-' of "-(...)" if:
+ * we saw "(...)" paren == 1
+ * we have no errors so far ! *err
+ * we did not see '+' of "(...)+" sign < 1
+ * We don't check len. We want a specific error message later if
+ * user tries "x^...-(Rn)". This is a feature not a bug.
+ */
+ if (!*err) {
+ if (paren && sign < 1)/* !sign is adequate test */ {
+ if (*q == '-') {
+ sign = -1;
+ q--;
+ }
+ }
+ /*
+ * We have back-tracked over most
+ * of the crud at the end of an operand.
+ * Unless err, we know: sign, paren. If paren, we know reg.
+ * The last case is of an expression "Rn".
+ * This is worth hunting for if !err, !paren.
+ * We wouldn't be here if err.
+ * We remember to save q, in case we didn't want "Rn" anyway.
+ */
+ if (!paren) {
+ if (*q == ' ' && q >= p) /* Expect all whitespace reduced to ' '. */
+ q--;
+ /* reverse over whitespace, but don't */
+ /* run back over *p */
+ if (q > p && q < p + 3) /* room for Rn or Rnn exactly? */
+ reg = vax_reg_parse (p[0], p[1], q < p + 2 ? 0 : p[2]);
+ else
+ reg = -1; /* always comes here if no register at all */
+ /*
+ * Here with a definitive reg value.
+ */
+ if (reg >= 0) {
+ oldq = q;
+ q = p - 1;
+ }
+ }
+ }
+ }
+ /*
+ * have reg. -1:absent; else 0:15
+ */
+
+ /*
+ * We have: err, at, len, hash, ndx, sign, paren, reg.
+ * Also, any remaining expression is from *p through *q inclusive.
+ * Should there be no expression, q == p-1. So expression length = q-p+1.
+ * This completes the first part: parsing the operand text.
+ */
+
+ /*
+ * We now want to boil the data down, checking consistency on the way.
+ * We want: len, mode, reg, ndx, err, p, q, wrn, bug.
+ * We will deliver a 4-bit reg, and a 4-bit mode.
+ */
+
+ /*
+ * Case of branch operand. Different. No L^B^W^I^S^ allowed for instance.
+ *
+ * in: at ?
+ * len ?
+ * hash ?
+ * p:q ?
+ * sign ?
+ * paren ?
+ * reg ?
+ * ndx ?
+ *
+ * out: mode 0
+ * reg -1
+ * len ' '
+ * p:q whatever was input
+ * ndx -1
+ * err " " or error message, and other outputs trashed
+ */
+ /* branch operands have restricted forms */
+ if (!*err && access == 'b') {
+ if (at || hash || sign || paren || ndx >= 0 || reg >= 0 || len != ' ')
+ err = "invalid branch operand";
+ else
+ err = " ";
+ }
+
+ /* Since nobody seems to use it: comment this 'feature'(?) out for now. */
+#ifdef NEVER
+ /*
+ * Case of stand-alone operand. e.g. ".long foo"
+ *
+ * in: at ?
+ * len ?
+ * hash ?
+ * p:q ?
+ * sign ?
+ * paren ?
+ * reg ?
+ * ndx ?
+ *
+ * out: mode 0
+ * reg -1
+ * len ' '
+ * p:q whatever was input
+ * ndx -1
+ * err " " or error message, and other outputs trashed
+ */
+ if (!*err) {
+ if (access == ' ') { /* addresses have restricted forms */
+ if (at)
+ err = "address prohibits @";
+ else {
+ if (hash)
+ err = "address prohibits #";
+ else {
+ if (sign) {
+ if (sign < 0)
+ err = "address prohibits -()";
+ else
+ err = "address prohibits ()+";
+ } else {
+ if (paren)
+ err = "address prohibits ()";
+ else {
+ if (ndx >= 0)
+ err = "address prohibits []";
+ else {
+ if (reg >= 0)
+ err = "address prohibits register";
+ else {
+ if (len != ' ')
+ err = "address prohibits displacement length specifier";
+ else {
+ err = " "; /* succeed */
+ mode = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /*#Ifdef NEVER*/
+
+ /*
+ * Case of S^#.
+ *
+ * in: at 0
+ * len 's' definition
+ * hash 1 demand
+ * p:q demand not empty
+ * sign 0 by paren == 0
+ * paren 0 by "()" scan logic because "S^" seen
+ * reg -1 or nn by mistake
+ * ndx -1
+ *
+ * out: mode 0
+ * reg -1
+ * len 's'
+ * exp
+ * ndx -1
+ */
+ if (!*err && len == 's') {
+ if (!hash || paren || at || ndx >= 0)
+ err = "invalid operand of S^#";
+ else {
+ if (reg >= 0) {
+ /*
+ * SHIT! we saw S^#Rnn ! put the Rnn back in
+ * expression. KLUDGE! Use oldq so we don't
+ * need to know exact length of reg name.
+ */
+ q = oldq;
+ reg = 0;
+ }
+ /*
+ * We have all the expression we will ever get.
+ */
+ if (p > q)
+ err = "S^# needs expression";
+ else if (access == 'r') {
+ err = " "; /* WIN! */
+ mode = 0;
+ } else
+ err = "S^# may only read-access";
+ }
+ }
+
+ /*
+ * Case of -(Rn), which is weird case.
+ *
+ * in: at 0
+ * len '
+ * hash 0
+ * p:q q<p
+ * sign -1 by definition
+ * paren 1 by definition
+ * reg present by definition
+ * ndx optional
+ *
+ * out: mode 7
+ * reg present
+ * len ' '
+ * exp "" enforce empty expression
+ * ndx optional warn if same as reg
+ */
+ if (!*err && sign < 0) {
+ if (len != ' ' || hash || at || p <= q)
+ err = "invalid operand of -()";
+ else {
+ err = " "; /* win */
+ mode = 7;
+ if (reg == PC)
+ wrn = "-(PC) unpredictable";
+ else if (reg == ndx)
+ wrn = "[]index same as -()register: unpredictable";
+ }
+ }
+
+ /*
+ * We convert "(Rn)" to "@Rn" for our convenience.
+ * (I hope this is convenient: has someone got a better way to parse this?)
+ * A side-effect of this is that "@Rn" is a valid operand.
+ */
+ if (paren && !sign && !hash && !at && len == ' ' && p > q) {
+ at = 1;
+ paren = 0;
+ }
+
+ /*
+ * Case of (Rn)+, which is slightly different.
+ *
+ * in: at
+ * len ' '
+ * hash 0
+ * p:q q<p
+ * sign +1 by definition
+ * paren 1 by definition
+ * reg present by definition
+ * ndx optional
+ *
+ * out: mode 8+@
+ * reg present
+ * len ' '
+ * exp "" enforce empty expression
+ * ndx optional warn if same as reg
+ */
+ if (!*err && sign > 0) {
+ if (len != ' ' || hash || p <= q)
+ err = "invalid operand of ()+";
+ else {
+ err = " "; /* win */
+ mode = 8 + (at ? 1 : 0);
+ if (reg == PC)
+ wrn = "(PC)+ unpredictable";
+ else if (reg == ndx)
+ wrn = "[]index same as ()+register: unpredictable";
+ }
+ }
+
+ /*
+ * Case of #, without S^.
+ *
+ * in: at
+ * len ' ' or 'i'
+ * hash 1 by definition
+ * p:q
+ * sign 0
+ * paren 0
+ * reg absent
+ * ndx optional
+ *
+ * out: mode 8+@
+ * reg PC
+ * len ' ' or 'i'
+ * exp
+ * ndx optional
+ */
+ if (!*err && hash) {
+ if (len != 'i' && len != ' ')
+ err = "# conflicts length";
+ else if (paren)
+ err = "# bars register";
+ else {
+ if (reg >= 0) {
+ /*
+ * SHIT! we saw #Rnn! Put the Rnn back into the expression.
+ * By using oldq, we don't need to know how long Rnn was.
+ * KLUDGE!
+ */
+ q = oldq;
+ reg = -1; /* no register any more */
+ }
+ err = " "; /* win */
+
+ /* JF a bugfix, I think! */
+ if (at && access == 'a')
+ vopP->vop_nbytes=4;
+
+ mode = (at ? 9 : 8);
+ reg = PC;
+ if ((access == 'm' || access == 'w') && !at)
+ wrn = "writing or modifying # is unpredictable";
+ }
+ }
+ /*
+ * If !*err, then sign == 0
+ * hash == 0
+ */
+
+ /*
+ * Case of Rn. We seperate this one because it has a few special
+ * errors the remaining modes lack.
+ *
+ * in: at optional
+ * len ' '
+ * hash 0 by program logic
+ * p:q empty
+ * sign 0 by program logic
+ * paren 0 by definition
+ * reg present by definition
+ * ndx optional
+ *
+ * out: mode 5+@
+ * reg present
+ * len ' ' enforce no length
+ * exp "" enforce empty expression
+ * ndx optional warn if same as reg
+ */
+ if (!*err && !paren && reg >= 0) {
+ if (len != ' ')
+ err = "length not needed";
+ else if (at) {
+ err = " "; /* win */
+ mode = 6; /* @Rn */
+ } else if (ndx >= 0)
+ err = "can't []index a register, because it has no address";
+ else if (access == 'a')
+ err = "a register has no address";
+ else {
+ /*
+ * Idea here is to detect from length of datum
+ * and from register number if we will touch PC.
+ * Warn if we do.
+ * vop_nbytes is number of bytes in operand.
+ * Compute highest byte affected, compare to PC0.
+ */
+ if ((vopP->vop_nbytes + reg * 4) > 60)
+ wrn = "PC part of operand unpredictable";
+ err = " "; /* win */
+ mode = 5; /* Rn */
+ }
+ }
+ /*
+ * If !*err, sign == 0
+ * hash == 0
+ * paren == 1 OR reg == -1
+ */
+
+ /*
+ * Rest of cases fit into one bunch.
+ *
+ * in: at optional
+ * len ' ' or 'b' or 'w' or 'l'
+ * hash 0 by program logic
+ * p:q expected (empty is not an error)
+ * sign 0 by program logic
+ * paren optional
+ * reg optional
+ * ndx optional
+ *
+ * out: mode 10 + @ + len
+ * reg optional
+ * len ' ' or 'b' or 'w' or 'l'
+ * exp maybe empty
+ * ndx optional warn if same as reg
+ */
+ if (!*err) {
+ err = " "; /* win (always) */
+ mode = 10 + (at ? 1 : 0);
+ switch (len) {
+ case 'l':
+ mode += 2;
+ case 'w':
+ mode += 2;
+ case ' ': /* assumed B^ until our caller changes it */
+ case 'b':
+ break;
+ }
+ }
+
+ /*
+ * here with completely specified mode
+ * len
+ * reg
+ * expression p,q
+ * ndx
+ */
+
+ if (*err == ' ')
+ err = ""; /* " " is no longer an error */
+
+ vopP->vop_mode = mode;
+ vopP->vop_reg = reg;
+ vopP->vop_short = len;
+ vopP->vop_expr_begin = p;
+ vopP->vop_expr_end = q;
+ vopP->vop_ndx = ndx;
+ vopP->vop_error = err;
+ vopP->vop_warn = wrn;
+ return (bug);
+
+} /* vip_op() */
+
+/*
+
+ Summary of vip_op outputs.
+
+ mode reg len ndx
+ (Rn) => @Rn
+ {@}Rn 5+@ n ' ' optional
+ branch operand 0 -1 ' ' -1
+ S^#foo 0 -1 's' -1
+ -(Rn) 7 n ' ' optional
+ {@}(Rn)+ 8+@ n ' ' optional
+ {@}#foo, no S^ 8+@ PC " i" optional
+ {@}{q^}{(Rn)} 10+@+q option " bwl" optional
+
+ */
+
+#ifdef TEST /* #Define to use this testbed. */
+
+/*
+ * Follows a test program for this function.
+ * We declare arrays non-local in case some of our tiny-minded machines
+ * default to small stacks. Also, helps with some debuggers.
+ */
+
+#include <stdio.h>
+
+char answer[100]; /* human types into here */
+char *p; /* */
+char *myerr;
+char *mywrn;
+char *mybug;
+char myaccess;
+char mywidth;
+char mymode;
+char myreg;
+char mylen;
+char *myleft;
+char *myright;
+char myndx;
+int my_operand_length;
+char my_immediate[200];
+char my_indirect[200];
+char my_displen[200];
+
+main ()
+{
+ char *vip_op (); /* make cc happy */
+
+ printf ("enter immediate symbols eg enter # ");
+ gets (my_immediate);
+ printf ("enter indirect symbols eg enter @ ");
+ gets (my_indirect);
+ printf ("enter displen symbols eg enter ^ ");
+ gets (my_displen);
+ vip_op_defaults (my_immediate, my_indirect, my_displen);
+ for (;;) {
+ printf ("access,width (eg 'ab' or 'wh') [empty line to quit] : ");
+ fflush (stdout);
+ gets (answer);
+ if (!answer[0])
+ exit (0);
+ myaccess = answer[0];
+ mywidth = answer[1];
+ switch (mywidth) {
+ case 'b':
+ my_operand_length = 1;
+ break;
+ case 'd':
+ my_operand_length = 8;
+ break;
+ case 'f':
+ my_operand_length = 4;
+ break;
+ case 'g':
+ my_operand_length = 16;
+ break;
+ case 'h':
+ my_operand_length = 32;
+ break;
+ case 'l':
+ my_operand_length = 4;
+ break;
+ case 'o':
+ my_operand_length = 16;
+ break;
+ case 'q':
+ my_operand_length = 8;
+ break;
+ case 'w':
+ my_operand_length = 2;
+ break;
+ case '!':
+ case '?':
+ case '-':
+ my_operand_length = 0;
+ break;
+
+ default:
+ my_operand_length = 2;
+ printf ("I dn't understand access width %c\n", mywidth);
+ break;
+ }
+ printf ("VAX assembler instruction operand: ");
+ fflush (stdout);
+ gets (answer);
+ mybug = vip_op (answer, myaccess, mywidth, my_operand_length,
+ &mymode, &myreg, &mylen, &myleft, &myright, &myndx,
+ &myerr, &mywrn);
+ if (*myerr) {
+ printf ("error: \"%s\"\n", myerr);
+ if (*mybug)
+ printf (" bug: \"%s\"\n", mybug);
+ } else {
+ if (*mywrn)
+ printf ("warning: \"%s\"\n", mywrn);
+ mumble ("mode", mymode);
+ mumble ("register", myreg);
+ mumble ("index", myndx);
+ printf ("width:'%c' ", mylen);
+ printf ("expression: \"");
+ while (myleft <= myright)
+ putchar (*myleft++);
+ printf ("\"\n");
+ }
+ }
+}
+
+mumble (text, value)
+char *text;
+int value;
+{
+ printf ("%s:", text);
+ if (value >= 0)
+ printf ("%xx", value);
+ else
+ printf ("ABSENT");
+ printf (" ");
+}
+
+#endif /* ifdef TEST */
+
+/* end: vip_op.c */
+
+const int md_short_jump_size = 3;
+const int md_long_jump_size = 6;
+const int md_reloc_size = 8; /* Size of relocation record */
+
+void
+ md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - (from_addr + 1);
+ *ptr++ = 0x31;
+ md_number_to_chars(ptr, offset, 2);
+}
+
+void
+ md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
+char *ptr;
+long from_addr, to_addr;
+fragS *frag;
+symbolS *to_symbol;
+{
+ long offset;
+
+ offset = to_addr - S_GET_VALUE(to_symbol);
+ *ptr++ = 0x17;
+ *ptr++ = 0x9F;
+ md_number_to_chars(ptr, offset, 4);
+ fix_new(frag, ptr - frag->fr_literal, 4, to_symbol, (symbolS *) 0, (long) 0, 0, NO_RELOC);
+}
+
+#ifdef OBJ_VMS
+extern char vms_name_mapping;
+#endif
+
+int
+ md_parse_option (argP, cntP, vecP)
+char **argP;
+int *cntP;
+char ***vecP;
+{
+ char *temp_name; /* name for -t or -d options */
+ char opt;
+
+ switch (**argP) {
+ case 'J':
+ /* as_warn ("I can do better than -J!"); */
+ break;
+
+ case 'S':
+ as_warn ("SYMBOL TABLE not implemented");
+ break; /* SYMBOL TABLE not implemented */
+
+ case 'T':
+ as_warn ("TOKEN TRACE not implemented");
+ break; /* TOKEN TRACE not implemented */
+
+ case 'd':
+ case 't':
+ opt= **argP;
+ if (**argP) { /* Rest of argument is filename. */
+ temp_name = *argP;
+ while (**argP)
+ (*argP)++;
+ } else if (*cntP) {
+ while (**argP)
+ (*argP)++;
+ --(*cntP);
+ temp_name = *++(*vecP);
+ **vecP = NULL; /* Remember this is not a file-name. */
+ } else {
+ as_warn ("I expected a filename after -%c.",opt);
+ temp_name = "{absent}";
+ }
+
+ if (opt == 'd')
+ as_warn ("Displacement length %s ignored!", temp_name);
+ else
+ as_warn ("I don't need or use temp. file \"%s\".", temp_name);
+ break;
+
+ case 'V':
+ as_warn ("I don't use an interpass file! -V ignored");
+ break;
+
+#ifdef OBJ_VMS
+ case '+': /* For g++ */
+ break;
+
+ case '1': /* For backward compatibility */
+ break;
+
+ case 'h': /* No hashing of mixed-case names */
+ vms_name_mapping = 0;
+ (*argP)++;
+ if (**argP) vms_name_mapping = *((*argP)++) - '0';
+ (*argP)--;
+ break;
+
+ case 'H': /* Show new symbol after hash truncation */
+ break;
+#endif
+
+ default:
+ return 0;
+
+ }
+ return 1;
+}
+
+/* We have no need to default values of symbols. */
+
+/* ARGSUSED */
+symbolS *
+ md_undefined_symbol (name)
+char *name;
+{
+ return 0;
+}
+
+/* Parse an operand that is machine-specific.
+ We just return without modifying the expression if we have nothing
+ to do. */
+
+/* ARGSUSED */
+void
+ md_operand (expressionP)
+expressionS *expressionP;
+{
+}
+
+/* Round up a section size to the appropriate boundary. */
+long
+ md_section_align (segment, size)
+segT segment;
+long size;
+{
+ return size; /* Byte alignment is fine */
+}
+
+/* Exactly what point is a PC-relative offset relative TO?
+ On the vax, they're relative to the address of the offset, plus
+ its size. (??? Is this right? FIXME-SOON) */
+long
+ md_pcrel_from (fixP)
+fixS *fixP;
+{
+ return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/* end of tc-vax.c */
diff --git a/gnu/usr.bin/as/config/tc-vax.h b/gnu/usr.bin/as/config/tc-vax.h
new file mode 100644
index 0000000..f995a6c
--- /dev/null
+++ b/gnu/usr.bin/as/config/tc-vax.h
@@ -0,0 +1,26 @@
+/*
+ * This file is tc-vax.h.
+ */
+
+#define TC_VAX 1
+
+#define LOCAL_LABELS_FB
+#define NO_LISTING
+
+ /* use this to compare against gas-1.38 */
+#ifdef OLD_GAS
+#define REVERSE_SORT_RELOCS
+#endif
+
+#define tc_aout_pre_write_hook(x) {;} /* not used */
+#define tc_crawl_symbol_chain(a) {;} /* not used */
+#define tc_headers_hook(a) {;} /* not used */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc-vax.h */
diff --git a/gnu/usr.bin/as/config/te-dpx2.h b/gnu/usr.bin/as/config/te-dpx2.h
new file mode 100644
index 0000000..5f358a2
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-dpx2.h
@@ -0,0 +1,8 @@
+/* Machine specific defines for the dpx2 machine */
+#define dpx2
+#define TC_M68K
+
+/* The magic number is not the usual MC68MAGIC. */
+#define FILE_HEADER_MAGIC MC68KBCSMAGIC
+
+/* end of te-dpx2.h */
diff --git a/gnu/usr.bin/as/config/te-generic.h b/gnu/usr.bin/as/config/te-generic.h
new file mode 100644
index 0000000..e7ec708
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-generic.h
@@ -0,0 +1,25 @@
+/*
+ * This file is te-generic.h and is intended to be a template for
+ * target environment specific header files.
+ *
+ * It is my intent that this file will evolve into a file suitable for config,
+ * compile, and copying as an aid for testing and porting. xoxorich.
+ */
+/*
+ * $FreeBSD$
+ */
+
+
+#define TE_GENERIC 1
+
+/* these define interfaces */
+#include "obj-format.h"
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of te-generic.h */
diff --git a/gnu/usr.bin/as/config/te-hpux.h b/gnu/usr.bin/as/config/te-hpux.h
new file mode 100644
index 0000000..5458df6
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-hpux.h
@@ -0,0 +1,99 @@
+/* Special version of <a.out.h> for use under hp-ux.
+ Copyright (C) 1988, 1992 Free Software Foundation, Inc.
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define TE_HPUX
+
+#define HP9000S200_ID (0x20C)
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (HP9000S200_ID)
+
+ /* hpux has "special" headers. */
+#define H_GET_HEADER_SIZE(h) (64)
+
+#include "obj-format.h"
+
+/* This stuff is from an old a.out.hpux.h. It isn't used anymore,
+ (see obj-aout.c, obj_header_append) but I'm including it here for
+ context. xoxorich. */
+
+#if comment
+
+/* The `exec' structure and overall layout must be close to HP's when
+ we are running on an HP system, otherwise we will not be able to
+ execute the resulting file. */
+
+/* Allow this file to be included twice. */
+#ifndef __GNU_EXEC_MACROS__
+
+struct exec
+{
+ unsigned short a_machtype; /* machine type */
+ unsigned short a_info; /* magic number */
+ unsigned long a_spare1;
+ unsigned long a_spare2;
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned long a_trsize; /* length of relocation info for text, in bytes */
+ unsigned long a_drsize; /* length of relocation info for data, in bytes */
+ unsigned long a_spare3; /* HP = pascal interface size */
+ unsigned long a_spare4; /* HP = symbol table size */
+ unsigned long a_spare5; /* HP = debug name table size */
+ unsigned long a_entry; /* start address */
+ unsigned long a_spare6; /* HP = source line table size */
+ unsigned long a_spare7; /* HP = value table size */
+ unsigned long a_syms; /* length of symbol table data in file, in bytes */
+ unsigned long a_spare8;
+};
+
+/* Tell a.out.gnu.h not to define `struct exec'. */
+#define __STRUCT_EXEC_OVERRIDE__
+
+#include "a.out.gnu.h"
+
+#undef N_MAGIC
+#undef N_MACHTYPE
+#undef N_FLAGS
+#undef N_SET_INFO
+#undef N_SET_MAGIC
+#undef N_SET_MACHTYPE
+#undef N_SET_FLAGS
+
+#define N_MAGIC(exec) ((exec) . a_magic)
+#define N_MACHTYPE(exec) ((exec) . a_machtype)
+#define N_SET_MAGIC(exec, magic) (((exec) . a_magic) = (magic))
+#define N_SET_MACHTYPE(exec, machtype) (((exec) . a_machtype) = (machtype))
+
+#undef N_BADMAG
+#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x)))
+
+#define _N_BADMACH(x) \
+(((N_MACHTYPE (x)) != HP9000S200_ID) && \
+ ((N_MACHTYPE (x)) != HP98x6_ID))
+
+#define HP98x6_ID 0x20A
+#define HP9000S200_ID 0x20C
+
+#undef _N_HDROFF
+#define _N_HDROFF(x) (SEGMENT_SIZE - (sizeof (struct exec)))
+
+#define SEGMENT_SIZE 0x1000
+
+#endif /* __GNU_EXEC_MACROS__ */
+
+#endif /* comment */
+
+/* end of te-hpux.h */
diff --git a/gnu/usr.bin/as/config/te-i386aix.h b/gnu/usr.bin/as/config/te-i386aix.h
new file mode 100644
index 0000000..dcadbc3
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-i386aix.h
@@ -0,0 +1,19 @@
+/*
+ * This file is te-i386aix.h and is built from pieces of code from Minh Tran-Le
+ * <TRANLE@INTELLICORP.COM> by rich@cygnus.com.
+ */
+
+#define TE_I386AIX 1
+
+#include "obj-format.h"
+
+#define KEEP_RELOC_INFO
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 79
+ * End:
+ */
+
+/* end of te-i386aix.h */
diff --git a/gnu/usr.bin/as/config/te-ic960.h b/gnu/usr.bin/as/config/te-ic960.h
new file mode 100644
index 0000000..7a9dbe7
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-ic960.h
@@ -0,0 +1,46 @@
+/* This file is twe-ic960.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file is te-ic960.h and is intended to define ic960 environment
+ * specific differences.
+ */
+
+#define TE_IC960 1
+
+/* intel uses host byte order for headers */
+#ifdef CROSS_COMPILE
+#undef CROSS_COMPILE
+#endif /* CROSS_COMPILE */
+
+#define OBJ_COFF_OMIT_OPTIONAL_HEADER
+#define LOCAL_LABEL(name) ( (name[0] == 'L') \
+ || (name[0] == '.' \
+ && (name[1] == 'C' || name[1] == 'I' || name[1] == '.')))
+#include "obj-format.h"
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of te-ic960.h */
diff --git a/gnu/usr.bin/as/config/te-sco386.h b/gnu/usr.bin/as/config/te-sco386.h
new file mode 100644
index 0000000..da8de1d
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-sco386.h
@@ -0,0 +1,7 @@
+/* Machine specific defines for the SCO Unix V.3.2 ODT */
+#define scounix
+
+/* Return true if s (a non null string pointer), points to a local variable name. */
+#define LOCAL_LABEL(n) ((n)[0] == '.' && (n)[1] == 'L')
+
+/* end of te-sco386.h */
diff --git a/gnu/usr.bin/as/config/te-sequent.h b/gnu/usr.bin/as/config/te-sequent.h
new file mode 100644
index 0000000..fbf9d9a
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-sequent.h
@@ -0,0 +1,32 @@
+/*
+ * This file is te-sequent.h and is intended to set up emulation with
+ * sequent's development tools.
+ *
+ */
+
+#define TE_SEQUENT 1
+
+ /* sequent has a "special" header. */
+#define H_GET_HEADER_SIZE(h) (128)
+
+#ifdef TC_I386
+ /* zmagic is 0x22eb */
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0x12eb)
+#endif /* TC_I386 */
+
+#ifdef TC_NS32K
+ /* zmagic is 0x10ea */
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (0x00ea)
+#endif /* TC_NS32K */
+
+/* these define interfaces */
+#include "obj-format.h"
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of te-sequent.h */
diff --git a/gnu/usr.bin/as/config/te-sun3.h b/gnu/usr.bin/as/config/te-sun3.h
new file mode 100644
index 0000000..ec4d29a
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-sun3.h
@@ -0,0 +1,49 @@
+/* te-sun3.h -- Sun-3 target environment declarations.
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This header file contains the #defines specific
+ to SUN computer SUN 3 series computers. (The only kind
+ we have around here, unfortunatly.)
+
+ Rumor has it that this file will work on the Sun-2 if the assembler
+ is called with -m68010 This is not tested. */
+
+
+/* Could also be :
+ #define S_LOCAL_NAME(s) (S_GET_NAME(s)[0] == '.' &&
+ S_GET_NAME(s)[1] == 'L' ||
+ S_GET_NAME(s)[1] == '.')
+ */
+
+/* This variable contains the value to write out at the beginning of
+ the a.out file. The 2<<16 means that this is a 68020 file instead
+ of an old-style 68000 file */
+
+#define DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE (2<<16|OMAGIC) /* Magic byte for file header */
+
+#include "obj-format.h"
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of te-sun3.h */
diff --git a/gnu/usr.bin/as/config/te-sysv32.h b/gnu/usr.bin/as/config/te-sysv32.h
new file mode 100644
index 0000000..99702fb
--- /dev/null
+++ b/gnu/usr.bin/as/config/te-sysv32.h
@@ -0,0 +1,4 @@
+/* Remove leading underscore from the gcc generated symbol names */
+#define STRIP_UNDERSCORE
+
+/* end of te-sysv32.h */
diff --git a/gnu/usr.bin/as/config/vax-inst.h b/gnu/usr.bin/as/config/vax-inst.h
new file mode 100644
index 0000000..47c5ef0
--- /dev/null
+++ b/gnu/usr.bin/as/config/vax-inst.h
@@ -0,0 +1,77 @@
+/* vax-inst.h - GNU - Part of vax.c
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This is part of vax-ins-parse.c & friends.
+ * We want to parse a vax instruction text into a tree defined here.
+ */
+
+#define VIT_MAX_OPERANDS (6) /* maximum number of operands in one */
+/* single vax instruction */
+
+struct vop /* vax instruction operand */
+{
+ short int vop_ndx; /* -1, or index register. eg 7=[R7] */
+ short int vop_reg; /* -1, or register number. eg @I^#=0xF */
+ /* Helps distinguish "abs" from "abs(PC)". */
+ short int vop_mode; /* addressing mode 4 bits. eg I^#=0x9 */
+ char vop_short; /* operand displacement length as written */
+ /* ' '=none, "bilsw"=B^I^L^S^W^. */
+ char vop_access; /* 'b'branch ' 'no-instruction 'amrvw'norm */
+ char vop_width; /* Operand width, one of "bdfghloqw" */
+ char *vop_warn; /* warning message of this operand, if any */
+ char *vop_error; /* say if operand is inappropriate */
+ char *vop_expr_begin; /* Unparsed expression, 1st char ... */
+ char *vop_expr_end; /* ... last char. */
+ unsigned char vop_nbytes; /* number of bytes in datum */
+};
+
+
+typedef long vax_opcodeT; /* For initialising array of opcodes */
+/* Some synthetic opcodes > 16 bits! */
+
+#define VIT_OPCODE_SYNTHETIC 0x80000000 /* Not real hardware instruction. */
+#define VIT_OPCODE_SPECIAL 0x40000000 /* Not normal branch optimising. */
+/* Never set without ..._SYNTHETIC */
+
+#define VAX_WIDTH_UNCONDITIONAL_JUMP '-' /* These are encoded into */
+#define VAX_WIDTH_CONDITIONAL_JUMP '?' /* vop_width when vop_access == 'b' */
+#define VAX_WIDTH_WORD_JUMP '!' /* and VIT_OPCODE_SYNTHETIC set. */
+#define VAX_WIDTH_BYTE_JUMP ':' /* */
+
+#define VAX_JMP (0x17) /* Useful for branch optimising. Jump instr*/
+#define VAX_PC_RELATIVE_MODE (0xef) /* Use it after VAX_JMP */
+#define VAX_ABSOLUTE_MODE (0x9F) /* Use as @#... */
+#define VAX_BRB (0x11) /* Canonical branch. */
+#define VAX_BRW (0x31) /* Another canonical branch */
+#define VAX_WIDEN_WORD (0x20) /* Add this to byte branch to get word br. */
+#define VAX_WIDEN_LONG (0x6) /* Add this to byte branch to get long jmp.*/
+/* Needs VAX_PC_RELATIVE_MODE byte after it*/
+
+struct vit /* vax instruction tree */
+{
+ /* vit_opcode is char[] for portability. */
+ char vit_opcode[ sizeof (vax_opcodeT) ];
+ unsigned char vit_opcode_nbytes; /* How long is _opcode? (chars) */
+ unsigned char vit_operands;/* */
+ struct vop vit_operand[VIT_MAX_OPERANDS]; /* operands */
+ char * vit_error; /* "" or error text */
+};
+
+/* end of vax-inst.h */
diff --git a/gnu/usr.bin/as/configdos.bat b/gnu/usr.bin/as/configdos.bat
new file mode 100644
index 0000000..18331cd
--- /dev/null
+++ b/gnu/usr.bin/as/configdos.bat
@@ -0,0 +1,14 @@
+@echo off
+echo Configuring GAS for H8/300
+
+copy config\ho-go32.h host.h
+copy config\tc-h8300.c targ-cpu.c
+copy config\tc-h8300.h targ-cpu.h
+copy config\te-generic.h targ-env.h
+copy config\objcoff-bfd.h obj-format.h
+copy config\objcoff-bfd.c obj-format.c
+copy config\atof-ieee.c atof-targ.c
+
+copy Makefile.dos Makefile
+
+
diff --git a/gnu/usr.bin/as/configure.in b/gnu/usr.bin/as/configure.in
new file mode 100755
index 0000000..52f4b29
--- /dev/null
+++ b/gnu/usr.bin/as/configure.in
@@ -0,0 +1,204 @@
+# This file is configure.in
+#
+# Copyright (C) 1987-1992 Free Software Foundation, Inc.
+#
+# This file is part of GAS, the GNU Assembler.
+#
+# GAS is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GAS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GAS; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#
+
+# This file is a shell script that supplies the information necessary
+# to tailor a template configure script into the configure script
+# appropriate for this directory. For more information, check any
+# existing configure script.
+
+srctrigger=as.c
+srcname="gas"
+need_bfd=
+configdirs=doc
+
+# per-host:
+
+gas_host=generic
+
+case "${host_cpu}" in
+a29k | rs6000 | vax)
+ case "${host_os}" in
+ vms*) gas_host=vms ;;
+ *) gas_host=${host_cpu} ;;
+ esac
+ ;;
+mips)
+ case "${host_os}" in
+ ultrix) gas_host=decstation ;;
+ esac
+ ;;
+i386)
+ case "${host_os}" in
+ aix*) gas_host=i386aix ;;
+ sysv4*)
+ gas_host=i386
+ host_makefile_frag=config/ho-i386v4
+ ;;
+ esac
+ ;;
+*)
+ case "${host_os}" in
+ ansi | ultrix | hpux | sysv*) gas_host=${host_os} ;;
+ *)
+ case "${host_vendor}" in
+ sun)
+ case "${host_cpu}" in
+ m68k) gas_host=sun3 ;;
+ i386) gas_host=sun386 ;;
+ sparc) gas_host=sun4 ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+esac
+
+# per-target:
+
+# assign cpu type
+environment=generic
+
+cpu_type=${target_cpu}
+
+# assign object format
+case ${target_os} in
+aix*)
+ case "${target_cpu}" in
+ i386) obj_format=coff
+ target_cpu=i386aix
+ environment=i386aix
+ ;;
+ esac
+ ;;
+
+bout*) obj_format=bout ;;
+nindy*) obj_format=bout ;;
+bsd* | sunos*)
+ obj_format=aout
+ case "${target_cpu}" in
+ m68k) environment=sun3 ;;
+ i386 | ns32k)
+ case "${target_vendor}" in
+ sequent) environment=${target_vendor} ;;
+ esac
+ esac
+ ;;
+
+ebmon-old)
+ obj_format=coff
+ need_bfd="$(unsubdir)/../bfd$(subdir)/libbfd.a"
+ target_cpu=ebmon29k
+ ;;
+
+ebmon)
+ obj_format=coffbfd
+ need_bfd="$(unsubdir)/../bfd$(subdir)/libbfd.a"
+ target_cpu=ebmon29k
+ ;;
+
+generic) obj_format=generic ;;
+
+hms)
+ obj_format=coffbfd
+ need_bfd="$(unsubdir)/../bfd$(subdir)/libbfd.a"
+ ;;
+
+hpux)
+ obj_format=aout
+ environment=hpux
+ ;;
+
+sysv32)
+ obj_format=coff
+ environment=sysv32
+ ;;
+
+vms)
+ obj_format=vms
+ ;;
+
+coff* | sysv*)
+ obj_format=coff
+
+ case ${target_vendor} in
+ bull) environment=dpx2 ;;
+ sco) environment=sco386 ;;
+ sun) environment=sun3 ;;
+ *)
+ esac
+ ;;
+vxworks)
+ case ${target_cpu} in
+ i960) obj_format=bout ;;
+ *) obj_format=aout ;;
+ esac
+ ;;
+*)
+ case ${target_vendor} in
+ aout) obj_format=aout ;;
+ bout) obj_format=bout ;;
+ coff)
+ obj_format=coff
+ case ${target_cpu} in
+ i960) environment=ic960 ;;
+ esac
+ ;;
+ sequent)
+ obj_format=aout
+ environment=sequent
+ ;;
+ *) obj_format=aout ;;
+ esac
+ ;;
+
+esac
+
+# assign floating point type
+case ${target_cpu} in
+ns32k) atof=ns32k ;;
+tahoe) atof=tahoe ;;
+vax) atof=vax ;;
+*) atof=ieee ;;
+esac
+
+# and target makefile frag
+
+target_makefile_frag=config/mt-${target_cpu}
+
+files="config/ho-${gas_host}.h config/tc-${cpu_type}.c \
+ config/tc-${cpu_type}.h config/te-${environment}.h \
+ config/obj-${obj_format}.h config/obj-${obj_format}.c \
+ config/atof-${atof}.c"
+
+links="host.h targ-cpu.c targ-cpu.h targ-env.h obj-format.h obj-format.c atof-targ.c"
+
+# post-target:
+
+if [ ${target_alias} != ${host_alias} ] ; then
+ echo INTERNAL_CFLAGS=-DCROSS_COMPILE > Makefile.tem
+ cat Makefile >> Makefile.tem
+ mv Makefile.tem Makefile
+else
+ true
+fi
+
+# end of gas/configure.in
diff --git a/gnu/usr.bin/as/debug.c b/gnu/usr.bin/as/debug.c
new file mode 100644
index 0000000..e91947f
--- /dev/null
+++ b/gnu/usr.bin/as/debug.c
@@ -0,0 +1,104 @@
+/* This file is debug.c
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Routines for debug use only. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+#include "subsegs.h"
+
+dmp_frags()
+{
+ frchainS *chp;
+ char *p;
+
+ for ( chp=frchain_root; chp; chp = chp->frch_next ){
+ switch ( chp->frch_seg ){
+ case SEG_DATA:
+ p ="Data";
+ break;
+ case SEG_TEXT:
+ p ="Text";
+ break;
+ default:
+ p ="???";
+ break;
+ }
+ printf("\nSEGMENT %s %d\n", p, chp->frch_subseg);
+ dmp_frag( chp->frch_root,"\t");
+ }
+}
+
+dmp_frag( fp, indent )
+ struct frag *fp;
+ char *indent;
+{
+ for ( ; fp; fp = fp->fr_next ){
+ printf("%sFRAGMENT @ 0x%x\n", indent, fp);
+ switch( fp->fr_type ){
+ case rs_align:
+ printf("%srs_align(%d)\n",indent, fp->fr_offset);
+ break;
+ case rs_fill:
+ printf("%srs_fill(%d)\n",indent, fp->fr_offset);
+ printf("%s", indent);
+ var_chars( fp, fp->fr_var + fp->fr_fix );
+ printf("%s\t repeated %d times,",
+ indent, fp->fr_offset);
+ printf(" fixed length if # chars == 0)\n");
+ break;
+ case rs_org:
+ printf("%srs_org(%d+sym @0x%x)\n",indent,
+ fp->fr_offset, fp->fr_symbol);
+ printf("%sfill with ",indent);
+ var_chars( fp, 1 );
+ printf("\n");
+ break;
+ case rs_machine_dependent:
+ printf("%smachine_dep\n",indent);
+ break;
+ default:
+ printf("%sunknown type\n",indent);
+ break;
+ }
+ printf("%saddr=%d(0x%x)\n",indent,fp->fr_address,fp->fr_address);
+ printf("%sfr_fix=%d\n",indent,fp->fr_fix);
+ printf("%sfr_var=%d\n",indent,fp->fr_var);
+ printf("%sfr_offset=%d\n",indent,fp->fr_offset);
+ printf("%schars @ 0x%x\n",indent,fp->fr_literal);
+ printf("\n");
+ }
+}
+
+var_chars( fp, n )
+ struct frag *fp;
+ int n;
+{
+ unsigned char *p;
+
+ for ( p=(unsigned char*)fp->fr_literal; n; n-- , p++ ){
+ printf("%02x ", *p );
+ }
+}
+
+/* end of debug.c */
diff --git a/gnu/usr.bin/as/expr.c b/gnu/usr.bin/as/expr.c
new file mode 100644
index 0000000..c46961c
--- /dev/null
+++ b/gnu/usr.bin/as/expr.c
@@ -0,0 +1,1000 @@
+/* expr.c -operands, expressions-
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This is really a branch office of as-read.c. I split it out to clearly
+ * distinguish the world of expressions from the world of statements.
+ * (It also gives smaller files to re-compile.)
+ * Here, "operand"s are of expressions, not instructions.
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <ctype.h>
+#include <string.h>
+
+#include "as.h"
+
+#include "obstack.h"
+
+#if __STDC__ == 1
+static void clean_up_expression(expressionS *expressionP);
+#else /* __STDC__ */
+static void clean_up_expression(); /* Internal. */
+#endif /* not __STDC__ */
+extern const char EXP_CHARS[]; /* JF hide MD floating pt stuff all the same place */
+extern const char FLT_CHARS[];
+
+#ifdef LOCAL_LABELS_DOLLAR
+extern int local_label_defined[];
+#endif
+
+/*
+ * Build any floating-point literal here.
+ * Also build any bignum literal here.
+ */
+
+/* LITTLENUM_TYPE generic_buffer[6]; */ /* JF this is a hack */
+/* Seems atof_machine can backscan through generic_bignum and hit whatever
+ happens to be loaded before it in memory. And its way too complicated
+ for me to fix right. Thus a hack. JF: Just make generic_bignum bigger,
+ and never write into the early words, thus they'll always be zero.
+ I hate Dean's floating-point code. Bleh.
+ */
+LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER+6];
+FLONUM_TYPE generic_floating_point_number =
+{
+ &generic_bignum[6], /* low (JF: Was 0) */
+ &generic_bignum[SIZE_OF_LARGE_NUMBER+6 - 1], /* high JF: (added +6) */
+ 0, /* leader */
+ 0, /* exponent */
+ 0 /* sign */
+ };
+/* If nonzero, we've been asked to assemble nan, +inf or -inf */
+int generic_floating_point_magic;
+
+/*
+ * Summary of operand().
+ *
+ * in: Input_line_pointer points to 1st char of operand, which may
+ * be a space.
+ *
+ * out: A expressionS. X_seg determines how to understand the rest of the
+ * expressionS.
+ * The operand may have been empty: in this case X_seg == SEG_ABSENT.
+ * Input_line_pointer->(next non-blank) char after operand.
+ *
+ */
+
+static segT
+ operand (expressionP)
+register expressionS * expressionP;
+{
+ register char c;
+ register char *name; /* points to name of symbol */
+ register symbolS * symbolP; /* Points to symbol */
+
+ extern const char hex_value[]; /* In hex_value.c */
+
+#ifdef PIC
+/* XXX */ expressionP->X_got_symbol = 0;
+#endif
+ SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
+ c = * input_line_pointer ++; /* Input_line_pointer->past char in c. */
+ if (isdigit(c) || (c == 'H' && input_line_pointer[0] == '\''))
+ {
+ register valueT number; /* offset or (absolute) value */
+ register short int digit; /* value of next digit in current radix */
+ /* invented for humans only, hope */
+ /* optimising compiler flushes it! */
+ register short int radix; /* 2, 8, 10 or 16 */
+ /* 0 means we saw start of a floating- */
+ /* point constant. */
+ register short int maxdig = 0;/* Highest permitted digit value. */
+ register int too_many_digits = 0; /* If we see >= this number of */
+ /* digits, assume it is a bignum. */
+ register char * digit_2; /*->2nd digit of number. */
+ int small; /* TRUE if fits in 32 bits. */
+
+
+ if (c == 'H' || c == '0') { /* non-decimal radix */
+ if ((c = *input_line_pointer ++) == 'x' || c == 'X' || c == '\'') {
+ c = *input_line_pointer ++; /* read past "0x" or "0X" or H' */
+ maxdig = radix = 16;
+ too_many_digits = 9;
+ } else {
+ /* If it says '0f' and the line ends or it DOESN'T look like
+ a floating point #, its a local label ref. DTRT */
+ /* likewise for the b's. xoxorich. */
+ if ((c == 'f' || c == 'b' || c == 'B')
+ && (!*input_line_pointer ||
+ (!strchr("+-.0123456789iInN",*input_line_pointer) &&
+ !strchr(EXP_CHARS,*input_line_pointer)))) {
+ maxdig = radix = 10;
+ too_many_digits = 11;
+ c = '0';
+ input_line_pointer -= 2;
+
+ } else if (c == 'b' || c == 'B') {
+ c = *input_line_pointer++;
+ maxdig = radix = 2;
+ too_many_digits = 33;
+
+ } else if (c && strchr(FLT_CHARS,c)) {
+ radix = 0; /* Start of floating-point constant. */
+ /* input_line_pointer->1st char of number. */
+ expressionP->X_add_number = -(isupper(c) ? tolower(c) : c);
+
+ } else { /* By elimination, assume octal radix. */
+ radix = maxdig = 8;
+ too_many_digits = 11;
+ }
+ } /* c == char after "0" or "0x" or "0X" or "0e" etc. */
+ } else {
+ maxdig = radix = 10;
+ too_many_digits = 11;
+ } /* if operand starts with a zero */
+
+ if (radix) { /* Fixed-point integer constant. */
+ /* May be bignum, or may fit in 32 bits. */
+ /*
+ * Most numbers fit into 32 bits, and we want this case to be fast.
+ * So we pretend it will fit into 32 bits. If, after making up a 32
+ * bit number, we realise that we have scanned more digits than
+ * comfortably fit into 32 bits, we re-scan the digits coding
+ * them into a bignum. For decimal and octal numbers we are conservative: some
+ * numbers may be assumed bignums when in fact they do fit into 32 bits.
+ * Numbers of any radix can have excess leading zeros: we strive
+ * to recognise this and cast them back into 32 bits.
+ * We must check that the bignum really is more than 32
+ * bits, and change it back to a 32-bit number if it fits.
+ * The number we are looking for is expected to be positive, but
+ * if it fits into 32 bits as an unsigned number, we let it be a 32-bit
+ * number. The cavalier approach is for speed in ordinary cases.
+ */
+ digit_2 = input_line_pointer;
+ for (number=0; (digit=hex_value[c])<maxdig; c = * input_line_pointer ++)
+ {
+ number = number * radix + digit;
+ }
+ /* C contains character after number. */
+ /* Input_line_pointer->char after C. */
+ small = input_line_pointer - digit_2 < too_many_digits;
+ if (!small)
+ {
+ /*
+ * We saw a lot of digits. Manufacture a bignum the hard way.
+ */
+ LITTLENUM_TYPE *leader; /*->high order littlenum of the bignum. */
+ LITTLENUM_TYPE *pointer; /*->littlenum we are frobbing now. */
+ long carry;
+
+ leader = generic_bignum;
+ generic_bignum[0] = 0;
+ generic_bignum[1] = 0;
+ /* We could just use digit_2, but lets be mnemonic. */
+ input_line_pointer = --digit_2; /*->1st digit. */
+ c = *input_line_pointer++;
+ for (; (carry = hex_value[c]) < maxdig; c = *input_line_pointer++)
+ {
+ for (pointer = generic_bignum;
+ pointer <= leader;
+ pointer++)
+ {
+ long work;
+
+ work = carry + radix * *pointer;
+ *pointer = work & LITTLENUM_MASK;
+ carry = work >> LITTLENUM_NUMBER_OF_BITS;
+ }
+ if (carry)
+ {
+ if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
+ { /* Room to grow a longer bignum. */
+ *++leader = carry;
+ }
+ }
+ }
+ /* Again, C is char after number, */
+ /* input_line_pointer->after C. */
+ know(sizeof (int) * 8 == 32);
+ know(LITTLENUM_NUMBER_OF_BITS == 16);
+ /* Hence the constant "2" in the next line. */
+ if (leader < generic_bignum + 2)
+ { /* Will fit into 32 bits. */
+ number =
+ ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
+ | (generic_bignum[0] & LITTLENUM_MASK);
+ small = 1;
+ }
+ else
+ {
+ number = leader - generic_bignum + 1; /* Number of littlenums in the bignum. */
+ }
+ }
+ if (small)
+ {
+ /*
+ * Here with number, in correct radix. c is the next char.
+ * Note that unlike Un*x, we allow "011f" "0x9f" to
+ * both mean the same as the (conventional) "9f". This is simply easier
+ * than checking for strict canonical form. Syntax sux!
+ */
+ if (number<10)
+ {
+ if (0
+#ifdef LOCAL_LABELS_FB
+ || c == 'b'
+#endif
+#ifdef LOCAL_LABELS_DOLLAR
+ || (c == '$' && local_label_defined[number])
+#endif
+ )
+ {
+ /*
+ * Backward ref to local label.
+ * Because it is backward, expect it to be DEFINED.
+ */
+ /*
+ * Construct a local label.
+ */
+ name = local_label_name ((int)number, 0);
+ if (((symbolP = symbol_find(name)) != NULL) /* seen before */
+ && (S_IS_DEFINED(symbolP))) /* symbol is defined: OK */
+ { /* Expected path: symbol defined. */
+ /* Local labels are never absolute. Don't waste time checking absoluteness. */
+ know(SEG_NORMAL(S_GET_SEGMENT(symbolP)));
+
+ expressionP->X_add_symbol = symbolP;
+ expressionP->X_add_number = 0;
+ expressionP->X_seg = S_GET_SEGMENT(symbolP);
+ }
+ else
+ { /* Either not seen or not defined. */
+ as_bad("Backw. ref to unknown label \"%d:\", 0 assumed.",
+ number);
+ expressionP->X_add_number = 0;
+ expressionP->X_seg = SEG_ABSOLUTE;
+ }
+ }
+ else
+ {
+ if (0
+#ifdef LOCAL_LABELS_FB
+ || c == 'f'
+#endif
+#ifdef LOCAL_LABELS_DOLLAR
+ || (c == '$' && !local_label_defined[number])
+#endif
+ )
+ {
+ /*
+ * Forward reference. Expect symbol to be undefined or
+ * unknown. Undefined: seen it before. Unknown: never seen
+ * it in this pass.
+ * Construct a local label name, then an undefined symbol.
+ * Don't create a XSEG frag for it: caller may do that.
+ * Just return it as never seen before.
+ */
+ name = local_label_name((int)number, 1);
+ symbolP = symbol_find_or_make(name);
+ /* We have no need to check symbol properties. */
+#ifndef MANY_SEGMENTS
+ /* Since "know" puts its arg into a "string", we
+ can't have newlines in the argument. */
+ know(S_GET_SEGMENT(symbolP) == SEG_UNKNOWN || S_GET_SEGMENT(symbolP) == SEG_TEXT || S_GET_SEGMENT(symbolP) == SEG_DATA);
+#endif
+ expressionP->X_add_symbol = symbolP;
+ expressionP->X_seg = SEG_UNKNOWN;
+ expressionP->X_subtract_symbol = NULL;
+ expressionP->X_add_number = 0;
+ }
+ else
+ { /* Really a number, not a local label. */
+ expressionP->X_add_number = number;
+ expressionP->X_seg = SEG_ABSOLUTE;
+ input_line_pointer--; /* Restore following character. */
+ } /* if (c == 'f') */
+ } /* if (c == 'b') */
+ }
+ else
+ { /* Really a number. */
+ expressionP->X_add_number = number;
+ expressionP->X_seg = SEG_ABSOLUTE;
+ input_line_pointer--; /* Restore following character. */
+ } /* if (number<10) */
+ }
+ else
+ {
+ expressionP->X_add_number = number;
+ expressionP->X_seg = SEG_BIG;
+ input_line_pointer --; /*->char following number. */
+ } /* if (small) */
+ } /* (If integer constant) */
+ else
+ { /* input_line_pointer->*/
+ /* floating-point constant. */
+ int error_code;
+
+ error_code = atof_generic
+ (& input_line_pointer, ".", EXP_CHARS,
+ & generic_floating_point_number);
+
+ if (error_code)
+ {
+ if (error_code == ERROR_EXPONENT_OVERFLOW)
+ {
+ as_bad("Bad floating-point constant: exponent overflow, probably assembling junk");
+ }
+ else
+ {
+ as_bad("Bad floating-point constant: unknown error code=%d.", error_code);
+ }
+ }
+ expressionP->X_seg = SEG_BIG;
+ /* input_line_pointer->just after constant, */
+ /* which may point to whitespace. */
+ know(expressionP->X_add_number < 0); /* < 0 means "floating point". */
+ } /* if (not floating-point constant) */
+ }
+ else if (c == '.' && !is_part_of_name(*input_line_pointer)) {
+ extern struct obstack frags;
+
+ /*
+ JF: '.' is pseudo symbol with value of current location in current
+ segment...
+ */
+ symbolP = symbol_new("\001L0",
+ now_seg,
+ (valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
+ frag_now);
+
+ expressionP->X_add_number=0;
+ expressionP->X_add_symbol=symbolP;
+ expressionP->X_seg = now_seg;
+
+ } else if (is_name_beginner(c)) { /* here if did not begin with a digit */
+
+ /*
+ * Identifier begins here.
+ * This is kludged for speed, so code is repeated.
+ */
+ name = input_line_pointer - 1;
+ c = get_symbol_end();
+ symbolP = symbol_find_or_make(name);
+ /*
+ * If we have an absolute symbol or a reg, then we know its value now.
+ */
+ expressionP->X_seg = S_GET_SEGMENT(symbolP);
+ switch (expressionP->X_seg)
+ {
+ case SEG_ABSOLUTE:
+ case SEG_REGISTER:
+ expressionP->X_add_number = S_GET_VALUE(symbolP);
+ break;
+
+ default:
+ expressionP->X_add_number = 0;
+#ifdef PIC
+ if (symbolP == GOT_symbol) {
+ expressionP->X_got_symbol = symbolP;
+ got_referenced = 1;
+ } else
+#endif
+ expressionP->X_add_symbol = symbolP;
+ }
+ *input_line_pointer = c;
+ expressionP->X_subtract_symbol = NULL;
+ } else if (c == '(' || c == '[') {/* didn't begin with digit & not a name */
+ (void)expression(expressionP);
+ /* Expression() will pass trailing whitespace */
+ if (c == '(' && *input_line_pointer++ != ')' ||
+ c == '[' && *input_line_pointer++ != ']') {
+ as_bad("Missing ')' assumed");
+ input_line_pointer--;
+ }
+ /* here with input_line_pointer->char after "(...)" */
+ } else if (c == '~' || c == '-' || c == '+') {
+ /* unary operator: hope for SEG_ABSOLUTE */
+ switch (operand (expressionP)) {
+ case SEG_ABSOLUTE:
+ /* input_line_pointer->char after operand */
+ if (c == '-') {
+ expressionP->X_add_number = - expressionP->X_add_number;
+ /*
+ * Notice: '-' may overflow: no warning is given. This is compatible
+ * with other people's assemblers. Sigh.
+ */
+ } else if (c == '~') {
+ expressionP->X_add_number = ~ expressionP->X_add_number;
+ } else if (c != '+') {
+ know(0);
+ } /* switch on unary operator */
+ break;
+
+ default: /* unary on non-absolute is unsuported */
+ if (!SEG_NORMAL(operand(expressionP)))
+ {
+ as_bad("Unary operator %c ignored because bad operand follows", c);
+ break;
+ }
+ /* Fall through for normal segments ****/
+ case SEG_PASS1:
+ case SEG_UNKNOWN:
+ if (c == '-') { /* JF I hope this hack works */
+ expressionP->X_subtract_symbol=expressionP->X_add_symbol;
+ expressionP->X_add_symbol=0;
+ expressionP->X_seg=SEG_DIFFERENCE;
+ break;
+ }
+ /* Expression undisturbed from operand(). */
+ }
+ }
+ else if (c == '\'')
+ {
+ /*
+ * Warning: to conform to other people's assemblers NO ESCAPEMENT is permitted
+ * for a single quote. The next character, parity errors and all, is taken
+ * as the value of the operand. VERY KINKY.
+ */
+ expressionP->X_add_number = * input_line_pointer ++;
+ expressionP->X_seg = SEG_ABSOLUTE;
+ }
+ else
+ {
+ /* can't imagine any other kind of operand */
+ expressionP->X_seg = SEG_ABSENT;
+ input_line_pointer --;
+ md_operand (expressionP);
+ }
+ /*
+ * It is more 'efficient' to clean up the expressions when they are created.
+ * Doing it here saves lines of code.
+ */
+ clean_up_expression(expressionP);
+ SKIP_WHITESPACE(); /*->1st char after operand. */
+ know(*input_line_pointer != ' ');
+ return(expressionP->X_seg);
+} /* operand() */
+
+/* Internal. Simplify a struct expression for use by expr() */
+
+/*
+ * In: address of a expressionS.
+ * The X_seg field of the expressionS may only take certain values.
+ * Now, we permit SEG_PASS1 to make code smaller & faster.
+ * Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT.
+ * Out: expressionS may have been modified:
+ * 'foo-foo' symbol references cancelled to 0,
+ * which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
+ * Unused fields zeroed to help expr().
+ */
+
+static void
+ clean_up_expression (expressionP)
+register expressionS *expressionP;
+{
+ switch (expressionP->X_seg) {
+ case SEG_ABSENT:
+ case SEG_PASS1:
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_subtract_symbol = NULL;
+ expressionP->X_add_number = 0;
+ break;
+
+ case SEG_BIG:
+ case SEG_ABSOLUTE:
+ expressionP->X_subtract_symbol = NULL;
+ expressionP->X_add_symbol = NULL;
+ break;
+
+ case SEG_UNKNOWN:
+ expressionP->X_subtract_symbol = NULL;
+ break;
+
+ case SEG_DIFFERENCE:
+ /*
+ * It does not hurt to 'cancel' NULL == NULL
+ * when comparing symbols for 'eq'ness.
+ * It is faster to re-cancel them to NULL
+ * than to check for this special case.
+ */
+ if (expressionP->X_subtract_symbol == expressionP->X_add_symbol
+ || (expressionP->X_subtract_symbol
+ && expressionP->X_add_symbol
+ && expressionP->X_subtract_symbol->sy_frag == expressionP->X_add_symbol->sy_frag
+ && S_GET_VALUE(expressionP->X_subtract_symbol) == S_GET_VALUE(expressionP->X_add_symbol))) {
+ expressionP->X_subtract_symbol = NULL;
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_seg = SEG_ABSOLUTE;
+ }
+ break;
+
+ case SEG_REGISTER:
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_subtract_symbol = NULL;
+ break;
+
+ default:
+ if (SEG_NORMAL(expressionP->X_seg)) {
+ expressionP->X_subtract_symbol = NULL;
+ }
+ else {
+ BAD_CASE (expressionP->X_seg);
+ }
+ break;
+ }
+} /* clean_up_expression() */
+
+/*
+ * expr_part ()
+ *
+ * Internal. Made a function because this code is used in 2 places.
+ * Generate error or correct X_?????_symbol of expressionS.
+ */
+
+/*
+ * symbol_1 += symbol_2 ... well ... sort of.
+ */
+
+static segT
+ expr_part (symbol_1_PP, symbol_2_P)
+symbolS ** symbol_1_PP;
+symbolS * symbol_2_P;
+{
+ segT return_value;
+#ifndef MANY_SEGMENTS
+ know((* symbol_1_PP) == NULL || (S_GET_SEGMENT(*symbol_1_PP) == SEG_TEXT) || (S_GET_SEGMENT(*symbol_1_PP) == SEG_DATA) || (S_GET_SEGMENT(*symbol_1_PP) == SEG_BSS) || (!S_IS_DEFINED(* symbol_1_PP)));
+ know(symbol_2_P == NULL || (S_GET_SEGMENT(symbol_2_P) == SEG_TEXT) || (S_GET_SEGMENT(symbol_2_P) == SEG_DATA) || (S_GET_SEGMENT(symbol_2_P) == SEG_BSS) || (!S_IS_DEFINED(symbol_2_P)));
+#endif
+ if (* symbol_1_PP)
+ {
+ if (!S_IS_DEFINED(* symbol_1_PP))
+ {
+ if (symbol_2_P)
+ {
+ return_value = SEG_PASS1;
+ * symbol_1_PP = NULL;
+ }
+ else
+ {
+ know(!S_IS_DEFINED(* symbol_1_PP));
+ return_value = SEG_UNKNOWN;
+ }
+ }
+ else
+ {
+ if (symbol_2_P)
+ {
+ if (!S_IS_DEFINED(symbol_2_P))
+ {
+ * symbol_1_PP = NULL;
+ return_value = SEG_PASS1;
+ }
+ else
+ {
+ /* {seg1} - {seg2} */
+ as_bad("Expression too complex, 2 symbols forgotten: \"%s\" \"%s\"",
+ S_GET_NAME(* symbol_1_PP), S_GET_NAME(symbol_2_P));
+ * symbol_1_PP = NULL;
+ return_value = SEG_ABSOLUTE;
+ }
+ }
+ else
+ {
+ return_value = S_GET_SEGMENT(* symbol_1_PP);
+ }
+ }
+ }
+ else
+ { /* (* symbol_1_PP) == NULL */
+ if (symbol_2_P)
+ {
+ * symbol_1_PP = symbol_2_P;
+ return_value = S_GET_SEGMENT(symbol_2_P);
+ }
+ else
+ {
+ * symbol_1_PP = NULL;
+ return_value = SEG_ABSOLUTE;
+ }
+ }
+#ifndef MANY_SEGMENTS
+ know(return_value == SEG_ABSOLUTE || return_value == SEG_TEXT || return_value == SEG_DATA || return_value == SEG_BSS || return_value == SEG_UNKNOWN || return_value == SEG_PASS1);
+#endif
+ know((*symbol_1_PP) == NULL || (S_GET_SEGMENT(*symbol_1_PP) == return_value));
+ return (return_value);
+} /* expr_part() */
+
+void ps (s)
+symbolS *s;
+{
+ fprintf (stdout, "%s type %s%s",
+ S_GET_NAME(s),
+ S_IS_EXTERNAL(s) ? "EXTERNAL " : "",
+ segment_name(S_GET_SEGMENT(s)));
+}
+void pe (e)
+expressionS *e;
+{
+ fprintf (stdout, " segment %s\n", segment_name (e->X_seg));
+ fprintf (stdout, " add_number %ld (%lx)\n",
+ e->X_add_number, e->X_add_number);
+ if (e->X_add_symbol) {
+ fprintf (stdout, " add_symbol ");
+ ps (e->X_add_symbol);
+ fprintf (stdout, "\n");
+ }
+ if (e->X_subtract_symbol) {
+ fprintf (stdout, " sub_symbol ");
+ ps (e->X_subtract_symbol);
+ fprintf (stdout, "\n");
+ }
+}
+
+/* Expression parser. */
+
+/*
+ * We allow an empty expression, and just assume (absolute,0) silently.
+ * Unary operators and parenthetical expressions are treated as operands.
+ * As usual, Q == quantity == operand, O == operator, X == expression mnemonics.
+ *
+ * We used to do a aho/ullman shift-reduce parser, but the logic got so
+ * warped that I flushed it and wrote a recursive-descent parser instead.
+ * Now things are stable, would anybody like to write a fast parser?
+ * Most expressions are either register (which does not even reach here)
+ * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
+ * So I guess it doesn't really matter how inefficient more complex expressions
+ * are parsed.
+ *
+ * After expr(RANK,resultP) input_line_pointer->operator of rank <= RANK.
+ * Also, we have consumed any leading or trailing spaces (operand does that)
+ * and done all intervening operators.
+ */
+
+typedef enum
+{
+ O_illegal, /* (0) what we get for illegal op */
+
+ O_multiply, /* (1) * */
+ O_divide, /* (2) / */
+ O_modulus, /* (3) % */
+ O_left_shift, /* (4) < */
+ O_right_shift, /* (5) > */
+ O_bit_inclusive_or, /* (6) | */
+ O_bit_or_not, /* (7) ! */
+ O_bit_exclusive_or, /* (8) ^ */
+ O_bit_and, /* (9) & */
+ O_add, /* (10) + */
+ O_subtract /* (11) - */
+ }
+operatorT;
+
+#define __ O_illegal
+
+static const operatorT op_encoding[256] = { /* maps ASCII->operators */
+
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+
+ __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
+ __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, O_left_shift, __, O_right_shift, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, O_bit_exclusive_or, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __,
+ __, __, __, __, O_bit_inclusive_or, __, __, __,
+
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
+ };
+
+
+/*
+ * Rank Examples
+ * 0 operand, (expression)
+ * 1 + -
+ * 2 & ^ ! |
+ * 3 * / % << >>
+ */
+static const operator_rankT
+ op_rank[] = { 0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1 };
+
+/* Return resultP->X_seg. */
+segT expr(rank, resultP)
+ register operator_rankT rank; /* Larger # is higher rank. */
+ register expressionS *resultP; /* Deliver result here. */
+{
+ expressionS right;
+ register operatorT op_left;
+ register char c_left; /* 1st operator character. */
+ register operatorT op_right;
+ register char c_right;
+
+ know(rank >= 0);
+ (void) operand(resultP);
+ know(*input_line_pointer != ' '); /* Operand() gobbles spaces. */
+ c_left = *input_line_pointer; /* Potential operator character. */
+ op_left = op_encoding[c_left];
+
+ while (op_left != O_illegal && op_rank[(int) op_left] > rank) {
+ input_line_pointer++; /*->after 1st character of operator. */
+
+ /* Operators "<<" and ">>" have 2 characters. */
+ if (*input_line_pointer == c_left && (c_left == '<' || c_left == '>')) {
+ input_line_pointer ++;
+ } /*->after operator. */
+ if (SEG_ABSENT == expr (op_rank[(int) op_left], &right)) {
+ as_warn("Missing operand value assumed absolute 0.");
+ resultP->X_add_number = 0;
+ resultP->X_subtract_symbol = NULL;
+ resultP->X_add_symbol = NULL;
+ resultP->X_seg = SEG_ABSOLUTE;
+ }
+
+ know(*input_line_pointer != ' ');
+ c_right = *input_line_pointer;
+ op_right = op_encoding[c_right];
+
+ if (*input_line_pointer == c_right && (c_right == '<' || c_right == '>')) {
+ input_line_pointer ++;
+ } /*->after operator. */
+
+ know((int) op_right == 0 || op_rank[(int) op_right] <= op_rank[(int) op_left]);
+ /* input_line_pointer->after right-hand quantity. */
+ /* left-hand quantity in resultP */
+ /* right-hand quantity in right. */
+ /* operator in op_left. */
+ if (resultP->X_seg == SEG_PASS1 || right.X_seg == SEG_PASS1) {
+ resultP->X_seg = SEG_PASS1;
+ } else {
+ if (resultP->X_seg == SEG_BIG) {
+ as_warn("Left operand of %c is a %s. Integer 0 assumed.",
+ c_left, resultP->X_add_number > 0 ? "bignum" : "float");
+ resultP->X_seg = SEG_ABSOLUTE;
+ resultP->X_add_symbol = 0;
+ resultP->X_subtract_symbol = 0;
+ resultP->X_add_number = 0;
+ }
+ if (right.X_seg == SEG_BIG) {
+ as_warn("Right operand of %c is a %s. Integer 0 assumed.",
+ c_left, right.X_add_number > 0 ? "bignum" : "float");
+ right.X_seg = SEG_ABSOLUTE;
+ right.X_add_symbol = 0;
+ right.X_subtract_symbol = 0;
+ right.X_add_number = 0;
+ }
+ if (op_left == O_subtract) {
+ /*
+ * Convert - into + by exchanging symbols and negating number.
+ * I know -infinity can't be negated in 2's complement:
+ * but then it can't be subtracted either. This trick
+ * does not cause any further inaccuracy.
+ */
+
+ register symbolS * symbolP;
+
+ right.X_add_number = - right.X_add_number;
+ symbolP = right.X_add_symbol;
+ right.X_add_symbol = right.X_subtract_symbol;
+ right.X_subtract_symbol = symbolP;
+ if (symbolP) {
+ right.X_seg = SEG_DIFFERENCE;
+ }
+ op_left = O_add;
+ }
+
+ if (op_left == O_add) {
+ segT seg1;
+ segT seg2;
+#ifndef MANY_SEGMENTS
+ know(resultP->X_seg == SEG_DATA
+ || resultP->X_seg == SEG_TEXT
+ || resultP->X_seg == SEG_BSS
+ || resultP->X_seg == SEG_UNKNOWN
+ || resultP->X_seg == SEG_DIFFERENCE
+ || resultP->X_seg == SEG_ABSOLUTE
+ || resultP->X_seg == SEG_PASS1);
+ know(right.X_seg == SEG_DATA
+ || right.X_seg == SEG_TEXT
+ || right.X_seg == SEG_BSS
+ || right.X_seg == SEG_UNKNOWN
+ || right.X_seg == SEG_DIFFERENCE
+ || right.X_seg == SEG_ABSOLUTE
+ || right.X_seg == SEG_PASS1);
+#endif
+ clean_up_expression(& right);
+ clean_up_expression(resultP);
+
+#ifdef PIC
+/* XXX - kludge here to accomodate "_GLOBAL_OFFSET_TABLE + (x - y)"
+ * expressions: this only works for this special case, the
+ * _GLOBAL_OFFSET_TABLE thing *must* be the left operand, the whole
+ * expression is given the segment of right expression (always a DIFFERENCE,
+ * which should get resolved by fixup_segment())
+ */
+ if (resultP->X_got_symbol) {
+ resultP->X_add_symbol = right.X_add_symbol;
+ resultP->X_subtract_symbol = right.X_subtract_symbol;
+ seg1 = S_GET_SEGMENT(right.X_add_symbol);
+ seg2 = S_GET_SEGMENT(right.X_subtract_symbol);
+ resultP->X_seg = right.X_seg;
+ } else {
+#endif
+ seg1 = expr_part(&resultP->X_add_symbol, right.X_add_symbol);
+ seg2 = expr_part(&resultP->X_subtract_symbol, right.X_subtract_symbol);
+#ifdef PIC
+ }
+#endif
+ if (seg1 == SEG_PASS1 || seg2 == SEG_PASS1) {
+ need_pass_2 = 1;
+ resultP->X_seg = SEG_PASS1;
+ } else if (seg2 == SEG_ABSOLUTE)
+ resultP->X_seg = seg1;
+ else if (seg1 != SEG_UNKNOWN
+ && seg1 != SEG_ABSOLUTE
+ && seg2 != SEG_UNKNOWN
+ && seg1 != seg2) {
+ know(seg2 != SEG_ABSOLUTE);
+ know(resultP->X_subtract_symbol);
+#ifndef MANY_SEGMENTS
+ know(seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1 == SEG_BSS);
+ know(seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2 == SEG_BSS);
+#endif
+ know(resultP->X_add_symbol);
+ know(resultP->X_subtract_symbol);
+ as_bad("Expression too complex: forgetting %s - %s",
+ S_GET_NAME(resultP->X_add_symbol),
+ S_GET_NAME(resultP->X_subtract_symbol));
+ resultP->X_seg = SEG_ABSOLUTE;
+ /* Clean_up_expression() will do the rest. */
+ } else
+ resultP->X_seg = SEG_DIFFERENCE;
+
+ resultP->X_add_number += right.X_add_number;
+ clean_up_expression(resultP);
+ } else { /* Not +. */
+ if (resultP->X_seg == SEG_UNKNOWN || right.X_seg == SEG_UNKNOWN) {
+ resultP->X_seg = SEG_PASS1;
+ need_pass_2 = 1;
+ } else {
+ resultP->X_subtract_symbol = NULL;
+ resultP->X_add_symbol = NULL;
+
+ /* Will be SEG_ABSOLUTE. */
+ if (resultP->X_seg != SEG_ABSOLUTE || right.X_seg != SEG_ABSOLUTE) {
+ as_bad("Relocation error. Absolute 0 assumed.");
+ resultP->X_seg = SEG_ABSOLUTE;
+ resultP->X_add_number = 0;
+ } else {
+ switch (op_left) {
+ case O_bit_inclusive_or:
+ resultP->X_add_number |= right.X_add_number;
+ break;
+
+ case O_modulus:
+ if (right.X_add_number) {
+ resultP->X_add_number %= right.X_add_number;
+ } else {
+ as_warn("Division by 0. 0 assumed.");
+ resultP->X_add_number = 0;
+ }
+ break;
+
+ case O_bit_and:
+ resultP->X_add_number &= right.X_add_number;
+ break;
+
+ case O_multiply:
+ resultP->X_add_number *= right.X_add_number;
+ break;
+
+ case O_divide:
+ if (right.X_add_number) {
+ resultP->X_add_number /= right.X_add_number;
+ } else {
+ as_warn("Division by 0. 0 assumed.");
+ resultP->X_add_number = 0;
+ }
+ break;
+
+ case O_left_shift:
+ resultP->X_add_number <<= right.X_add_number;
+ break;
+
+ case O_right_shift:
+ resultP->X_add_number >>= right.X_add_number;
+ break;
+
+ case O_bit_exclusive_or:
+ resultP->X_add_number ^= right.X_add_number;
+ break;
+
+ case O_bit_or_not:
+ resultP->X_add_number |= ~ right.X_add_number;
+ break;
+
+ default:
+ BAD_CASE(op_left);
+ break;
+ } /* switch (operator) */
+ }
+ } /* If we have to force need_pass_2. */
+ } /* If operator was +. */
+ } /* If we didn't set need_pass_2. */
+ op_left = op_right;
+ } /* While next operator is >= this rank. */
+
+ return(resultP->X_seg);
+} /* expr() */
+
+/*
+ * get_symbol_end()
+ *
+ * This lives here because it belongs equally in expr.c & read.c.
+ * Expr.c is just a branch office read.c anyway, and putting it
+ * here lessens the crowd at read.c.
+ *
+ * Assume input_line_pointer is at start of symbol name.
+ * Advance input_line_pointer past symbol name.
+ * Turn that character into a '\0', returning its former value.
+ * This allows a string compare (RMS wants symbol names to be strings)
+ * of the symbol name.
+ * There will always be a char following symbol name, because all good
+ * lines end in end-of-line.
+ */
+char
+ get_symbol_end()
+{
+ register char c;
+
+ while (is_part_of_name(c = *input_line_pointer++)) ;;
+ *--input_line_pointer = 0;
+ return (c);
+}
+
+
+unsigned int get_single_number()
+{
+ expressionS exp;
+ operand(&exp);
+ return exp.X_add_number;
+
+}
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of expr.c */
diff --git a/gnu/usr.bin/as/expr.h b/gnu/usr.bin/as/expr.h
new file mode 100644
index 0000000..ea06842
--- /dev/null
+++ b/gnu/usr.bin/as/expr.h
@@ -0,0 +1,85 @@
+/* expr.h -> header file for expr.c
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+/*
+ * Abbreviations (mnemonics).
+ *
+ * O operator
+ * Q quantity, operand
+ * X eXpression
+ */
+
+/*
+ * By popular demand, we define a struct to represent an expression.
+ * This will no doubt mutate as expressions become baroque.
+ *
+ * Currently, we support expressions like "foo-bar+42".
+ * In other words we permit a (possibly undefined) minuend, a
+ * (possibly undefined) subtrahend and an (absolute) augend.
+ * RMS says this is so we can have 1-pass assembly for any compiler
+ * emmissions, and a 'case' statement might emit 'undefined1 - undefined2'.
+ *
+ * To simplify table-driven dispatch, we also have a "segment" for the
+ * entire expression. That way we don't require complex reasoning about
+ * whether particular components are defined; and we can change component
+ * semantics without re-working all the dispatch tables in the assembler.
+ * In other words the "type" of an expression is its segment.
+ */
+
+typedef struct {
+ symbolS *X_add_symbol; /* foo */
+ symbolS *X_subtract_symbol; /* bar */
+ symbolS *X_got_symbol; /* got */
+ long X_add_number; /* 42. Must be signed. */
+ segT X_seg; /* What segment (expr type)? */
+}
+expressionS;
+
+/* result should be type (expressionS *). */
+#define expression(result) expr(0,result)
+
+/* If an expression is SEG_BIG, look here */
+/* for its value. These common data may */
+/* be clobbered whenever expr() is called. */
+extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */
+/* Enough to hold most precise flonum. */
+extern LITTLENUM_TYPE generic_bignum[]; /* Bignums returned here. */
+#define SIZE_OF_LARGE_NUMBER (20) /* Number of littlenums in above. */
+
+typedef char operator_rankT;
+
+#if __STDC__ == 1
+
+char get_symbol_end(void);
+segT expr(int rank, expressionS *resultP);
+unsigned int get_single_number(void);
+
+#else /* not __STDC__ */
+
+char get_symbol_end();
+segT expr();
+unsigned int get_single_number();
+
+#endif /* not __STDC__ */
+
+/* end of expr.h */
diff --git a/gnu/usr.bin/as/flo-const.c b/gnu/usr.bin/as/flo-const.c
new file mode 100644
index 0000000..51a4afc
--- /dev/null
+++ b/gnu/usr.bin/as/flo-const.c
@@ -0,0 +1,161 @@
+/* flonum_const.c - Useful Flonum constants
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "flonum.h"
+/* JF: I added the last entry to this table, and I'm not
+ sure if its right or not. Could go either way. I wish
+ I really understood this stuff. */
+
+
+const int table_size_of_flonum_powers_of_ten = 11;
+
+static const LITTLENUM_TYPE zero[] = { 1 };
+
+/***********************************************************************\
+ * *
+ * Warning: the low order bits may be WRONG here. *
+ * I took this from a suspect bc(1) script. *
+ * "minus_X"[] is supposed to be 10^(2^-X) expressed in base 2^16. *
+ * The radix point is just AFTER the highest element of the [] *
+ * *
+ * Because bc rounds DOWN for printing (I think), the lowest *
+ * significance littlenums should probably have 1 added to them. *
+ * *
+ \***********************************************************************/
+
+/* JF: If this equals 6553/(2^16)+39321/(2^32)+... it approaches .1 */
+static const LITTLENUM_TYPE minus_1[] = {
+ 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321,
+ 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 39321, 6553 };
+static const LITTLENUM_TYPE plus_1[] = { 10 };
+
+/* JF: If this equals 655/(2^16) + 23592/(2^32) + ... it approaches .01 */
+static const LITTLENUM_TYPE minus_2[] = {
+ 10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 49807,
+ 10485, 36700, 62914, 23592, 49807, 10485, 36700, 62914, 23592, 655 };
+static const LITTLENUM_TYPE plus_2[] = { 100 };
+
+/* This approaches .0001 */
+static const LITTLENUM_TYPE minus_3[] = {
+ 52533, 20027, 37329, 65116, 64067, 60397, 14784, 18979, 33659, 19503,
+ 2726, 9542, 629, 2202, 40475, 10590, 4299, 47815, 36280, 6 };
+static const LITTLENUM_TYPE plus_3[] = { 10000 };
+
+/* JF: this approaches 1e-8 */
+static const LITTLENUM_TYPE minus_4[] = {
+ 22516, 49501, 54293, 19424, 60699, 6716, 24348, 22618, 23904, 21327,
+ 3919, 44703, 19149, 28803, 48959, 6259, 50273, 62237, 42 };
+/* This equals 1525 * 2^16 + 57600 */
+static const LITTLENUM_TYPE plus_4[] = { 57600, 1525 };
+
+/* This approaches 1e-16 */
+static const LITTLENUM_TYPE minus_5[] = {
+ 22199, 45957, 17005, 26266, 10526, 16260, 55017, 35680, 40443, 19789,
+ 17356, 30195, 55905, 28426, 63010, 44197, 1844 };
+static const LITTLENUM_TYPE plus_5[] = { 28609, 34546, 35 };
+
+static const LITTLENUM_TYPE minus_6[] = {
+ 30926, 26518, 13110, 43018, 54982, 48258, 24658, 15209, 63366, 11929,
+ 20069, 43857, 60487, 51 };
+static const LITTLENUM_TYPE plus_6[] = { 61313, 34220, 16731, 11629, 1262 };
+
+static const LITTLENUM_TYPE minus_7[] = {
+ 29819, 14733, 21490, 40602, 31315, 65186, 2695 };
+static const LITTLENUM_TYPE plus_7[] = {
+ 7937, 49002, 60772, 28216, 38893, 55975, 63988, 59711, 20227, 24 };
+
+static const LITTLENUM_TYPE minus_8[] = {
+ 45849, 19069, 18068, 36324, 37948, 48745, 10873, 64360, 15961, 20566,
+ 24178, 15922, 59427, 110 };
+static const LITTLENUM_TYPE plus_8[] = {
+ 15873, 11925, 39177, 991, 14589, 19735, 25347, 65086, 53853, 938,
+ 37209, 47086, 33626, 23253, 32586, 42547, 9731, 59679, 590 };
+
+static const LITTLENUM_TYPE minus_9[] = {
+ 63601, 55221, 43562, 33661, 29067, 28203, 65417, 64352, 22462, 41110,
+ 12570, 28635, 23199, 50572, 28471, 27074, 46375, 64028, 13106, 63700,
+ 32698, 17493, 32420, 34382, 22750, 20681, 12300 };
+static const LITTLENUM_TYPE plus_9[] = {
+ 63564, 61556, 29377, 54467, 18621, 28141, 36415, 61241, 47119, 30026,
+ 19740, 46002, 13541, 61413, 30480, 38664, 32205, 50593, 51112, 48904,
+ 48263, 43814, 286, 30826, 52813, 62575, 61390, 24540, 21495, 5 };
+
+static const LITTLENUM_TYPE minus_10[] = {
+ 50313, 34681, 1464, 25889, 19575, 41125, 17635, 4598, 49708, 13427,
+ 17287, 56115, 53783, 38255, 32415, 17778, 31596, 7557, 20951, 18477,
+ 40353, 1178, 44405, 11837, 11571, 50963, 15649, 11698, 40675, 2308, };
+static const LITTLENUM_TYPE plus_10[] = {
+ 18520, 53764, 54535, 61910, 61962, 59843, 46270, 58053, 12473, 63785,
+ 2449, 43230, 50044, 47595, 10403, 35766, 32607, 1124, 24966, 35044,
+ 25524, 23631, 18826, 14518, 58448, 14562, 49618, 5588, 25396, 28 };
+
+static const LITTLENUM_TYPE minus_11[] = {
+ 6223, 59909, 62437, 59960, 14652, 45336, 48800, 7647, 51962, 37982,
+ 60436, 58176, 26767, 8440, 9831, 48556, 20994, 14148, 6757, 17221,
+ 60624, 46129, 53210, 44085, 54016, 24259, 11232, 21229, 21313, 81, };
+static const LITTLENUM_TYPE plus_11[] = {
+ 36159, 2055, 33615, 61362, 23581, 62454, 9748, 15275, 39284, 58636,
+ 16269, 42793, 47240, 45774, 50861, 48400, 9413, 40281, 4030, 9572,
+ 7984, 33038, 59522, 19450, 40593, 24486, 54320, 6661, 55766, 805, };
+
+/* Shut up complaints about differing pointer types. They only differ
+ in the const attribute, but there isn't any easy way to do this
+ */
+#define X (LITTLENUM_TYPE *)
+
+const FLONUM_TYPE flonum_negative_powers_of_ten[] = {
+ {X zero, X zero, X zero, 0, '+'},
+ {X minus_1, X minus_1 +19, X minus_1 + 19, -20, '+'},
+ {X minus_2, X minus_2 +19, X minus_2 + 19, -20, '+'},
+ {X minus_3, X minus_3 +19, X minus_3 + 19, -20, '+'},
+ {X minus_4, X minus_4 +18, X minus_4 + 18, -20, '+'},
+ {X minus_5, X minus_5 +16, X minus_5 + 16, -20, '+'},
+ {X minus_6, X minus_6 +13, X minus_6 + 13, -20, '+'},
+ {X minus_7, X minus_7 + 6, X minus_7 + 6, -20, '+'},
+ {X minus_8, X minus_8 +13, X minus_8 + 13, -40, '+'},
+ {X minus_9, X minus_9 +26, X minus_9 + 26, -80, '+'},
+ {X minus_10, X minus_10+29, X minus_10 + 29,-136, '+'},
+ {X minus_11, X minus_11+29, X minus_11 + 29,-242, '+'},
+};
+
+const FLONUM_TYPE flonum_positive_powers_of_ten[] = {
+ {X zero, X zero, X zero, 0, '+'},
+ {X plus_1, X plus_1 + 0, X plus_1 + 0, 0, '+'},
+ {X plus_2, X plus_2 + 0, X plus_2 + 0, 0, '+'},
+ {X plus_3, X plus_3 + 0, X plus_3 + 0, 0, '+'},
+ {X plus_4, X plus_4 + 1, X plus_4 + 1, 0, '+'},
+ {X plus_5, X plus_5 + 2, X plus_5 + 2, 1, '+'},
+ {X plus_6, X plus_6 + 4, X plus_6 + 4, 2, '+'},
+ {X plus_7, X plus_7 + 9, X plus_7 + 9, 4, '+'},
+ {X plus_8, X plus_8 + 18, X plus_8 + 18, 8, '+'},
+ {X plus_9, X plus_9 + 29, X plus_9 + 29, 24, '+'},
+ {X plus_10, X plus_10 + 29, X plus_10 + 29, 77, '+'},
+ {X plus_11, X plus_11 + 29, X plus_11 + 29, 183, '+'},
+};
+
+#ifdef HO_VMS
+dummy1()
+{
+}
+#endif
+/* end of flonum_const.c */
diff --git a/gnu/usr.bin/as/flo-copy.c b/gnu/usr.bin/as/flo-copy.c
new file mode 100644
index 0000000..15a6ed4
--- /dev/null
+++ b/gnu/usr.bin/as/flo-copy.c
@@ -0,0 +1,70 @@
+/* flonum_copy.c - copy a flonum
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+
+void
+ flonum_copy(in, out)
+FLONUM_TYPE *in;
+FLONUM_TYPE *out;
+{
+ int in_length; /* 0 origin */
+ int out_length; /* 0 origin */
+
+ out->sign = in->sign;
+ in_length = in->leader - in->low;
+
+ if (in_length < 0) {
+ out->leader = out->low - 1; /* 0.0 case */
+ } else {
+ out_length = out->high - out->low;
+ /*
+ * Assume no GAPS in packing of littlenums.
+ * I.e. sizeof(array) == sizeof(element) * number_of_elements.
+ */
+ if (in_length <= out_length) {
+ {
+ /*
+ * For defensive programming, zero any high-order littlenums we don't need.
+ * This is destroying evidence and wasting time, so why bother???
+ */
+ if (in_length < out_length) {
+memset((char *)(out->low + in_length + 1), '\0', out_length - in_length);
+ }
+ }
+ memcpy((void *)(out->low), (void *)(in->low), (int)((in_length + 1) * sizeof(LITTLENUM_TYPE)));
+ out->exponent = in->exponent;
+ out->leader = in->leader - in->low + out->low;
+ } else {
+ int shorten; /* 1-origin. Number of littlenums we drop. */
+
+ shorten = in_length - out_length;
+ /* Assume out_length >= 0 ! */
+ memcpy((void *)( out->low), (void *)(in->low + shorten), (int)((out_length + 1) * sizeof(LITTLENUM_TYPE)));
+ out->leader = out->high;
+ out->exponent = in->exponent + shorten;
+ }
+ } /* if any significant bits */
+} /* flonum_copy() */
+
+/* end of flonum_copy.c */
diff --git a/gnu/usr.bin/as/flonum-mult.c b/gnu/usr.bin/as/flonum-mult.c
new file mode 100644
index 0000000..cb28f64
--- /dev/null
+++ b/gnu/usr.bin/as/flonum-mult.c
@@ -0,0 +1,203 @@
+/* flonum_mult.c - multiply two flonums
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of Gas, the GNU Assembler.
+
+ The GNU assembler 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 GNU Assembler General
+ Public License for full details.
+
+ Everyone is granted permission to copy, modify and redistribute
+ the GNU Assembler, but only under the conditions described in the
+ GNU Assembler General Public License. A copy of this license is
+ supposed to have been given to you along with the GNU Assembler
+ 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. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "flonum.h"
+
+/* plan for a . b => p(roduct)
+
+
+ +-------+-------+-/ /-+-------+-------+
+ | a | a | ... | a | a |
+ | A | A-1 | | 1 | 0 |
+ +-------+-------+-/ /-+-------+-------+
+
+
+ +-------+-------+-/ /-+-------+-------+
+ | b | b | ... | b | b |
+ | B | B-1 | | 1 | 0 |
+ +-------+-------+-/ /-+-------+-------+
+
+
+ +-------+-------+-/ /-+-------+-/ /-+-------+-------+
+ | p | p | ... | p | ... | p | p |
+ | A+B+1| A+B | | N | | 1 | 0 |
+ +-------+-------+-/ /-+-------+-/ /-+-------+-------+
+
+ /^\
+ (carry) a .b ... | ... a .b a .b
+ A B | 0 1 0 0
+ |
+ ... | ... a .b
+ | 1 0
+ |
+ | ...
+ |
+ |
+ |
+ | ___
+ | \
+ +----- P = > a .b
+ N /__ i j
+
+ N = 0 ... A+B
+
+ for all i,j where i+j=N
+ [i,j integers > 0]
+
+ a[], b[], p[] may not intersect.
+ Zero length factors signify 0 significant bits: treat as 0.0.
+ 0.0 factors do the right thing.
+ Zero length product OK.
+
+ I chose the ForTran accent "foo[bar]" instead of the C accent "*garply"
+ because I felt the ForTran way was more intuitive. The C way would
+ probably yield better code on most C compilers. Dean Elsner.
+ (C style also gives deeper insight [to me] ... oh well ...)
+ */
+
+void flonum_multip (a, b, product)
+const FLONUM_TYPE *a;
+const FLONUM_TYPE *b;
+FLONUM_TYPE *product;
+{
+ int size_of_a; /* 0 origin */
+ int size_of_b; /* 0 origin */
+ int size_of_product; /* 0 origin */
+ int size_of_sum; /* 0 origin */
+ int extra_product_positions;/* 1 origin */
+ unsigned long work;
+ unsigned long carry;
+ long exponent;
+ LITTLENUM_TYPE * q;
+ long significant; /* TRUE when we emit a non-0 littlenum */
+ /* ForTran accent follows. */
+ int P; /* Scan product low-order -> high. */
+ int N; /* As in sum above. */
+ int A; /* Which [] of a? */
+ int B; /* Which [] of b? */
+
+ if ((a->sign != '-' && a->sign != '+') || (b->sign != '-' && b->sign != '+')) {
+ /* ...
+ Got to fail somehow. Any suggestions? */
+ product->sign=0;
+ return;
+ }
+ product->sign = (a->sign == b->sign) ? '+' : '-';
+ size_of_a = a->leader - a->low;
+ size_of_b = b->leader - b->low;
+ exponent = a->exponent + b->exponent;
+ size_of_product = product->high - product->low;
+ size_of_sum = size_of_a + size_of_b;
+ extra_product_positions = size_of_product - size_of_sum;
+ if (extra_product_positions < 0)
+ {
+ P = extra_product_positions; /* P < 0 */
+ exponent -= extra_product_positions; /* Increases exponent. */
+ }
+ else
+ {
+ P = 0;
+ }
+ carry = 0;
+ significant = 0;
+ for (N = 0;
+ N <= size_of_sum;
+ N++)
+ {
+ work = carry;
+ carry = 0;
+ for (A = 0;
+ A <= N;
+ A ++)
+ {
+ B = N - A;
+ if (A <= size_of_a && B <= size_of_b && B >= 0)
+ {
+#ifdef TRACE
+ printf("a:low[%d.]=%04x b:low[%d.]=%04x work_before=%08x\n", A, a->low[A], B, b->low[B], work);
+#endif
+ work += a->low[A] * b->low[B];
+ carry += work >> LITTLENUM_NUMBER_OF_BITS;
+ work &= LITTLENUM_MASK;
+#ifdef TRACE
+ printf("work=%08x carry=%04x\n", work, carry);
+#endif
+ }
+ }
+ significant |= work;
+ if (significant || P<0)
+ {
+ if (P >= 0)
+ {
+ product->low[P] = work;
+#ifdef TRACE
+ printf("P=%d. work[p]:=%04x\n", P, work);
+#endif
+ }
+ P ++;
+ }
+ else
+ {
+ extra_product_positions ++;
+ exponent ++;
+ }
+ }
+ /*
+ * [P]->position # size_of_sum + 1.
+ * This is where 'carry' should go.
+ */
+#ifdef TRACE
+ printf("final carry =%04x\n", carry);
+#endif
+ if (carry)
+ {
+ if (extra_product_positions > 0)
+ {
+ product->low[P] = carry;
+ }
+ else
+ {
+ /* No room at high order for carry littlenum. */
+ /* Shift right 1 to make room for most significant littlenum. */
+ exponent ++;
+ P --;
+ for (q = product->low + P;
+ q >= product->low;
+ q --)
+ {
+ work = * q;
+ * q = carry;
+ carry = work;
+ }
+ }
+ }
+ else
+ {
+ P --;
+ }
+ product->leader = product->low + P;
+ product->exponent = exponent;
+}
+
+/* end of flonum_mult.c */
diff --git a/gnu/usr.bin/as/flonum.h b/gnu/usr.bin/as/flonum.h
new file mode 100644
index 0000000..c0ed416
--- /dev/null
+++ b/gnu/usr.bin/as/flonum.h
@@ -0,0 +1,125 @@
+/* flonum.h - Floating point package
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+/***********************************************************************\
+ * *
+ * Arbitrary-precision floating point arithmetic. *
+ * *
+ * *
+ * Notation: a floating point number is expressed as *
+ * MANTISSA * (2 ** EXPONENT). *
+ * *
+ * If this offends more traditional mathematicians, then *
+ * please tell me your nomenclature for flonums! *
+ * *
+ \***********************************************************************/
+#if (__STDC__ != 1) && !defined(const)
+#define const /* empty */
+#endif
+
+#include "bignum.h"
+
+/***********************************************************************\
+ * *
+ * Variable precision floating point numbers. *
+ * *
+ * Exponent is the place value of the low littlenum. E.g.: *
+ * If 0: low points to the units littlenum. *
+ * If 1: low points to the LITTLENUM_RADIX littlenum. *
+ * If -1: low points to the 1/LITTLENUM_RADIX littlenum. *
+ * *
+ \***********************************************************************/
+
+/* JF: A sign value of 0 means we have been asked to assemble NaN
+ A sign value of 'P' means we've been asked to assemble +Inf
+ A sign value of 'N' means we've been asked to assemble -Inf
+ */
+struct FLONUM_STRUCT
+{
+ LITTLENUM_TYPE *low; /* low order littlenum of a bignum */
+ LITTLENUM_TYPE *high; /* high order littlenum of a bignum */
+ LITTLENUM_TYPE *leader; /* -> 1st non-zero littlenum */
+ /* If flonum is 0.0, leader == low-1 */
+ long exponent; /* base LITTLENUM_RADIX */
+ char sign; /* '+' or '-' */
+};
+
+typedef struct FLONUM_STRUCT FLONUM_TYPE;
+
+
+/***********************************************************************\
+ * *
+ * Since we can (& do) meet with exponents like 10^5000, it *
+ * is silly to make a table of ~ 10,000 entries, one for each *
+ * power of 10. We keep a table where item [n] is a struct *
+ * FLONUM_FLOATING_POINT representing 10^(2^n). We then *
+ * multiply appropriate entries from this table to get any *
+ * particular power of 10. For the example of 10^5000, a table *
+ * of just 25 entries suffices: 10^(2^-12)...10^(2^+12). *
+ * *
+ \***********************************************************************/
+
+
+extern const FLONUM_TYPE flonum_positive_powers_of_ten[];
+extern const FLONUM_TYPE flonum_negative_powers_of_ten[];
+extern const int table_size_of_flonum_powers_of_ten;
+/* Flonum_XXX_powers_of_ten[] table has */
+/* legal indices from 0 to */
+/* + this number inclusive. */
+
+
+
+/***********************************************************************\
+ * *
+ * Declare worker functions. *
+ * *
+ \***********************************************************************/
+
+#if __STDC__ == 1
+
+int atof_generic(char **address_of_string_pointer,
+ const char *string_of_decimal_marks,
+ const char *string_of_decimal_exponent_marks,
+ FLONUM_TYPE *address_of_generic_floating_point_number);
+
+void flonum_copy(FLONUM_TYPE *in, FLONUM_TYPE *out);
+void flonum_multip(const FLONUM_TYPE *a, const FLONUM_TYPE *b, FLONUM_TYPE *product);
+
+#else /* not __STDC__ */
+
+int atof_generic();
+void flonum_copy();
+void flonum_multip();
+
+#endif /* not __STDC__ */
+
+/***********************************************************************\
+ * *
+ * Declare error codes. *
+ * *
+ \***********************************************************************/
+
+#define ERROR_EXPONENT_OVERFLOW (2)
+
+/* end of flonum.h */
diff --git a/gnu/usr.bin/as/frags.c b/gnu/usr.bin/as/frags.c
new file mode 100644
index 0000000..dcdb4c5
--- /dev/null
+++ b/gnu/usr.bin/as/frags.c
@@ -0,0 +1,296 @@
+/* frags.c - manage frags -
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+
+struct obstack frags; /* All, and only, frags live here. */
+
+fragS zero_address_frag = {
+ 0, /* fr_address */
+ NULL, /* fr_next */
+ 0, /* fr_fix */
+ 0, /* fr_var */
+ 0, /* fr_symbol */
+ 0, /* fr_offset */
+ NULL, /* fr_opcode */
+ rs_fill, /* fr_type */
+ 0, /* fr_subtype */
+ 0, /* fr_pcrel_adjust */
+ 0, /* fr_bsr */
+ 0 /* fr_literal[0] */
+ };
+
+fragS bss_address_frag = {
+ 0, /* fr_address. Gets filled in to make up
+ sy_value-s. */
+ NULL, /* fr_next */
+ 0, /* fr_fix */
+ 0, /* fr_var */
+ 0, /* fr_symbol */
+ 0, /* fr_offset */
+ NULL, /* fr_opcode */
+ rs_fill, /* fr_type */
+ 0, /* fr_subtype */
+ 0, /* fr_pcrel_adjust */
+ 0, /* fr_bsr */
+ 0 /* fr_literal[0] */
+ };
+
+/*
+ * frag_grow()
+ *
+ * Internal.
+ * Try to augment current frag by nchars chars.
+ * If there is no room, close of the current frag with a ".fill 0"
+ * and begin a new frag. Unless the new frag has nchars chars available
+ * do not return. Do not set up any fields of *now_frag.
+ */
+static void frag_grow(nchars)
+unsigned int nchars;
+{
+ if (obstack_room (&frags) < nchars) {
+ unsigned int n,oldn;
+ long oldc;
+
+ frag_wane(frag_now);
+ frag_new(0);
+ oldn=(unsigned)-1;
+ oldc=frags.chunk_size;
+ frags.chunk_size=2*nchars;
+ while ((n=obstack_room(&frags))<nchars && n<oldn) {
+ frag_wane(frag_now);
+ frag_new(0);
+ oldn=n;
+ }
+ frags.chunk_size=oldc;
+ }
+ if (obstack_room (&frags) < nchars)
+ as_fatal("Can't extend frag %d. chars", nchars);
+} /* frag_grow() */
+
+/*
+ * frag_new()
+ *
+ * Call this to close off a completed frag, and start up a new (empty)
+ * frag, in the same subsegment as the old frag.
+ * [frchain_now remains the same but frag_now is updated.]
+ * Because this calculates the correct value of fr_fix by
+ * looking at the obstack 'frags', it needs to know how many
+ * characters at the end of the old frag belong to (the maximal)
+ * fr_var: the rest must belong to fr_fix.
+ * It doesn't actually set up the old frag's fr_var: you may have
+ * set fr_var == 1, but allocated 10 chars to the end of the frag:
+ * in this case you pass old_frags_var_max_size == 10.
+ *
+ * Make a new frag, initialising some components. Link new frag at end
+ * of frchain_now.
+ */
+void frag_new(old_frags_var_max_size)
+int old_frags_var_max_size; /* Number of chars (already allocated on
+ obstack frags) */
+/* in variable_length part of frag. */
+{
+ register fragS * former_last_fragP;
+ /* char *throw_away_pointer; JF unused */
+ register frchainS * frchP;
+ long tmp; /* JF */
+
+ frag_now->fr_fix = (char *) (obstack_next_free (&frags)) -
+ (frag_now->fr_literal) - old_frags_var_max_size;
+ /* Fix up old frag's fr_fix. */
+
+ obstack_finish (&frags);
+ /* This will align the obstack so the */
+ /* next struct we allocate on it will */
+ /* begin at a correct boundary. */
+ frchP = frchain_now;
+ know (frchP);
+ former_last_fragP = frchP->frch_last;
+ know (former_last_fragP);
+ know (former_last_fragP == frag_now);
+ obstack_blank (&frags, SIZEOF_STRUCT_FRAG);
+ /* We expect this will begin at a correct */
+ /* boundary for a struct. */
+ tmp=obstack_alignment_mask(&frags);
+ obstack_alignment_mask(&frags)=0; /* Turn off alignment */
+ /* If we ever hit a machine
+ where strings must be
+ aligned, we Lose Big */
+ frag_now=(fragS *)obstack_finish(&frags);
+ obstack_alignment_mask(&frags)=tmp; /* Restore alignment */
+
+ /* Just in case we don't get zero'd bytes */
+ memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
+
+ /* obstack_unaligned_done (&frags, &frag_now); */
+ /* know (frags.obstack_c_next_free == frag_now->fr_literal); */
+ /* Generally, frag_now->points to an */
+ /* address rounded up to next alignment. */
+ /* However, characters will add to obstack */
+ /* frags IMMEDIATELY after the struct frag, */
+ /* even if they are not starting at an */
+ /* alignment address. */
+ former_last_fragP->fr_next = frag_now;
+ frchP->frch_last = frag_now;
+
+#ifndef NO_LISTING
+ {
+ extern struct list_info_struct *listing_tail;
+ frag_now->line = listing_tail;
+ }
+#endif
+
+ frag_now->fr_next = NULL;
+} /* frag_new() */
+
+/*
+ * frag_more()
+ *
+ * Start a new frag unless we have n more chars of room in the current frag.
+ * Close off the old frag with a .fill 0.
+ *
+ * Return the address of the 1st char to write into. Advance
+ * frag_now_growth past the new chars.
+ */
+
+char *frag_more (nchars)
+int nchars;
+{
+ register char *retval;
+
+ frag_grow (nchars);
+ retval = obstack_next_free (&frags);
+ obstack_blank_fast (&frags, nchars);
+ return (retval);
+} /* frag_more() */
+
+/*
+ * frag_var()
+ *
+ * Start a new frag unless we have max_chars more chars of room in the current frag.
+ * Close off the old frag with a .fill 0.
+ *
+ * Set up a machine_dependent relaxable frag, then start a new frag.
+ * Return the address of the 1st char of the var part of the old frag
+ * to write into.
+ */
+
+char *frag_var(type, max_chars, var, subtype, symbol, offset, opcode)
+relax_stateT type;
+int max_chars;
+int var;
+relax_substateT subtype;
+symbolS *symbol;
+long offset;
+char *opcode;
+{
+ register char *retval;
+
+ frag_grow (max_chars);
+ retval = obstack_next_free (&frags);
+ obstack_blank_fast (&frags, max_chars);
+ frag_now->fr_var = var;
+ frag_now->fr_type = type;
+ frag_now->fr_subtype = subtype;
+ frag_now->fr_symbol = symbol;
+ frag_now->fr_offset = offset;
+ frag_now->fr_opcode = opcode;
+ /* default these to zero. */
+ frag_now->fr_pcrel_adjust = 0;
+ frag_now->fr_bsr = 0;
+ frag_new (max_chars);
+ return (retval);
+} /* frag_var() */
+
+/*
+ * frag_variant()
+ *
+ * OVE: This variant of frag_var assumes that space for the tail has been
+ * allocated by caller.
+ * No call to frag_grow is done.
+ * Two new arguments have been added.
+ */
+
+char *frag_variant(type, max_chars, var, subtype, symbol, offset, opcode, pcrel_adjust,bsr)
+relax_stateT type;
+int max_chars;
+int var;
+relax_substateT subtype;
+symbolS *symbol;
+long offset;
+char *opcode;
+int pcrel_adjust;
+char bsr;
+{
+ register char *retval;
+
+ /* frag_grow (max_chars); */
+ retval = obstack_next_free (&frags);
+ /* obstack_blank_fast (&frags, max_chars); */ /* OVE: so far the only diff */
+ frag_now->fr_var = var;
+ frag_now->fr_type = type;
+ frag_now->fr_subtype = subtype;
+ frag_now->fr_symbol = symbol;
+ frag_now->fr_offset = offset;
+ frag_now->fr_opcode = opcode;
+ frag_now->fr_pcrel_adjust = pcrel_adjust;
+ frag_now->fr_bsr = bsr;
+ frag_new(max_chars);
+ return(retval);
+} /* frag_variant() */
+
+/*
+ * frag_wane()
+ *
+ * Reduce the variable end of a frag to a harmless state.
+ */
+void frag_wane(fragP)
+register fragS * fragP;
+{
+ fragP->fr_type = rs_fill;
+ fragP->fr_offset = 0;
+ fragP->fr_var = 0;
+}
+
+/*
+ * frag_align()
+ *
+ * Make a frag for ".align foo,bar". Call is "frag_align (foo,bar);".
+ * Foo & bar are absolute integers.
+ *
+ * Call to close off the current frag with a ".align", then start a new
+ * (so far empty) frag, in the same subsegment as the last frag.
+ */
+
+void frag_align(alignment, fill_character)
+int alignment;
+int fill_character;
+{
+ *(frag_var (rs_align, 1, 1, (relax_substateT)0, (symbolS *)0,
+ (long)alignment, (char *)0)) = fill_character;
+} /* frag_align() */
+
+/* end of frags.c */
diff --git a/gnu/usr.bin/as/frags.h b/gnu/usr.bin/as/frags.h
new file mode 100644
index 0000000..287d107
--- /dev/null
+++ b/gnu/usr.bin/as/frags.h
@@ -0,0 +1,89 @@
+/* frags.h - Header file for the frag concept.
+
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+extern struct obstack frags;
+/* Frags ONLY live in this obstack. */
+/* We use obstack_next_free() macro */
+/* so please don't put any other objects */
+/* on this stack! */
+
+/*
+ * A macro to speed up appending exactly 1 char
+ * to current frag.
+ */
+/* JF changed < 1 to <= 1 to avoid a race conditon */
+#define FRAG_APPEND_1_CHAR(datum) \
+{ \
+ if (obstack_room( &frags ) <= 1) {\
+ frag_wane (frag_now); \
+ frag_new (0); \
+ } \
+ obstack_1grow( &frags, datum ); \
+ }
+
+
+#if __STDC__ == 1
+
+char *frag_more(int nchars);
+void frag_align(int alignment, int fill_character);
+void frag_new(int old_frags_var_max_size);
+void frag_wane(fragS *fragP);
+
+char *frag_variant(relax_stateT type,
+ int max_chars,
+ int var,
+ relax_substateT subtype,
+ symbolS *symbol,
+ long offset,
+ char *opcode,
+ int pcrel_adjust,
+ int bsr);
+
+char *frag_var(relax_stateT type,
+ int max_chars,
+ int var,
+ relax_substateT subtype,
+ symbolS *symbol,
+ long offset,
+ char *opcode);
+
+#else /* not __STDC__ */
+
+char *frag_more();
+char *frag_var();
+char *frag_variant();
+void frag_align();
+void frag_new();
+void frag_wane();
+
+#endif /* not __STDC__ */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of frags.h */
diff --git a/gnu/usr.bin/as/gas-format.el b/gnu/usr.bin/as/gas-format.el
new file mode 100644
index 0000000..32c6426
--- /dev/null
+++ b/gnu/usr.bin/as/gas-format.el
@@ -0,0 +1,79 @@
+;; -*- lisp-interaction -*-
+;; -*- emacs-lisp -*-
+;;
+;;
+;; originally from...
+;; Rich's personal .emacs file. feel free to copy.
+;;
+;; this file sets emacs up for the type of C source code formatting used within
+;; gas. I don't use gnu indent. If you do, and find a setup that approximates
+;; these settings, please send it to me.
+;;
+;; Last Mod Thu Feb 13 00:59:16 PST 1992, by rich@sendai
+;;
+
+;;
+;;
+;; This section sets constants used by c-mode for formating
+;;
+;;
+
+
+;; If `c-auto-newline' is non-`nil', newlines are inserted both
+;;before and after braces that you insert, and after colons and semicolons.
+;;Correct C indentation is done on all the lines that are made this way.
+
+(setq c-auto-newline nil)
+
+
+;; If `c-tab-always-indent' is non-`nil', the TAB command
+;;in C mode does indentation only if point is at the left margin or within
+;;the line's indentation. If there is non-whitespace to the left of point,
+;;then TAB just inserts a tab character in the buffer. Normally,
+;;this variable is `nil', and TAB always reindents the current line.
+
+(setq c-tab-always-indent nil)
+
+;; C does not have anything analogous to particular function names for which
+;;special forms of indentation are desirable. However, it has a different
+;;need for customization facilities: many different styles of C indentation
+;;are in common use.
+;;
+;; There are six variables you can set to control the style that Emacs C
+;;mode will use.
+;;
+;;`c-indent-level'
+;; Indentation of C statements within surrounding block. The surrounding
+;; block's indentation is the indentation of the line on which the
+;; open-brace appears.
+
+(setq c-indent-level 8)
+
+;;`c-continued-statement-offset'
+;; Extra indentation given to a substatement, such as the then-clause of
+;; an if or body of a while.
+
+(setq c-continued-statement-offset 4)
+
+;;`c-brace-offset'
+;; Extra indentation for line if it starts with an open brace.
+
+(setq c-brace-offset 0)
+
+;;`c-brace-imaginary-offset'
+;; An open brace following other text is treated as if it were this far
+;; to the right of the start of its line.
+
+(setq c-brace-imaginary-offset 0)
+
+;;`c-argdecl-indent'
+;; Indentation level of declarations of C function arguments.
+
+(setq c-argdecl-indent 0)
+
+;;`c-label-offset'
+;; Extra indentation for line that is a label, or case or default.
+
+(setq c-label-offset -8)
+
+;; end of gas-format.el
diff --git a/gnu/usr.bin/as/hash.c b/gnu/usr.bin/as/hash.c
new file mode 100644
index 0000000..dae2746
--- /dev/null
+++ b/gnu/usr.bin/as/hash.c
@@ -0,0 +1,992 @@
+/* hash.c - hash table lookup strings -
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * BUGS, GRIPES, APOLOGIA etc.
+ *
+ * A typical user doesn't need ALL this: I intend to make a library out
+ * of it one day - Dean Elsner.
+ * Also, I want to change the definition of a symbol to (address,length)
+ * so I can put arbitrary binary in the names stored. [see hsh.c for that]
+ *
+ * This slime is common coupled inside the module. Com-coupling (and other
+ * vandalism) was done to speed running time. The interfaces at the
+ * module's edges are adequately clean.
+ *
+ * There is no way to (a) run a test script through this heap and (b)
+ * compare results with previous scripts, to see if we have broken any
+ * code. Use GNU (f)utilities to do this. A few commands assist test.
+ * The testing is awkward: it tries to be both batch & interactive.
+ * For now, interactive rules!
+ */
+
+/*
+ * The idea is to implement a symbol table. A test jig is here.
+ * Symbols are arbitrary strings; they can't contain '\0'.
+ * [See hsh.c for a more general symbol flavour.]
+ * Each symbol is associated with a char*, which can point to anything
+ * you want, allowing an arbitrary property list for each symbol.
+ *
+ * The basic operations are:
+ *
+ * new creates symbol table, returns handle
+ * find (symbol) returns char*
+ * insert (symbol,char*) error if symbol already in table
+ * delete (symbol) returns char* if symbol was in table
+ * apply so you can delete all symbols before die()
+ * die destroy symbol table (free up memory)
+ *
+ * Supplementary functions include:
+ *
+ * say how big? what % full?
+ * replace (symbol,newval) report previous value
+ * jam (symbol,value) assert symbol:=value
+ *
+ * You, the caller, have control over errors: this just reports them.
+ *
+ * This package requires malloc(), free().
+ * Malloc(size) returns NULL or address of char[size].
+ * Free(address) frees same.
+ */
+
+/*
+ * The code and its structures are re-enterent.
+ * Before you do anything else, you must call hash_new() which will
+ * return the address of a hash-table-control-block (or NULL if there
+ * is not enough memory). You then use this address as a handle of the
+ * symbol table by passing it to all the other hash_...() functions.
+ * The only approved way to recover the memory used by the symbol table
+ * is to call hash_die() with the handle of the symbol table.
+ *
+ * Before you call hash_die() you normally delete anything pointed to
+ * by individual symbols. After hash_die() you can't use that symbol
+ * table again.
+ *
+ * The char* you associate with a symbol may not be NULL (0) because
+ * NULL is returned whenever a symbol is not in the table. Any other
+ * value is OK, except DELETED, #defined below.
+ *
+ * When you supply a symbol string for insertion, YOU MUST PRESERVE THE
+ * STRING until that symbol is deleted from the table. The reason is that
+ * only the address you supply, NOT the symbol string itself, is stored
+ * in the symbol table.
+ *
+ * You may delete and add symbols arbitrarily.
+ * Any or all symbols may have the same 'value' (char *). In fact, these
+ * routines don't do anything with your symbol values.
+ *
+ * You have no right to know where the symbol:char* mapping is stored,
+ * because it moves around in memory; also because we may change how it
+ * works and we don't want to break your code do we? However the handle
+ * (address of struct hash_control) is never changed in
+ * the life of the symbol table.
+ *
+ * What you CAN find out about a symbol table is:
+ * how many slots are in the hash table?
+ * how many slots are filled with symbols?
+ * (total hashes,collisions) for (reads,writes) (*)
+ * All of the above values vary in time.
+ * (*) some of these numbers will not be meaningful if we change the
+ * internals.
+ */
+
+/*
+ * I N T E R N A L
+ *
+ * Hash table is an array of hash_entries; each entry is a pointer to a
+ * a string and a user-supplied value 1 char* wide.
+ *
+ * The array always has 2 ** n elements, n>0, n integer.
+ * There is also a 'wall' entry after the array, which is always empty
+ * and acts as a sentinel to stop running off the end of the array.
+ * When the array gets too full, we create a new array twice as large
+ * and re-hash the symbols into the new array, then forget the old array.
+ * (Of course, we copy the values into the new array before we junk the
+ * old array!)
+ *
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <stdio.h>
+
+#ifndef FALSE
+#define FALSE (0)
+#define TRUE (!FALSE)
+#endif /* no FALSE yet */
+
+#include <ctype.h>
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+#include "as.h"
+
+#define error as_fatal
+
+#define DELETED ((char *)1) /* guarenteed invalid address */
+#define START_POWER (11) /* power of two: size of new hash table *//* JF was 6 */
+/* JF These next two aren't used any more. */
+/* #define START_SIZE (64) / * 2 ** START_POWER */
+/* #define START_FULL (32) / * number of entries before table expands */
+#define islive(ptr) (ptr->hash_string && ptr->hash_string != DELETED)
+/* above TRUE if a symbol is in entry @ ptr */
+
+#define STAT_SIZE (0) /* number of slots in hash table */
+/* the wall does not count here */
+/* we expect this is always a power of 2 */
+#define STAT_ACCESS (1) /* number of hash_ask()s */
+#define STAT__READ (0) /* reading */
+#define STAT__WRITE (1) /* writing */
+#define STAT_COLLIDE (3) /* number of collisions (total) */
+/* this may exceed STAT_ACCESS if we have */
+/* lots of collisions/access */
+#define STAT_USED (5) /* slots used right now */
+#define STATLENGTH (6) /* size of statistics block */
+#if STATLENGTH != HASH_STATLENGTH
+Panic! Please make #include "stat.h" agree with previous definitions!
+#endif
+
+ /* #define SUSPECT to do runtime checks */
+ /* #define TEST to be a test jig for hash...() */
+
+#ifdef TEST /* TEST: use smaller hash table */
+#undef START_POWER
+#define START_POWER (3)
+#undef START_SIZE
+#define START_SIZE (8)
+#undef START_FULL
+#define START_FULL (4)
+#endif
+
+/*------------------ plan ---------------------------------- i = internal
+
+ struct hash_control * c;
+ struct hash_entry * e; i
+ int b[z]; buffer for statistics
+ z size of b
+ char * s; symbol string (address) [ key ]
+ char * v; value string (address) [datum]
+ boolean f; TRUE if we found s in hash table i
+ char * t; error string; "" means OK
+ int a; access type [0...n) i
+
+ c=hash_new () create new hash_control
+
+ hash_die (c) destroy hash_control (and hash table)
+ table should be empty.
+ doesn't check if table is empty.
+ c has no meaning after this.
+
+ hash_say (c,b,z) report statistics of hash_control.
+ also report number of available statistics.
+
+ v=hash_delete (c,s) delete symbol, return old value if any.
+ ask() NULL means no old value.
+ f
+
+ v=hash_replace (c,s,v) replace old value of s with v.
+ ask() NULL means no old value: no table change.
+ f
+
+ t=hash_insert (c,s,v) insert (s,v) in c.
+ ask() return error string.
+ f it is an error to insert if s is already
+ in table.
+ if any error, c is unchanged.
+
+ t=hash_jam (c,s,v) assert that new value of s will be v. i
+ ask() it may decide to GROW the table. i
+ f i
+ grow() i
+ t=hash_grow (c) grow the hash table. i
+ jam() will invoke JAM. i
+
+ ?=hash_apply (c,y) apply y() to every symbol in c.
+ y evtries visited in 'unspecified' order.
+
+ v=hash_find (c,s) return value of s, or NULL if s not in c.
+ ask()
+ f
+
+ f,e=hash_ask() (c,s,a) return slot where s SHOULD live. i
+ code() maintain collision stats in c. i
+
+ .=hash_code (c,s) compute hash-code for s, i
+ from parameters of c. i
+
+ */
+
+static char hash_found; /* returned by hash_ask() to stop extra */
+/* testing. hash_ask() wants to return both */
+/* a slot and a status. This is the status. */
+/* TRUE: found symbol */
+/* FALSE: absent: empty or deleted slot */
+/* Also returned by hash_jam(). */
+/* TRUE: we replaced a value */
+/* FALSE: we inserted a value */
+
+static struct hash_entry * hash_ask();
+static int hash_code ();
+static char * hash_grow();
+
+/*
+ * h a s h _ n e w ( )
+ *
+ */
+struct hash_control *
+ hash_new() /* create a new hash table */
+/* return NULL if failed */
+/* return handle (address of struct hash) */
+{
+ register struct hash_control * retval;
+ register struct hash_entry * room; /* points to hash table */
+ register struct hash_entry * wall;
+ register struct hash_entry * entry;
+ register int * ip; /* scan stats block of struct hash_control */
+ register int * nd; /* limit of stats block */
+
+ if (( room = (struct hash_entry *) malloc( sizeof(struct
+ hash_entry)*((1<<START_POWER) + 1) ) ) != NULL)
+ /* +1 for the wall entry */
+ {
+ if (( retval = (struct hash_control *) malloc(sizeof(struct
+ hash_control)) ) != NULL)
+ {
+ nd = retval->hash_stat + STATLENGTH;
+ for (ip=retval->hash_stat; ip<nd; ip++)
+ {
+ *ip = 0;
+ }
+
+ retval->hash_stat[STAT_SIZE] = 1<<START_POWER;
+ retval->hash_mask = (1<<START_POWER) - 1;
+ retval->hash_sizelog = START_POWER;
+ /* works for 1's compl ok */
+ retval->hash_where = room;
+ retval->hash_wall =
+ wall = room + (1<<START_POWER);
+ retval->hash_full = (1<<START_POWER)/2;
+ for (entry=room; entry <= wall; entry++)
+ {
+ entry->hash_string = NULL;
+ }
+ }
+ }
+ else
+ {
+ retval = NULL; /* no room for table: fake a failure */
+ }
+ return(retval); /* return NULL or set-up structs */
+}
+
+/*
+ * h a s h _ d i e ( )
+ *
+ * Table should be empty, but this is not checked.
+ * To empty the table, try hash_apply()ing a symbol deleter.
+ * Return to free memory both the hash table and it's control
+ * block.
+ * 'handle' has no meaning after this function.
+ * No errors are recoverable.
+ */
+void
+ hash_die(handle)
+struct hash_control * handle;
+{
+ free((char *)handle->hash_where);
+ free((char *)handle);
+}
+
+/*
+ * h a s h _ s a y ( )
+ *
+ * Return the size of the statistics table, and as many statistics as
+ * we can until either (a) we have run out of statistics or (b) caller
+ * has run out of buffer.
+ * NOTE: hash_say treats all statistics alike.
+ * These numbers may change with time, due to insertions, deletions
+ * and expansions of the table.
+ * The first "statistic" returned is the length of hash_stat[].
+ * Then contents of hash_stat[] are read out (in ascending order)
+ * until your buffer or hash_stat[] is exausted.
+ */
+void
+ hash_say(handle,buffer,bufsiz)
+register struct hash_control * handle;
+register int buffer[/*bufsiz*/];
+register int bufsiz;
+{
+ register int * nd; /* limit of statistics block */
+ register int * ip; /* scan statistics */
+
+ ip = handle->hash_stat;
+ nd = ip + min(bufsiz-1,STATLENGTH);
+ if (bufsiz>0) /* trust nothing! bufsiz <= 0 is dangerous */
+ {
+ *buffer++ = STATLENGTH;
+ for (; ip<nd; ip++,buffer++)
+ {
+ *buffer = *ip;
+ }
+ }
+}
+
+/*
+ * h a s h _ d e l e t e ( )
+ *
+ * Try to delete a symbol from the table.
+ * If it was there, return its value (and adjust STAT_USED).
+ * Otherwise, return NULL.
+ * Anyway, the symbol is not present after this function.
+ *
+ */
+char * /* NULL if string not in table, else */
+ /* returns value of deleted symbol */
+ hash_delete(handle,string)
+register struct hash_control * handle;
+register char * string;
+{
+ register char * retval; /* NULL if string not in table */
+ register struct hash_entry * entry; /* NULL or entry of this symbol */
+
+ entry = hash_ask(handle,string,STAT__WRITE);
+ if (hash_found)
+ {
+ retval = entry->hash_value;
+ entry->hash_string = DELETED; /* mark as deleted */
+ handle->hash_stat[STAT_USED] -= 1; /* slots-in-use count */
+#ifdef SUSPECT
+ if (handle->hash_stat[STAT_USED]<0)
+ {
+ error("hash_delete");
+ }
+#endif /* def SUSPECT */
+ }
+ else
+ {
+ retval = NULL;
+ }
+ return(retval);
+}
+
+/*
+ * h a s h _ r e p l a c e ( )
+ *
+ * Try to replace the old value of a symbol with a new value.
+ * Normally return the old value.
+ * Return NULL and don't change the table if the symbol is not already
+ * in the table.
+ */
+char *
+ hash_replace(handle,string,value)
+register struct hash_control * handle;
+register char * string;
+register char * value;
+{
+ register struct hash_entry * entry;
+ register char * retval;
+
+ entry = hash_ask(handle,string,STAT__WRITE);
+ if (hash_found)
+ {
+ retval = entry->hash_value;
+ entry->hash_value = value;
+ }
+ else
+ {
+ retval = NULL;
+ }
+ ;
+ return (retval);
+}
+
+/*
+ * h a s h _ i n s e r t ( )
+ *
+ * Insert a (symbol-string, value) into the hash table.
+ * Return an error string, "" means OK.
+ * It is an 'error' to insert an existing symbol.
+ */
+
+char * /* return error string */
+ hash_insert(handle,string,value)
+register struct hash_control * handle;
+register char * string;
+register char * value;
+{
+ register struct hash_entry * entry;
+ register char * retval;
+
+ retval = "";
+ if (handle->hash_stat[STAT_USED] > handle->hash_full)
+ {
+ retval = hash_grow(handle);
+ }
+ if ( ! * retval)
+ {
+ entry = hash_ask(handle,string,STAT__WRITE);
+ if (hash_found)
+ {
+ retval = "exists";
+ }
+ else
+ {
+ entry->hash_value = value;
+ entry->hash_string = string;
+ handle->hash_stat[STAT_USED] += 1;
+ }
+ }
+ return(retval);
+}
+
+/*
+ * h a s h _ j a m ( )
+ *
+ * Regardless of what was in the symbol table before, after hash_jam()
+ * the named symbol has the given value. The symbol is either inserted or
+ * (its value is) relpaced.
+ * An error message string is returned, "" means OK.
+ *
+ * WARNING: this may decide to grow the hashed symbol table.
+ * To do this, we call hash_grow(), WHICH WILL recursively CALL US.
+ *
+ * We report status internally: hash_found is TRUE if we replaced, but
+ * false if we inserted.
+ */
+char *
+ hash_jam(handle,string,value)
+register struct hash_control * handle;
+register char * string;
+register char * value;
+{
+ register char * retval;
+ register struct hash_entry * entry;
+
+ retval = "";
+ if (handle->hash_stat[STAT_USED] > handle->hash_full)
+ {
+ retval = hash_grow(handle);
+ }
+ if (! * retval)
+ {
+ entry = hash_ask(handle,string,STAT__WRITE);
+ if ( ! hash_found)
+ {
+ entry->hash_string = string;
+ handle->hash_stat[STAT_USED] += 1;
+ }
+ entry->hash_value = value;
+ }
+ return(retval);
+}
+
+/*
+ * h a s h _ g r o w ( )
+ *
+ * Grow a new (bigger) hash table from the old one.
+ * We choose to double the hash table's size.
+ * Return a human-scrutible error string: "" if OK.
+ * Warning! This uses hash_jam(), which had better not recurse
+ * back here! Hash_jam() conditionally calls us, but we ALWAYS
+ * call hash_jam()!
+ * Internal.
+ */
+static char *
+ hash_grow(handle) /* make a hash table grow */
+struct hash_control * handle;
+{
+ register struct hash_entry * newwall;
+ register struct hash_entry * newwhere;
+ struct hash_entry * newtrack;
+ register struct hash_entry * oldtrack;
+ register struct hash_entry * oldwhere;
+ register struct hash_entry * oldwall;
+ register int temp;
+ int newsize;
+ char * string;
+ char * retval;
+#ifdef SUSPECT
+ int oldused;
+#endif
+
+ /*
+ * capture info about old hash table
+ */
+ oldwhere = handle->hash_where;
+ oldwall = handle->hash_wall;
+#ifdef SUSPECT
+ oldused = handle->hash_stat[STAT_USED];
+#endif
+ /*
+ * attempt to get enough room for a hash table twice as big
+ */
+ temp = handle->hash_stat[STAT_SIZE];
+ if (( newwhere = (struct hash_entry *)
+ xmalloc((long)((temp+temp+1)*sizeof(struct hash_entry)))) != NULL)
+ /* +1 for wall slot */
+ {
+ retval = ""; /* assume success until proven otherwise */
+ /*
+ * have enough room: now we do all the work.
+ * double the size of everything in handle,
+ * note: hash_mask frob works for 1's & for 2's complement machines
+ */
+ handle->hash_mask = handle->hash_mask + handle->hash_mask + 1;
+ handle->hash_stat[STAT_SIZE] <<= 1;
+ newsize = handle->hash_stat[STAT_SIZE];
+ handle->hash_where = newwhere;
+ handle->hash_full <<= 1;
+ handle->hash_sizelog += 1;
+ handle->hash_stat[STAT_USED] = 0;
+ handle->hash_wall =
+ newwall = newwhere + newsize;
+ /*
+ * set all those pesky new slots to vacant.
+ */
+ for (newtrack=newwhere; newtrack <= newwall; newtrack++)
+ {
+ newtrack->hash_string = NULL;
+ }
+ /*
+ * we will do a scan of the old table, the hard way, using the
+ * new control block to re-insert the data into new hash table.
+ */
+ handle->hash_stat[STAT_USED] = 0; /* inserts will bump it up to correct */
+ for (oldtrack=oldwhere; oldtrack < oldwall; oldtrack++)
+ {
+ if (((string = oldtrack->hash_string) != NULL) && string != DELETED)
+ {
+ if ( * (retval = hash_jam(handle,string,oldtrack->hash_value) ) )
+ {
+ break;
+ }
+ }
+ }
+#ifdef SUSPECT
+ if ( !*retval && handle->hash_stat[STAT_USED] != oldused)
+ {
+ retval = "hash_used";
+ }
+#endif
+ if (!*retval)
+ {
+ /*
+ * we have a completely faked up control block.
+ * return the old hash table.
+ */
+ free((char *)oldwhere);
+ /*
+ * Here with success. retval is already "".
+ */
+ }
+ }
+ else
+ {
+ retval = "no room";
+ }
+ return(retval);
+}
+
+/*
+ * h a s h _ a p p l y ( )
+ *
+ * Use this to scan each entry in symbol table.
+ * For each symbol, this calls (applys) a nominated function supplying the
+ * symbol's value (and the symbol's name).
+ * The idea is you use this to destroy whatever is associted with
+ * any values in the table BEFORE you destroy the table with hash_die.
+ * Of course, you can use it for other jobs; whenever you need to
+ * visit all extant symbols in the table.
+ *
+ * We choose to have a call-you-back idea for two reasons:
+ * asthetic: it is a neater idea to use apply than an explicit loop
+ * sensible: if we ever had to grow the symbol table (due to insertions)
+ * then we would lose our place in the table when we re-hashed
+ * symbols into the new table in a different order.
+ *
+ * The order symbols are visited depends entirely on the hashing function.
+ * Whenever you insert a (symbol, value) you risk expanding the table. If
+ * you do expand the table, then the hashing function WILL change, so you
+ * MIGHT get a different order of symbols visited. In other words, if you
+ * want the same order of visiting symbols as the last time you used
+ * hash_apply() then you better not have done any hash_insert()s or
+ * hash_jam()s since the last time you used hash_apply().
+ *
+ * In future we may use the value returned by your nominated function.
+ * One idea is to abort the scan if, after applying the function to a
+ * certain node, the function returns a certain code.
+ * To be safe, please make your functions of type char *. If you always
+ * return NULL, then the scan will complete, visiting every symbol in
+ * the table exactly once. ALL OTHER RETURNED VALUES have no meaning yet!
+ * Caveat Actor!
+ *
+ * The function you supply should be of the form:
+ * char * myfunct(string,value)
+ * char * string; |* the symbol's name *|
+ * char * value; |* the symbol's value *|
+ * {
+ * |* ... *|
+ * return(NULL);
+ * }
+ *
+ * The returned value of hash_apply() is (char*)NULL. In future it may return
+ * other values. NULL means "completed scan OK". Other values have no meaning
+ * yet. (The function has no graceful failures.)
+ */
+char *
+ hash_apply(handle,function)
+struct hash_control * handle;
+char* (*function)();
+{
+ register struct hash_entry * entry;
+ register struct hash_entry * wall;
+
+ wall = handle->hash_wall;
+ for (entry = handle->hash_where; entry < wall; entry++)
+ {
+ if (islive(entry)) /* silly code: tests entry->string twice! */
+ {
+ (*function)(entry->hash_string,entry->hash_value);
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * h a s h _ f i n d ( )
+ *
+ * Given symbol string, find value (if any).
+ * Return found value or NULL.
+ */
+char *
+ hash_find(handle,string) /* return char* or NULL */
+struct hash_control * handle;
+char * string;
+{
+ register struct hash_entry * entry;
+ register char * retval;
+
+ entry = hash_ask(handle,string,STAT__READ);
+ if (hash_found)
+ {
+ retval = entry->hash_value;
+ }
+ else
+ {
+ retval = NULL;
+ }
+ return(retval);
+}
+
+/*
+ * h a s h _ a s k ( )
+ *
+ * Searches for given symbol string.
+ * Return the slot where it OUGHT to live. It may be there.
+ * Return hash_found: TRUE only if symbol is in that slot.
+ * Access argument is to help keep statistics in control block.
+ * Internal.
+ */
+static struct hash_entry * /* string slot, may be empty or deleted */
+ hash_ask(handle,string,access)
+struct hash_control * handle;
+char * string;
+int access; /* access type */
+{
+ register char *string1; /* JF avoid strcmp calls */
+ register char * s;
+ register int c;
+ register struct hash_entry * slot;
+ register int collision; /* count collisions */
+
+ slot = handle->hash_where + hash_code(handle,string); /* start looking here */
+ handle->hash_stat[STAT_ACCESS+access] += 1;
+ collision = 0;
+ hash_found = FALSE;
+ while (((s = slot->hash_string) != NULL) && s != DELETED)
+ {
+ for (string1=string;;) {
+ if ((c= *s++) == 0) {
+ if (!*string1)
+ hash_found = TRUE;
+ break;
+ }
+ if (*string1++ != c)
+ break;
+ }
+ if (hash_found)
+ break;
+ collision++;
+ slot++;
+ }
+ /*
+ * slot: return:
+ * in use: we found string slot
+ * at empty:
+ * at wall: we fell off: wrap round ????
+ * in table: dig here slot
+ * at DELETED: dig here slot
+ */
+ if (slot == handle->hash_wall)
+ {
+ slot = handle->hash_where; /* now look again */
+ while (((s = slot->hash_string) != NULL) && s != DELETED)
+ {
+ for (string1=string;*s;string1++,s++) {
+ if (*string1 != *s)
+ break;
+ }
+ if (*s == *string1) {
+ hash_found = TRUE;
+ break;
+ }
+ collision++;
+ slot++;
+ }
+ /*
+ * slot: return:
+ * in use: we found it slot
+ * empty: wall: ERROR IMPOSSIBLE !!!!
+ * in table: dig here slot
+ * DELETED:dig here slot
+ */
+ }
+ /* fprintf(stderr,"hash_ask(%s)->%d(%d)\n",string,hash_code(handle,string),collision); */
+ handle->hash_stat[STAT_COLLIDE+access] += collision;
+ return(slot); /* also return hash_found */
+}
+
+/*
+ * h a s h _ c o d e
+ *
+ * Does hashing of symbol string to hash number.
+ * Internal.
+ */
+static int
+ hash_code(handle,string)
+struct hash_control * handle;
+register char * string;
+{
+ register long h; /* hash code built here */
+ register long c; /* each character lands here */
+ register int n; /* Amount to shift h by */
+
+ n = (handle->hash_sizelog - 3);
+ h = 0;
+ while ((c = *string++) != 0)
+ {
+ h += c;
+ h = (h<<3) + (h>>n) + c;
+ }
+ return (h & handle->hash_mask);
+}
+
+/*
+ * Here is a test program to exercise above.
+ */
+#ifdef TEST
+
+#define TABLES (6) /* number of hash tables to maintain */
+/* (at once) in any testing */
+#define STATBUFSIZE (12) /* we can have 12 statistics */
+
+int statbuf[STATBUFSIZE]; /* display statistics here */
+char answer[100]; /* human farts here */
+char * hashtable[TABLES]; /* we test many hash tables at once */
+char * h; /* points to curent hash_control */
+char ** pp;
+char * p;
+char * name;
+char * value;
+int size;
+int used;
+char command;
+int number; /* number 0:TABLES-1 of current hashed */
+/* symbol table */
+
+main()
+{
+ char (*applicatee());
+ char * hash_find();
+ char * destroy();
+ char * what();
+ struct hash_control * hash_new();
+ char * hash_replace();
+ int * ip;
+
+ number = 0;
+ h = 0;
+ printf("type h <RETURN> for help\n");
+ for (;;)
+ {
+ printf("hash_test command: ");
+ fgets(answer, 100, stdin);
+ command = answer[0];
+ if (isupper(command)) command = tolower(command); /* ecch! */
+ switch (command)
+ {
+ case '#':
+ printf("old hash table #=%d.\n",number);
+ whattable();
+ break;
+ case '?':
+ for (pp=hashtable; pp<hashtable+TABLES; pp++)
+ {
+ printf("address of hash table #%d control block is %xx\n"
+ ,pp-hashtable,*pp);
+ }
+ break;
+ case 'a':
+ hash_apply(h,applicatee);
+ break;
+ case 'd':
+ hash_apply(h,destroy);
+ hash_die(h);
+ break;
+ case 'f':
+ p = hash_find(h,name=what("symbol"));
+ printf("value of \"%s\" is \"%s\"\n",name,p?p:"NOT-PRESENT");
+ break;
+ case 'h':
+ printf("# show old, select new default hash table number\n");
+ printf("? display all hashtable control block addresses\n");
+ printf("a apply a simple display-er to each symbol in table\n");
+ printf("d die: destroy hashtable\n");
+ printf("f find value of nominated symbol\n");
+ printf("h this help\n");
+ printf("i insert value into symbol\n");
+ printf("j jam value into symbol\n");
+ printf("n new hashtable\n");
+ printf("r replace a value with another\n");
+ printf("s say what %% of table is used\n");
+ printf("q exit this program\n");
+ printf("x delete a symbol from table, report its value\n");
+ break;
+ case 'i':
+ p = hash_insert(h,name=what("symbol"),value=what("value"));
+ if (*p)
+ {
+ printf("symbol=\"%s\" value=\"%s\" error=%s\n",name,value,p);
+ }
+ break;
+ case 'j':
+ p = hash_jam(h,name=what("symbol"),value=what("value"));
+ if (*p)
+ {
+ printf("symbol=\"%s\" value=\"%s\" error=%s\n",name,value,p);
+ }
+ break;
+ case 'n':
+ h = hashtable[number] = (char *) hash_new();
+ break;
+ case 'q':
+ exit();
+ case 'r':
+ p = hash_replace(h,name=what("symbol"),value=what("value"));
+ printf("old value was \"%s\"\n",p?p:"{}");
+ break;
+ case 's':
+ hash_say(h,statbuf,STATBUFSIZE);
+ for (ip=statbuf; ip<statbuf+STATBUFSIZE; ip++)
+ {
+ printf("%d ",*ip);
+ }
+ printf("\n");
+ break;
+ case 'x':
+ p = hash_delete(h,name=what("symbol"));
+ printf("old value was \"%s\"\n",p?p:"{}");
+ break;
+ default:
+ printf("I can't understand command \"%c\"\n",command);
+ break;
+ }
+ }
+}
+
+char *
+ what(description)
+char * description;
+{
+ char * retval;
+ char * malloc();
+
+ printf(" %s : ",description);
+ fgets(answer, 100, stdin);
+ /* will one day clean up answer here */
+ retval = malloc(strlen(answer)+1);
+ if (!retval)
+ {
+ error("room");
+ }
+ (void)strcpy(retval,answer);
+ return(retval);
+}
+
+char *
+ destroy(string,value)
+char * string;
+char * value;
+{
+ free(string);
+ free(value);
+ return(NULL);
+}
+
+
+char *
+ applicatee(string,value)
+char * string;
+char * value;
+{
+ printf("%.20s-%.20s\n",string,value);
+ return(NULL);
+}
+
+whattable() /* determine number: what hash table to use */
+/* also determine h: points to hash_control */
+{
+
+ for (;;)
+ {
+ printf(" what hash table (%d:%d) ? ",0,TABLES-1);
+ fgets(answer, 100, stdin);
+ sscanf(answer,"%d",&number);
+ if (number >= 0 && number<TABLES)
+ {
+ h = hashtable[number];
+ if (!h)
+ {
+ printf("warning: current hash-table-#%d. has no hash-control\n",number);
+ }
+ return;
+ }
+ else
+ {
+ printf("invalid hash table number: %d\n",number);
+ }
+ }
+}
+
+
+
+#endif /* #ifdef TEST */
+
+/* end of hash.c */
diff --git a/gnu/usr.bin/as/hash.h b/gnu/usr.bin/as/hash.h
new file mode 100644
index 0000000..b6e8038
--- /dev/null
+++ b/gnu/usr.bin/as/hash.h
@@ -0,0 +1,65 @@
+/* hash.h - for hash.c
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+#ifndef hashH
+#define hashH
+
+struct hash_entry
+{
+ char *hash_string; /* points to where the symbol string is */
+ /* NULL means slot is not used */
+ /* DELETED means slot was deleted */
+ char *hash_value; /* user's datum, associated with symbol */
+};
+
+
+#define HASH_STATLENGTH (6)
+struct hash_control
+{
+ struct hash_entry *hash_where; /* address of hash table */
+ int hash_sizelog; /* Log of ( hash_mask + 1 ) */
+ int hash_mask; /* masks a hash into index into table */
+ int hash_full; /* when hash_stat[STAT_USED] exceeds this, */
+ /* grow table */
+ struct hash_entry * hash_wall; /* point just after last (usable) entry */
+ /* here we have some statistics */
+ int hash_stat[HASH_STATLENGTH]; /* lies & statistics */
+ /* we need STAT_USED & STAT_SIZE */
+};
+
+ /* fixme: prototype. */
+
+/* returns */
+struct hash_control *hash_new(); /* [control block] */
+void hash_die();
+void hash_say();
+char *hash_delete(); /* previous value */
+char *hash_relpace(); /* previous value */
+char *hash_insert(); /* error string */
+char *hash_apply(); /* 0 means OK */
+char *hash_find(); /* value */
+char *hash_jam(); /* error text (internal) */
+
+#endif /* #ifdef hashH */
+
+/* end of hash.h */
diff --git a/gnu/usr.bin/as/hex-value.c b/gnu/usr.bin/as/hex-value.c
new file mode 100644
index 0000000..9b52e88
--- /dev/null
+++ b/gnu/usr.bin/as/hex-value.c
@@ -0,0 +1,61 @@
+/* hex_value.c - char=>radix-value -
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Export: Hex_value[]. Converts digits to their radix-values.
+ * As distributed assumes 8 bits per char (256 entries) and ASCII.
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#define __ (42) /* blatently illegal digit value */
+/* exceeds any normal radix */
+
+#if (__STDC__ != 1) && !defined(const)
+#define const /* empty */
+#endif
+const char
+ hex_value[256] = { /* for fast ASCII -> binary */
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, __, __, __, __, __, __,
+ __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
+ __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
+ };
+
+#ifdef HO_VMS
+dummy2()
+{
+}
+#endif
+
+/* end of hex_value.c */
diff --git a/gnu/usr.bin/as/input-file.c b/gnu/usr.bin/as/input-file.c
new file mode 100644
index 0000000..23e6a32
--- /dev/null
+++ b/gnu/usr.bin/as/input-file.c
@@ -0,0 +1,327 @@
+/* input_file.c - Deal with Input Files -
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Confines all details of reading source bytes to this module.
+ * All O/S specific crocks should live here.
+ * What we lose in "efficiency" we gain in modularity.
+ * Note we don't need to #include the "as.h" file. No common coupling!
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#ifdef USG
+#define setbuffer(stream, buf, size) setvbuf((stream), (buf), _IOFBF, (size))
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "as.h"
+#include "input-file.h"
+
+/* This variable is non-zero if the file currently being read should be
+ preprocessed by app. It is zero if the file can be read straight in.
+ */
+int preprocess = 0;
+
+/*
+ * This code opens a file, then delivers BUFFER_SIZE character
+ * chunks of the file on demand.
+ * BUFFER_SIZE is supposed to be a number chosen for speed.
+ * The caller only asks once what BUFFER_SIZE is, and asks before
+ * the nature of the input files (if any) is known.
+ */
+
+#define BUFFER_SIZE (32 * 1024)
+
+/*
+ * We use static data: the data area is not sharable.
+ */
+
+FILE *f_in;
+/* static JF remove static so app.c can use file_name */
+char * file_name;
+
+/* Struct for saving the state of this module for file includes. */
+struct saved_file {
+ FILE *f_in;
+ char *file_name;
+ int preprocess;
+ char *app_save;
+};
+
+/* These hooks accomodate most operating systems. */
+
+void input_file_begin() {
+ f_in = (FILE *)0;
+}
+
+void input_file_end () { }
+
+/* Return BUFFER_SIZE. */
+int input_file_buffer_size() {
+ return (BUFFER_SIZE);
+}
+
+int input_file_is_open() {
+ return f_in != (FILE *)0;
+}
+
+/* Push the state of our input, returning a pointer to saved info that
+ can be restored with input_file_pop (). */
+char *input_file_push () {
+ register struct saved_file *saved;
+
+ saved = (struct saved_file *)xmalloc (sizeof *saved);
+
+ saved->f_in = f_in;
+ saved->file_name = file_name;
+ saved->preprocess = preprocess;
+ if (preprocess)
+ saved->app_save = app_push ();
+
+ input_file_begin (); /* Initialize for new file */
+
+ return (char *)saved;
+}
+
+void
+ input_file_pop (arg)
+char *arg;
+{
+ register struct saved_file *saved = (struct saved_file *)arg;
+
+ input_file_end (); /* Close out old file */
+
+ f_in = saved->f_in;
+ file_name = saved->file_name;
+ preprocess = saved->preprocess;
+ if (preprocess)
+ app_pop (saved->app_save);
+
+ free(arg);
+}
+
+#ifdef DONTDEF /* JF save old version in case we need it */
+void
+ input_file_open (filename, preprocess, debugging)
+char * filename; /* "" means use stdin. Must not be 0. */
+int preprocess; /* TRUE if needs app. */
+int debugging; /* TRUE if we are debugging assembler. */
+{
+ assert( filename != 0 ); /* Filename may not be NULL. */
+ if (filename[0])
+ { /* We have a file name. Suck it and see. */
+ file_handle = open (filename, O_RDONLY, 0);
+ file_name = filename;
+ }
+ else
+ { /* use stdin for the input file. */
+ file_handle = fileno (stdin);
+ file_name = "{standard input}"; /* For error messages. */
+ }
+ if (file_handle < 0)
+ as_perror ("Can't open %s for reading", file_name);
+ if ( preprocess )
+ {
+ /*
+ * This code was written in haste for a frobbed BSD 4.2.
+ * I have a flight to catch: will someone please do proper
+ * error checks? - Dean.
+ */
+ int pid;
+ char temporary_file_name[12];
+ int fd;
+ union wait status;
+
+ (void)strcpy (temporary_file_name, "#appXXXXXX");
+ (void)mktemp (temporary_file_name);
+ pid = vfork ();
+ if (pid == -1)
+ {
+ as_perror ("Vfork failed", file_name);
+ _exit (144);
+ }
+ if (pid == 0)
+ {
+ (void)dup2 (file_handle, fileno(stdin));
+ fd = open (temporary_file_name, O_WRONLY + O_TRUNC + O_CREAT, 0666);
+ if (fd == -1)
+ {
+ (void)write(2,"Can't open temporary\n",21);
+ _exit (99);
+ }
+ (void)dup2 (fd, fileno(stdout));
+ /* JF for testing #define PREPROCESSOR "/lib/app" */
+#define PREPROCESSOR "./app"
+ execl (PREPROCESSOR, PREPROCESSOR, (char *)0);
+ execl ("app","app",(char *)0);
+ (void)write(2,"Exec of app failed. Get help.\n",31);
+ (void)unlink(temporary_file_name);
+ _exit (11);
+ }
+ (void)wait (& status);
+ if (status.w_status & 0xFF00) /* JF was 0xF000, was wrong */
+ {
+ file_handle = -1;
+ as_bad( "Can't preprocess file \"%s\", status = %xx", file_name, status.w_status );
+ }
+ else
+ {
+ file_handle = open (temporary_file_name, O_RDONLY, 0);
+ if ( ! debugging && unlink(temporary_file_name))
+ as_perror ("Can't delete temp file %s", temporary_file_name);
+ }
+ if (file_handle == -1)
+ as_perror ("Can't retrieve temp file %s", temporary_file_name);
+ }
+}
+#else
+
+void
+ input_file_open (filename,pre)
+char * filename; /* "" means use stdin. Must not be 0. */
+int pre;
+{
+ int c;
+ char buf[80];
+
+ preprocess = pre;
+
+ assert( filename != 0 ); /* Filename may not be NULL. */
+ if (filename[0]) { /* We have a file name. Suck it and see. */
+ f_in=fopen(filename,"r");
+ file_name=filename;
+ } else { /* use stdin for the input file. */
+ f_in = stdin;
+ file_name = "{standard input}"; /* For error messages. */
+ }
+ if (f_in == (FILE *)0) {
+ as_perror ("Can't open %s for reading", file_name);
+ return;
+ }
+
+#ifndef HO_VMS
+ /* Ask stdio to buffer our input at BUFFER_SIZE, with a dynamically
+ allocated buffer. */
+ setvbuf(f_in, (char *)NULL, _IOFBF, BUFFER_SIZE);
+#endif /* HO_VMS */
+
+ c = getc(f_in);
+ if (c == '#') { /* Begins with comment, may not want to preprocess */
+ c = getc(f_in);
+ if (c == 'N') {
+ fgets(buf,80,f_in);
+ if (!strcmp(buf,"O_APP\n"))
+ preprocess=0;
+ if (!strchr(buf,'\n'))
+ ungetc('#',f_in); /* It was longer */
+ else
+ ungetc('\n',f_in);
+ } else if (c == '\n')
+ ungetc('\n',f_in);
+ else
+ ungetc('#',f_in);
+ } else
+ ungetc(c,f_in);
+
+#ifdef DONTDEF
+ if ( preprocess ) {
+ char temporary_file_name[17];
+ FILE *f_out;
+
+ (void)strcpy (temporary_file_name, "/tmp/#appXXXXXX");
+ (void)mktemp (temporary_file_name);
+ f_out=fopen(temporary_file_name,"w+");
+ if (f_out == (FILE *)0)
+ as_perror("Can't open temp file %s",temporary_file_name);
+
+ /* JF this will have to be moved on any system that
+ does not support removal of open files. */
+ (void)unlink(temporary_file_name);/* JF do it NOW */
+ do_scrub(f_in,f_out);
+ (void)fclose(f_in); /* All done with it */
+ (void)rewind(f_out);
+ f_in=f_out;
+ }
+#endif
+}
+#endif
+
+/* Close input file. */
+void input_file_close() {
+ if (f_in != NULL) {
+ fclose (f_in);
+ } /* don't close a null file pointer */
+ f_in = 0;
+} /* input_file_close() */
+
+char *
+ input_file_give_next_buffer (where)
+char * where; /* Where to place 1st character of new buffer. */
+{
+ char * return_value; /* -> Last char of what we read, + 1. */
+ register int size;
+
+ if (f_in == (FILE *)0)
+ return 0;
+ /*
+ * fflush (stdin); could be done here if you want to synchronise
+ * stdin and stdout, for the case where our input file is stdin.
+ * Since the assembler shouldn't do any output to stdout, we
+ * don't bother to synch output and input.
+ */
+ if (preprocess) {
+ char *p;
+ int n;
+ int ch;
+ extern FILE *scrub_file;
+
+ scrub_file=f_in;
+ for (p = where, n = BUFFER_SIZE; n; --n) {
+
+ ch = do_scrub_next_char(scrub_from_file, scrub_to_file);
+ if (ch == EOF)
+ break;
+ *p++=ch;
+ }
+ size=BUFFER_SIZE-n;
+ } else
+ size= fread(where,sizeof(char),BUFFER_SIZE,f_in);
+ if (size < 0)
+ {
+ as_perror ("Can't read from %s", file_name);
+ size = 0;
+ }
+ if (size)
+ return_value = where + size;
+ else
+ {
+ if (fclose (f_in))
+ as_perror ("Can't close %s", file_name);
+ f_in = (FILE *)0;
+ return_value = 0;
+ }
+ return (return_value);
+}
+
+/* end of input-file.c */
diff --git a/gnu/usr.bin/as/input-file.h b/gnu/usr.bin/as/input-file.h
new file mode 100644
index 0000000..73c33df
--- /dev/null
+++ b/gnu/usr.bin/as/input-file.h
@@ -0,0 +1,88 @@
+/* input_file.h header for input-file.c
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*"input_file.c":Operating-system dependant functions to read source files.*/
+
+/*
+ * $FreeBSD$
+ */
+
+
+/*
+ * No matter what the operating system, this module must provide the
+ * following services to its callers.
+ *
+ * input_file_begin() Call once before anything else.
+ *
+ * input_file_end() Call once after everything else.
+ *
+ * input_file_buffer_size() Call anytime. Returns largest possible
+ * delivery from
+ * input_file_give_next_buffer().
+ *
+ * input_file_open(name) Call once for each input file.
+ *
+ * input_file_give_next_buffer(where) Call once to get each new buffer.
+ * Return 0: no more chars left in file,
+ * the file has already been closed.
+ * Otherwise: return a pointer to just
+ * after the last character we read
+ * into the buffer.
+ * If we can only read 0 characters, then
+ * end-of-file is faked.
+ *
+ * input_file_push() Push state, which can be restored
+ * later. Does implicit input_file_begin.
+ * Returns char * to saved state.
+ *
+ * input_file_pop (arg) Pops previously saved state.
+ *
+ * input_file_close () Closes opened file.
+ *
+ * All errors are reported (using as_perror) so caller doesn't have to think
+ * about I/O errors. No I/O errors are fatal: an end-of-file may be faked.
+ */
+
+#if __STDC__ == 1
+
+char *input_file_give_next_buffer(char *where);
+char *input_file_push(void);
+int input_file_buffer_size(void);
+int input_file_is_open(void);
+void input_file_begin(void);
+void input_file_close(void);
+void input_file_end(void);
+void input_file_open(char *filename, int pre);
+void input_file_pop(char *arg);
+
+#else /* not __STDC__ */
+
+char *input_file_give_next_buffer();
+char *input_file_push();
+int input_file_buffer_size();
+int input_file_is_open();
+void input_file_begin();
+void input_file_close();
+void input_file_end();
+void input_file_open();
+void input_file_pop();
+
+#endif /* not __STDC__ */
+
+/* end of input_file.h */
diff --git a/gnu/usr.bin/as/input-scrub.c b/gnu/usr.bin/as/input-scrub.c
new file mode 100644
index 0000000..d93d7ce
--- /dev/null
+++ b/gnu/usr.bin/as/input-scrub.c
@@ -0,0 +1,420 @@
+/* input_scrub.c - Break up input buffers into whole numbers of lines.
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <errno.h> /* Need this to make errno declaration right */
+#include "as.h"
+#include "input-file.h"
+
+/*
+ * O/S independent module to supply buffers of sanitised source code
+ * to rest of assembler. We get sanitized input data of arbitrary length.
+ * We break these buffers on line boundaries, recombine pieces that
+ * were broken across buffers, and return a buffer of full lines to
+ * the caller.
+ * The last partial line begins the next buffer we build and return to caller.
+ * The buffer returned to caller is preceeded by BEFORE_STRING and followed
+ * by AFTER_STRING, as sentinels. The last character before AFTER_STRING
+ * is a newline.
+ * Also looks after line numbers, for e.g. error messages.
+ */
+
+/*
+ * We don't care how filthy our buffers are, but our callers assume
+ * that the following sanitation has already been done.
+ *
+ * No comments, reduce a comment to a space.
+ * Reduce a tab to a space unless it is 1st char of line.
+ * All multiple tabs and spaces collapsed into 1 char. Tab only
+ * legal if 1st char of line.
+ * # line file statements converted to .line x;.file y; statements.
+ * Escaped newlines at end of line: remove them but add as many newlines
+ * to end of statement as you removed in the middle, to synch line numbers.
+ */
+
+#define BEFORE_STRING ("\n")
+#define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */
+#define BEFORE_SIZE (1)
+#define AFTER_SIZE (1)
+
+static char *buffer_start; /*->1st char of full buffer area. */
+static char *partial_where; /*->after last full line in buffer. */
+static int partial_size; /* >=0. Number of chars in partial line in buffer. */
+static char save_source[AFTER_SIZE];
+/* Because we need AFTER_STRING just after last */
+/* full line, it clobbers 1st part of partial */
+/* line. So we preserve 1st part of partial */
+/* line here. */
+static unsigned int buffer_length; /* What is the largest size buffer that */
+/* input_file_give_next_buffer() could */
+/* return to us? */
+
+/* Saved information about the file that .include'd this one. When we hit EOF,
+ we automatically pop to that file. */
+
+static char *next_saved_file;
+
+/* We can have more than one source file open at once, though the info for all
+ but the latest one are saved off in a struct input_save. These files remain
+ open, so we are limited by the number of open files allowed by the
+ underlying OS. We may also sequentially read more than one source file in an
+ assembly. */
+
+/* We must track the physical file and line number for error messages. We also
+ track a "logical" file and line number corresponding to (C?) compiler
+ source line numbers. Whenever we open a file we must fill in
+ physical_input_file. So if it is NULL we have not opened any files yet. */
+
+static char *physical_input_file;
+static char *logical_input_file;
+
+typedef unsigned int line_numberT; /* 1-origin line number in a source file. */
+/* A line ends in '\n' or eof. */
+
+static line_numberT physical_input_line;
+static int logical_input_line;
+
+/* Struct used to save the state of the input handler during include files */
+struct input_save
+ {
+ char *buffer_start;
+ char *partial_where;
+ int partial_size;
+ char save_source[AFTER_SIZE];
+ unsigned int buffer_length;
+ char *physical_input_file;
+ char *logical_input_file;
+ line_numberT physical_input_line;
+ int logical_input_line;
+ char *next_saved_file; /* Chain of input_saves */
+ char *input_file_save; /* Saved state of input routines */
+ char *saved_position; /* Caller's saved position in buf */
+ };
+
+static char *input_scrub_push PARAMS ((char *saved_position));
+static char *input_scrub_pop PARAMS ((char *arg));
+static void as_1_char PARAMS ((unsigned int c, FILE * stream));
+
+/* Push the state of input reading and scrubbing so that we can #include.
+ The return value is a 'void *' (fudged for old compilers) to a save
+ area, which can be restored by passing it to input_scrub_pop(). */
+static char *
+input_scrub_push (saved_position)
+ char *saved_position;
+{
+ register struct input_save *saved;
+
+ saved = (struct input_save *) xmalloc (sizeof *saved);
+
+ saved->saved_position = saved_position;
+ saved->buffer_start = buffer_start;
+ saved->partial_where = partial_where;
+ saved->partial_size = partial_size;
+ saved->buffer_length = buffer_length;
+ saved->physical_input_file = physical_input_file;
+ saved->logical_input_file = logical_input_file;
+ saved->physical_input_line = physical_input_line;
+ saved->logical_input_line = logical_input_line;
+ memcpy (saved->save_source, save_source, sizeof (save_source));
+ saved->next_saved_file = next_saved_file;
+ saved->input_file_save = input_file_push ();
+
+ input_file_begin (); /* Reinitialize! */
+ logical_input_line = -1;
+ logical_input_file = (char *) NULL;
+ buffer_length = input_file_buffer_size ();
+
+ buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
+ memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
+
+ return ((char *) saved);
+} /* input_scrub_push() */
+
+static char *
+input_scrub_pop (arg)
+ char *arg;
+{
+ register struct input_save *saved;
+ char *saved_position;
+
+ input_scrub_end (); /* Finish off old buffer */
+
+ saved = (struct input_save *) arg;
+
+ input_file_pop (saved->input_file_save);
+ saved_position = saved->saved_position;
+ buffer_start = saved->buffer_start;
+ buffer_length = saved->buffer_length;
+ physical_input_file = saved->physical_input_file;
+ logical_input_file = saved->logical_input_file;
+ physical_input_line = saved->physical_input_line;
+ logical_input_line = saved->logical_input_line;
+ partial_where = saved->partial_where;
+ partial_size = saved->partial_size;
+ next_saved_file = saved->next_saved_file;
+ memcpy (save_source, saved->save_source, sizeof (save_source));
+
+ free (arg);
+ return saved_position;
+}
+
+
+void
+input_scrub_begin ()
+{
+ know (strlen (BEFORE_STRING) == BEFORE_SIZE);
+ know (strlen (AFTER_STRING) == AFTER_SIZE || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1));
+
+ input_file_begin ();
+
+ buffer_length = input_file_buffer_size ();
+
+ buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
+ memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
+
+ /* Line number things. */
+ logical_input_line = -1;
+ logical_input_file = (char *) NULL;
+ physical_input_file = NULL; /* No file read yet. */
+ next_saved_file = NULL; /* At EOF, don't pop to any other file */
+ do_scrub_begin ();
+}
+
+void
+input_scrub_end ()
+{
+ if (buffer_start)
+ {
+ free (buffer_start);
+ buffer_start = 0;
+ input_file_end ();
+ }
+}
+
+/* Start reading input from a new file. */
+
+char * /* Return start of caller's part of buffer. */
+input_scrub_new_file (filename)
+ char *filename;
+{
+ input_file_open (filename, !flagseen['f']);
+ physical_input_file = filename[0] ? filename : "{standard input}";
+ physical_input_line = 0;
+
+ partial_size = 0;
+ return (buffer_start + BEFORE_SIZE);
+}
+
+
+/* Include a file from the current file. Save our state, cause it to
+ be restored on EOF, and begin handling a new file. Same result as
+ input_scrub_new_file. */
+
+char *
+input_scrub_include_file (filename, position)
+ char *filename;
+ char *position;
+{
+ next_saved_file = input_scrub_push (position);
+ return input_scrub_new_file (filename);
+}
+
+void
+input_scrub_close ()
+{
+ input_file_close ();
+}
+
+char *
+input_scrub_next_buffer (bufp)
+ char **bufp;
+{
+ register char *limit; /*->just after last char of buffer. */
+
+ *bufp = buffer_start + BEFORE_SIZE;
+
+ if (partial_size)
+ {
+ memcpy (buffer_start + BEFORE_SIZE, partial_where,
+ (unsigned int) partial_size);
+ memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE);
+ }
+ limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size);
+ if (limit)
+ {
+ register char *p; /* Find last newline. */
+
+ for (p = limit; *--p != '\n';);;
+ ++p;
+ if (p <= buffer_start + BEFORE_SIZE)
+ {
+ as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__);
+ }
+ partial_where = p;
+ partial_size = limit - p;
+ memcpy (save_source, partial_where, (int) AFTER_SIZE);
+ memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE);
+ }
+ else
+ {
+ partial_where = 0;
+ if (partial_size > 0)
+ {
+ as_warn ("Partial line at end of file ignored");
+ }
+ /* If we should pop to another file at EOF, do it. */
+ if (next_saved_file)
+ {
+ *bufp = input_scrub_pop (next_saved_file); /* Pop state */
+ /* partial_where is now correct to return, since we popped it. */
+ }
+ }
+ return (partial_where);
+} /* input_scrub_next_buffer() */
+
+/*
+ * The remaining part of this file deals with line numbers, error
+ * messages and so on.
+ */
+
+
+int
+seen_at_least_1_file () /* TRUE if we opened any file. */
+{
+ return (physical_input_file != NULL);
+}
+
+void
+bump_line_counters ()
+{
+ ++physical_input_line;
+ if (logical_input_line >= 0)
+ ++logical_input_line;
+}
+
+/*
+ * new_logical_line()
+ *
+ * Tells us what the new logical line number and file are.
+ * If the line_number is -1, we don't change the current logical line
+ * number. If it is -2, we decrement the logical line number (this is
+ * to support the .appfile pseudo-op inserted into the stream by
+ * do_scrub_next_char).
+ * If the fname is NULL, we don't change the current logical file name.
+ */
+void
+new_logical_line (fname, line_number)
+ char *fname; /* DON'T destroy it! We point to it! */
+ int line_number;
+{
+ if (fname)
+ {
+ logical_input_file = fname;
+ } /* if we have a file name */
+
+ if (line_number >= 0)
+ logical_input_line = line_number;
+ else if (line_number == -2 && logical_input_line > 0)
+ --logical_input_line;
+} /* new_logical_line() */
+
+/*
+ * a s _ w h e r e ()
+ *
+ * Return the current file name and line number.
+ * namep should be char * const *, but there are compilers which screw
+ * up declarations like that, and it's easier to avoid it.
+ */
+void
+as_where (namep, linep)
+ char **namep;
+ unsigned int *linep;
+{
+ if (logical_input_file != NULL
+ && (linep == NULL || logical_input_line >= 0))
+ {
+ *namep = logical_input_file;
+ if (linep != NULL)
+ *linep = logical_input_line;
+ }
+ else if (physical_input_file != NULL)
+ {
+ *namep = physical_input_file;
+ if (linep != NULL)
+ *linep = physical_input_line;
+ }
+ else
+ {
+ *namep = (char *) "*unknown*";
+ if (linep != NULL)
+ *linep = 0;
+ }
+} /* as_where() */
+
+
+
+
+/*
+ * a s _ h o w m u c h ()
+ *
+ * Output to given stream how much of line we have scanned so far.
+ * Assumes we have scanned up to and including input_line_pointer.
+ * No free '\n' at end of line.
+ */
+void
+as_howmuch (stream)
+ FILE *stream; /* Opened for write please. */
+{
+ register char *p; /* Scan input line. */
+ /* register char c; JF unused */
+
+ for (p = input_line_pointer - 1; *p != '\n'; --p)
+ {
+ }
+ ++p; /* p->1st char of line. */
+ for (; p <= input_line_pointer; p++)
+ {
+ /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
+ /* c = *p & 0xFF; JF unused */
+ as_1_char ((unsigned char) *p, stream);
+ }
+}
+
+static void
+as_1_char (c, stream)
+ unsigned int c;
+ FILE *stream;
+{
+ if (c > 127)
+ {
+ (void) putc ('%', stream);
+ c -= 128;
+ }
+ if (c < 32)
+ {
+ (void) putc ('^', stream);
+ c += '@';
+ }
+ (void) putc (c, stream);
+}
+
+/* end of input_scrub.c */
diff --git a/gnu/usr.bin/as/link.cmd b/gnu/usr.bin/as/link.cmd
new file mode 100644
index 0000000..a035ca8
--- /dev/null
+++ b/gnu/usr.bin/as/link.cmd
@@ -0,0 +1,10 @@
+ALIGN=1024
+RESNUM 0x0000, 0x8000
+; Putting in .lit1 gives errors.
+ORDER .data=0x80002000, .data1, .lit, .bss
+; Let's put this on the command line so it goes first, which is what
+; GDB expects.
+; LOAD /s2/amd/29k/lib/crt0.o
+LOAD /s2/amd/29k/lib/libqcb0h.lib
+LOAD /s2/amd/29k/lib/libscb0h.lib
+LOAD /s2/amd/29k/lib/libacb0h.lib
diff --git a/gnu/usr.bin/as/listing.c b/gnu/usr.bin/as/listing.c
new file mode 100644
index 0000000..87da713
--- /dev/null
+++ b/gnu/usr.bin/as/listing.c
@@ -0,0 +1,1079 @@
+/* listing.c - mainting assembly listings
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ Contributed by Steve Chamberlain
+ sac@cygnus.com
+
+
+ A listing page looks like:
+
+ LISTING_HEADER sourcefilename pagenumber
+ TITLE LINE
+ SUBTITLE LINE
+ linenumber address data source
+ linenumber address data source
+ linenumber address data source
+ linenumber address data source
+
+ If not overridden, the listing commands are:
+
+ .title "stuff"
+ Put "stuff" onto the title line
+ .sbttl "stuff"
+ Put stuff onto the subtitle line
+
+ If these commands come within 10 lines of the top of the page, they
+ will affect the page they are on, as well as any subsequent page
+
+ .eject
+ Thow a page
+ .list
+ Increment the enable listing counter
+ .nolist
+ Decrement the enable listing counter
+
+ .psize Y[,X]
+ Set the paper size to X wide and Y high. Setting a psize Y of
+ zero will suppress form feeds except where demanded by .eject
+
+ If the counter goes below zero, listing is suppressed.
+
+
+ Listings are a maintained by read calling various listing_<foo>
+ functions. What happens most is that the macro NO_LISTING is not
+ defined (from the Makefile), then the macro LISTING_NEWLINE expands
+ into a call to listing_newline. The call is done from read.c, every
+ time it sees a newline, and -l is on the command line.
+
+ The function listing_newline remembers the frag associated with the
+ newline, and creates a new frag - note that this is wasteful, but not
+ a big deal, since listing slows things down a lot anyway. The
+ function also rememebers when the filename changes.
+
+ When all the input has finished, and gas has had a chance to settle
+ down, the listing is output. This is done by running down the list of
+ frag/source file records, and opening the files as needed and printing
+ out the bytes and chars associated with them.
+
+ The only things which the architecture can change about the listing
+ are defined in these macros:
+
+ LISTING_HEADER The name of the architecture
+ LISTING_WORD_SIZE The make of the number of bytes in a word, this determines
+ the clumping of the output data. eg a value of
+ 2 makes words look like 1234 5678, whilst 1
+ would make the same value look like 12 34 56
+ 78
+ LISTING_LHS_WIDTH Number of words of above size for the lhs
+
+ LISTING_LHS_WIDTH_SECOND Number of words for the data on the lhs
+ for the second line
+
+ LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation
+ LISTING_RHS_WIDTH Number of chars from the input file to print
+ on a line
+*/
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <ctype.h>
+
+#include "as.h"
+#include <obstack.h>
+#include "input-file.h"
+#include "subsegs.h"
+
+#ifndef NO_LISTING
+#ifndef LISTING_HEADER
+#define LISTING_HEADER "GAS LISTING"
+#endif
+#ifndef LISTING_WORD_SIZE
+#define LISTING_WORD_SIZE 4
+#endif
+#ifndef LISTING_LHS_WIDTH
+#define LISTING_LHS_WIDTH 1
+#endif
+#ifndef LISTING_LHS_WIDTH_SECOND
+#define LISTING_LHS_WIDTH_SECOND 1
+#endif
+#ifndef LISTING_RHS_WIDTH
+#define LISTING_RHS_WIDTH 100
+#endif
+#ifndef LISTING_LHS_CONT_LINES
+#define LISTING_LHS_CONT_LINES 4
+#endif
+
+
+
+
+static struct list_info_struct *head;
+struct list_info_struct *listing_tail;
+extern int listing;
+extern fragS *frag_now;
+
+
+static int paper_width = 200;
+static int paper_height = 60;
+
+
+/* this static array is used to keep the text of data to be printed
+ before the start of the line.
+ It is stored so we can give a bit more info on the next line. To much, and large
+ initialized arrays will use up lots of paper.
+ */
+
+static char data_buffer[100];
+static unsigned int data_buffer_size;
+
+
+/* Prototypes. */
+static void listing_message PARAMS ((const char *name, const char *message));
+static file_info_type *file_info PARAMS ((const char *file_name));
+static void new_frag PARAMS ((void));
+static char *buffer_line PARAMS ((file_info_type *file,
+ char *line, unsigned int size));
+static void listing_page PARAMS ((list_info_type *list));
+static unsigned int calc_hex PARAMS ((list_info_type *list));
+static void print_lines PARAMS ((list_info_type *list,
+ char *string,
+ unsigned int address));
+static void list_symbol_table PARAMS ((void));
+static void print_source PARAMS ((file_info_type *current_file,
+ list_info_type *list,
+ char *buffer,
+ unsigned int width));
+static int debugging_pseudo PARAMS ((char *line));
+static void listing_listing PARAMS ((char *name));
+
+
+static void
+listing_message (name, message)
+ const char *name;
+ const char *message;
+{
+ unsigned int l = strlen (name) + strlen (message) + 1;
+ char *n = (char *) xmalloc (l);
+ strcpy (n, name);
+ strcat (n, message);
+ if (listing_tail != (list_info_type *) NULL)
+ {
+ listing_tail->message = n;
+ }
+}
+
+void
+listing_warning (message)
+ const char *message;
+{
+ listing_message ("Warning:", message);
+}
+
+void
+listing_error (message)
+ const char *message;
+{
+ listing_message ("Error:", message);
+}
+
+
+
+
+static file_info_type *file_info_head;
+
+static file_info_type *
+file_info (file_name)
+ const char *file_name;
+{
+ /* Find an entry with this file name */
+ file_info_type *p = file_info_head;
+
+ while (p != (file_info_type *) NULL)
+ {
+ if (strcmp (p->filename, file_name) == 0)
+ return p;
+ p = p->next;
+ }
+
+ /* Make new entry */
+
+ p = (file_info_type *) xmalloc (sizeof (file_info_type));
+ p->next = file_info_head;
+ file_info_head = p;
+ p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
+ strcpy (p->filename, file_name);
+ p->linenum = 0;
+ p->end_pending = 0;
+
+ /* Do we really prefer binary mode for this?? */
+#define FOPEN_RB "r"
+ p->file = fopen (p->filename, FOPEN_RB);
+ if (p->file)
+ fgetc (p->file);
+
+ return p;
+}
+
+
+static void
+new_frag ()
+{
+
+ frag_wane (frag_now);
+ frag_new (0);
+
+}
+
+void
+listing_newline (ps)
+ char *ps;
+{
+ char *file;
+ unsigned int line;
+ static unsigned int last_line = 0xffff;
+ static char *last_file = NULL;
+ list_info_type *new;
+
+ as_where (&file, &line);
+ if (line != last_line || last_file && file && strcmp(file, last_file))
+ {
+ last_line = line;
+ last_file = file;
+ new_frag ();
+
+ new = (list_info_type *) xmalloc (sizeof (list_info_type));
+ new->frag = frag_now;
+ new->line = line;
+ new->file = file_info (file);
+
+ if (listing_tail)
+ {
+ listing_tail->next = new;
+ }
+ else
+ {
+ head = new;
+ }
+ listing_tail = new;
+ new->next = (list_info_type *) NULL;
+ new->message = (char *) NULL;
+ new->edict = EDICT_NONE;
+ new->hll_file = (file_info_type *) NULL;
+ new->hll_line = 0;
+ new_frag ();
+ }
+}
+
+/* Attach all current frags to the previous line instead of the
+ current line. This is called by the MIPS backend when it discovers
+ that it needs to add some NOP instructions; the added NOP
+ instructions should go with the instruction that has the delay, not
+ with the new instruction. */
+
+void
+listing_prev_line ()
+{
+ list_info_type *l;
+ fragS *f;
+
+ if (head == (list_info_type *) NULL
+ || head == listing_tail)
+ return;
+
+ new_frag ();
+
+ for (l = head; l->next != listing_tail; l = l->next)
+ ;
+
+ for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
+ if (f->line == listing_tail)
+ f->line = l;
+
+ listing_tail->frag = frag_now;
+ new_frag ();
+}
+
+/*
+ This function returns the next source line from the file supplied,
+ truncated to size. It appends a fake line to the end of each input
+ file to make
+*/
+
+static char *
+buffer_line (file, line, size)
+ file_info_type * file;
+ char *line;
+ unsigned int size;
+{
+ unsigned int count = 0;
+ int c;
+
+ char *p = line;
+
+ /* If we couldn't open the file, return an empty line */
+ if (file->file == (FILE *) NULL)
+ {
+ return "";
+ }
+
+ if (file->linenum == 0)
+ rewind (file->file);
+
+ if (file->end_pending == 10)
+ {
+ *p++ = '\n';
+ fseek (file->file, 0, 0);
+ file->linenum = 0;
+ file->end_pending = 0;
+ }
+ c = fgetc (file->file);
+
+
+ size -= 1; /* leave room for null */
+
+ while (c != EOF && c != '\n')
+ {
+ if (count < size)
+ *p++ = c;
+ count++;
+
+ c = fgetc (file->file);
+
+ }
+ if (c == EOF)
+ {
+ file->end_pending++;
+ *p++ = '.';
+ *p++ = '.';
+ *p++ = '.';
+ }
+ file->linenum++;
+ *p++ = 0;
+ return line;
+}
+
+
+static const char *fn;
+
+static unsigned int eject; /* Eject pending */
+static unsigned int page; /* Current page number */
+static char *title; /* current title */
+static char *subtitle; /* current subtitle */
+static unsigned int on_page; /* number of lines printed on current page */
+
+
+static void
+listing_page (list)
+ list_info_type *list;
+{
+ /* Grope around, see if we can see a title or subtitle edict coming up
+ soon (we look down 10 lines of the page and see if it's there)*/
+ if ((eject || (on_page >= paper_height)) && paper_height != 0)
+ {
+ unsigned int c = 10;
+ int had_title = 0;
+ int had_subtitle = 0;
+
+ page++;
+
+ while (c != 0 && list)
+ {
+ if (list->edict == EDICT_SBTTL && !had_subtitle)
+ {
+ had_subtitle = 1;
+ subtitle = list->edict_arg;
+ }
+ if (list->edict == EDICT_TITLE && !had_title)
+ {
+ had_title = 1;
+ title = list->edict_arg;
+ }
+ list = list->next;
+ c--;
+ }
+
+
+ if (page > 1)
+ {
+ printf ("\f");
+ }
+
+ printf ("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
+ printf ("%s\n", title);
+ printf ("%s\n", subtitle);
+ on_page = 3;
+ eject = 0;
+ }
+}
+
+
+static unsigned int
+calc_hex (list)
+ list_info_type * list;
+{
+ list_info_type *first = list;
+ unsigned int address = (unsigned int) ~0;
+
+ fragS *frag;
+ fragS *frag_ptr;
+
+ unsigned int byte_in_frag;
+
+
+ /* Find first frag which says it belongs to this line */
+ frag = list->frag;
+ while (frag && frag->line != list)
+ frag = frag->fr_next;
+
+ frag_ptr = frag;
+
+ data_buffer_size = 0;
+
+ /* Dump all the frags which belong to this line */
+ while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
+ {
+ /* Print as many bytes from the fixed part as is sensible */
+ byte_in_frag = 0;
+ while (byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof (data_buffer) - 10)
+ {
+ if (address == ~0)
+ {
+ address = frag_ptr->fr_address;
+ }
+
+ sprintf (data_buffer + data_buffer_size,
+ "%02X",
+ (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
+ data_buffer_size += 2;
+ byte_in_frag++;
+ }
+ {
+ unsigned int var_rep_max = byte_in_frag;
+ unsigned int var_rep_idx = byte_in_frag;
+
+ /* Print as many bytes from the variable part as is sensible */
+ while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset
+ && data_buffer_size < sizeof (data_buffer) - 10)
+ {
+ if (address == ~0)
+ {
+ address = frag_ptr->fr_address;
+ }
+ sprintf (data_buffer + data_buffer_size,
+ "%02X",
+ (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
+#if 0
+ data_buffer[data_buffer_size++] = '*';
+ data_buffer[data_buffer_size++] = '*';
+#endif
+ data_buffer_size += 2;
+
+ var_rep_idx++;
+ byte_in_frag++;
+
+ if (var_rep_idx >= frag_ptr->fr_var)
+ var_rep_idx = var_rep_max;
+ }
+ }
+
+ frag_ptr = frag_ptr->fr_next;
+ }
+ data_buffer[data_buffer_size++] = 0;
+ return address;
+}
+
+
+
+
+
+
+static void
+print_lines (list, string, address)
+ list_info_type *list;
+ char *string;
+ unsigned int address;
+{
+ unsigned int idx;
+ unsigned int nchars;
+ unsigned int lines;
+ unsigned int byte_in_word = 0;
+ char *src = data_buffer;
+
+ /* Print the stuff on the first line */
+ listing_page (list);
+ nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH;
+ /* Print the hex for the first line */
+ if (address == ~0)
+ {
+ printf ("% 4d ", list->line);
+ for (idx = 0; idx < nchars; idx++)
+ printf (" ");
+
+ printf ("\t%s\n", string ? string : "");
+ on_page++;
+ listing_page (0);
+
+ }
+ else
+ {
+ if (had_errors ())
+ {
+ printf ("% 4d ???? ", list->line);
+ }
+ else
+ {
+ printf ("% 4d %04x ", list->line, address);
+ }
+
+ /* And the data to go along with it */
+ idx = 0;
+
+ while (*src && idx < nchars)
+ {
+ printf ("%c%c", src[0], src[1]);
+ src += 2;
+ byte_in_word++;
+ if (byte_in_word == LISTING_WORD_SIZE)
+ {
+ printf (" ");
+ idx++;
+ byte_in_word = 0;
+ }
+ idx += 2;
+ }
+
+ for (; idx < nchars; idx++)
+ printf (" ");
+
+ printf ("\t%s\n", string ? string : "");
+ on_page++;
+ listing_page (list);
+ if (list->message)
+ {
+ printf ("**** %s\n", list->message);
+ listing_page (list);
+ on_page++;
+ }
+
+ for (lines = 0;
+ lines < LISTING_LHS_CONT_LINES
+ && *src;
+ lines++)
+ {
+ nchars = ((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND - 1;
+ idx = 0;
+ /* Print any more lines of data, but more compactly */
+ printf ("% 4d ", list->line);
+
+ while (*src && idx < nchars)
+ {
+ printf ("%c%c", src[0], src[1]);
+ src += 2;
+ idx += 2;
+ byte_in_word++;
+ if (byte_in_word == LISTING_WORD_SIZE)
+ {
+ printf (" ");
+ idx++;
+ byte_in_word = 0;
+ }
+ }
+
+ printf ("\n");
+ on_page++;
+ listing_page (list);
+
+ }
+
+
+ }
+}
+
+
+static void
+list_symbol_table ()
+{
+ extern symbolS *symbol_rootP;
+ int got_some = 0;
+
+ symbolS *ptr;
+ eject = 1;
+ listing_page (0);
+
+ for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
+ {
+ if (ptr->sy_frag->line)
+ {
+ if (S_GET_NAME (ptr))
+ {
+ char buf[30];
+ valueT val = S_GET_VALUE (ptr);
+
+ /* @@ Note that this is dependent on the compilation options,
+ not solely on the target characteristics. */
+ if (sizeof (val) == 4 && sizeof (int) == 4)
+ sprintf (buf, "%08lx", (unsigned long) val);
+#if defined (BFD64)
+ else if (sizeof (val) > 4)
+ {
+ char buf1[30];
+ sprintf_vma (buf1, val);
+ strcpy (buf, "00000000");
+ strcpy (buf + 8 - strlen (buf1), buf1);
+ }
+#endif
+ else
+ abort ();
+
+ if (!got_some)
+ {
+ printf ("DEFINED SYMBOLS\n");
+ on_page++;
+ got_some = 1;
+ }
+
+ printf ("%20s:%-5d %s:%s %s\n",
+ ptr->sy_frag->line->file->filename,
+ ptr->sy_frag->line->line,
+ segment_name (S_GET_SEGMENT (ptr)),
+ buf, S_GET_NAME (ptr));
+
+ on_page++;
+ listing_page (0);
+ }
+ }
+
+ }
+ if (!got_some)
+ {
+ printf ("NO DEFINED SYMBOLS\n");
+ on_page++;
+ }
+ printf ("\n");
+ on_page++;
+ listing_page (0);
+
+ got_some = 0;
+
+ for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
+ {
+ if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
+ {
+ if (ptr->sy_frag->line == 0
+#ifdef notyet
+ && S_GET_SEGMENT (ptr) != reg_section)
+#else
+ && !S_IS_REGISTER(ptr))
+#endif
+ {
+ if (!got_some)
+ {
+ got_some = 1;
+ printf ("UNDEFINED SYMBOLS\n");
+ on_page++;
+ listing_page (0);
+ }
+ printf ("%s\n", S_GET_NAME (ptr));
+ on_page++;
+ listing_page (0);
+ }
+ }
+ }
+ if (!got_some)
+ {
+ printf ("NO UNDEFINED SYMBOLS\n");
+ on_page++;
+ listing_page (0);
+ }
+}
+
+static void
+print_source (current_file, list, buffer, width)
+ file_info_type *current_file;
+ list_info_type *list;
+ char *buffer;
+ unsigned int width;
+{
+ if (current_file->file)
+ {
+ while (current_file->linenum < list->hll_line)
+ {
+ char *p = buffer_line (current_file, buffer, width);
+ printf ("%4d:%-13s **** %s\n", current_file->linenum, current_file->filename, p);
+ on_page++;
+ listing_page (list);
+ }
+ }
+}
+
+/* Sometimes the user doesn't want to be bothered by the debugging
+ records inserted by the compiler, see if the line is suspicious */
+
+static int
+debugging_pseudo (line)
+ char *line;
+{
+ while (isspace (*line))
+ line++;
+
+ if (*line != '.')
+ return 0;
+
+ line++;
+
+ if (strncmp (line, "def", 3) == 0)
+ return 1;
+ if (strncmp (line, "val", 3) == 0)
+ return 1;
+ if (strncmp (line, "scl", 3) == 0)
+ return 1;
+ if (strncmp (line, "line", 4) == 0)
+ return 1;
+ if (strncmp (line, "endef", 5) == 0)
+ return 1;
+ if (strncmp (line, "ln", 2) == 0)
+ return 1;
+ if (strncmp (line, "type", 4) == 0)
+ return 1;
+ if (strncmp (line, "size", 4) == 0)
+ return 1;
+ if (strncmp (line, "dim", 3) == 0)
+ return 1;
+ if (strncmp (line, "tag", 3) == 0)
+ return 1;
+
+ if (strncmp (line, "stabs", 5) == 0)
+ return 1;
+ if (strncmp (line, "stabn", 5) == 0)
+ return 1;
+
+ return 0;
+
+}
+
+static void
+listing_listing (name)
+ char *name;
+{
+ list_info_type *list = head;
+ file_info_type *current_hll_file = (file_info_type *) NULL;
+ char *message;
+ char *buffer;
+ char *p;
+ int show_listing = 1;
+ unsigned int width;
+
+ buffer = xmalloc (LISTING_RHS_WIDTH);
+ eject = 1;
+ list = head;
+
+ while (list != (list_info_type *) NULL && 0)
+ {
+ if (list->next)
+ list->frag = list->next->frag;
+ list = list->next;
+
+ }
+
+ list = head->next;
+
+
+ while (list)
+ {
+ width = LISTING_RHS_WIDTH > paper_width ? paper_width :
+ LISTING_RHS_WIDTH;
+
+ switch (list->edict)
+ {
+ case EDICT_LIST:
+ show_listing++;
+ break;
+ case EDICT_NOLIST:
+ show_listing--;
+ break;
+ case EDICT_EJECT:
+ break;
+ case EDICT_NONE:
+ break;
+ case EDICT_TITLE:
+ title = list->edict_arg;
+ break;
+ case EDICT_SBTTL:
+ subtitle = list->edict_arg;
+ break;
+ default:
+ abort ();
+ }
+
+ if (show_listing > 0)
+ {
+ /* Scan down the list and print all the stuff which can be done
+ with this line (or lines). */
+ message = 0;
+
+ if (list->hll_file)
+ {
+ current_hll_file = list->hll_file;
+ }
+
+ if (current_hll_file && list->hll_line && listing & LISTING_HLL)
+ {
+ print_source (current_hll_file, list, buffer, width);
+ }
+
+ while (list->file->file &&
+ list->file->linenum < list->line && !list->file->end_pending) {
+ p = buffer_line (list->file, buffer, width);
+
+ if (!((listing & LISTING_NODEBUG) && debugging_pseudo (p)))
+ {
+ print_lines (list, p, calc_hex (list));
+ }
+ }
+
+ if (list->edict == EDICT_EJECT)
+ {
+ eject = 1;
+ }
+ }
+ else
+ {
+
+ while (list->file->file &&
+ list->file->linenum < list->line && !list->file->end_pending)
+ p = buffer_line (list->file, buffer, width);
+ }
+
+ list = list->next;
+ }
+ free (buffer);
+}
+
+void
+listing_print (name)
+ char *name;
+{
+ title = "";
+ subtitle = "";
+
+ if (listing & LISTING_NOFORM)
+ {
+ paper_height = 0;
+ }
+
+ if (listing & LISTING_LISTING)
+ {
+ listing_listing (name);
+
+ }
+ if (listing & LISTING_SYMBOLS)
+ {
+ list_symbol_table ();
+ }
+}
+
+
+void
+listing_file (name)
+ const char *name;
+{
+ fn = name;
+}
+
+void
+listing_eject (ignore)
+ int ignore;
+{
+ listing_tail->edict = EDICT_EJECT;
+}
+
+void
+listing_flags (ignore)
+ int ignore;
+{
+ while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
+ input_line_pointer++;
+
+}
+
+void
+listing_list (on)
+ int on;
+{
+ listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
+}
+
+
+void
+listing_psize (ignore)
+ int ignore;
+{
+ paper_height = get_absolute_expression ();
+
+ if (paper_height < 0 || paper_height > 1000)
+ {
+ paper_height = 0;
+ as_warn ("strange paper height, set to no form");
+ }
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ paper_width = get_absolute_expression ();
+ }
+}
+
+
+void
+listing_title (depth)
+ int depth;
+{
+ char *start;
+ char *ttl;
+ unsigned int length;
+
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\"')
+ {
+ input_line_pointer++;
+ start = input_line_pointer;
+
+ while (*input_line_pointer)
+ {
+ if (*input_line_pointer == '\"')
+ {
+ length = input_line_pointer - start;
+ ttl = xmalloc (length + 1);
+ memcpy (ttl, start, length);
+ ttl[length] = 0;
+ listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
+ listing_tail->edict_arg = ttl;
+ input_line_pointer++;
+ demand_empty_rest_of_line ();
+ return;
+ }
+ else if (*input_line_pointer == '\n')
+ {
+ as_bad ("New line in title");
+ demand_empty_rest_of_line ();
+ return;
+ }
+ else
+ {
+ input_line_pointer++;
+ }
+ }
+ }
+ else
+ {
+ as_bad ("expecting title in quotes");
+ }
+}
+
+
+
+void
+listing_source_line (line)
+ unsigned int line;
+{
+ new_frag ();
+ listing_tail->hll_line = line;
+ new_frag ();
+
+}
+
+void
+listing_source_file (file)
+ const char *file;
+{
+ if (listing_tail)
+ listing_tail->hll_file = file_info (file);
+}
+
+
+
+#else
+
+
+/* Dummy functions for when compiled without listing enabled */
+
+void
+listing_flags (ignore)
+ int ignore;
+{
+ s_ignore (0);
+}
+
+void
+listing_list (on)
+ int on;
+{
+ s_ignore (0);
+}
+
+void
+listing_eject (ignore)
+ int ignore;
+{
+ s_ignore (0);
+}
+
+void
+listing_psize (ignore)
+ int ignore;
+{
+ s_ignore (0);
+}
+
+void
+listing_title (depth)
+ int depth;
+{
+ s_ignore (0);
+}
+
+void
+listing_file (name)
+ const char *name;
+{
+
+}
+
+void
+listing_newline (name)
+ char *name;
+{
+
+}
+
+void
+listing_source_line (n)
+ unsigned int n;
+{
+
+}
+void
+listing_source_file (n)
+ const char *n;
+{
+
+}
+
+#endif
diff --git a/gnu/usr.bin/as/listing.h b/gnu/usr.bin/as/listing.h
new file mode 100644
index 0000000..4dece8f
--- /dev/null
+++ b/gnu/usr.bin/as/listing.h
@@ -0,0 +1,115 @@
+/* This file is listing.h
+ Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+#ifndef __listing_h__
+#define __listing_h__
+
+#define LISTING_LISTING 1
+#define LISTING_SYMBOLS 2
+#define LISTING_NOFORM 4
+#define LISTING_HLL 8
+#define LISTING_NODEBUG 16
+
+#define LISTING_DEFAULT (LISTING_LISTING | LISTING_HLL | LISTING_SYMBOLS)
+
+#ifndef NO_LISTING
+#define LISTING_NEWLINE() { if (listing) listing_newline(input_line_pointer); }
+#else
+#define LISTING_NEWLINE() {;}
+#endif
+
+
+/* This structure remembers which .s were used */
+typedef struct file_info_struct
+{
+ char *filename;
+ int linenum;
+ FILE *file;
+ struct file_info_struct *next;
+ int end_pending;
+
+}
+
+file_info_type;
+
+
+/* this structure rememebrs which line from which file goes into which
+ frag */
+typedef struct list_info_struct
+{
+ /* Frag which this line of source is nearest to */
+ fragS *frag;
+ /* The actual line in the source file */
+ unsigned int line;
+ /* Pointer to the file info struct for the file which this line
+ belongs to */
+ file_info_type *file;
+
+ /* Next in list */
+ struct list_info_struct *next;
+
+
+ /* Pointer to the file info struct for the high level language
+ source line that belongs here */
+ file_info_type *hll_file;
+
+ /* High level language source line */
+ int hll_line;
+
+
+ /* Pointer to any error message associated with this line */
+ char *message;
+
+ enum
+ {
+ EDICT_NONE,
+ EDICT_SBTTL,
+ EDICT_TITLE,
+ EDICT_NOLIST,
+ EDICT_LIST,
+ EDICT_EJECT
+ } edict;
+ char *edict_arg;
+
+}
+
+list_info_type;
+
+void listing_eject PARAMS ((int));
+void listing_error PARAMS ((const char *message));
+void listing_file PARAMS ((const char *name));
+void listing_flags PARAMS ((int));
+void listing_list PARAMS ((int on));
+void listing_newline PARAMS ((char *ps));
+void listing_prev_line PARAMS ((void));
+void listing_print PARAMS ((char *name));
+void listing_psize PARAMS ((int));
+void listing_source_file PARAMS ((const char *));
+void listing_source_line PARAMS ((unsigned int));
+void listing_title PARAMS ((int depth));
+void listing_warning PARAMS ((const char *message));
+void listing_width PARAMS ((unsigned int x));
+
+#endif /* __listing_h__ */
+
+/* end of listing.h */
diff --git a/gnu/usr.bin/as/make-gas.com b/gnu/usr.bin/as/make-gas.com
new file mode 100644
index 0000000..cb3064d
--- /dev/null
+++ b/gnu/usr.bin/as/make-gas.com
@@ -0,0 +1,86 @@
+$! Set the def dir to proper place for use in batch. Works for interactive to.
+$flnm = f$enviroment("PROCEDURE") ! get current procedure name
+$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$!
+$! Command file to build a GNU assembler on VMS
+$!
+$! If you are using a version of GCC that supports global constants
+$! you should remove the define="const=" from the gcc lines.
+$!
+$! Caution: Versions 1.38.1 and earlier had a bug in the handling of
+$! some static constants. If you are using such a version of the
+$! assembler, and you wish to compile without the "const=" hack,
+$! you should first build this version *with* the "const="
+$! definition, and then use that assembler to rebuild it without the
+$! "const=" definition. Failure to do this will result in an assembler
+$! that will mung floating point constants.
+$!
+$! Note: The version of gas shipped on the GCC VMS tapes has been patched
+$! to fix the above mentioned bug.
+$!
+$ write sys$output "If this assembler is going to be used with GCC 1.n, you"
+$ write sys$Output "need to modify the driver to supply the -1 switch to gas."
+$ write sys$output "This is required because of a small change in how global"
+$ write sys$Output "constant variables are handled. Failure to include this"
+$ write sys$output "will result in linker warning messages about mismatched
+$ write sys$output "psect attributes."
+$!
+$ C_DEFS :="""VMS"""
+$! C_DEFS :="""VMS""","""const="""
+$ C_INCLUDES :=/include=([],[.config],[-.include])
+$ C_FLAGS := /debug 'c_includes'
+$!
+$!
+$ if "''p1'" .eqs. "LINK" then goto Link
+$!
+$! This helps gcc 1.nn find the aout/* files.
+$!
+$ aout_dev = f$parse(flnm,,,"DEVICE")
+$ tmp = aout_dev - ":"
+$if f$trnlnm(tmp).nes."" then aout_dev = f$trnlnm(tmp)
+$ aout_dir = aout_dev+f$parse(flnm,,,"DIRECTORY")' -
+ - "GAS]" + "INCLUDE.AOUT.]" - "]["
+$assign 'aout_dir' aout/tran=conc
+$ opcode_dir = aout_dev+f$parse(flnm,,,"DIRECTORY")' -
+ - "GAS]" + "INCLUDE.OPCODE.]" - "]["
+$assign 'opcode_dir' opcode/tran=conc
+$!
+$ gcc 'c_flags'/define=('C_DEFS') as.c
+$ gcc 'c_flags'/define=("error=as_fatal",'C_DEFS') xrealloc.c
+$ gcc 'c_flags'/define=("error=as_fatal",'C_DEFS') xmalloc.c
+$ gcc 'c_flags'/define=("error=as_fatal",'C_DEFS') hash.c
+$ gcc 'c_flags'/define=('C_DEFS') obstack.c
+$ gcc 'c_flags'/define=('C_DEFS') hex-value.c
+$ gcc 'c_flags'/define=('C_DEFS') messages.c
+$ gcc 'c_flags'/define=('C_DEFS') atof-generic.c
+$ gcc 'c_flags'/define=('C_DEFS') expr.c
+$ gcc 'c_flags'/define=('C_DEFS') cond.c
+$ gcc 'c_flags'/define=('C_DEFS') app.c
+$ gcc 'c_flags'/define=('C_DEFS') frags.c
+$ gcc 'c_flags'/define=('C_DEFS') input-file.c
+$ gcc 'c_flags'/define=('C_DEFS') input-scrub.c
+$ gcc 'c_flags'/define=('C_DEFS') output-file.c
+$ gcc 'c_flags'/define=('C_DEFS') read.c
+$ gcc 'c_flags'/define=('C_DEFS') subsegs.c
+$ gcc 'c_flags'/define=('C_DEFS') symbols.c
+$ gcc 'c_flags'/define=('C_DEFS') write.c
+$ gcc 'c_flags'/define=('C_DEFS') version.c
+$ gcc 'c_flags'/define=('C_DEFS') flonum-const.c
+$ gcc 'c_flags'/define=('C_DEFS') flonum-copy.c
+$ gcc 'c_flags'/define=('C_DEFS') flonum-mult.c
+$ gcc 'c_flags'/define=('C_DEFS') strstr.c
+$ gcc 'c_flags'/define=('C_DEFS') bignum-copy.c
+$ gcc 'c_flags'/define=('C_DEFS') listing.c
+$ gcc 'c_flags'/define=('C_DEFS') atof-targ.c
+$ gcc 'c_flags'/define=("error=as_fatal",'C_DEFS') targ-cpu.c
+$ gcc 'c_flags'/define=("error=as_fatal",'C_DEFS') obj-format.c
+$ Link:
+$ link/nomap/exec=gcc-as version.opt/opt+sys$input:/opt
+!
+! Linker options file for GNU assembler
+!
+as,xrealloc,xmalloc,hash,hex-value,atof-generic,messages,expr,app,cond,-
+frags,input-file,input-scrub,output-file,read,subsegs,symbols,write,-
+version,flonum-const,flonum-copy,flonum-mult,strstr,bignum-copy,listing,-
+obstack,targ-cpu,atof-targ,obj-format,-
+gnu_cc:[000000]gcclib/lib,sys$share:vaxcrtl/lib
diff --git a/gnu/usr.bin/as/makefile.dos b/gnu/usr.bin/as/makefile.dos
new file mode 100644
index 0000000..2d2a989
--- /dev/null
+++ b/gnu/usr.bin/as/makefile.dos
@@ -0,0 +1,593 @@
+# Makefile for GNU Assembler
+# Copyright (C) 1987, 1988, 1990, 1991 Free Software Foundation, Inc.
+
+#This file is part of GNU GAS.
+
+#GNU GAS is free software; you can redistribute it and/or modify
+#it under the terms of the GNU General Public License as published by
+#the Free Software Foundation; either version 1, or (at your option)
+#any later version.
+
+#GNU GAS is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+
+#You should have received a copy of the GNU General Public License
+#along with GNU GAS; see the file COPYING. If not, write to
+#the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# $FreeBSD$
+
+# The targets for external use include:
+# all, doc, proto, install, uninstall, includes, TAGS,
+# clean, cleanconfig, realclean, stage1, stage2, stage3, stage4.
+
+# Variables that exist for you to override.
+# See below for how to change them for certain systems.
+
+LIBDEPS=
+CROSS=
+HDEFINES=
+CPPFLAGS=
+
+ALLOCA =
+CFLAGS = -g -D__MSDOS__ -D__GO32__ -I../include
+INTERNAL_CFLAGS = $(CROSS)
+OLDCC = cc
+BISON = bison
+BISONFLAGS = -v
+AR = ar
+OLDAR_FLAGS = qc
+AR_FLAGS = rc
+SHELL = /bin/sh
+# on sysV, define this as cp.
+INSTALL = install -c
+# These permit overriding just for certain files.
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_FILE = $(INSTALL)
+
+# Define this as & to perform parallel make on a Sequent.
+# Note that this has some bugs, and it seems currently necessary
+# to compile all the gen* files first by hand to avoid erroneous results.
+P =
+
+# How to invoke ranlib.
+RANLIB = ranlib
+# Test to use to see whether ranlib exists on the system.
+RANLIB_TEST = [ -f /usr/bin/ranlib -o -f /bin/ranlib ]
+
+# CFLAGS for use with OLDCC, for compiling gnulib.
+# NOTE: -O does not work on some Unix systems!
+CCLIBFLAGS = -O
+
+# Version of ar to use when compiling gnulib.
+OLDAR = ar
+
+version=`$(unsubdir)/../gcc$(subdir)/gcc -dumpversion`
+
+# Directory where sources are, from where we are.
+srcdir = .
+# Common prefix for installation directories.
+# NOTE: This directory must exist when you start installation.
+ddestdir = /usr/local
+# Directory in which to put the executable for the command `gcc'
+bindir = $(ddestdir)/bin
+# Directory in which to put the directories used by the compiler.
+libdir = $(ddestdir)/lib
+# Directory in which the compiler finds executables, libraries, etc.
+libsubdir = $(libdir)/gcc/$(target_alias)/$(version)
+# Number to put in man-page filename.
+manext = 1
+# Directory in which to put man pages.
+mandir = $(destdir)/H-independent/man/man$(manext)
+
+# Additional system libraries to link with.
+CLIB=
+
+# Specify the rule for actually making gnulib.
+GNULIB = gnulib.portable
+
+# Specify the rule for actually making gnulib2.
+GNULIB2 = gnulib2.portable
+
+# List of extra C and assembler files to add to gnulib.
+# Assembler files should have names ending in `.asm'.
+LIBFUNCS_EXTRA =
+
+# Program to convert libraries.
+LIBCONVERT =
+
+# Control whether header files are installed.
+INSTALL_HEADERS=install-headers
+
+# Change this to empty to prevent installing limits.h
+LIMITS_H = limits.h
+
+# Directory to link to, when using the target `maketest'.
+DIR = ../gcc
+
+# For better debugging under COFF, define SEPARATE_AUX_OUTPUT in config.h
+# and define the following variable as `aux-output2.c' in make-...
+AUX_OUTPUT2 =
+
+# Flags to use when cross-building GCC.
+# Prefix to apply to names of object files when using them
+# to run on the machine we are compiling on.
+HOST_PREFIX=
+# Prefix to apply to names of object files when compiling them
+# to run on the machine we are compiling on.
+# The default for this variable is chosen to keep these rules
+# out of the way of the other rules for compiling the same source files.
+HOST_PREFIX_1=loser-
+HOST_CC=$(CC)
+HOST_CFLAGS=$(ALL_CFLAGS)
+HOST_LDFLAGS=$(LDFLAGS)
+HOST_CPPFLAGS=$(CPPFLAGS)
+
+# Choose the real default target.
+ALL=as.new
+
+# End of variables for you to override.
+
+# Lists of files for various purposes.
+
+REAL_SOURCES = \
+ app.c \
+ as.c \
+ atof-generic.c \
+ bignum-copy.c \
+ cond.c \
+ expr.c \
+ fn-const.c \
+ fn-copy.c \
+ flonum-mult.c \
+ frags.c \
+ hash.c \
+ hex-value.c \
+ input-file.c \
+ input-scrub.c \
+ messages.c \
+ output-file.c \
+ read.c \
+ strstr.c \
+ subsegs.c \
+ symbols.c \
+ version.c \
+ write.c \
+ xmalloc.c \
+ xrealloc.c
+
+# in an expedient order
+LINKED_SOURCES = \
+ targ-cpu.c \
+ obj-format.c \
+ atof-targ.c
+
+SOURCES = $(LINKED_SOURCES) $(REAL_SOURCES)
+
+REAL_HEADERS = \
+ as.h \
+ bignum.h \
+ expr.h \
+ flonum.h \
+ frags.h \
+ hash.h \
+ input-file.h \
+ tc.h \
+ obj.h \
+ read.h \
+ struc-symbol.h \
+ subsegs.h \
+ symbols.h \
+ syscalls.h \
+ write.h
+
+LINKED_HEADERS = \
+ a.out.gnu.h \
+ a.out.h \
+ host.h \
+ targ-env.h \
+ targ-cpu.h \
+ obj-format.h \
+ atof-targ.h
+
+HEADERS = $(LINKED_HEADERS) $(REAL_HEADERS)
+
+OBJS = \
+ targ-cpu.o \
+ obj-format.o \
+ atof-targ.o \
+ app.o \
+ as.o \
+ atof-generic.o \
+ bignum-copy.o \
+ cond.o \
+ expr.o \
+ fn-const.o \
+ fn-copy.o \
+ flonum-mult.o \
+ frags.o \
+ hash.o \
+ hex-value.o \
+ input-file.o \
+ input-scrub.o \
+ messages.o \
+ output-file.o \
+ read.o \
+ strstr.o \
+ subsegs.o \
+ symbols.o \
+ version.o \
+ write.o \
+ xmalloc.o \
+ xrealloc.o
+
+#### host, target, and site specific Makefile frags come in here.
+TARG_CPU_DEPENDENTS=../include/h8300-opcode.h
+LOCAL_LOADLIBES=../bfd/libbfd.a
+TDEFINES=-DBFD -DBFD_HEADERS -DMANY_SEGMENTS
+
+
+# Definition of `all' is here so that new rules inserted by sed
+# do not specify the default target.
+# The real definition is under `all.internal'.
+
+all: $(ALL)
+all-info:
+install-info:
+
+fake-as: force
+ - rm -f ./as.new
+ cp /bin/as ./fake-as
+
+# Now figure out from those variables how to compile and link.
+
+# This is the variable actually used when we compile.
+ALL_CFLAGS = $(INTERNAL_CFLAGS) $(CFLAGS) $(HDEFINES) $(TDEFINES)
+
+# Even if ALLOCA is set, don't use it if compiling with GCC.
+USE_ALLOCA= `if [ x"${CC}" = x"${OLDCC}" ] ; then echo ${ALLOCA}; else true; fi`
+USE_HOST_ALLOCA= `if [ x"${CC}" = x"${OLDCC}" ] ; then echo ${HOST_PREFIX}${ALLOCA}; else true; fi`
+
+# Likewise, for use in the tools that must run on this machine
+# even if we are cross-building GCC.
+# We don't use USE_ALLOCA because backquote expansion doesn't work in deps.
+HOST_LIBDEPS= $(HOST_PREFIX)$(OBSTACK) $(HOST_PREFIX)$(ALLOCA) $(HOST_PREFIX)$(MALLOC)
+
+# How to link with both our special library facilities
+# and the system's installed libraries.
+
+LIBS = $(LOCAL_LOADLIBES) $(CLIB) $(unsubdir)/../libiberty$(subdir)/libiberty.a
+
+# Likewise, for use in the tools that must run on this machine
+# even if we are cross-building GCC.
+HOST_LIBS = $(HOST_PREFIX)$(OBSTACK) $(USE_HOST_ALLOCA) $(HOST_PREFIX)$(MALLOC) $(CLIB)
+
+# Specify the directories to be searched for header files.
+# Both . and srcdir are used, in that order,
+# so that tm.h and config.h will be found in the compilation
+# subdirectory rather than in the source directory.
+INCLUDES = -I. -I$(srcdir) -Iconfig
+SUBDIR_INCLUDES = -I.. -I../$(srcdir) -I../config
+
+# Always use -Iconfig when compiling.
+.c.o:
+ $(CC) -c $(ALL_CFLAGS) $(CPPFLAGS) $(INCLUDES) $<
+
+# This tells GNU make version 3 not to export all the variables
+# defined in this file into the environment.
+.NOEXPORT:
+
+# Files to be copied away after each stage in building.
+STAGE_GCC=gcc
+STAGESTUFF = *.o as.new
+
+# The files that "belong" in CONFIG_H are deliberately omitted
+# because having them there would not be useful in actual practice.
+# All they would do is cause complete recompilation every time
+# one of the machine description files is edited.
+# That may or may not be what one wants to do.
+# If it is, rm *.o is an easy way to do it.
+# CONFIG_H = config.h tm.h
+CONFIG_H =
+
+as.new: $(OBJS) $(LIBDEPS)
+ -mv -f as.new as.old
+ >as.rf $(ALL_CFLAGS) $(LDFLAGS) -o as.new $(OBJS) $(LIBS) $(LOADLIBES)
+ $(CC) @as.rf
+
+objdump:
+
+all.internal: native
+# This is what is made with the host's compiler if making a cross assembler.
+native: config.status as
+
+config.status:
+ @echo You must configure gas. Look at the INSTALL file for details.
+ @false
+
+compilations: ${OBJS}
+
+# Compiling object files from source files.
+
+app.o : app.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+as.o : as.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+atof-generic.o : atof-generic.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+bignum-copy.o : bignum-copy.c as.h host.h \
+ targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+cond.o : cond.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+
+debug.o : debug.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+expr.o : expr.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+
+fn-const.o : fn-const.c flonum.h bignum.h
+fn-copy.o : fn-copy.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+flonum-mult.o : flonum-mult.c flonum.h bignum.h
+frags.o : frags.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+hash.o : hash.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+hex-value.o : hex-value.c
+input-file.o : input-file.c as.h host.h \
+ targ-env.h obj-format.h targ-cpu.h \
+ struc-symbol.h write.h flonum.h bignum.h expr.h \
+ frags.h hash.h read.h symbols.h tc.h obj.h input-file.h
+input-scrub.o : input-scrub.c \
+ as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ input-file.h
+messages.o : messages.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h
+obstack.o : obstack.c
+output-file.o : output-file.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ output-file.h
+read.o : read.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+
+strstr.o : strstr.c
+subsegs.o : subsegs.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+symbols.o : symbols.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h
+version.o : version.c
+write.o : write.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h symbols.h tc.h obj.h \
+ subsegs.h output-file.h
+xmalloc.o : xmalloc.c
+xrealloc.o : xrealloc.c
+atof-targ.o : atof-targ.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+ symbols.h tc.h obj.h
+obj-format.o : obj-format.c as.h host.h targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+ symbols.h tc.h obj.h
+targ-cpu.o : targ-cpu.c targ-env.h obj-format.h \
+ targ-cpu.h struc-symbol.h \
+ write.h flonum.h bignum.h expr.h frags.h hash.h read.h \
+ symbols.h tc.h obj.h $(TARG_CPU_DEPENDENTS)
+
+
+# Compile the libraries to be used by gen*.
+# If we are not cross-building, gen* use the same .o's that cc1 will use,
+# and HOST_PREFIX_1 is `foobar', just to ensure these rules don't conflict
+# with the rules for rtl.o, alloca.o, etc.
+$(HOST_PREFIX_1)alloca.o: alloca.c
+ rm -f $(HOST_PREFIX)alloca.c
+ cp alloca.c $(HOST_PREFIX)alloca.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)alloca.c
+
+$(HOST_PREFIX_1)obstack.o: obstack.c
+ rm -f $(HOST_PREFIX)obstack.c
+ cp obstack.c $(HOST_PREFIX)obstack.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)obstack.c
+
+$(HOST_PREFIX_1)malloc.o: malloc.c
+ rm -f $(HOST_PREFIX)malloc.c
+ cp malloc.c $(HOST_PREFIX)malloc.c
+ $(HOST_CC) -c $(HOST_CFLAGS) $(HOST_CPPFLAGS) $(INCLUDES) $(HOST_PREFIX)malloc.c
+
+# Remake the info files.
+
+doc: as.info
+
+as.info: doc/as.texinfo
+ (cd doc; make as.info; mv as.info $srcdir)
+
+
+# Deletion of files made during compilation.
+# There are three levels of this: `clean', `cleanconfig' and `realclean'.
+# `clean' deletes what you want to delete ordinarily to save space.
+# This is most, but not all, of the files made by compilation.
+# `cleanconfig' also deletes everything depending
+# on the choice of config files.
+# `realclean' also deletes everything that could be regenerated automatically.
+
+clean:
+ -rm -f $(STAGESTUFF)
+# Delete the temporary source copies for cross compilation.
+ -rm -f $(HOST_PREFIX_1)alloca.c $(HOST_PREFIX_1)malloc.c
+ -rm -f $(HOST_PREFIX_1)obstack.c
+# Delete the stamp files except stamp-gnulib2.
+ -rm -f core
+
+# Like clean but also delete the links made to configure gas.
+cleanconfig: clean
+ -rm -f config.status Makefile host.h targ-env.h
+ -rm -f targ-cpu.h targ-cpu.c
+ -rm -f obj-format.h obj-format.c
+ -rm -f atof-targ.c
+
+# Get rid of every file that's generated from some other file (except INSTALL).
+realclean: cleanconfig
+ -rm -f gas.aux gas.cps gas.fns gas.info gas.kys gas.pgs gas.tps gas.vrs
+ -rm -f TAGS
+ -rm -f gas.info* gas.?? gas.??s gas.log gas.toc gas.*aux
+ -rm -f *.dvi
+
+# Entry points `install', `includes' and `uninstall'.
+
+# Copy the files into directories where they will be run.
+install: $(ALL)
+ $(INSTALL_PROGRAM) $(ALL) $(libsubdir)/as
+# cp $(ALL) $(bindir)/as.new
+# mv -f $(bindir)/as.new $(bindir)/as
+
+# Create the installation directory.
+install-dir:
+ -mkdir $(libdir)
+ -mkdir $(libdir)/gcc
+ -mkdir $(libdir)/gcc/$(target)
+ -mkdir $(libdir)/gcc/$(target)/$(version)
+
+# Install the compiler executables built during cross compilation.
+install-cross: native install-dir
+ -if [ -f cc1 ] ; then $(INSTALL_PROGRAM) cc1 $(libsubdir)/cc1; else true; fi
+ -if [ -f cc1plus ] ; then $(INSTALL_PROGRAM) cc1plus $(libsubdir)/cc1plus; else true; fi
+ $(INSTALL_PROGRAM) cpp $(libsubdir)/cpp
+ ./gcc -dumpspecs > $(libsubdir)/specs
+ $(INSTALL_PROGRAM) gcc $(bindir)/gcc
+
+# Install the man pages.
+install-man: install-dir gcc.1 protoize.1 unprotoize.1
+ $(INSTALL_FILE) gcc.1 $(mandir)/gcc.$(manext)
+ chmod a-x $(mandir)/gcc.$(manext)
+ $(INSTALL_FILE) protoize.1 $(mandir)/protoize.$(manext)
+ chmod a-x $(mandir)/protoize.$(manext)
+ $(INSTALL_FILE) unprotoize.1 $(mandir)/unprotoize.$(manext)
+ chmod a-x $(mandir)/unprotoize.$(manext)
+
+# Cancel installation by deleting the installed files.
+uninstall:
+ -rm -rf $(libsubdir)
+ -rm -rf $(bindir)/as
+ -rm -rf $(mandir)/gas.$(manext)
+
+
+# These exist for maintenance purposes.
+
+tags TAGS: force
+ etags $(REAL_SOURCES) $(REAL_HEADERS) README Makefile config/*.[hc]
+
+bootstrap: $(ALL) force
+ $(MAKE) stage1
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(ALL)
+ $(MAKE) stage2
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(ALL)
+ $(MAKE) comparison against=stage2
+
+bootstrap2: force
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage1/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(ALL)
+ $(MAKE) stage2
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(ALL)
+ $(MAKE) comparison against=stage2
+
+bootstrap3: force
+ $(MAKE) CC="$(CC)" CFLAGS="-O -Bstage2/ $(CFLAGS)" libdir=$(libdir) ALLOCA= $(ALL)
+ $(MAKE) comparison against=stage2
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1: force
+ -mkdir stage1
+ -mv $(STAGESTUFF) stage1
+ if [ -f stage1/as.new -a ! -f stage1/as ] ; then (cd stage1 ; ln -s as.new as) ; fi
+
+stage2: force
+ -mkdir stage2
+ -mv $(STAGESTUFF) stage2
+ if [ -f stage2/as.new -a ! -f stage2/as ] ; then (cd stage2 ; ln -s as.new as) ; fi
+
+stage3: force
+ -mkdir stage3
+ -mv $(STAGESTUFF) stage3
+ if [ -f stage3/as.new -a ! -f stage3/as ] ; then (cd stage3 ; ln -s as.new as) ; fi
+
+against=stage2
+
+comparison: force
+ for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i ; done
+
+de-stage1: force
+ - (cd stage1 ; rm as ; mv -f * ..)
+ - rmdir stage1
+
+de-stage2: force
+ - (cd stage2 ; rm as ; mv -f * ..)
+ - rmdir stage2
+
+de-stage3: force
+ - (cd stage3 ; rm as ; mv -f * ..)
+ - rmdir stage3
+
+# Copy just the executable files from a particular stage into a subdirectory,
+# and delete the object files. Use this if you're just verifying a version
+# that is pretty sure to work, and you are short of disk space.
+risky-stage1: force
+ -mkdir stage1
+ -mv cc1 cpp cccp gcc stage1
+ -rm -f stage1/gnulib
+ -cp gnulib stage1 && $(RANLIB) stage1/gnulib
+ -make clean
+
+risky-stage2: force
+ -mkdir stage2
+ -mv cc1 cpp cccp gcc stage2
+ -rm -f stage2/gnulib
+ -cp gnulib stage2 && $(RANLIB) stage2/gnulib
+ -make clean
+
+risky-stage3: force
+ -mkdir stage3
+ -mv cc1 cpp cccp gcc stage3
+ -rm -f stage3/gnulib
+ -cp gnulib stage3 && $(RANLIB) stage3/gnulib
+ -make clean
+
+risky-stage4: force
+ -mkdir stage4
+ -mv cc1 cpp cccp gcc stage4
+ -rm -f stage4/gnulib
+ -cp gnulib stage4 && $(RANLIB) stage4/gnulib
+ -make clean
+
+#In GNU Make, ignore whether `stage*' exists.
+.PHONY: stage1 stage2 stage3 stage4 clean realclean TAGS bootstrap
+.PHONY: risky-stage1 risky-stage2 risky-stage3 risky-stage4
+
+force:
+
+Makefile: Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
+
diff --git a/gnu/usr.bin/as/messages.c b/gnu/usr.bin/as/messages.c
new file mode 100644
index 0000000..1d65116
--- /dev/null
+++ b/gnu/usr.bin/as/messages.c
@@ -0,0 +1,595 @@
+/* messages.c - error reporter -
+ Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "as.h"
+
+#ifndef __STDC__
+#ifndef NO_STDARG
+#define NO_STDARG
+#endif
+#endif
+
+#ifndef NO_STDARG
+#include <stdarg.h>
+#else
+#ifndef NO_VARARGS
+#include <varargs.h>
+#endif /* NO_VARARGS */
+#endif /* NO_STDARG */
+
+extern char *strerror ();
+
+static void as_show_where PARAMS ((void));
+static void as_warn_internal PARAMS ((char *, unsigned int, char *));
+static void as_bad_internal PARAMS ((char *, unsigned int, char *));
+
+/*
+ * Despite the rest of the comments in this file, (FIXME-SOON),
+ * here is the current scheme for error messages etc:
+ *
+ * as_fatal() is used when gas is quite confused and
+ * continuing the assembly is pointless. In this case we
+ * exit immediately with error status.
+ *
+ * as_bad() is used to mark errors that result in what we
+ * presume to be a useless object file. Say, we ignored
+ * something that might have been vital. If we see any of
+ * these, assembly will continue to the end of the source,
+ * no object file will be produced, and we will terminate
+ * with error status. The new option, -Z, tells us to
+ * produce an object file anyway but we still exit with
+ * error status. The assumption here is that you don't want
+ * this object file but we could be wrong.
+ *
+ * as_warn() is used when we have an error from which we
+ * have a plausible error recovery. eg, masking the top
+ * bits of a constant that is longer than will fit in the
+ * destination. In this case we will continue to assemble
+ * the source, although we may have made a bad assumption,
+ * and we will produce an object file and return normal exit
+ * status (ie, no error). The new option -X tells us to
+ * treat all as_warn() errors as as_bad() errors. That is,
+ * no object file will be produced and we will exit with
+ * error status. The idea here is that we don't kill an
+ * entire make because of an error that we knew how to
+ * correct. On the other hand, sometimes you might want to
+ * stop the make at these points.
+ *
+ * as_tsktsk() is used when we see a minor error for which
+ * our error recovery action is almost certainly correct.
+ * In this case, we print a message and then assembly
+ * continues as though no error occurred.
+ */
+
+static void
+identify (file)
+ char *file;
+{
+ static int identified;
+ if (identified)
+ return;
+ identified++;
+
+ if (!file)
+ {
+ unsigned int x;
+ as_where (&file, &x);
+ }
+
+ fprintf (stderr, "%s: Assembler messages:\n", file);
+}
+
+static int warning_count; /* Count of number of warnings issued */
+
+int
+had_warnings ()
+{
+ return (warning_count);
+} /* had_err() */
+
+/* Nonzero if we've hit a 'bad error', and should not write an obj file,
+ and exit with a nonzero error code */
+
+static int error_count;
+
+int
+had_errors ()
+{
+ return (error_count);
+} /* had_errors() */
+
+
+/* Print the current location to stderr. */
+
+static void
+as_show_where ()
+{
+ char *file;
+ unsigned int line;
+
+ as_where (&file, &line);
+ identify (file);
+ fprintf (stderr, "%s:%u: ", file, line);
+}
+
+/*
+ * a s _ p e r r o r
+ *
+ * Like perror(3), but with more info.
+ */
+
+void
+as_perror (gripe, filename)
+ const char *gripe; /* Unpunctuated error theme. */
+ const char *filename;
+{
+ const char *errtxt;
+
+ as_show_where ();
+ fprintf (stderr, gripe, filename);
+#ifdef BFD_ASSEMBLER
+ errtxt = bfd_errmsg (bfd_get_error ());
+#else
+ errtxt = strerror (errno);
+#endif
+ fprintf (stderr, ": %s\n", errtxt);
+ errno = 0;
+#ifdef BFD_ASSEMBLER
+ bfd_set_error (bfd_error_no_error);
+#endif
+}
+
+/*
+ * a s _ t s k t s k ()
+ *
+ * Send to stderr a string as a warning, and locate warning
+ * in input file(s).
+ * Please only use this for when we have some recovery action.
+ * Please explain in string (which may have '\n's) what recovery was done.
+ */
+
+#ifndef NO_STDARG
+void
+as_tsktsk (const char *format,...)
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args, format);
+ vfprintf (stderr, format, args);
+ va_end (args);
+ (void) putc ('\n', stderr);
+} /* as_tsktsk() */
+
+#else
+#ifndef NO_VARARGS
+void
+as_tsktsk (format, va_alist)
+ char *format;
+ va_dcl
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args);
+ vfprintf (stderr, format, args);
+ va_end (args);
+ (void) putc ('\n', stderr);
+} /* as_tsktsk() */
+
+#else
+/*VARARGS1 */
+as_tsktsk (format, args)
+ char *format;
+{
+ as_show_where ();
+ _doprnt (format, &args, stderr);
+ (void) putc ('\n', stderr);
+} /* as_tsktsk */
+
+#endif /* not NO_VARARGS */
+#endif /* not NO_STDARG */
+
+/* The common portion of as_warn and as_warn_where. */
+
+static void
+as_warn_internal (file, line, buffer)
+ char *file;
+ unsigned int line;
+ char *buffer;
+{
+ ++warning_count;
+
+ if (file == NULL)
+ as_where (&file, &line);
+
+ identify (file);
+ fprintf (stderr, "%s:%u: Warning: ", file, line);
+ fputs (buffer, stderr);
+ (void) putc ('\n', stderr);
+#ifndef NO_LISTING
+ listing_warning (buffer);
+#endif
+}
+
+/*
+ * a s _ w a r n ()
+ *
+ * Send to stderr a string as a warning, and locate warning
+ * in input file(s).
+ * Please only use this for when we have some recovery action.
+ * Please explain in string (which may have '\n's) what recovery was done.
+ */
+
+#if 1
+#define flag_no_warnings (flagseen['W'])
+#endif
+
+#ifndef NO_STDARG
+void
+as_warn (const char *format,...)
+{
+ va_list args;
+ char buffer[200];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal ((char *) NULL, 0, buffer);
+ }
+} /* as_warn() */
+
+#else
+#ifndef NO_VARARGS
+void
+as_warn (format, va_alist)
+ char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[200];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal ((char *) NULL, 0, buffer);
+ }
+} /* as_warn() */
+
+#else
+/*VARARGS1 */
+as_warn (format, args)
+ char *format;
+{
+ if (!flag_no_warnings)
+ {
+ ++warning_count;
+ as_show_where ();
+ fprintf (stderr, "Warning: ");
+ _doprnt (format, &args, stderr);
+ (void) putc ('\n', stderr);
+ }
+} /* as_warn() */
+
+#endif /* not NO_VARARGS */
+#endif /* not NO_STDARG */
+
+/* as_warn_where, like as_bad but the file name and line number are
+ passed in. Unfortunately, we have to repeat the function in order
+ to handle the varargs correctly and portably. */
+
+#ifndef NO_STDARG
+void
+as_warn_where (char *file, unsigned int line, const char *format,...)
+{
+ va_list args;
+ char buffer[200];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal (file, line, buffer);
+ }
+} /* as_warn() */
+
+#else
+#ifndef NO_VARARGS
+void
+as_warn_where (file, line, format, va_alist)
+ char *file;
+ unsigned int line;
+ char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[200];
+
+ if (!flag_no_warnings)
+ {
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+ as_warn_internal (file, line, buffer);
+ }
+} /* as_warn() */
+
+#else
+/*VARARGS1 */
+as_warn_where (file, line, format, args)
+ char *file;
+ unsigned int line;
+ char *format;
+{
+ if (!flag_no_warnings)
+ {
+ ++warning_count;
+ identify (file);
+ fprintf (stderr, "%s:%u: Warning: ", file, line);
+ _doprnt (format, &args, stderr);
+ (void) putc ('\n', stderr);
+ }
+} /* as_warn() */
+
+#endif /* not NO_VARARGS */
+#endif /* not NO_STDARG */
+
+/* The common portion of as_bad and as_bad_where. */
+
+static void
+as_bad_internal (file, line, buffer)
+ char *file;
+ unsigned int line;
+ char *buffer;
+{
+ ++error_count;
+
+ if (file == NULL)
+ as_where (&file, &line);
+
+ identify (file);
+ fprintf (stderr, "%s:%u: Error: ", file, line);
+ fputs (buffer, stderr);
+ (void) putc ('\n', stderr);
+#ifndef NO_LISTING
+ listing_error (buffer);
+#endif
+}
+
+/*
+ * a s _ b a d ()
+ *
+ * Send to stderr a string as a warning, and locate warning in input file(s).
+ * Please us when there is no recovery, but we want to continue processing
+ * but not produce an object file.
+ * Please explain in string (which may have '\n's) what recovery was done.
+ */
+
+#ifndef NO_STDARG
+void
+as_bad (const char *format,...)
+{
+ va_list args;
+ char buffer[200];
+
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal ((char *) NULL, 0, buffer);
+}
+
+#else
+#ifndef NO_VARARGS
+void
+as_bad (format, va_alist)
+ char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[200];
+
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal ((char *) NULL, 0, buffer);
+}
+
+#else
+/*VARARGS1 */
+as_bad (format, args)
+ char *format;
+{
+ ++error_count;
+
+ as_show_where ();
+ fprintf (stderr, "Error: ");
+ _doprnt (format, &args, stderr);
+ (void) putc ('\n', stderr);
+} /* as_bad() */
+
+#endif /* not NO_VARARGS */
+#endif /* not NO_STDARG */
+
+/* as_bad_where, like as_bad but the file name and line number are
+ passed in. Unfortunately, we have to repeat the function in order
+ to handle the varargs correctly and portably. */
+
+#ifndef NO_STDARG
+void
+as_bad_where (char *file, unsigned int line, const char *format,...)
+{
+ va_list args;
+ char buffer[200];
+
+ va_start (args, format);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal (file, line, buffer);
+}
+
+#else
+#ifndef NO_VARARGS
+void
+as_bad_where (file, line, format, va_alist)
+ char *file;
+ unsigned int line;
+ char *format;
+ va_dcl
+{
+ va_list args;
+ char buffer[200];
+
+ va_start (args);
+ vsprintf (buffer, format, args);
+ va_end (args);
+
+ as_bad_internal (file, line, buffer);
+}
+
+#else
+/*VARARGS1 */
+as_bad_where (file, line, format, args)
+ char *file;
+ unsigned int line;
+ char *format;
+{
+ ++error_count;
+
+ identify (file);
+ fprintf (stderr, "%s:%u: Error: ", file, line);
+ _doprnt (format, &args, stderr);
+ (void) putc ('\n', stderr);
+} /* as_bad() */
+
+#endif /* not NO_VARARGS */
+#endif /* not NO_STDARG */
+
+/*
+ * a s _ f a t a l ()
+ *
+ * Send to stderr a string as a fatal message, and print location of error in
+ * input file(s).
+ * Please only use this for when we DON'T have some recovery action.
+ * It exit()s with a warning status.
+ */
+
+#ifndef NO_STDARG
+void
+as_fatal (const char *format,...)
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args, format);
+ fprintf (stderr, "Fatal error:");
+ vfprintf (stderr, format, args);
+ (void) putc ('\n', stderr);
+ va_end (args);
+ exit (33);
+} /* as_fatal() */
+
+#else
+#ifndef NO_VARARGS
+void
+as_fatal (format, va_alist)
+ char *format;
+ va_dcl
+{
+ va_list args;
+
+ as_show_where ();
+ va_start (args);
+ fprintf (stderr, "Fatal error:");
+ vfprintf (stderr, format, args);
+ (void) putc ('\n', stderr);
+ va_end (args);
+ exit (33);
+} /* as_fatal() */
+
+#else
+/*VARARGS1 */
+as_fatal (format, args)
+ char *format;
+{
+ as_show_where ();
+ fprintf (stderr, "Fatal error:");
+ _doprnt (format, &args, stderr);
+ (void) putc ('\n', stderr);
+ exit (33); /* What is a good exit status? */
+} /* as_fatal() */
+
+#endif /* not NO_VARARGS */
+#endif /* not NO_STDARG */
+
+void
+fprint_value (file, val)
+ FILE *file;
+ valueT val;
+{
+ if (sizeof (val) <= sizeof (long))
+ {
+ fprintf (file, "%ld", (long) val);
+ return;
+ }
+#ifdef BFD_ASSEMBLER
+ if (sizeof (val) <= sizeof (bfd_vma))
+ {
+ fprintf_vma (file, val);
+ return;
+ }
+#endif
+ abort ();
+}
+
+void
+sprint_value (buf, val)
+ char *buf;
+ valueT val;
+{
+ if (sizeof (val) <= sizeof (long))
+ {
+ sprintf (buf, "%ld", (long) val);
+ return;
+ }
+#ifdef BFD_ASSEMBLER
+ if (sizeof (val) <= sizeof (bfd_vma))
+ {
+ sprintf_vma (buf, val);
+ return;
+ }
+#endif
+ abort ();
+}
+
+/* end of messages.c */
diff --git a/gnu/usr.bin/as/obj.h b/gnu/usr.bin/as/obj.h
new file mode 100644
index 0000000..987e706
--- /dev/null
+++ b/gnu/usr.bin/as/obj.h
@@ -0,0 +1,77 @@
+/* obj.h - defines the object dependent hooks for all object
+ format backends.
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+#if __STDC__ == 1
+
+char *obj_default_output_file_name(void);
+void obj_crawl_symbol_chain(object_headers *headers);
+void obj_emit_relocations(char **where, fixS *fixP, relax_addressT segment_address_in_file);
+void obj_emit_strings(char **where);
+void obj_emit_symbols(char **where, symbolS *symbol_rootP);
+void obj_header_append(char **where, object_headers *headers);
+void obj_read_begin_hook(void);
+
+#ifndef obj_symbol_new_hook
+void obj_symbol_new_hook(symbolS *symbolP);
+#endif /* obj_symbol_new_hook */
+
+void obj_symbol_to_chars(char **where, symbolS *symbolP);
+
+#ifndef obj_pre_write_hook
+void obj_pre_write_hook(object_headers *headers);
+#endif /* obj_pre_write_hook */
+
+#else /* not __STDC__ */
+
+char *obj_default_output_file_name();
+void obj_crawl_symbol_chain();
+void obj_emit_relocations();
+void obj_emit_strings();
+void obj_emit_symbols();
+void obj_header_append();
+void obj_read_begin_hook();
+
+#ifndef obj_symbol_new_hook
+void obj_symbol_new_hook();
+#endif /* obj_symbol_new_hook */
+
+void obj_symbol_to_chars();
+
+#ifndef obj_pre_write_hook
+void obj_pre_write_hook();
+#endif /* obj_pre_write_hook */
+
+#endif /* not __STDC__ */
+
+extern const pseudo_typeS obj_pseudo_table[];
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of obj.h */
diff --git a/gnu/usr.bin/as/obstack.c b/gnu/usr.bin/as/obstack.c
new file mode 100644
index 0000000..4a39b56
--- /dev/null
+++ b/gnu/usr.bin/as/obstack.c
@@ -0,0 +1,374 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "obstack.h"
+
+#ifdef __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment. */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT ((char *)&((struct fooalign *) 0)->d - (char *)0)
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+ But in fact it might be less smart and round addresses to as much as
+ DEFAULT_ROUNDING. So we prepare for it to do that. */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+ On some machines, copying successive ints does not work;
+ in such a case, redefine COPYING_UNIT to `long' (if that works)
+ or `char' as a last resort. */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+/* The non-GNU-C macros copy the obstack into this global variable
+ to avoid multiple evaluation. */
+
+struct obstack *_obstack;
+
+/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
+ Objects start on multiples of ALIGNMENT (0 means use default).
+ CHUNKFUN is the function to use to allocate chunks,
+ and FREEFUN the function to free them. */
+
+void
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+ struct obstack *h;
+ int size;
+ int alignment;
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+{
+ register struct _obstack_chunk* chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+
+ chunk = h->chunk = (*h->chunkfun) (h->chunk_size);
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+ /* The initial chunk now contains no empty object. */
+ h->maybe_empty_object = 0;
+}
+
+/* Allocate a new current chunk for the obstack *H
+ on the assumption that LENGTH bytes need to be added
+ to the current object, or a new object of length LENGTH allocated.
+ Copies any partial object from the end of the old chunk
+ to the beginning of the new one. */
+
+void
+_obstack_newchunk (h, length)
+ struct obstack *h;
+ int length;
+{
+ register struct _obstack_chunk* old_chunk = h->chunk;
+ register struct _obstack_chunk* new_chunk;
+ register long new_size;
+ register int obj_size = h->next_free - h->object_base;
+ register int i;
+ int already;
+
+ /* Compute size for new chunk. */
+ new_size = (obj_size + length) + (obj_size >> 3) + 100;
+ if (new_size < h->chunk_size)
+ new_size = h->chunk_size;
+
+ /* Allocate and initialize the new chunk. */
+ new_chunk = h->chunk = (*h->chunkfun) (new_size);
+ new_chunk->prev = old_chunk;
+ new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+ /* Move the existing object to the new chunk.
+ Word at a time is fast and is safe if the object
+ is sufficiently aligned. */
+ if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+ {
+ for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+ i >= 0; i--)
+ ((COPYING_UNIT *)new_chunk->contents)[i]
+ = ((COPYING_UNIT *)h->object_base)[i];
+ /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+ but that can cross a page boundary on a machine
+ which does not do strict alignment for COPYING_UNITS. */
+ already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+ }
+ else
+ already = 0;
+ /* Copy remaining bytes one by one. */
+ for (i = already; i < obj_size; i++)
+ new_chunk->contents[i] = h->object_base[i];
+
+ /* If the object just copied was the only data in OLD_CHUNK,
+ free that chunk and remove it from the chain.
+ But not if that chunk might contain an empty object. */
+ if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
+ {
+ new_chunk->prev = old_chunk->prev;
+ (*h->freefun) (old_chunk);
+ }
+
+ h->object_base = new_chunk->contents;
+ h->next_free = h->object_base + obj_size;
+ /* The new chunk certainly contains no empty object yet. */
+ h->maybe_empty_object = 0;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+ This is here for debugging.
+ If you use it in a program, you are probably losing. */
+
+int
+_obstack_allocated_p (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ /* We use >= rather than > since the object cannot be exactly at
+ the beginning of the chunk but might be an empty object exactly
+ at the end of an adjacent chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp->prev;
+ lp = plp;
+ }
+ return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+ more recently than OBJ. If OBJ is zero, free everything in H. */
+
+#undef obstack_free
+
+/* This function has two names with identical definitions.
+ This is the first one, called from non-ANSI code. */
+
+void
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = h->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp->prev;
+ (*h->freefun) (lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ if (lp)
+ {
+ h->object_base = h->next_free = (char *)(obj);
+ h->chunk_limit = lp->limit;
+ h->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+/* This function is used from ANSI code. */
+
+void
+obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = h->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp->prev;
+ (*h->freefun) (lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ if (lp)
+ {
+ h->object_base = h->next_free = (char *)(obj);
+ h->chunk_limit = lp->limit;
+ h->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+#if 0
+/* These are now turned off because the applications do not use it
+ and it uses bcopy via obstack_grow, which causes trouble on sysV. */
+
+/* Now define the functional versions of the obstack macros.
+ Define them to simply use the corresponding macros to do the job. */
+
+#ifdef __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+ they won't pass through the macro names in parentheses. */
+
+/* The function names appear in parentheses in order to prevent
+ the macro-definitions of the names from being expanded there. */
+
+POINTER (obstack_base) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_room (obstack);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+#endif /* 0 */
diff --git a/gnu/usr.bin/as/obstack.h b/gnu/usr.bin/as/obstack.h
new file mode 100644
index 0000000..c1b4484
--- /dev/null
+++ b/gnu/usr.bin/as/obstack.h
@@ -0,0 +1,448 @@
+/* obstack.h - object stack macros
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects. Each object starts life
+small, and may grow to maturity. (Consider building a word syllable
+by syllable.) An object can move while it is growing. Once it has
+been "finished" it never changes address again. So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
+by calling `obstack_chunk_free'. You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables. Unless you are "fascist pig with a read-only mind"
+[Gosper's immortal quote from HAKMEM item 154, out of context] you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols. At the time you are reading a symbol you don't know
+how long it is. One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer. This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently. Use one obstack for all symbol
+names. As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it. Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses. When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk. When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies. No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk. We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object. This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+ We allocate large chunks.
+ We carve out one object at a time from the current chunk.
+ Once carved, an object never moves.
+ We are free to append data of any size to the currently
+ growing object.
+ Exactly one object is growing in an obstack at any one time.
+ You can run one obstack per control block.
+ You may have as many control blocks as you dare.
+ Because of the way we do it, you can `unwind' a obstack
+ back to a previous state. (You may remove objects much
+ as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once. */
+
+#ifndef __OBSTACKS__
+#define __OBSTACKS__
+
+/* We use subtraction of (char *)0 instead of casting to int
+ because on word-addressable machines a simple cast to int
+ may ignore the byte-within-word field of the pointer. */
+
+#ifndef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((P) - (char *)0)
+#endif
+
+#ifndef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((P) + (char *)0)
+#endif
+
+struct _obstack_chunk /* Lives at front of each chunk. */
+{
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
+};
+
+struct obstack /* control current object in current chunk */
+{
+ long chunk_size; /* preferred size to allocate chunks in */
+ struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
+ int temp; /* Temporary for some macros. */
+ int alignment_mask; /* Mask of alignment for each object. */
+ struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
+ void (*freefun) (); /* User's function to free a chunk. */
+ /* Nonzero means there is a possibility the current chunk contains
+ a zero-length object. This prevents freeing the chunk
+ if we allocate a bigger chunk to replace it. */
+ char maybe_empty_object;
+};
+
+/* Declare the external functions we use; they are in obstack.c. */
+
+#ifdef __STDC__
+ extern void _obstack_newchunk (struct obstack *, int);
+ extern void _obstack_free (struct obstack *, void *);
+ extern void _obstack_begin (struct obstack *, int, int,
+ void *(*) (), void (*) ());
+#else
+ extern void _obstack_newchunk ();
+ extern void _obstack_free ();
+ extern void _obstack_begin ();
+#endif
+
+#ifdef __STDC__
+
+/* Do the function-declarations after the structs
+ but before defining the macros. */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, void *data, int size);
+void obstack_grow0 (struct obstack *obstack, void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+ so we do not declare them. */
+
+/* Pointer to beginning of object being allocated or to be allocated next.
+ Note that this might not be the final address of the object
+ because a new chunk might be needed to hold the final size. */
+
+#define obstack_base(h) ((h)->object_base)
+
+/* Size for allocating ordinary chunks. */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk. */
+
+#define obstack_next_free(h) ((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object. */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ())obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ())obstack_chunk_free)
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#if defined (__GNUC__) && defined (__STDC__)
+#if __GNUC__ < 2
+#define __extension__
+#endif
+
+/* For GNU C, if not -traditional,
+ we can define these macros to compute all args only once
+ without using a global variable.
+ Also, we can avoid using the `temp' slot, to make faster code. */
+
+#define obstack_object_size(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->next_free - __o->object_base); })
+
+#define obstack_room(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->chunk_limit - __o->next_free); })
+
+/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
+ so that we can avoid having void expressions
+ in the arms of the conditional expression.
+ Casting the third operand to void was tried before,
+ but some compilers won't accept it. */
+#define obstack_grow(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len > __o->chunk_limit) \
+ ? (_obstack_newchunk (__o, __len), 0) : 0); \
+ memcpy (__o->next_free, where, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_grow0(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->next_free + __len + 1 > __o->chunk_limit) \
+ ? (_obstack_newchunk (__o, __len + 1), 0) : 0), \
+ memcpy (__o->next_free, where, __len), \
+ __o->next_free += __len, \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+#define obstack_1grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + 1 > __o->chunk_limit) \
+ ? (_obstack_newchunk (__o, 1), 0) : 0), \
+ *(__o->next_free)++ = (datum); \
+ (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers or ints,
+ and that the data added so far to the current object
+ shares that much alignment. */
+
+#define obstack_ptr_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ ? (_obstack_newchunk (__o, sizeof (void *)), 0) : 0), \
+ *(*(void ***)&__o->next_free)++ = ((void *)datum); \
+ (void) 0; })
+
+#define obstack_int_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (int) > __o->chunk_limit) \
+ ? (_obstack_newchunk (__o, sizeof (int)), 0) : 0), \
+ *(*(int **)&__o->next_free)++ = ((int)datum); \
+ (void) 0; })
+
+#define obstack_ptr_grow_fast(h,aptr) (*(*(void ***)&(h)->next_free)++ = (void *)aptr)
+#define obstack_int_grow_fast(h,aint) (*(*(int **)&(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ ((__o->chunk_limit - __o->next_free < __len) \
+ ? (_obstack_newchunk (__o, __len), 0) : 0); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+#define obstack_alloc(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy0(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+/* The local variable is named __o1 to avoid a name conflict
+ when obstack_blank is called. */
+#define obstack_finish(OBSTACK) \
+__extension__ \
+({ struct obstack *__o1 = (OBSTACK); \
+ void *value = (void *) __o1->object_base; \
+ if (__o1->next_free == value) \
+ __o1->maybe_empty_object = 1; \
+ __o1->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
+ & ~ (__o1->alignment_mask)); \
+ ((__o1->next_free - (char *)__o1->chunk \
+ > __o1->chunk_limit - (char *)__o1->chunk) \
+ ? (__o1->next_free = __o1->chunk_limit) : 0); \
+ __o1->object_base = __o1->next_free; \
+ value; })
+
+#define obstack_free(OBSTACK, OBJ) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (OBJ); \
+ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ __o->next_free = __o->object_base = __obj; \
+ else (obstack_free) (__o, __obj); })
+
+#else /* not __GNUC__ or not __STDC__ */
+
+#define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+#define obstack_room(h) \
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+#define obstack_grow(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_grow0(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp), \
+ (h)->next_free += (h)->temp, \
+ *((h)->next_free)++ = 0)
+
+#define obstack_1grow(h,datum) \
+( (((h)->next_free + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), 1), 0) : 0), \
+ *((h)->next_free)++ = (datum))
+
+#define obstack_ptr_grow(h,datum) \
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
+ *(*(char ***)&(h)->next_free)++ = ((char *)datum))
+
+#define obstack_int_grow(h,datum) \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
+ *(*(int **)&(h)->next_free)++ = ((int)datum))
+
+#define obstack_ptr_grow_fast(h,aptr) (*(*(char ***)&(h)->next_free)++ = (char *)aptr)
+#define obstack_int_grow_fast(h,aint) (*(*(int **)&(h)->next_free)++ = (int)aint)
+#define obstack_blank(h,length) \
+( (h)->temp = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
+ (h)->next_free += (h)->temp)
+
+#define obstack_alloc(h,length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+#define obstack_copy(h,where,length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_copy0(h,where,length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_finish(h) \
+( ((h)->next_free == (h)->object_base \
+ ? (((h)->maybe_empty_object = 1), 0) \
+ : 0), \
+ (h)->temp = __PTR_TO_INT ((h)->object_base), \
+ (h)->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
+ & ~ ((h)->alignment_mask)), \
+ (((h)->next_free - (char *)(h)->chunk \
+ > (h)->chunk_limit - (char *)(h)->chunk) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ __INT_TO_PTR ((h)->temp))
+
+#ifdef __STDC__
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
+#else
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
+#endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+#endif /* not __OBSTACKS__ */
diff --git a/gnu/usr.bin/as/opcode/ChangeLog b/gnu/usr.bin/as/opcode/ChangeLog
new file mode 100644
index 0000000..dcb0498
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/ChangeLog
@@ -0,0 +1,56 @@
+Mon Feb 24 02:02:04 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * ns32k.h: SEQUENT_COMPATIBILITY -> TE_SEQUENT.
+
+ * i860.h: added "fst.q".
+
+Fri Feb 21 01:29:51 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * i386.h: added inb, inw, outb, outw opcodes, added att syntax for
+ scmp, slod, smov, ssca, ssto. Curtesy Minh Tran-Le
+ <TRANLE@INTELLICORP.COM>.
+
+Thu Jan 30 07:31:44 1992 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * h8300.h: turned op_type enum into #define list
+
+Thu Jan 30 01:07:24 1992 John Gilmore (gnu at cygnus.com)
+
+ * sparc.h: Remove "cypress" architecture. Remove "fitox" and
+ similar instructions -- they've been renamed to "fitoq", etc.
+ REALLY fix tsubcctv. Fix "fcmpeq" and "fcmpq" which had wrong
+ number of arguments.
+ * h8300.h: Remove extra ; which produces compiler warning.
+
+Tue Jan 28 22:59:22 1992 Stu Grossman (grossman at cygnus.com)
+
+ * sparc.h: fix opcode for tsubcctv.
+
+Tue Jan 7 17:19:39 1992 K. Richard Pixley (rich at cygnus.com)
+
+ * sparc.h: fba and cba are now aliases for fb and cb respectively.
+
+Fri Dec 27 10:55:50 1991 Per Bothner (bothner at cygnus.com)
+
+ * sparc.h (nop): Made the 'lose' field be even tighter,
+ so only a standard 'nop' is disassembled as a nop.
+
+Sun Dec 22 12:18:18 1991 Michael Tiemann (tiemann at cygnus.com)
+
+ * sparc.h (nop): Add RD_GO to `lose' so that only %g0 in dest is
+ disassembled as a nop.
+
+Tue Dec 10 00:22:20 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * sparc.h: fix a typo.
+
+Sat Nov 30 20:40:51 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * a29k.h, arm.h, h8300.h, i386.h, i860.h, i960.h , m68k.h,
+ m88k.h, mips.h , np1.h, ns32k.h, pn.h, pyr.h, sparc.h, tahoe.h,
+ vax.h, ChangeLog: renamed from ../<foo>-opcode.h
+
+
+
+
+
diff --git a/gnu/usr.bin/as/opcode/a29k.h b/gnu/usr.bin/as/opcode/a29k.h
new file mode 100644
index 0000000..8c36167
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/a29k.h
@@ -0,0 +1,327 @@
+/* Table of opcodes for the AMD 29000
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct a29k_opcode {
+ /* Name of the instruction. */
+ char *name;
+
+ /* Opcode word */
+ unsigned long opcode;
+
+ /* A string of characters which describe the operands.
+ Valid characters are:
+ , Itself. The character appears in the assembly code.
+ a RA. The register number is in bits 8-15 of the instruction.
+ b RB. The register number is in bits 0-7 of the instruction.
+ c RC. The register number is in bits 16-23 of the instruction.
+ i An immediate operand is in bits 0-7 of the instruction.
+ x Bits 0-7 and 16-23 of the instruction are bits 0-7 and 8-15
+ (respectively) of the immediate operand.
+ h Same as x but the instruction contains bits 16-31 of the
+ immediate operand.
+ X Same as x but bits 16-31 of the signed immediate operand
+ are set to 1 (thus the operand is always negative).
+ P,A Bits 0-7 and 16-23 of the instruction are bits 2-9 and 10-17
+ (respectively) of the immediate operand.
+ P=PC-relative, sign-extended to 32 bits.
+ A=Absolute, zero-extended to 32 bits.
+ e CE bit (bit 23) for a load/store instruction.
+ n Control field (bits 16-22) for a load/store instruction.
+ v Immediate operand in bits 16-23 of the instruction.
+ (used for trap numbers).
+ s SA. Special-purpose register number in bits 8-15
+ of the instruction.
+ u UI--bit 7 of the instruction.
+ r RND--bits 4-6 of the instruction.
+ d FD--bits 2-3 of the instruction.
+ f FS--bits 0-1 of the instruction.
+
+ Extensions for 29050:
+
+ d FMT--bits 2-3 of the instruction (not really new).
+ f ACN--bits 0-1 of the instruction (not really new).
+ F FUNC--Special function in bits 18-21 of the instruction.
+ C ACN--bits 16-17 specifying the accumlator register. */
+ char *args;
+};
+
+#ifndef CONST
+#define CONST
+#endif /* CONST */
+
+static CONST struct a29k_opcode a29k_opcodes[] =
+{
+
+{ "add", 0x14000000, "c,a,b" },
+{ "add", 0x15000000, "c,a,i" },
+{ "addc", 0x1c000000, "c,a,b" },
+{ "addc", 0x1d000000, "c,a,i" },
+{ "addcs", 0x18000000, "c,a,b" },
+{ "addcs", 0x19000000, "c,a,i" },
+{ "addcu", 0x1a000000, "c,a,b" },
+{ "addcu", 0x1b000000, "c,a,i" },
+{ "adds", 0x10000000, "c,a,b" },
+{ "adds", 0x11000000, "c,a,i" },
+{ "addu", 0x12000000, "c,a,b" },
+{ "addu", 0x13000000, "c,a,i" },
+{ "and", 0x90000000, "c,a,b" },
+{ "and", 0x91000000, "c,a,i" },
+{ "andn", 0x9c000000, "c,a,b" },
+{ "andn", 0x9d000000, "c,a,i" },
+{ "aseq", 0x70000000, "v,a,b" },
+{ "aseq", 0x71000000, "v,a,i" },
+{ "asge", 0x5c000000, "v,a,b" },
+{ "asge", 0x5d000000, "v,a,i" },
+{ "asgeu", 0x5e000000, "v,a,b" },
+{ "asgeu", 0x5f000000, "v,a,i" },
+{ "asgt", 0x58000000, "v,a,b" },
+{ "asgt", 0x59000000, "v,a,i" },
+{ "asgtu", 0x5a000000, "v,a,b" },
+{ "asgtu", 0x5b000000, "v,a,i" },
+{ "asle", 0x54000000, "v,a,b" },
+{ "asle", 0x55000000, "v,a,i" },
+{ "asleu", 0x56000000, "v,a,b" },
+{ "asleu", 0x57000000, "v,a,i" },
+{ "aslt", 0x50000000, "v,a,b" },
+{ "aslt", 0x51000000, "v,a,i" },
+{ "asltu", 0x52000000, "v,a,b" },
+{ "asltu", 0x53000000, "v,a,i" },
+{ "asneq", 0x72000000, "v,a,b" },
+{ "asneq", 0x73000000, "v,a,i" },
+{ "call", 0xa8000000, "a,P" },
+{ "call", 0xa9000000, "a,A" },
+{ "calli", 0xc8000000, "a,b" },
+{ "class", 0xe6000000, "c,a,f" },
+{ "clz", 0x08000000, "c,b" },
+{ "clz", 0x09000000, "c,i" },
+{ "const", 0x03000000, "a,x" },
+{ "consth", 0x02000000, "a,h" },
+{ "consthz", 0x05000000, "a,h" },
+{ "constn", 0x01000000, "a,X" },
+{ "convert", 0xe4000000, "c,a,u,r,d,f" },
+{ "cpbyte", 0x2e000000, "c,a,b" },
+{ "cpbyte", 0x2f000000, "c,a,i" },
+{ "cpeq", 0x60000000, "c,a,b" },
+{ "cpeq", 0x61000000, "c,a,i" },
+{ "cpge", 0x4c000000, "c,a,b" },
+{ "cpge", 0x4d000000, "c,a,i" },
+{ "cpgeu", 0x4e000000, "c,a,b" },
+{ "cpgeu", 0x4f000000, "c,a,i" },
+{ "cpgt", 0x48000000, "c,a,b" },
+{ "cpgt", 0x49000000, "c,a,i" },
+{ "cpgtu", 0x4a000000, "c,a,b" },
+{ "cpgtu", 0x4b000000, "c,a,i" },
+{ "cple", 0x44000000, "c,a,b" },
+{ "cple", 0x45000000, "c,a,i" },
+{ "cpleu", 0x46000000, "c,a,b" },
+{ "cpleu", 0x47000000, "c,a,i" },
+{ "cplt", 0x40000000, "c,a,b" },
+{ "cplt", 0x41000000, "c,a,i" },
+{ "cpltu", 0x42000000, "c,a,b" },
+{ "cpltu", 0x43000000, "c,a,i" },
+{ "cpneq", 0x62000000, "c,a,b" },
+{ "cpneq", 0x63000000, "c,a,i" },
+{ "dadd", 0xf1000000, "c,a,b" },
+{ "ddiv", 0xf7000000, "c,a,b" },
+{ "deq", 0xeb000000, "c,a,b" },
+{ "dge", 0xef000000, "c,a,b" },
+{ "dgt", 0xed000000, "c,a,b" },
+{ "div", 0x6a000000, "c,a,b" },
+{ "div", 0x6b000000, "c,a,i" },
+{ "div0", 0x68000000, "c,b" },
+{ "div0", 0x69000000, "c,i" },
+{ "divide", 0xe1000000, "c,a,b" },
+{ "dividu", 0xe3000000, "c,a,b" },
+{ "divl", 0x6c000000, "c,a,b" },
+{ "divl", 0x6d000000, "c,a,i" },
+{ "divrem", 0x6e000000, "c,a,b" },
+{ "divrem", 0x6f000000, "c,a,i" },
+{ "dmac", 0xd9000000, "F,C,a,b" },
+{ "dmsm", 0xdb000000, "c,a,b" },
+{ "dmul", 0xf5000000, "c,a,b" },
+{ "dsub", 0xf3000000, "c,a,b" },
+{ "emulate", 0xd7000000, "v,a,b" },
+{ "exbyte", 0x0a000000, "c,a,b" },
+{ "exbyte", 0x0b000000, "c,a,i" },
+{ "exhw", 0x7c000000, "c,a,b" },
+{ "exhw", 0x7d000000, "c,a,i" },
+{ "exhws", 0x7e000000, "c,a" },
+{ "extract", 0x7a000000, "c,a,b" },
+{ "extract", 0x7b000000, "c,a,i" },
+{ "fadd", 0xf0000000, "c,a,b" },
+{ "fdiv", 0xf6000000, "c,a,b" },
+{ "fdmul", 0xf9000000, "c,a,b" },
+{ "feq", 0xea000000, "c,a,b" },
+{ "fge", 0xee000000, "c,a,b" },
+{ "fgt", 0xec000000, "c,a,b" },
+{ "fmac", 0xd8000000, "F,C,a,b" },
+{ "fmsm", 0xda000000, "c,a,b" },
+{ "fmul", 0xf4000000, "c,a,b" },
+{ "fsub", 0xf2000000, "c,a,b" },
+{ "halt", 0x89000000, "" },
+{ "inbyte", 0x0c000000, "c,a,b" },
+{ "inbyte", 0x0d000000, "c,a,i" },
+{ "inhw", 0x78000000, "c,a,b" },
+{ "inhw", 0x79000000, "c,a,i" },
+{ "inv", 0x9f000000, "" },
+{ "iret", 0x88000000, "" },
+{ "iretinv", 0x8c000000, "" },
+{ "jmp", 0xa0000000, "P" },
+{ "jmp", 0xa1000000, "A" },
+{ "jmpf", 0xa4000000, "a,P" },
+{ "jmpf", 0xa5000000, "a,A" },
+{ "jmpfdec", 0xb4000000, "a,P" },
+{ "jmpfdec", 0xb5000000, "a,A" },
+{ "jmpfi", 0xc4000000, "a,b" },
+{ "jmpi", 0xc0000000, "b" },
+{ "jmpt", 0xac000000, "a,P" },
+{ "jmpt", 0xad000000, "a,A" },
+{ "jmpti", 0xcc000000, "a,b" },
+{ "load", 0x16000000, "e,n,a,b" },
+{ "load", 0x17000000, "e,n,a,i" },
+{ "loadl", 0x06000000, "e,n,a,b" },
+{ "loadl", 0x07000000, "e,n,a,i" },
+{ "loadm", 0x36000000, "e,n,a,b" },
+{ "loadm", 0x37000000, "e,n,a,i" },
+{ "loadset", 0x26000000, "e,n,a,b" },
+{ "loadset", 0x27000000, "e,n,a,i" },
+{ "mfacc", 0xe9000100, "c,d,f" },
+{ "mfsr", 0xc6000000, "c,s" },
+{ "mftlb", 0xb6000000, "c,a" },
+{ "mtacc", 0xe8010000, "a,d,f" },
+{ "mtsr", 0xce000000, "s,b" },
+{ "mtsrim", 0x04000000, "s,x" },
+{ "mttlb", 0xbe000000, "a,b" },
+{ "mul", 0x64000000, "c,a,b" },
+{ "mul", 0x65000000, "c,a,i" },
+{ "mull", 0x66000000, "c,a,b" },
+{ "mull", 0x67000000, "c,a,i" },
+{ "multiplu", 0xe2000000, "c,a,b" },
+{ "multiply", 0xe0000000, "c,a,b" },
+{ "multm", 0xde000000, "c,a,b" },
+{ "multmu", 0xdf000000, "c,a,b" },
+{ "mulu", 0x74000000, "c,a,b" },
+{ "mulu", 0x75000000, "c,a,i" },
+{ "nand", 0x9a000000, "c,a,b" },
+{ "nand", 0x9b000000, "c,a,i" },
+{ "nop", 0x70400101, "" },
+{ "nor", 0x98000000, "c,a,b" },
+{ "nor", 0x99000000, "c,a,i" },
+{ "or", 0x92000000, "c,a,b" },
+{ "or", 0x93000000, "c,a,i" },
+{ "orn", 0xaa000000, "c,a,b" },
+{ "orn", 0xab000000, "c,a,i" },
+
+/* The description of "setip" in Chapter 8 ("instruction set") of the user's
+ manual claims that these are absolute register numbers. But section
+ 7.2.1 explains that they are not. The latter is correct, so print
+ these normally ("lr0", "lr5", etc.). */
+{ "setip", 0x9e000000, "c,a,b" },
+
+{ "sll", 0x80000000, "c,a,b" },
+{ "sll", 0x81000000, "c,a,i" },
+{ "sqrt", 0xe5000000, "c,a,f" },
+{ "sra", 0x86000000, "c,a,b" },
+{ "sra", 0x87000000, "c,a,i" },
+{ "srl", 0x82000000, "c,a,b" },
+{ "srl", 0x83000000, "c,a,i" },
+{ "store", 0x1e000000, "e,n,a,b" },
+{ "store", 0x1f000000, "e,n,a,i" },
+{ "storel", 0x0e000000, "e,n,a,b" },
+{ "storel", 0x0f000000, "e,n,a,i" },
+{ "storem", 0x3e000000, "e,n,a,b" },
+{ "storem", 0x3f000000, "e,n,a,i" },
+{ "sub", 0x24000000, "c,a,b" },
+{ "sub", 0x25000000, "c,a,i" },
+{ "subc", 0x2c000000, "c,a,b" },
+{ "subc", 0x2d000000, "c,a,i" },
+{ "subcs", 0x28000000, "c,a,b" },
+{ "subcs", 0x29000000, "c,a,i" },
+{ "subcu", 0x2a000000, "c,a,b" },
+{ "subcu", 0x2b000000, "c,a,i" },
+{ "subr", 0x34000000, "c,a,b" },
+{ "subr", 0x35000000, "c,a,i" },
+{ "subrc", 0x3c000000, "c,a,b" },
+{ "subrc", 0x3d000000, "c,a,i" },
+{ "subrcs", 0x38000000, "c,a,b" },
+{ "subrcs", 0x39000000, "c,a,i" },
+{ "subrcu", 0x3a000000, "c,a,b" },
+{ "subrcu", 0x3b000000, "c,a,i" },
+{ "subrs", 0x30000000, "c,a,b" },
+{ "subrs", 0x31000000, "c,a,i" },
+{ "subru", 0x32000000, "c,a,b" },
+{ "subru", 0x33000000, "c,a,i" },
+{ "subs", 0x20000000, "c,a,b" },
+{ "subs", 0x21000000, "c,a,i" },
+{ "subu", 0x22000000, "c,a,b" },
+{ "subu", 0x23000000, "c,a,i" },
+{ "xnor", 0x96000000, "c,a,b" },
+{ "xnor", 0x97000000, "c,a,i" },
+{ "xor", 0x94000000, "c,a,b" },
+{ "xor", 0x95000000, "c,a,i" },
+
+{ "", 0x0, "" } /* Dummy entry, not included in NUM_OPCODES. This
+ lets code examine entry i+1 without checking
+ if we've run off the end of the table. */
+};
+
+CONST unsigned int num_opcodes = (((sizeof a29k_opcodes) / (sizeof a29k_opcodes[0])) - 1);
+
+/*
+ * $Log: a29k.h,v $
+ * Revision 1.1 1993/10/02 21:00:40 pk
+ * GNU gas 1.92.3 based assembler supporting PIC code (for i386 and sparc).
+ *
+ * Revision 1.2 1992/02/29 17:10:43 rich
+ * various smallish fixes from mail archives
+ *
+ * Revision 1.1.1.1 1992/02/24 02:34:30 rich
+ * devo fork
+ *
+ * Revision 1.1 1991/12/01 02:22:19 sac
+ * Initial revision
+ *
+ * Revision 1.5 1991/11/07 16:59:19 sac
+ * Fixed encoding of mtacc instruction.
+ *
+ * Revision 1.4 1991/08/06 07:20:27 rich
+ * Fixing CONST declarations.
+ *
+ * Revision 1.3 1991/08/05 22:31:05 rich
+ * *** empty log message ***
+ *
+ * Revision 1.2 1991/07/15 23:34:04 steve
+ * *** empty log message ***
+ *
+ * Revision 1.1 1991/05/19 00:19:33 rich
+ * Initial revision
+ *
+ * Revision 1.1.1.1 1991/04/04 18:15:23 rich
+ * new gas main line
+ *
+ * Revision 1.1 1991/04/04 18:15:23 rich
+ * Initial revision
+ *
+ * Revision 1.2 1991/03/30 17:13:19 rich
+ * num_opcodes now unsigned. Also, added rcsid and log.
+ *
+ *
+ */
+
+/* end of a29k-opcode.h */
diff --git a/gnu/usr.bin/as/opcode/h8300.h b/gnu/usr.bin/as/opcode/h8300.h
new file mode 100644
index 0000000..59dea0d
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/h8300.h
@@ -0,0 +1,266 @@
+/* Opcode table for the H8-300
+ Copyright (C) 1991,1992 Free Software Foundation.
+ Written by Steve Chamberlain, sac@cygnus.com.
+
+This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You 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. */
+
+typedef int op_type;
+
+#define Hex0 0
+#define Hex1 1
+#define Hex2 2
+#define Hex3 3
+#define Hex4 4
+#define Hex5 5
+#define Hex6 6
+#define Hex7 7
+#define Hex8 8
+#define Hex9 9
+#define HexA 10
+#define HexB 11
+#define HexC 12
+#define HexD 13
+#define HexE 14
+#define HexF 15
+#define START 0x20
+#define KBIT 0x21 /* K is #1, or #2, yielding 0x0 or 0x8 */
+#define IMM3 0x22 /* bit number */
+#define RD8 0x23 /* 8 bit reg as 2nd op */
+#define RD16 0x24 /* 16 bit reg as 2nd op */
+#define RS8 0x25 /* 8 bit reg as 1st op */
+#define RS16 0x26 /* 16 bit reg 1st op */
+#define IMM8 0x27 /* constant which fits into 8 bits */
+#define IMM16 0x28 /* constant which fits into 16 bits */
+#define CCR 0x29 /* CCR reg */
+#define ABS8SRC 0x2a /* abs 8 address mode */
+#define ABS8DST 0x2b /* abs 8 address mode */
+#define DISP8 0x2c /* pc rel displacement */
+#define ABS16SRC 0x2d /* abs 16 address mode */
+#define ABS16OR8SRC 0x2e /* abs 16 address mode, but could be abs 8 */
+#define ABS16DST 0x2f /* abs 16 address mode */
+#define ABS16OR8DST 0x30 /* abs 16 address mode */
+#define DISPSRC 0x31 /* @(r:16) address mode src */
+#define DISPDST 0x32 /* @(r:16) address mode dst*/
+#define DISPREG 0x33 /* register from DISP address mode */
+#define RDDEC 0x34 /* @-rn mode */
+#define RSINC 0x35 /* @rn+ mode */
+#define RDIND 0x36 /* @R mode dst */
+#define RSIND 0x37 /* @R mode src */
+#define MEMIND 0x38 /* @@abs8 mode */
+#define ABS16ORREL8SRC 0x39 /* abs 16bit or pcrel */
+#define IGNORE 0x3a
+#define B30 0x40 /* bit 3 must be low */
+#define B31 0x80 /* bit 3 must be high */
+#define E 0x81 /* End of list */
+
+
+
+struct code
+{
+ op_type nib[9];
+} ;
+
+struct arg
+{
+ op_type nib[3];
+} ;
+
+struct h8_opcode
+{
+ char *name;
+ struct arg args;
+ struct code data;
+ char length;
+ char noperands;
+ char idx;
+ char size;
+
+};
+
+
+
+
+
+#ifdef DEFINE_TABLE
+
+#define BITOP(imm, name, op00, op01,op10,op11, op20,op21)\
+{ name, {imm,RD8,E}, {op00, op01, imm, RD8,E}},\
+{ name, {imm,RDIND,E}, {op10, op11, RDIND, 0, op00,op01, imm, 0,E}},\
+{ name, {imm,ABS8DST,E},{op20, op21, ABS8DST, IGNORE, op00,op01, imm, 0,E}}
+
+#define EBITOP(imm, name, op00, op01,op10,op11, op20,op21)\
+ BITOP(imm, name, op00+1, op01, op10,op11, op20,op21),\
+ BITOP(RS8, name, op00, op01, op10,op11, op20,op21)
+
+#define WTWOP(name, op1, op2) \
+{ name, {RS16, RD16, E}, { op1, op2, RS16, RD16, E}}
+
+#define BRANCH(name, op) \
+{ name,{DISP8,E}, { Hex4, op, DISP8,IGNORE,E }}
+
+#define SOP(name) \
+{ name
+#define EOP }
+
+
+#define TWOOP(name, op1, op2,op3) \
+{ name, {IMM8, RD8,E}, { op1, RD8, IMM8,IGNORE,E}},\
+{ name, {RS8, RD8, E}, { op2, op3, RS8, RD8 ,E}}
+
+#define UNOP(name, op1, op2) \
+{ name, {RS8, E}, { op1, op2, 0, RS8, E}}
+
+#define UNOP3(name, op1, op2, op3) \
+{ name , {RS8, E}, {op1, op2, op3, RS8, E}}
+
+struct h8_opcode h8_opcodes[]
+=
+{
+ TWOOP("add.b", Hex8, Hex0,Hex8),
+ WTWOP("add.w", Hex0, Hex9),
+ SOP("adds"), {KBIT,RD16|B30, E}, {Hex0, HexB, KBIT, RD16|B30, E} EOP,
+ TWOOP("addx", Hex9,Hex0,HexE),
+ TWOOP("and", HexE,Hex1,Hex6),
+ SOP("andc"), {IMM8, CCR, E}, { Hex0, Hex6, IMM8,IGNORE, E} EOP,
+ BITOP(IMM3|B30, "band", Hex7, Hex6, Hex7, HexC, Hex7, HexE),
+ BRANCH("bra", Hex0),
+ BRANCH("bt", Hex0),
+ BRANCH("brn", Hex1),
+ BRANCH("bf", Hex1),
+ BRANCH("bhi", Hex2),
+ BRANCH("bls", Hex3),
+ BRANCH("bcc", Hex4),
+ BRANCH("bhs", Hex4),
+ BRANCH("bcs", Hex5),
+ BRANCH("blo", Hex5),
+ BRANCH("bne", Hex6),
+ BRANCH("beq", Hex7),
+ BRANCH("bvc", Hex8),
+ BRANCH("bvs", Hex9),
+ BRANCH("bpl", HexA),
+ BRANCH("bmi", HexB),
+ BRANCH("bge", HexC),
+ BRANCH("blt", HexD),
+ BRANCH("bgt", HexE),
+ BRANCH("ble", HexF),
+ EBITOP(IMM3|B30,"bclr", Hex6, Hex2, Hex7, HexD, Hex7, HexF),
+ BITOP(IMM3|B31,"biand", Hex7, Hex6, Hex7, HexC, Hex7, HexE),
+ BITOP(IMM3|B31, "bild", Hex7, Hex7,Hex7, HexC, Hex7, HexE),
+ BITOP(IMM3|B31, "bior", Hex7, Hex4,Hex7, HexC, Hex7, HexE),
+ BITOP(IMM3|B31, "bist", Hex6, Hex7,Hex7, HexD, Hex7, HexE),
+ BITOP(IMM3|B31, "bixor", Hex7, Hex5,Hex7, HexC, Hex7, HexE),
+ BITOP(IMM3|B30, "bld", Hex7, Hex7,Hex7, HexC, Hex7, HexE),
+ EBITOP(IMM3|B30,"bnot", Hex6, Hex1, Hex7, HexD, Hex7, HexF),
+ BITOP(IMM3|B30,"bor", Hex7, Hex4,Hex7, HexC, Hex7, HexE),
+ EBITOP(IMM3|B30,"bset", Hex6, Hex0,Hex7, HexD, Hex7, HexF),
+ SOP("bsr"),{DISP8, E},{ Hex5, Hex5, DISP8,IGNORE, E}, EOP,
+ BITOP(IMM3|B30, "bst", Hex6, Hex7,Hex7, HexD, Hex7, HexF),
+ EBITOP(IMM3|B30, "btst", Hex6, Hex3,Hex7, HexC, Hex7, HexE),
+ BITOP(IMM3|B30, "bxor", Hex7,Hex5,Hex7, HexC, Hex7, HexE),
+ TWOOP( "cmp.b",HexA, Hex1, HexC),
+ WTWOP( "cmp.w",Hex1,HexD),
+ UNOP( "daa",Hex0, HexF),
+ UNOP( "das",Hex1, HexF),
+ UNOP( "dec",Hex1, HexA),
+ SOP("divxu"),{RS8, RD16|B30, E}, { Hex5, Hex1, RS8, RD16|B30, E} EOP,
+ SOP("eepmov"),{ E}, {Hex7, HexB, Hex5, HexC, Hex5, Hex9, Hex8, HexF,E} EOP,
+ UNOP( "inc", Hex0, HexA),
+ SOP("jmp"),{RSIND|B30, E}, {Hex5, Hex9, RSIND|B30, Hex0, E} EOP,
+ SOP("jmp"),{ABS16ORREL8SRC, E}, {Hex5, HexA, Hex0, Hex0, ABS16ORREL8SRC, IGNORE,IGNORE,IGNORE,E} EOP,
+ SOP("jmp"),{MEMIND, E}, {Hex5, HexB, MEMIND,IGNORE, E} EOP,
+ SOP("jsr"),{RSIND|B30, E}, {Hex5, HexD, RSIND|B30, Hex0, E} EOP,
+ SOP("jsr"),{ABS16ORREL8SRC, E}, {Hex5, HexE, Hex0, Hex0,
+ ABS16ORREL8SRC,IGNORE,IGNORE,IGNORE, E} EOP,
+ SOP("jsr"),{MEMIND, E}, {Hex5, HexF, MEMIND, IGNORE,E} EOP,
+ SOP("ldc"),{IMM8, CCR, E}, { Hex0, Hex7, IMM8,IGNORE, E} EOP,
+ SOP("ldc"),{RS8, CCR, E}, { Hex0, Hex3, Hex0, RS8, E} EOP,
+ SOP("mov.b"),{RS8, RD8, E}, { Hex0, HexC, RS8, RD8, E} EOP,
+ SOP("mov.b"),{IMM8, RD8, E}, { HexF, RD8, IMM8,IGNORE, E} EOP,
+ SOP("mov.b"),{RSIND|B30,RD8, E}, { Hex6, Hex8, RSIND|B30, RD8, E} EOP,
+ SOP("mov.b"),{DISPSRC,RD8, E}, { Hex6, HexE, DISPREG|B30, RD8,
+ DISPSRC, IGNORE, IGNORE, IGNORE, E} EOP,
+ SOP("mov.b"),{RSINC|B30, RD8, E}, { Hex6, HexC, RSINC|B30, RD8, E} EOP,
+ SOP("mov.b"),{ABS16OR8SRC, RD8, E}, { Hex6, HexA, Hex0, RD8,ABS16OR8SRC,
+ IGNORE,IGNORE,IGNORE,E} EOP,
+ SOP("mov.b"),{ABS8SRC, RD8, E}, { Hex2, RD8, ABS8SRC,IGNORE, E} EOP,
+ SOP("mov.b"),{RS8, RDIND|B30, E}, { Hex6, Hex8, RDIND|B31, RS8, E} EOP,
+ SOP("mov.b"),{RS8, DISPDST, E}, { Hex6, HexE, DISPREG|B31,
+ RS8,DISPDST, IGNORE, IGNORE, IGNORE, E} EOP,
+ SOP("mov.b"),{RS8, RDDEC|B31, E}, { Hex6, HexC, RDDEC|B31, RS8, E} EOP,
+ SOP( "mov.b"),{RS8, ABS16OR8DST, E}, { Hex6, HexA, Hex8, RS8,
+ ABS16OR8DST,IGNORE,IGNORE,IGNORE, E} EOP,
+ SOP( "mov.b"),{RS8, ABS8DST, E}, { Hex3, RS8, ABS8DST,IGNORE, E} EOP,
+ SOP( "mov.w"),{RS16|B30, RD16|B30, E},{ Hex0, HexD, RS16|B30,
+ RD16|B30, E} EOP,
+ SOP("mov.w"),{IMM16, RD16|B30, E}, { Hex7, Hex9, Hex0, RD16|B30,
+ IMM16,IGNORE,IGNORE,IGNORE, E} EOP,
+ SOP("mov.w"),{RSIND|B30,RD16|B30, E},{ Hex6, Hex9, RSIND|B30,
+ RD16|B30, E} EOP,
+ SOP("mov.w"),{DISPSRC,RD16|B30, E}, { Hex6, HexF, DISPREG|B30,
+ RD16|B30, DISPSRC, IGNORE, IGNORE, IGNORE,E} EOP,
+ SOP("mov.w"),{RSINC|B30, RD16|B30, E}, { Hex6, HexD, RSINC|B30,
+ RD16|B30, E}EOP,
+ SOP("mov.w"), {ABS16SRC, RD16|B30, E}, { Hex6, HexB, Hex0,
+ RD16|B30,ABS16SRC,IGNORE,IGNORE,IGNORE, E} EOP,
+SOP("mov.w"), {RS16|B30, RDIND|B30, E},{ Hex6, Hex9, RDIND|B31,
+ RS16|B30, E} EOP,
+SOP("mov.w"), {RS16|B30, DISPDST, E}, { Hex6, HexF, DISPREG|B31,
+ RS16|B30,DISPDST, IGNORE,IGNORE,IGNORE,E} EOP,
+SOP("mov.w"), {RS16|B30, RDDEC|B30, E},{ Hex6, HexD, RDDEC|B31,
+ RS16|B30, E} EOP,
+SOP("mov.w"), {RS16|B30, ABS16DST, E}, { Hex6, HexB, Hex8, RS16|B30,
+ ABS16DST, IGNORE, IGNORE, IGNORE, E} EOP,
+SOP("movfpe"), {ABS16SRC, RD8, E}, { Hex6, HexA, Hex4, RD8,
+ ABS16SRC,IGNORE,IGNORE,IGNORE, E} EOP,
+SOP("movtpe"), {RS8, ABS16DST, E}, { Hex6, HexA, HexC, RS8,
+ ABS16DST,IGNORE,IGNORE,IGNORE,
+ E} EOP,
+SOP("mulxu"), {RS8, RD16|B30, E}, { Hex5, Hex0, RS8, RD16|B30, E} EOP,
+SOP( "neg"), {RS8, E}, { Hex1, Hex7, Hex8, RS8, E} EOP,
+SOP( "nop"), {E}, { Hex0, Hex0, Hex0, Hex0,E} EOP,
+SOP( "not"), {RS8,E}, { Hex1, Hex7, Hex0, RS8,E} EOP,
+TWOOP("or", HexC, Hex1, Hex4),
+SOP( "orc"), {IMM8, CCR,E}, { Hex0, Hex4, IMM8,IGNORE,E} EOP,
+SOP( "pop"), {RS16|B30,E}, { Hex6, HexD, Hex7, RS16|B30,E} EOP,
+SOP( "push"), {RS16|B30,E}, { Hex6, HexD, HexF, RS16|B30,E} EOP,
+ UNOP3( "rotl",Hex1, Hex2,Hex8),
+ UNOP3( "rotr",Hex1, Hex3, Hex8),
+ UNOP3( "rotxl",Hex1, Hex2, Hex0),
+ UNOP3( "rotxr",Hex1, Hex3, Hex0),
+SOP("rte"), {E}, { Hex5, Hex6, Hex7, Hex0,E} EOP,
+SOP("rts"), {E}, { Hex5, Hex4, Hex7, Hex0,E} EOP,
+ UNOP3( "shal", Hex1, Hex0, Hex8),
+ UNOP3( "shar", Hex1, Hex1, Hex8),
+ UNOP3( "shll", Hex1, Hex0, Hex0),
+ UNOP3( "shlr", Hex1, Hex1, Hex0),
+SOP("sleep"), {E}, { Hex0, Hex1, Hex8, Hex0,E} EOP,
+SOP("stc"), {CCR, RD8,E}, { Hex0, Hex2, Hex0, RD8,E} EOP,
+SOP("sub.b"), {RS8,RD8,E}, { Hex1, Hex8, RS8, RD8,E} EOP,
+SOP("sub.w"), {RS16|B30, RD16|B30,E}, {Hex1, Hex9, RS16|B30,RD16|B30,E} EOP,
+SOP("subs"), {KBIT,RD16|B30,E}, { Hex1, HexB, KBIT, RD16|B30,E} EOP,
+ TWOOP("subx",HexB, Hex1, HexE),
+ TWOOP("xor", HexD, Hex1, Hex5),
+SOP("xorc"), {IMM8, CCR,E}, { Hex0, Hex5, IMM8,IGNORE,E} EOP,
+ 0
+};
+#else
+extern struct h8_opcode h8_opcodes[] ;
+#endif
+
+
+
+
diff --git a/gnu/usr.bin/as/opcode/i386.h b/gnu/usr.bin/as/opcode/i386.h
new file mode 100644
index 0000000..b87b056
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/i386.h
@@ -0,0 +1,883 @@
+/* i386-opcode.h -- Intel 80386 opcode table
+ Copyright (C) 1989, 1991, Free Software Foundation.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* $FreeBSD$ */
+
+static const template i386_optab[] = {
+
+#define _ None
+/* move instructions */
+{ "mov", 2, 0xa0, _, DW|NoModrm, Disp32, Acc, 0 },
+{ "mov", 2, 0x88, _, DW|Modrm, Reg, Reg|Mem, 0 },
+{ "mov", 2, 0xb0, _, ShortFormW, Imm, Reg, 0 },
+{ "mov", 2, 0xc6, _, W|Modrm, Imm, Reg|Mem, 0 },
+{ "mov", 2, 0x8c, _, D|Modrm, SReg3|SReg2, WordReg|WordMem, 0 },
+/* move to/from control debug registers */
+{ "mov", 2, 0x0f20, _, D|Modrm, Control, Reg32, 0},
+{ "mov", 2, 0x0f21, _, D|Modrm, Debug, Reg32, 0},
+{ "mov", 2, 0x0f24, _, D|Modrm, Test, Reg32, 0},
+
+/* move with sign extend */
+/* "movsbl" & "movsbw" must not be unified into "movsb" to avoid
+ conflict with the "movs" string move instruction. Thus,
+ {"movsb", 2, 0x0fbe, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg16|Reg32, 0},
+ is not kosher; we must seperate the two instructions. */
+{"movsbl", 2, 0x0fbe, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg32, 0},
+{"movsbw", 2, 0x660fbe, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg16, 0},
+{"movswl", 2, 0x0fbf, _, ReverseRegRegmem|Modrm, Reg16|Mem, Reg32, 0},
+
+/* move with zero extend */
+{"movzb", 2, 0x0fb6, _, ReverseRegRegmem|Modrm, Reg8|Mem, Reg16|Reg32, 0},
+{"movzwl", 2, 0x0fb7, _, ReverseRegRegmem|Modrm, Reg16|Mem, Reg32, 0},
+
+/* push instructions */
+{"push", 1, 0x50, _, ShortForm, WordReg,0,0 },
+{"push", 1, 0xff, 0x6, Modrm, WordReg|WordMem, 0, 0 },
+{"push", 1, 0x6a, _, NoModrm, Imm8S, 0, 0},
+{"push", 1, 0x68, _, NoModrm, Imm16|Imm32, 0, 0},
+{"push", 1, 0x06, _, Seg2ShortForm, SReg2,0,0 },
+{"push", 1, 0x0fa0, _, Seg3ShortForm, SReg3,0,0 },
+/* push all */
+{"pusha", 0, 0x60, _, NoModrm, 0, 0, 0 },
+
+/* pop instructions */
+{"pop", 1, 0x58, _, ShortForm, WordReg,0,0 },
+{"pop", 1, 0x8f, 0x0, Modrm, WordReg|WordMem, 0, 0 },
+#define POP_SEG_SHORT 0x7
+{"pop", 1, 0x07, _, Seg2ShortForm, SReg2,0,0 },
+{"pop", 1, 0x0fa1, _, Seg3ShortForm, SReg3,0,0 },
+/* pop all */
+{"popa", 0, 0x61, _, NoModrm, 0, 0, 0 },
+
+/* xchg exchange instructions
+ xchg commutes: we allow both operand orders */
+{"xchg", 2, 0x90, _, ShortForm, WordReg, Acc, 0 },
+{"xchg", 2, 0x90, _, ShortForm, Acc, WordReg, 0 },
+{"xchg", 2, 0x86, _, W|Modrm, Reg, Reg|Mem, 0 },
+{"xchg", 2, 0x86, _, W|Modrm, Reg|Mem, Reg, 0 },
+
+/* in/out from ports */
+{"in", 2, 0xe4, _, W|NoModrm, Imm8, Acc, 0 },
+{"in", 2, 0xec, _, W|NoModrm, InOutPortReg, Acc, 0 },
+{"out", 2, 0xe6, _, W|NoModrm, Acc, Imm8, 0 },
+{"out", 2, 0xee, _, W|NoModrm, Acc, InOutPortReg, 0 },
+
+#if 0
+{"inb", 1, 0xe4, _, NoModrm, Imm8, 0, 0 },
+{"inb", 1, 0xec, _, NoModrm, WordMem, 0, 0 },
+{"inw", 1, 0x66e5, _, NoModrm, Imm8, 0, 0 },
+{"inw", 1, 0x66ed, _, NoModrm, WordMem, 0, 0 },
+{"outb", 1, 0xe6, _, NoModrm, Imm8, 0, 0 },
+{"outb", 1, 0xee, _, NoModrm, WordMem, 0, 0 },
+{"outw", 1, 0x66e7, _, NoModrm, Imm8, 0, 0 },
+{"outw", 1, 0x66ef, _, NoModrm, WordMem, 0, 0 },
+#endif
+
+/* load effective address */
+{"lea", 2, 0x8d, _, Modrm, WordMem, WordReg, 0 },
+
+/* load segment registers from memory */
+{"lds", 2, 0xc5, _, Modrm, Mem, Reg32, 0},
+{"les", 2, 0xc4, _, Modrm, Mem, Reg32, 0},
+{"lfs", 2, 0x0fb4, _, Modrm, Mem, Reg32, 0},
+{"lgs", 2, 0x0fb5, _, Modrm, Mem, Reg32, 0},
+{"lss", 2, 0x0fb2, _, Modrm, Mem, Reg32, 0},
+
+/* flags register instructions */
+{"clc", 0, 0xf8, _, NoModrm, 0, 0, 0},
+{"cld", 0, 0xfc, _, NoModrm, 0, 0, 0},
+{"cli", 0, 0xfa, _, NoModrm, 0, 0, 0},
+{"clts", 0, 0x0f06, _, NoModrm, 0, 0, 0},
+{"cmc", 0, 0xf5, _, NoModrm, 0, 0, 0},
+{"lahf", 0, 0x9f, _, NoModrm, 0, 0, 0},
+{"sahf", 0, 0x9e, _, NoModrm, 0, 0, 0},
+{"pushf", 0, 0x9c, _, NoModrm, 0, 0, 0},
+{"popf", 0, 0x9d, _, NoModrm, 0, 0, 0},
+{"stc", 0, 0xf9, _, NoModrm, 0, 0, 0},
+{"std", 0, 0xfd, _, NoModrm, 0, 0, 0},
+{"sti", 0, 0xfb, _, NoModrm, 0, 0, 0},
+
+{"add", 2, 0x0, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"add", 2, 0x83, 0, Modrm, Imm8S, WordReg|WordMem, 0},
+{"add", 2, 0x4, _, W|NoModrm, Imm, Acc, 0},
+{"add", 2, 0x80, 0, W|Modrm, Imm, Reg|Mem, 0},
+
+{"inc", 1, 0x40, _, ShortForm, WordReg, 0, 0},
+{"inc", 1, 0xfe, 0, W|Modrm, Reg|Mem, 0, 0},
+
+{"sub", 2, 0x28, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"sub", 2, 0x83, 5, Modrm, Imm8S, WordReg|WordMem, 0},
+{"sub", 2, 0x2c, _, W|NoModrm, Imm, Acc, 0},
+{"sub", 2, 0x80, 5, W|Modrm, Imm, Reg|Mem, 0},
+
+{"dec", 1, 0x48, _, ShortForm, WordReg, 0, 0},
+{"dec", 1, 0xfe, 1, W|Modrm, Reg|Mem, 0, 0},
+
+{"sbb", 2, 0x18, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"sbb", 2, 0x83, 3, Modrm, Imm8S, WordReg|WordMem, 0},
+{"sbb", 2, 0x1c, _, W|NoModrm, Imm, Acc, 0},
+{"sbb", 2, 0x80, 3, W|Modrm, Imm, Reg|Mem, 0},
+
+{"cmp", 2, 0x38, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"cmp", 2, 0x83, 7, Modrm, Imm8S, WordReg|WordMem, 0},
+{"cmp", 2, 0x3c, _, W|NoModrm, Imm, Acc, 0},
+{"cmp", 2, 0x80, 7, W|Modrm, Imm, Reg|Mem, 0},
+
+{"test", 2, 0x84, _, W|Modrm, Reg|Mem, Reg, 0},
+{"test", 2, 0x84, _, W|Modrm, Reg, Reg|Mem, 0},
+{"test", 2, 0xa8, _, W|NoModrm, Imm, Acc, 0},
+{"test", 2, 0xf6, 0, W|Modrm, Imm, Reg|Mem, 0},
+
+{"and", 2, 0x20, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"and", 2, 0x83, 4, Modrm, Imm8S, WordReg|WordMem, 0},
+{"and", 2, 0x24, _, W|NoModrm, Imm, Acc, 0},
+{"and", 2, 0x80, 4, W|Modrm, Imm, Reg|Mem, 0},
+
+{"or", 2, 0x08, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"or", 2, 0x83, 1, Modrm, Imm8S, WordReg|WordMem, 0},
+{"or", 2, 0x0c, _, W|NoModrm, Imm, Acc, 0},
+{"or", 2, 0x80, 1, W|Modrm, Imm, Reg|Mem, 0},
+
+{"xor", 2, 0x30, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"xor", 2, 0x83, 6, Modrm, Imm8S, WordReg|WordMem, 0},
+{"xor", 2, 0x34, _, W|NoModrm, Imm, Acc, 0},
+{"xor", 2, 0x80, 6, W|Modrm, Imm, Reg|Mem, 0},
+
+{"adc", 2, 0x10, _, DW|Modrm, Reg, Reg|Mem, 0},
+{"adc", 2, 0x83, 2, Modrm, Imm8S, WordReg|WordMem, 0},
+{"adc", 2, 0x14, _, W|NoModrm, Imm, Acc, 0},
+{"adc", 2, 0x80, 2, W|Modrm, Imm, Reg|Mem, 0},
+
+{"neg", 1, 0xf6, 3, W|Modrm, Reg|Mem, 0, 0},
+{"not", 1, 0xf6, 2, W|Modrm, Reg|Mem, 0, 0},
+
+{"aaa", 0, 0x37, _, NoModrm, 0, 0, 0},
+{"aas", 0, 0x3f, _, NoModrm, 0, 0, 0},
+{"daa", 0, 0x27, _, NoModrm, 0, 0, 0},
+{"das", 0, 0x2f, _, NoModrm, 0, 0, 0},
+{"aad", 0, 0xd50a, _, NoModrm, 0, 0, 0},
+{"aam", 0, 0xd40a, _, NoModrm, 0, 0, 0},
+
+/* conversion insns */
+/* conversion: intel naming */
+{"cbw", 0, 0x6698, _, NoModrm, 0, 0, 0},
+{"cwd", 0, 0x6699, _, NoModrm, 0, 0, 0},
+{"cwde", 0, 0x98, _, NoModrm, 0, 0, 0},
+{"cdq", 0, 0x99, _, NoModrm, 0, 0, 0},
+/* att naming */
+{"cbtw", 0, 0x6698, _, NoModrm, 0, 0, 0},
+{"cwtl", 0, 0x98, _, NoModrm, 0, 0, 0},
+{"cwtd", 0, 0x6699, _, NoModrm, 0, 0, 0},
+{"cltd", 0, 0x99, _, NoModrm, 0, 0, 0},
+
+/* Warning! the mul/imul (opcode 0xf6) must only have 1 operand! They are
+ expanding 64-bit multiplies, and *cannot* be selected to accomplish
+ 'imul %ebx, %eax' (opcode 0x0faf must be used in this case)
+ These multiplies can only be selected with single opearnd forms. */
+{"mul", 1, 0xf6, 4, W|Modrm, Reg|Mem, 0, 0},
+{"imul", 1, 0xf6, 5, W|Modrm, Reg|Mem, 0, 0},
+
+
+
+
+/* imulKludge here is needed to reverse the i.rm.reg & i.rm.regmem fields.
+ These instructions are exceptions: 'imul $2, %eax, %ecx' would put
+ '%eax' in the reg field and '%ecx' in the regmem field if we did not
+ switch them. */
+{"imul", 2, 0x0faf, _, Modrm|ReverseRegRegmem, WordReg|Mem, WordReg, 0},
+{"imul", 3, 0x6b, _, Modrm|ReverseRegRegmem, Imm8S, WordReg|Mem, WordReg},
+{"imul", 3, 0x69, _, Modrm|ReverseRegRegmem, Imm16|Imm32, WordReg|Mem, WordReg},
+/*
+ imul with 2 operands mimicks imul with 3 by puting register both
+ in i.rm.reg & i.rm.regmem fields
+*/
+{"imul", 2, 0x6b, _, Modrm|imulKludge, Imm8S, WordReg, 0},
+{"imul", 2, 0x69, _, Modrm|imulKludge, Imm16|Imm32, WordReg, 0},
+{"div", 1, 0xf6, 6, W|Modrm, Reg|Mem, 0, 0},
+{"div", 2, 0xf6, 6, W|Modrm, Reg|Mem, Acc, 0},
+{"idiv", 1, 0xf6, 7, W|Modrm, Reg|Mem, 0, 0},
+{"idiv", 2, 0xf6, 7, W|Modrm, Reg|Mem, Acc, 0},
+
+{"rol", 2, 0xd0, 0, W|Modrm, Imm1, Reg|Mem, 0},
+{"rol", 2, 0xc0, 0, W|Modrm, Imm8, Reg|Mem, 0},
+{"rol", 2, 0xd2, 0, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"rol", 1, 0xd0, 0, W|Modrm, Reg|Mem, 0, 0},
+
+{"ror", 2, 0xd0, 1, W|Modrm, Imm1, Reg|Mem, 0},
+{"ror", 2, 0xc0, 1, W|Modrm, Imm8, Reg|Mem, 0},
+{"ror", 2, 0xd2, 1, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"ror", 1, 0xd0, 1, W|Modrm, Reg|Mem, 0, 0},
+
+{"rcl", 2, 0xd0, 2, W|Modrm, Imm1, Reg|Mem, 0},
+{"rcl", 2, 0xc0, 2, W|Modrm, Imm8, Reg|Mem, 0},
+{"rcl", 2, 0xd2, 2, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"rcl", 1, 0xd0, 2, W|Modrm, Reg|Mem, 0, 0},
+
+{"rcr", 2, 0xd0, 3, W|Modrm, Imm1, Reg|Mem, 0},
+{"rcr", 2, 0xc0, 3, W|Modrm, Imm8, Reg|Mem, 0},
+{"rcr", 2, 0xd2, 3, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"rcr", 1, 0xd0, 3, W|Modrm, Reg|Mem, 0, 0},
+
+{"sal", 2, 0xd0, 4, W|Modrm, Imm1, Reg|Mem, 0},
+{"sal", 2, 0xc0, 4, W|Modrm, Imm8, Reg|Mem, 0},
+{"sal", 2, 0xd2, 4, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"sal", 1, 0xd0, 4, W|Modrm, Reg|Mem, 0, 0},
+{"shl", 2, 0xd0, 4, W|Modrm, Imm1, Reg|Mem, 0},
+{"shl", 2, 0xc0, 4, W|Modrm, Imm8, Reg|Mem, 0},
+{"shl", 2, 0xd2, 4, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"shl", 1, 0xd0, 4, W|Modrm, Reg|Mem, 0, 0},
+
+{"shld", 3, 0x0fa4, _, Modrm, Imm8, WordReg, WordReg|Mem},
+{"shld", 3, 0x0fa5, _, Modrm, ShiftCount, WordReg, WordReg|Mem},
+
+{"shr", 2, 0xd0, 5, W|Modrm, Imm1, Reg|Mem, 0},
+{"shr", 2, 0xc0, 5, W|Modrm, Imm8, Reg|Mem, 0},
+{"shr", 2, 0xd2, 5, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"shr", 1, 0xd0, 5, W|Modrm, Reg|Mem, 0, 0},
+
+{"shrd", 3, 0x0fac, _, Modrm, Imm8, WordReg, WordReg|Mem},
+{"shrd", 3, 0x0fad, _, Modrm, ShiftCount, WordReg, WordReg|Mem},
+
+{"sar", 2, 0xd0, 7, W|Modrm, Imm1, Reg|Mem, 0},
+{"sar", 2, 0xc0, 7, W|Modrm, Imm8, Reg|Mem, 0},
+{"sar", 2, 0xd2, 7, W|Modrm, ShiftCount, Reg|Mem, 0},
+{"sar", 1, 0xd0, 7, W|Modrm, Reg|Mem, 0, 0},
+
+/* control transfer instructions */
+#define CALL_PC_RELATIVE 0xe8
+{"call", 1, 0xe8, _, JumpDword, Disp32, 0, 0},
+{"call", 1, 0xff, 2, Modrm, Reg|Mem|JumpAbsolute, 0, 0},
+#define CALL_FAR_IMMEDIATE 0x9a
+{"lcall", 2, 0x9a, _, JumpInterSegment, Imm16, Abs32, 0},
+{"lcall", 1, 0xff, 3, Modrm, Mem, 0, 0},
+
+#define JUMP_PC_RELATIVE 0xeb
+{"jmp", 1, 0xeb, _, Jump, Disp, 0, 0},
+{"jmp", 1, 0xff, 4, Modrm, Reg32|Mem|JumpAbsolute, 0, 0},
+#define JUMP_FAR_IMMEDIATE 0xea
+{"ljmp", 2, 0xea, _, JumpInterSegment, Imm16, Imm32, 0},
+{"ljmp", 1, 0xff, 5, Modrm, Mem, 0, 0},
+
+{"ret", 0, 0xc3, _, NoModrm, 0, 0, 0},
+{"ret", 1, 0xc2, _, NoModrm, Imm16, 0, 0},
+{"lret", 0, 0xcb, _, NoModrm, 0, 0, 0},
+{"lret", 1, 0xca, _, NoModrm, Imm16, 0, 0},
+{"enter", 2, 0xc8, _, NoModrm, Imm16, Imm8, 0},
+{"leave", 0, 0xc9, _, NoModrm, 0, 0, 0},
+
+/* conditional jumps */
+{"jo", 1, 0x70, _, Jump, Disp, 0, 0},
+
+{"jno", 1, 0x71, _, Jump, Disp, 0, 0},
+
+{"jb", 1, 0x72, _, Jump, Disp, 0, 0},
+{"jc", 1, 0x72, _, Jump, Disp, 0, 0},
+{"jnae", 1, 0x72, _, Jump, Disp, 0, 0},
+
+{"jnb", 1, 0x73, _, Jump, Disp, 0, 0},
+{"jnc", 1, 0x73, _, Jump, Disp, 0, 0},
+{"jae", 1, 0x73, _, Jump, Disp, 0, 0},
+
+{"je", 1, 0x74, _, Jump, Disp, 0, 0},
+{"jz", 1, 0x74, _, Jump, Disp, 0, 0},
+
+{"jne", 1, 0x75, _, Jump, Disp, 0, 0},
+{"jnz", 1, 0x75, _, Jump, Disp, 0, 0},
+
+{"jbe", 1, 0x76, _, Jump, Disp, 0, 0},
+{"jna", 1, 0x76, _, Jump, Disp, 0, 0},
+
+{"jnbe", 1, 0x77, _, Jump, Disp, 0, 0},
+{"ja", 1, 0x77, _, Jump, Disp, 0, 0},
+
+{"js", 1, 0x78, _, Jump, Disp, 0, 0},
+
+{"jns", 1, 0x79, _, Jump, Disp, 0, 0},
+
+{"jp", 1, 0x7a, _, Jump, Disp, 0, 0},
+{"jpe", 1, 0x7a, _, Jump, Disp, 0, 0},
+
+{"jnp", 1, 0x7b, _, Jump, Disp, 0, 0},
+{"jpo", 1, 0x7b, _, Jump, Disp, 0, 0},
+
+{"jl", 1, 0x7c, _, Jump, Disp, 0, 0},
+{"jnge", 1, 0x7c, _, Jump, Disp, 0, 0},
+
+{"jnl", 1, 0x7d, _, Jump, Disp, 0, 0},
+{"jge", 1, 0x7d, _, Jump, Disp, 0, 0},
+
+{"jle", 1, 0x7e, _, Jump, Disp, 0, 0},
+{"jng", 1, 0x7e, _, Jump, Disp, 0, 0},
+
+{"jnle", 1, 0x7f, _, Jump, Disp, 0, 0},
+{"jg", 1, 0x7f, _, Jump, Disp, 0, 0},
+
+/* these turn into pseudo operations when disp is larger than 8 bits */
+#define IS_JUMP_ON_CX_ZERO(o) \
+ (o == 0x67e3)
+#define IS_JUMP_ON_ECX_ZERO(o) \
+ (o == 0xe3)
+
+{"jcxz", 1, 0x67e3, _, JumpByte, Disp, 0, 0},
+{"jecxz", 1, 0xe3, _, JumpByte, Disp, 0, 0},
+
+#define IS_LOOP_ECX_TIMES(o) \
+ (o == 0xe2 || o == 0xe1 || o == 0xe0)
+
+{"loop", 1, 0xe2, _, JumpByte, Disp, 0, 0},
+
+{"loopz", 1, 0xe1, _, JumpByte, Disp, 0, 0},
+{"loope", 1, 0xe1, _, JumpByte, Disp, 0, 0},
+
+{"loopnz", 1, 0xe0, _, JumpByte, Disp, 0, 0},
+{"loopne", 1, 0xe0, _, JumpByte, Disp, 0, 0},
+
+/* set byte on flag instructions */
+{"seto", 1, 0x0f90, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setno", 1, 0x0f91, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setc", 1, 0x0f92, 0, Modrm, Reg8|Mem, 0, 0},
+{"setb", 1, 0x0f92, 0, Modrm, Reg8|Mem, 0, 0},
+{"setnae", 1, 0x0f92, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setnc", 1, 0x0f93, 0, Modrm, Reg8|Mem, 0, 0},
+{"setnb", 1, 0x0f93, 0, Modrm, Reg8|Mem, 0, 0},
+{"setae", 1, 0x0f93, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"sete", 1, 0x0f94, 0, Modrm, Reg8|Mem, 0, 0},
+{"setz", 1, 0x0f94, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setne", 1, 0x0f95, 0, Modrm, Reg8|Mem, 0, 0},
+{"setnz", 1, 0x0f95, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setbe", 1, 0x0f96, 0, Modrm, Reg8|Mem, 0, 0},
+{"setna", 1, 0x0f96, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setnbe", 1, 0x0f97, 0, Modrm, Reg8|Mem, 0, 0},
+{"seta", 1, 0x0f97, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"sets", 1, 0x0f98, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setns", 1, 0x0f99, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setp", 1, 0x0f9a, 0, Modrm, Reg8|Mem, 0, 0},
+{"setpe", 1, 0x0f9a, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setnp", 1, 0x0f9b, 0, Modrm, Reg8|Mem, 0, 0},
+{"setpo", 1, 0x0f9b, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setl", 1, 0x0f9c, 0, Modrm, Reg8|Mem, 0, 0},
+{"setnge", 1, 0x0f9c, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setnl", 1, 0x0f9d, 0, Modrm, Reg8|Mem, 0, 0},
+{"setge", 1, 0x0f9d, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setle", 1, 0x0f9e, 0, Modrm, Reg8|Mem, 0, 0},
+{"setng", 1, 0x0f9e, 0, Modrm, Reg8|Mem, 0, 0},
+
+{"setnle", 1, 0x0f9f, 0, Modrm, Reg8|Mem, 0, 0},
+{"setg", 1, 0x0f9f, 0, Modrm, Reg8|Mem, 0, 0},
+
+#define IS_STRING_INSTRUCTION(o) \
+ ((o) == 0xa6 || (o) == 0x6c || (o) == 0x6e || (o) == 0x6e || \
+ (o) == 0xac || (o) == 0xa4 || (o) == 0xae || (o) == 0xaa || \
+ (o) == 0xd7)
+
+/* string manipulation */
+{"cmps", 0, 0xa6, _, W|NoModrm, 0, 0, 0},
+{"scmp", 0, 0xa6, _, W|NoModrm, 0, 0, 0},
+{"ins", 0, 0x6c, _, W|NoModrm, 0, 0, 0},
+{"outs", 0, 0x6e, _, W|NoModrm, 0, 0, 0},
+{"lods", 0, 0xac, _, W|NoModrm, 0, 0, 0},
+{"slod", 0, 0xac, _, W|NoModrm, 0, 0, 0},
+{"movs", 0, 0xa4, _, W|NoModrm, 0, 0, 0},
+{"smov", 0, 0xa4, _, W|NoModrm, 0, 0, 0},
+{"scas", 0, 0xae, _, W|NoModrm, 0, 0, 0},
+{"ssca", 0, 0xae, _, W|NoModrm, 0, 0, 0},
+{"stos", 0, 0xaa, _, W|NoModrm, 0, 0, 0},
+{"ssto", 0, 0xaa, _, W|NoModrm, 0, 0, 0},
+{"xlat", 0, 0xd7, _, NoModrm, 0, 0, 0},
+
+/* bit manipulation */
+{"bsf", 2, 0x0fbc, _, Modrm|ReverseRegRegmem, Reg|Mem, Reg, 0},
+{"bsr", 2, 0x0fbd, _, Modrm|ReverseRegRegmem, Reg|Mem, Reg, 0},
+{"bt", 2, 0x0fa3, _, Modrm, Reg, Reg|Mem, 0},
+{"bt", 2, 0x0fba, 4, Modrm, Imm8, Reg|Mem, 0},
+{"btc", 2, 0x0fbb, _, Modrm, Reg, Reg|Mem, 0},
+{"btc", 2, 0x0fba, 7, Modrm, Imm8, Reg|Mem, 0},
+{"btr", 2, 0x0fb3, _, Modrm, Reg, Reg|Mem, 0},
+{"btr", 2, 0x0fba, 6, Modrm, Imm8, Reg|Mem, 0},
+{"bts", 2, 0x0fab, _, Modrm, Reg, Reg|Mem, 0},
+{"bts", 2, 0x0fba, 5, Modrm, Imm8, Reg|Mem, 0},
+
+/* interrupts & op. sys insns */
+/* See i386.c for conversion of 'int $3' into the special int 3 insn. */
+#define INT_OPCODE 0xcd
+#define INT3_OPCODE 0xcc
+{"int", 1, 0xcd, _, NoModrm, Imm8, 0, 0},
+{"int3", 0, 0xcc, _, NoModrm, 0, 0, 0},
+{"into", 0, 0xce, _, NoModrm, 0, 0, 0},
+{"iret", 0, 0xcf, _, NoModrm, 0, 0, 0},
+
+{"boundl", 2, 0x62, _, Modrm, Reg32, Mem, 0},
+{"boundw", 2, 0x6662, _, Modrm, Reg16, Mem, 0},
+
+{"hlt", 0, 0xf4, _, NoModrm, 0, 0, 0},
+{"wait", 0, 0x9b, _, NoModrm, 0, 0, 0},
+/* nop is actually 'xchgl %eax, %eax' */
+{"nop", 0, 0x90, _, NoModrm, 0, 0, 0},
+
+/* protection control */
+{"arpl", 2, 0x63, _, Modrm, Reg16, Reg16|Mem, 0},
+{"lar", 2, 0x0f02, _, Modrm|ReverseRegRegmem, WordReg|Mem, WordReg, 0},
+{"lgdt", 1, 0x0f01, 2, Modrm, Mem, 0, 0},
+{"lidt", 1, 0x0f01, 3, Modrm, Mem, 0, 0},
+{"lldt", 1, 0x0f00, 2, Modrm, WordReg|Mem, 0, 0},
+{"lmsw", 1, 0x0f01, 6, Modrm, WordReg|Mem, 0, 0},
+{"lsl", 2, 0x0f03, _, Modrm|ReverseRegRegmem, WordReg|Mem, WordReg, 0},
+{"ltr", 1, 0x0f00, 3, Modrm, WordReg|Mem, 0, 0},
+
+{"sgdt", 1, 0x0f01, 0, Modrm, Mem, 0, 0},
+{"sidt", 1, 0x0f01, 1, Modrm, Mem, 0, 0},
+{"sldt", 1, 0x0f00, 0, Modrm, WordReg|Mem, 0, 0},
+{"smsw", 1, 0x0f01, 4, Modrm, WordReg|Mem, 0, 0},
+{"str", 1, 0x0f00, 1, Modrm, Reg16|Mem, 0, 0},
+
+{"verr", 1, 0x0f00, 4, Modrm, WordReg|Mem, 0, 0},
+{"verw", 1, 0x0f00, 5, Modrm, WordReg|Mem, 0, 0},
+
+/* floating point instructions */
+
+/* load */
+{"fld", 1, 0xd9c0, _, ShortForm, FloatReg, 0, 0}, /* register */
+{"flds", 1, 0xd9, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem float */
+{"fldl", 1, 0xdd, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem double */
+{"fldl", 1, 0xd9c0, _, ShortForm, FloatReg, 0, 0}, /* register */
+{"fild", 1, 0xdf, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem word (16) */
+{"fildl", 1, 0xdb, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem dword (32) */
+{"fildq", 1, 0xdf, 5, Modrm, Mem, 0, 0}, /* %st0 <-- mem qword (64) */
+{"fildll", 1, 0xdf, 5, Modrm, Mem, 0, 0}, /* %st0 <-- mem qword (64) */
+{"filds", 1, 0xdf, 0, Modrm, Mem, 0, 0}, /* %st0 <-- mem dword */
+{"fldt", 1, 0xdb, 5, Modrm, Mem, 0, 0}, /* %st0 <-- mem efloat */
+{"fbld", 1, 0xdf, 4, Modrm, Mem, 0, 0}, /* %st0 <-- mem bcd */
+
+/* store (no pop) */
+{"fst", 1, 0xddd0, _, ShortForm, FloatReg, 0, 0}, /* register */
+{"fsts", 1, 0xd9, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem float */
+{"fistl", 1, 0xdb, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem dword */
+{"fstl", 1, 0xdd, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem double */
+{"fstl", 1, 0xddd0, _, ShortForm, FloatReg, 0, 0}, /* register */
+{"fists", 1, 0xdf, 2, Modrm, Mem, 0, 0}, /* %st0 --> mem word */
+
+/* store (with pop) */
+{"fstp", 1, 0xddd8, _, ShortForm, FloatReg, 0, 0}, /* register */
+{"fstps", 1, 0xd9, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem float */
+{"fistpl", 1, 0xdb, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem word */
+{"fstpl", 1, 0xdd, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem double */
+{"fstpl", 1, 0xddd8, _, ShortForm, FloatReg, 0, 0}, /* register */
+{"fistps", 1, 0xdf, 3, Modrm, Mem, 0, 0}, /* %st0 --> mem dword */
+{"fistpll", 1, 0xdf, 7, Modrm, Mem, 0, 0}, /* %st0 --> mem qword */
+{"fistpq", 1, 0xdf, 7, Modrm, Mem, 0, 0}, /* %st0 --> mem qword */
+{"fstpt", 1, 0xdb, 7, Modrm, Mem, 0, 0}, /* %st0 --> mem efloat */
+{"fbstp", 1, 0xdf, 6, Modrm, Mem, 0, 0}, /* %st0 --> mem bcd */
+
+/* exchange %st<n> with %st0 */
+{"fxch", 1, 0xd9c8, _, ShortForm, FloatReg, 0, 0},
+
+/* comparison (without pop) */
+{"fcom", 1, 0xd8d0, _, ShortForm, FloatReg, 0, 0},
+{"fcoms", 1, 0xd8, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem float */
+{"ficoml", 1, 0xda, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem word */
+{"fcoml", 1, 0xdc, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem double */
+{"fcoml", 1, 0xd8d0, _, ShortForm, FloatReg, 0, 0},
+{"ficoms", 1, 0xde, 2, Modrm, Mem, 0, 0}, /* compare %st0, mem dword */
+
+/* comparison (with pop) */
+{"fcomp", 1, 0xd8d8, _, ShortForm, FloatReg, 0, 0},
+{"fcomps", 1, 0xd8, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem float */
+{"ficompl", 1, 0xda, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem word */
+{"fcompl", 1, 0xdc, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem double */
+{"fcompl", 1, 0xd8d8, _, ShortForm, FloatReg, 0, 0},
+{"ficomps", 1, 0xde, 3, Modrm, Mem, 0, 0}, /* compare %st0, mem dword */
+{"fcompp", 0, 0xded9, _, NoModrm, 0, 0, 0}, /* compare %st0, %st1 & pop twice */
+
+/* unordered comparison (with pop) */
+{"fucom", 1, 0xdde0, _, ShortForm, FloatReg, 0, 0},
+{"fucomp", 1, 0xdde8, _, ShortForm, FloatReg, 0, 0},
+{"fucompp", 0, 0xdae9, _, NoModrm, 0, 0, 0}, /* ucompare %st0, %st1 & pop twice */
+
+{"ftst", 0, 0xd9e4, _, NoModrm, 0, 0, 0}, /* test %st0 */
+{"fxam", 0, 0xd9e5, _, NoModrm, 0, 0, 0}, /* examine %st0 */
+
+/* load constants into %st0 */
+{"fld1", 0, 0xd9e8, _, NoModrm, 0, 0, 0}, /* %st0 <-- 1.0 */
+{"fldl2t", 0, 0xd9e9, _, NoModrm, 0, 0, 0}, /* %st0 <-- log2(10) */
+{"fldl2e", 0, 0xd9ea, _, NoModrm, 0, 0, 0}, /* %st0 <-- log2(e) */
+{"fldpi", 0, 0xd9eb, _, NoModrm, 0, 0, 0}, /* %st0 <-- pi */
+{"fldlg2", 0, 0xd9ec, _, NoModrm, 0, 0, 0}, /* %st0 <-- log10(2) */
+{"fldln2", 0, 0xd9ed, _, NoModrm, 0, 0, 0}, /* %st0 <-- ln(2) */
+{"fldz", 0, 0xd9ee, _, NoModrm, 0, 0, 0}, /* %st0 <-- 0.0 */
+
+/* arithmetic */
+
+/* add */
+{"fadd", 1, 0xd8c0, _, ShortForm, FloatReg, 0, 0},
+{"fadd", 2, 0xd8c0, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
+{"fadd", 0, 0xdcc1, _, NoModrm, 0, 0, 0}, /* alias for fadd %st, %st(1) */
+{"faddp", 1, 0xdec0, _, ShortForm, FloatReg, 0, 0},
+{"faddp", 2, 0xdac0, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
+{"faddp", 0, 0xdec1, _, NoModrm, 0, 0, 0}, /* alias for faddp %st, %st(1) */
+{"fadds", 1, 0xd8, 0, Modrm, Mem, 0, 0},
+{"fiaddl", 1, 0xda, 0, Modrm, Mem, 0, 0},
+{"faddl", 1, 0xdc, 0, Modrm, Mem, 0, 0},
+{"fiadds", 1, 0xde, 0, Modrm, Mem, 0, 0},
+
+/* sub */
+/* Note: intel has decided that certain of these operations are reversed
+ in assembler syntax. */
+{"fsub", 1, 0xd8e0, _, ShortForm, FloatReg, 0, 0},
+{"fsub", 2, 0xd8e0, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fsub", 2, 0xdce8, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fsub", 2, 0xdce0, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fsub", 0, 0xdce1, _, NoModrm, 0, 0, 0},
+{"fsubp", 1, 0xdee0, _, ShortForm, FloatReg, 0, 0},
+{"fsubp", 2, 0xdee0, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fsubp", 2, 0xdee8, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fsubp", 2, 0xdee0, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fsubp", 0, 0xdee1, _, NoModrm, 0, 0, 0},
+{"fsubs", 1, 0xd8, 4, Modrm, Mem, 0, 0},
+{"fisubl", 1, 0xda, 4, Modrm, Mem, 0, 0},
+{"fsubl", 1, 0xdc, 4, Modrm, Mem, 0, 0},
+{"fisubs", 1, 0xde, 4, Modrm, Mem, 0, 0},
+
+/* sub reverse */
+{"fsubr", 1, 0xd8e8, _, ShortForm, FloatReg, 0, 0},
+{"fsubr", 2, 0xd8e8, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fsubr", 2, 0xdce0, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fsubr", 2, 0xdce8, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fsubr", 0, 0xdce9, _, NoModrm, 0, 0, 0},
+{"fsubrp", 1, 0xdee8, _, ShortForm, FloatReg, 0, 0},
+{"fsubrp", 2, 0xdee8, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fsubrp", 2, 0xdee0, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fsubrp", 2, 0xdee8, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fsubrp", 0, 0xdee9, _, NoModrm, 0, 0, 0},
+{"fsubrs", 1, 0xd8, 5, Modrm, Mem, 0, 0},
+{"fisubrl", 1, 0xda, 5, Modrm, Mem, 0, 0},
+{"fsubrl", 1, 0xdc, 5, Modrm, Mem, 0, 0},
+{"fisubrs", 1, 0xde, 5, Modrm, Mem, 0, 0},
+
+/* mul */
+{"fmul", 1, 0xd8c8, _, ShortForm, FloatReg, 0, 0},
+{"fmul", 2, 0xd8c8, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
+{"fmul", 0, 0xdcc9, _, NoModrm, 0, 0, 0},
+{"fmulp", 1, 0xdec8, _, ShortForm, FloatReg, 0, 0},
+{"fmulp", 2, 0xdec8, _, ShortForm|FloatD, FloatReg, FloatAcc, 0},
+{"fmulp", 0, 0xdec9, _, NoModrm, 0, 0, 0},
+{"fmuls", 1, 0xd8, 1, Modrm, Mem, 0, 0},
+{"fimull", 1, 0xda, 1, Modrm, Mem, 0, 0},
+{"fmull", 1, 0xdc, 1, Modrm, Mem, 0, 0},
+{"fimuls", 1, 0xde, 1, Modrm, Mem, 0, 0},
+
+/* div */
+/* Note: intel has decided that certain of these operations are reversed
+ in assembler syntax. */
+{"fdiv", 1, 0xd8f0, _, ShortForm, FloatReg, 0, 0},
+{"fdiv", 2, 0xd8f0, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fdiv", 2, 0xdcf8, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fdiv", 2, 0xdcf0, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fdiv", 0, 0xdcf1, _, NoModrm, 0, 0, 0},
+{"fdivp", 1, 0xdef0, _, ShortForm, FloatReg, 0, 0},
+{"fdivp", 2, 0xdef0, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fdivp", 2, 0xdef8, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fdivp", 2, 0xdef0, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fdivp", 0, 0xdef1, _, NoModrm, 0, 0, 0},
+{"fdivs", 1, 0xd8, 6, Modrm, Mem, 0, 0},
+{"fidivl", 1, 0xda, 6, Modrm, Mem, 0, 0},
+{"fdivl", 1, 0xdc, 6, Modrm, Mem, 0, 0},
+{"fidivs", 1, 0xde, 6, Modrm, Mem, 0, 0},
+
+/* div reverse */
+{"fdivr", 1, 0xd8f8, _, ShortForm, FloatReg, 0, 0},
+{"fdivr", 2, 0xd8f8, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fdivr", 2, 0xdcf0, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fdivr", 2, 0xdcf8, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fdivr", 0, 0xdcf9, _, NoModrm, 0, 0, 0},
+{"fdivrp", 1, 0xdef8, _, ShortForm, FloatReg, 0, 0},
+{"fdivrp", 2, 0xdef8, _, ShortForm, FloatReg, FloatAcc, 0},
+#ifdef NON_BROKEN_OPCODES
+{"fdivrp", 2, 0xdef0, _, ShortForm, FloatAcc, FloatReg, 0},
+#else
+{"fdivrp", 2, 0xdef8, _, ShortForm, FloatAcc, FloatReg, 0},
+#endif
+{"fdivrp", 0, 0xdef9, _, NoModrm, 0, 0, 0},
+{"fdivrs", 1, 0xd8, 7, Modrm, Mem, 0, 0},
+{"fidivrl", 1, 0xda, 7, Modrm, Mem, 0, 0},
+{"fdivrl", 1, 0xdc, 7, Modrm, Mem, 0, 0},
+{"fidivrs", 1, 0xde, 7, Modrm, Mem, 0, 0},
+
+{"f2xm1", 0, 0xd9f0, _, NoModrm, 0, 0, 0},
+{"fyl2x", 0, 0xd9f1, _, NoModrm, 0, 0, 0},
+{"fptan", 0, 0xd9f2, _, NoModrm, 0, 0, 0},
+{"fpatan", 0, 0xd9f3, _, NoModrm, 0, 0, 0},
+{"fxtract", 0, 0xd9f4, _, NoModrm, 0, 0, 0},
+{"fprem1", 0, 0xd9f5, _, NoModrm, 0, 0, 0},
+{"fdecstp", 0, 0xd9f6, _, NoModrm, 0, 0, 0},
+{"fincstp", 0, 0xd9f7, _, NoModrm, 0, 0, 0},
+{"fprem", 0, 0xd9f8, _, NoModrm, 0, 0, 0},
+{"fyl2xp1", 0, 0xd9f9, _, NoModrm, 0, 0, 0},
+{"fsqrt", 0, 0xd9fa, _, NoModrm, 0, 0, 0},
+{"fsincos", 0, 0xd9fb, _, NoModrm, 0, 0, 0},
+{"frndint", 0, 0xd9fc, _, NoModrm, 0, 0, 0},
+{"fscale", 0, 0xd9fd, _, NoModrm, 0, 0, 0},
+{"fsin", 0, 0xd9fe, _, NoModrm, 0, 0, 0},
+{"fcos", 0, 0xd9ff, _, NoModrm, 0, 0, 0},
+
+{"fchs", 0, 0xd9e0, _, NoModrm, 0, 0, 0},
+{"fabs", 0, 0xd9e1, _, NoModrm, 0, 0, 0},
+
+/* processor control */
+{"fninit", 0, 0xdbe3, _, NoModrm, 0, 0, 0},
+{"finit", 0, 0xdbe3, _, NoModrm, 0, 0, 0},
+{"fldcw", 1, 0xd9, 5, Modrm, Mem, 0, 0},
+{"fnstcw", 1, 0xd9, 7, Modrm, Mem, 0, 0},
+{"fstcw", 1, 0xd9, 7, Modrm, Mem, 0, 0},
+{"fnstsw", 1, 0xdfe0, _, NoModrm, Acc, 0, 0},
+{"fnstsw", 1, 0xdd, 7, Modrm, Mem, 0, 0},
+{"fnstsw", 0, 0xdfe0, _, NoModrm, 0, 0, 0},
+{"fstsw", 1, 0xdfe0, _, NoModrm, Acc, 0, 0},
+{"fstsw", 1, 0xdd, 7, Modrm, Mem, 0, 0},
+{"fstsw", 0, 0xdfe0, _, NoModrm, 0, 0, 0},
+{"fnclex", 0, 0xdbe2, _, NoModrm, 0, 0, 0},
+{"fclex", 0, 0xdbe2, _, NoModrm, 0, 0, 0},
+/*
+ We ignore the short format (287) versions of fstenv/fldenv & fsave/frstor
+ instructions; i'm not sure how to add them or how they are different.
+ My 386/387 book offers no details about this.
+*/
+{"fnstenv", 1, 0xd9, 6, Modrm, Mem, 0, 0},
+{"fstenv", 1, 0xd9, 6, Modrm, Mem, 0, 0},
+{"fldenv", 1, 0xd9, 4, Modrm, Mem, 0, 0},
+{"fnsave", 1, 0xdd, 6, Modrm, Mem, 0, 0},
+{"fsave", 1, 0xdd, 6, Modrm, Mem, 0, 0},
+{"frstor", 1, 0xdd, 4, Modrm, Mem, 0, 0},
+
+{"ffree", 1, 0xddc0, _, ShortForm, FloatReg, 0, 0},
+{"fnop", 0, 0xd9d0, _, NoModrm, 0, 0, 0},
+{"fwait", 0, 0x9b, _, NoModrm, 0, 0, 0},
+
+/*
+ opcode prefixes; we allow them as seperate insns too
+ (see prefix table below)
+*/
+{"aword", 0, 0x67, _, NoModrm, 0, 0, 0},
+{"addr16", 0, 0x67, _, NoModrm, 0, 0, 0},
+{"word", 0, 0x66, _, NoModrm, 0, 0, 0},
+{"data16", 0, 0x66, _, NoModrm, 0, 0, 0},
+{"lock", 0, 0xf0, _, NoModrm, 0, 0, 0},
+{"cs", 0, 0x2e, _, NoModrm, 0, 0, 0},
+{"ds", 0, 0x3e, _, NoModrm, 0, 0, 0},
+{"es", 0, 0x26, _, NoModrm, 0, 0, 0},
+{"fs", 0, 0x64, _, NoModrm, 0, 0, 0},
+{"gs", 0, 0x65, _, NoModrm, 0, 0, 0},
+{"ss", 0, 0x36, _, NoModrm, 0, 0, 0},
+{"rep", 0, 0xf3, _, NoModrm, 0, 0, 0},
+{"repe", 0, 0xf3, _, NoModrm, 0, 0, 0},
+{ "repne", 0, 0xf2, _, NoModrm, 0, 0, 0},
+{"repz", 0, 0xf3, _, NoModrm, 0, 0, 0},
+{ "repnz", 0, 0xf2, _, NoModrm, 0, 0, 0},
+
+/* 486 extensions */
+{"bswap", 1, 0x0fc8, _, ShortForm, Reg32,0,0 },
+{"xadd", 2, 0x0fc0, _, DW|Modrm, Reg, Reg|Mem, 0 },
+{"cmpxchg", 2, 0x0fb0, _, DW|Modrm, Reg, Reg|Mem, 0 },
+{"invd", 0, 0x0f08, _, NoModrm, 0, 0, 0},
+{"wbinvd", 0, 0x0f09, _, NoModrm, 0, 0, 0},
+{"invlpg", 1, 0x0f01, 7, Modrm, Mem, 0, 0},
+
+/* Pentium and late-model 486 extensions */
+{"cpuid", 0, 0x0fa2, _, NoModrm, 0, 0, 0},
+
+/* Pentium extensions */
+{"wrmsr", 0, 0x0f30, _, NoModrm, 0, 0, 0},
+{"rdtsc", 0, 0x0f31, _, NoModrm, 0, 0, 0},
+{"rdmsr", 0, 0x0f32, _, NoModrm, 0, 0, 0},
+{"cmpxchg8b", 1, 0x0fc7, 1, Modrm, Mem, 0, 0},
+
+/* Pentium Pro extensions */
+{"rdpmc", 0, 0x0f33, _, NoModrm, 0, 0, 0},
+
+{"ud2", 0, 0x0fff, _, NoModrm, 0, 0, 0}, /* official undefined instr. */
+
+{"cmovo", 2, 0x0f40, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovno", 2, 0x0f41, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovb", 2, 0x0f42, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovae", 2, 0x0f43, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmove", 2, 0x0f44, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovne", 2, 0x0f45, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovbe", 2, 0x0f46, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmova", 2, 0x0f47, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovs", 2, 0x0f48, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovns", 2, 0x0f49, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovp", 2, 0x0f4a, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovnp", 2, 0x0f4b, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovl", 2, 0x0f4c, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovge", 2, 0x0f4d, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovle", 2, 0x0f4e, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+{"cmovg", 2, 0x0f4f, _, Modrm|ReverseRegRegmem, WordReg|WordMem, WordReg, 0},
+
+{"fcmovb", 2, 0xdac0, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcmove", 2, 0xdac8, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcmovbe",2, 0xdad0, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcmovu", 2, 0xdad8, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcmovnb", 2, 0xdbc0, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcmovne", 2, 0xdbc8, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcmovnbe",2, 0xdbd0, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcmovnu", 2, 0xdbd8, _, ShortForm, FloatReg, FloatAcc, 0},
+
+{"fcomi", 2, 0xdbf0, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fucomi", 2, 0xdbe8, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fcomip", 2, 0xdff0, _, ShortForm, FloatReg, FloatAcc, 0},
+{"fucomip",2, 0xdfe8, _, ShortForm, FloatReg, FloatAcc, 0},
+
+
+{"", 0, 0, 0, 0, 0, 0, 0} /* sentinal */
+};
+#undef _
+
+static const template *i386_optab_end
+ = i386_optab + sizeof (i386_optab)/sizeof(i386_optab[0]);
+
+/* 386 register table */
+
+static const reg_entry i386_regtab[] = {
+ /* 8 bit regs */
+ {"al", Reg8|Acc, 0}, {"cl", Reg8|ShiftCount, 1}, {"dl", Reg8, 2},
+ {"bl", Reg8, 3},
+ {"ah", Reg8, 4}, {"ch", Reg8, 5}, {"dh", Reg8, 6}, {"bh", Reg8, 7},
+ /* 16 bit regs */
+ {"ax", Reg16|Acc, 0}, {"cx", Reg16, 1}, {"dx", Reg16|InOutPortReg, 2}, {"bx", Reg16, 3},
+ {"sp", Reg16, 4}, {"bp", Reg16, 5}, {"si", Reg16, 6}, {"di", Reg16, 7},
+ /* 32 bit regs */
+ {"eax", Reg32|Acc, 0}, {"ecx", Reg32, 1}, {"edx", Reg32, 2}, {"ebx", Reg32, 3},
+ {"esp", Reg32, 4}, {"ebp", Reg32, 5}, {"esi", Reg32, 6}, {"edi", Reg32, 7},
+ /* segment registers */
+ {"es", SReg2, 0}, {"cs", SReg2, 1}, {"ss", SReg2, 2},
+ {"ds", SReg2, 3}, {"fs", SReg3, 4}, {"gs", SReg3, 5},
+ /* control registers */
+ {"cr0", Control, 0}, {"cr2", Control, 2}, {"cr3", Control, 3},
+ {"cr4", Control, 4},
+ /* debug registers */
+ {"db0", Debug, 0}, {"db1", Debug, 1}, {"db2", Debug, 2},
+ {"db3", Debug, 3}, {"db6", Debug, 6}, {"db7", Debug, 7},
+ {"dr0", Debug, 0}, {"dr1", Debug, 1}, {"dr2", Debug, 2},
+ {"dr3", Debug, 3}, {"dr6", Debug, 6}, {"dr7", Debug, 7},
+ /* test registers */
+ {"tr3", Test, 3}, {"tr4", Test, 4}, {"tr5", Test, 5},
+ {"tr6", Test, 6}, {"tr7", Test, 7},
+ /* float registers */
+ {"st(0)", FloatReg|FloatAcc, 0},
+ {"st", FloatReg|FloatAcc, 0},
+ {"st(1)", FloatReg, 1}, {"st(2)", FloatReg, 2},
+ {"st(3)", FloatReg, 3}, {"st(4)", FloatReg, 4}, {"st(5)", FloatReg, 5},
+ {"st(6)", FloatReg, 6}, {"st(7)", FloatReg, 7}
+};
+
+#define MAX_REG_NAME_SIZE 8 /* for parsing register names from input */
+
+static const reg_entry *i386_regtab_end
+ = i386_regtab + sizeof(i386_regtab)/sizeof(i386_regtab[0]);
+
+/* segment stuff */
+static const seg_entry cs = { "cs", 0x2e };
+static const seg_entry ds = { "ds", 0x3e };
+static const seg_entry ss = { "ss", 0x36 };
+static const seg_entry es = { "es", 0x26 };
+static const seg_entry fs = { "fs", 0x64 };
+static const seg_entry gs = { "gs", 0x65 };
+static const seg_entry null = { "", 0x0 };
+
+/*
+ This table is used to store the default segment register implied by all
+ possible memory addressing modes.
+ It is indexed by the mode & modrm entries of the modrm byte as follows:
+ index = (mode<<3) | modrm;
+*/
+static const seg_entry *one_byte_segment_defaults[] = {
+ /* mode 0 */
+ &ds, &ds, &ds, &ds, &null, &ds, &ds, &ds,
+ /* mode 1 */
+ &ds, &ds, &ds, &ds, &null, &ss, &ds, &ds,
+ /* mode 2 */
+ &ds, &ds, &ds, &ds, &null, &ss, &ds, &ds,
+ /* mode 3 --- not a memory reference; never referenced */
+};
+
+static const seg_entry *two_byte_segment_defaults[] = {
+ /* mode 0 */
+ &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
+ /* mode 1 */
+ &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
+ /* mode 2 */
+ &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
+ /* mode 3 --- not a memory reference; never referenced */
+};
+
+static const prefix_entry i386_prefixtab[] = {
+ { "addr16", 0x67 }, /* address size prefix ==> 16bit addressing
+ * (How is this useful?) */
+#define WORD_PREFIX_OPCODE 0x66
+ { "data16", 0x66 }, /* operand size prefix */
+ { "lock", 0xf0 }, /* bus lock prefix */
+ { "wait", 0x9b }, /* wait for coprocessor */
+ { "cs", 0x2e }, { "ds", 0x3e }, /* segment overrides ... */
+ { "es", 0x26 }, { "fs", 0x64 },
+ { "gs", 0x65 }, { "ss", 0x36 },
+/* REPE & REPNE used to detect rep/repne with a non-string instruction */
+#define REPNE 0xf2
+#define REPE 0xf3
+ { "rep", 0xf3 }, { "repe", 0xf3 }, { "repz", 0xf3 }, /* repeat string instructions */
+ { "repne", 0xf2 }, { "repnz", 0xf2 }
+};
+
+static const prefix_entry *i386_prefixtab_end
+ = i386_prefixtab + sizeof(i386_prefixtab)/sizeof(i386_prefixtab[0]);
+
+/* end of i386-opcode.h */
diff --git a/gnu/usr.bin/as/opcode/i860.h b/gnu/usr.bin/as/opcode/i860.h
new file mode 100644
index 0000000..b429a22
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/i860.h
@@ -0,0 +1,495 @@
+/* Table of opcodes for the i860.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+struct i860_opcode
+{
+ const char *name;
+ unsigned long match; /* Bits that must be set. */
+ unsigned long lose; /* Bits that must not be set. */
+ const char *args;
+ /* Nonzero if this is a possible expand-instruction. */
+ char expand;
+};
+
+enum expand_type
+{
+ E_MOV = 1, E_ADDR, E_U32, E_AND, E_S32, E_DELAY
+};
+
+/*
+ All i860 opcodes are 32 bits, except for the pseudoinstructions
+ and the operations utilizing a 32-bit address expression, an
+ unsigned 32-bit constant, or a signed 32-bit constant.
+ These opcodes are expanded into a two-instruction sequence for
+ any situation where the immediate operand does not fit in 32 bits.
+ In the case of the add and subtract operations the expansion is
+ to a three-instruction sequence (ex: orh, or, adds). In cases
+ where the address is to be relocated, the instruction is
+ expanded to handle the worse case, this could be optimized at
+ the final link if the actual address were known.
+
+ The pseudoinstructions are: mov, fmov, pmov, nop, and fnop.
+ These instructions are implemented as a one or two instruction
+ sequence of other operations.
+
+ The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing one character
+ for each operand of the instruction.
+
+Kinds of operands:
+ # Number used by optimizer. It is ignored.
+ 1 src1 integer register.
+ 2 src2 integer register.
+ d dest register.
+ c ctrlreg control register.
+ i 16 bit immediate.
+ I 16 bit immediate, aligned.
+ 5 5 bit immediate.
+ l lbroff 26 bit PC relative immediate.
+ r sbroff 16 bit PC relative immediate.
+ s split 16 bit immediate.
+ S split 16 bit immediate, aligned.
+ e src1 floating point register.
+ f src2 floating point register.
+ g dest floating point register.
+
+*/
+
+/* The order of the opcodes in this table is significant:
+
+ * The assembler requires that all instances of the same mnemonic must be
+ consecutive. If they aren't, the assembler will bomb at runtime.
+
+ * The disassembler should not care about the order of the opcodes. */
+
+static struct i860_opcode i860_opcodes[] =
+{
+
+/* REG-Format Instructions */
+{ "ld.c", 0x30000000, 0xcc000000, "c,d", 0 }, /* ld.c csrc2,idest */
+{ "ld.b", 0x00000000, 0xfc000000, "1(2),d", 0 }, /* ld.b isrc1(isrc2),idest */
+{ "ld.b", 0x04000000, 0xf8000000, "I(2),d", E_ADDR }, /* ld.b #const(isrc2),idest */
+{ "ld.s", 0x10000000, 0xec000001, "1(2),d", 0 }, /* ld.s isrc1(isrc2),idest */
+{ "ld.s", 0x14000001, 0xe8000000, "I(2),d", E_ADDR }, /* ld.s #const(isrc2),idest */
+{ "ld.l", 0x10000001, 0xec000000, "1(2),d", 0 }, /* ld.l isrc1(isrc2),idest */
+{ "ld.l", 0x14000001, 0xe8000000, "I(2),d", E_ADDR }, /* ld.l #const(isrc2),idest */
+
+{ "st.c", 0x38000000, 0xc4000000, "1,c", 0 }, /* st.c isrc1ni,csrc2 */
+{ "st.b", 0x0c000000, 0xf0000000, "1,S(2)", E_ADDR }, /* st.b isrc1ni,#const(isrc2) */
+{ "st.s", 0x1c000000, 0xe0000000, "1,S(2)", E_ADDR }, /* st.s isrc1ni,#const(isrc2) */
+{ "st.l", 0x1c000001, 0xe0000000, "1,S(2)", E_ADDR }, /* st.l isrc1ni,#const(isrc2) */
+
+{ "ixfr", 0x08000000, 0xf4000000, "1,g", 0 }, /* ixfr isrc1ni,fdest */
+
+{ "fld.l", 0x20000002, 0xdc000001, "1(2),g", 0 }, /* fld.l isrc1(isrc2),fdest */
+{ "fld.l", 0x24000002, 0xd8000001, "i(2),g", E_ADDR }, /* fld.l #const(isrc2),fdest */
+{ "fld.l", 0x20000003, 0xdc000000, "1(2)++,g", 0 }, /* fld.l isrc1(isrc2)++,fdest */
+{ "fld.l", 0x24000003, 0xd8000000, "i(2)++,g", E_ADDR }, /* fld.l #const(isrc2)++,fdest */
+{ "fld.d", 0x20000000, 0xdc000007, "1(2),g", 0 }, /* fld.d isrc1(isrc2),fdest */
+{ "fld.d", 0x24000000, 0xd8000007, "i(2),g", E_ADDR }, /* fld.d #const(isrc2),fdest */
+{ "fld.d", 0x20000001, 0xdc000006, "1(2)++,g", 0 }, /* fld.d isrc1(isrc2)++,fdest */
+{ "fld.d", 0x24000001, 0xd8000006, "i(2)++,g", E_ADDR }, /* fld.d #const(isrc2)++,fdest */
+{ "fld.q", 0x20000004, 0xdc000003, "1(2),g", 0 }, /* fld.q isrc1(isrc2),fdest */
+{ "fld.q", 0x24000004, 0xd8000003, "i(2),g", E_ADDR }, /* fld.q #const(isrc2),fdest */
+{ "fld.q", 0x20000005, 0xdc000002, "1(2)++,g", 0 }, /* fld.q isrc1(isrc2)++,fdest */
+{ "fld.q", 0x24000005, 0xd8000002, "i(2)++,g", E_ADDR }, /* fld.q #const(isrc2)++,fdest */
+
+{ "pfld.l", 0x60000000, 0x9c000003, "1(2),g", 0 }, /* pfld.l isrc1(isrc2),fdest */
+{ "pfld.l", 0x64000000, 0x98000003, "i(2),g", E_ADDR }, /* pfld.l #const(isrc2),fdest */
+{ "pfld.l", 0x60000001, 0x9c000002, "1(2)++,g", 0 }, /* pfld.l isrc1(isrc2)++,fdest */
+{ "pfld.l", 0x64000001, 0x98000002, "i(2)++,g", E_ADDR }, /* pfld.l #const(isrc2)++,fdest */
+{ "pfld.d", 0x60000000, 0x9c000007, "1(2),g", 0 }, /* pfld.d isrc1(isrc2),fdest */
+{ "pfld.d", 0x64000000, 0x98000007, "i(2),g", E_ADDR }, /* pfld.d #const(isrc2),fdest */
+{ "pfld.d", 0x60000001, 0x9c000006, "1(2)++,g", 0 }, /* pfld.d isrc1(isrc2)++,fdest */
+{ "pfld.d", 0x64000001, 0x98000006, "i(2)++,g", E_ADDR }, /* pfld.d #const(isrc2)++,fdest */
+
+{ "fst.l", 0x28000002, 0xd4000001, "g,1(2)", 0 }, /* fst.l fdest,isrc1(isrc2) */
+{ "fst.l", 0x2c000002, 0xd0000001, "g,i(2)", E_ADDR }, /* fst.l fdest,#const(isrc2) */
+{ "fst.l", 0x28000003, 0xd4000000, "g,1(2)++", 0 }, /* fst.l fdest,isrc1(isrc2)++ */
+{ "fst.l", 0x2c000003, 0xd0000000, "g,i(2)++", E_ADDR }, /* fst.l fdest,#const(isrc2)++ */
+{ "fst.d", 0x28000000, 0xd4000007, "g,1(2)", 0 }, /* fst.d fdest,isrc1(isrc2) */
+{ "fst.d", 0x2c000000, 0xd0000007, "g,i(2)", E_ADDR }, /* fst.d fdest,#const(isrc2) */
+{ "fst.d", 0x28000001, 0xd4000006, "g,1(2)++", 0 }, /* fst.d fdest,isrc1(isrc2)++ */
+{ "fst.d", 0x2c000001, 0xd0000006, "g,i(2)++", E_ADDR }, /* fst.d fdest,#const(isrc2)++ */
+{ "fst.q", 0x28000004, 0xd4000003, "g,1(2)", 0 }, /* fst.q fdest,isrc1(isrc2) */
+{ "fst.q", 0x2c000004, 0xd0000003, "g,i(2)", E_ADDR }, /* fst.q fdest,#const(isrc2) */
+{ "fst.q", 0x28000005, 0xd4000002, "g,1(2)++", 0 }, /* fst.q fdest,isrc1(isrc2)++ */
+{ "fst.q", 0x2c000005, 0xd0000002, "g,i(2)++", E_ADDR }, /* fst.q fdest,#const(isrc2)++ */
+
+{ "pst.d", 0x3c000000, 0xc0000007, "g,i(2)", E_ADDR }, /* pst.d fdest,#const(isrc2) */
+{ "pst.d", 0x3c000001, 0xc0000006, "g,i(2)++", E_ADDR }, /* pst.d fdest,#const(isrc2)++ */
+
+{ "addu", 0x80000000, 0x7c000000, "1,2,d", 0 }, /* addu isrc1,isrc2,idest */
+{ "addu", 0x84000000, 0x78000000, "i,2,d", E_S32 }, /* addu #const,isrc2,idest */
+{ "adds", 0x90000000, 0x6c000000, "1,2,d", 0 }, /* adds isrc1,isrc2,idest */
+{ "adds", 0x94000000, 0x68000000, "i,2,d", E_S32 }, /* adds #const,isrc2,idest */
+{ "subu", 0x88000000, 0x74000000, "1,2,d", 0 }, /* subu isrc1,isrc2,idest */
+{ "subu", 0x8c000000, 0x70000000, "i,2,d", E_S32 }, /* subu #const,isrc2,idest */
+{ "subs", 0x98000000, 0x64000000, "1,2,d", 0 }, /* subs isrc1,isrc2,idest */
+{ "subs", 0x9c000000, 0x60000000, "i,2,d", E_S32 }, /* subs #const,isrc2,idest */
+
+{ "shl", 0xa0000000, 0x5c000000, "1,2,d", 0 }, /* shl isrc1,isrc2,idest */
+{ "shl", 0xa4000000, 0x58000000, "i,2,d", 0 }, /* shl #const,isrc2,idest */
+{ "shr", 0xa8000000, 0x54000000, "1,2,d", 0 }, /* shr isrc1,isrc2,idest */
+{ "shr", 0xac000000, 0x50000000, "i,2,d", 0 }, /* shr #const,isrc2,idest */
+{ "shrd", 0xb0000000, 0x4c000000, "1,2,d", 0 }, /* shrd isrc1,isrc2,idest */
+{ "shra", 0xb8000000, 0x44000000, "1,2,d", 0 }, /* shra isrc1,isrc2,idest */
+{ "shra", 0xbc000000, 0x40000000, "i,2,d", 0 }, /* shra #const,isrc2,idest */
+
+{ "mov", 0xa0000000, 0x5c00f800, "2,d", 0 }, /* shl r0,isrc2,idest */
+{ "mov", 0x94000000, 0x69e00000, "i,d", E_MOV }, /* adds #const,r0,idest */
+{ "nop", 0xa0000000, 0x5ffff800, "", 0 }, /* shl r0,r0,r0 */
+{ "fnop", 0xb0000000, 0x4ffff800, "", 0 }, /* shrd r0,r0,r0 */
+
+{ "trap", 0x44000000, 0xb8000000, "1,2,d", 0 }, /* trap isrc1ni,isrc2,idest */
+
+{ "flush", 0x34000000, 0xc81f0001, "i(2)", E_ADDR }, /* flush #const(isrc2) */
+{ "flush", 0x34000001, 0xc81f0000, "i(2)++", E_ADDR }, /* flush #const(isrc2)++ */
+
+{ "and", 0xc0000000, 0x3c000000, "1,2,d", 0 }, /* and isrc1,isrc2,idest */
+{ "and", 0xc4000000, 0x38000000, "i,2,d", E_AND }, /* and #const,isrc2,idest */
+{ "andh", 0xc8000000, 0x34000000, "1,2,d", 0 }, /* andh isrc1,isrc2,idest */
+{ "andh", 0xcc000000, 0x30000000, "i,2,d", 0 }, /* andh #const,isrc2,idest */
+{ "andnot", 0xd0000000, 0x2c000000, "1,2,d", 0 }, /* andnot isrc1,isrc2,idest */
+{ "andnot", 0xd4000000, 0x28000000, "i,2,d", E_U32 }, /* andnot #const,isrc2,idest */
+{ "andnoth", 0xd8000000, 0x24000000, "1,2,d", 0 }, /* andnoth isrc1,isrc2,idest */
+{ "andnoth", 0xdc000000, 0x20000000, "i,2,d", 0 }, /* andnoth #const,isrc2,idest */
+{ "or", 0xe0000000, 0x1c000000, "1,2,d", 0 }, /* or isrc1,isrc2,idest */
+{ "or", 0xe4000000, 0x18000000, "i,2,d", E_U32 }, /* or #const,isrc2,idest */
+{ "orh", 0xe8000000, 0x14000000, "1,2,d", 0 }, /* orh isrc1,isrc2,idest */
+{ "orh", 0xec000000, 0x10000000, "i,2,d", 0 }, /* orh #const,isrc2,idest */
+{ "xor", 0xf0000000, 0x0c000000, "1,2,d", 0 }, /* xor isrc1,isrc2,idest */
+{ "xor", 0xf4000000, 0x08000000, "i,2,d", E_U32 }, /* xor #const,isrc2,idest */
+{ "xorh", 0xf8000000, 0x04000000, "1,2,d", 0 }, /* xorh isrc1,isrc2,idest */
+{ "xorh", 0xfc000000, 0x00000000, "i,2,d", 0 }, /* xorh #const,isrc2,idest */
+
+{ "bte", 0x58000000, 0xa4000000, "1,2,s", 0 }, /* bte isrc1s,isrc2,sbroff */
+{ "bte", 0x5c000000, 0xa0000000, "5,2,s", 0 }, /* bte #const5,isrc2,sbroff */
+{ "btne", 0x50000000, 0xac000000, "1,2,s", 0 }, /* btne isrc1s,isrc2,sbroff */
+{ "btne", 0x54000000, 0xa8000000, "5,2,s", 0 }, /* btne #const5,isrc2,sbroff */
+{ "bla", 0xb4000000, 0x48000000, "1,2,s", E_DELAY }, /* bla isrc1s,isrc2,sbroff */
+{ "bri", 0x40000000, 0xbc000000, "1", E_DELAY }, /* bri isrc1ni */
+
+/* Core Escape Instruction Format */
+{ "lock", 0x4c000001, 0xb000001e, "", 0 }, /* lock set BL in dirbase */
+{ "calli", 0x4c000002, 0xb000001d, "1", E_DELAY }, /* calli isrc1ni */
+{ "intovr", 0x4c000004, 0xb000001b, "", 0 }, /* intovr trap on integer overflow */
+{ "unlock", 0x4c000007, 0xb0000018, "", 0 }, /* unlock clear BL in dirbase */
+
+/* CTRL-Format Instructions */
+{ "br", 0x68000000, 0x94000000, "l", E_DELAY }, /* br lbroff */
+{ "call", 0x6c000000, 0x90000000, "l", E_DELAY }, /* call lbroff */
+{ "bc", 0x70000000, 0x8c000000, "l", 0 }, /* bc lbroff */
+{ "bc.t", 0x74000000, 0x88000000, "l", E_DELAY }, /* bc.t lbroff */
+{ "bnc", 0x78000000, 0x84000000, "l", 0 }, /* bnc lbroff */
+{ "bnc.t", 0x7c000000, 0x80000000, "l", E_DELAY }, /* bnc.t lbroff */
+
+/* Floating Point Escape Instruction Format - pfam.p fsrc1,fsrc2,fdest */
+{ "r2p1.ss", 0x48000400, 0xb40003ff, "e,f,g", 0 },
+{ "r2p1.sd", 0x48000480, 0xb400037f, "e,f,g", 0 },
+{ "r2p1.dd", 0x48000580, 0xb400027f, "e,f,g", 0 },
+{ "r2pt.ss", 0x48000401, 0xb40003fe, "e,f,g", 0 },
+{ "r2pt.sd", 0x48000481, 0xb400037e, "e,f,g", 0 },
+{ "r2pt.dd", 0x48000581, 0xb400027e, "e,f,g", 0 },
+{ "r2ap1.ss", 0x48000402, 0xb40003fd, "e,f,g", 0 },
+{ "r2ap1.sd", 0x48000482, 0xb400037d, "e,f,g", 0 },
+{ "r2ap1.dd", 0x48000582, 0xb400027d, "e,f,g", 0 },
+{ "r2apt.ss", 0x48000403, 0xb40003fc, "e,f,g", 0 },
+{ "r2apt.sd", 0x48000483, 0xb400037c, "e,f,g", 0 },
+{ "r2apt.dd", 0x48000583, 0xb400027c, "e,f,g", 0 },
+{ "i2p1.ss", 0x48000404, 0xb40003fb, "e,f,g", 0 },
+{ "i2p1.sd", 0x48000484, 0xb400037b, "e,f,g", 0 },
+{ "i2p1.dd", 0x48000584, 0xb400027b, "e,f,g", 0 },
+{ "i2pt.ss", 0x48000405, 0xb40003fa, "e,f,g", 0 },
+{ "i2pt.sd", 0x48000485, 0xb400037a, "e,f,g", 0 },
+{ "i2pt.dd", 0x48000585, 0xb400027a, "e,f,g", 0 },
+{ "i2ap1.ss", 0x48000406, 0xb40003f9, "e,f,g", 0 },
+{ "i2ap1.sd", 0x48000486, 0xb4000379, "e,f,g", 0 },
+{ "i2ap1.dd", 0x48000586, 0xb4000279, "e,f,g", 0 },
+{ "i2apt.ss", 0x48000407, 0xb40003f8, "e,f,g", 0 },
+{ "i2apt.sd", 0x48000487, 0xb4000378, "e,f,g", 0 },
+{ "i2apt.dd", 0x48000587, 0xb4000278, "e,f,g", 0 },
+{ "rat1p2.ss", 0x48000408, 0xb40003f7, "e,f,g", 0 },
+{ "rat1p2.sd", 0x48000488, 0xb4000377, "e,f,g", 0 },
+{ "rat1p2.dd", 0x48000588, 0xb4000277, "e,f,g", 0 },
+{ "m12apm.ss", 0x48000409, 0xb40003f6, "e,f,g", 0 },
+{ "m12apm.sd", 0x48000489, 0xb4000376, "e,f,g", 0 },
+{ "m12apm.dd", 0x48000589, 0xb4000276, "e,f,g", 0 },
+{ "ra1p2.ss", 0x4800040a, 0xb40003f5, "e,f,g", 0 },
+{ "ra1p2.sd", 0x4800048a, 0xb4000375, "e,f,g", 0 },
+{ "ra1p2.dd", 0x4800058a, 0xb4000275, "e,f,g", 0 },
+{ "m12ttpa.ss", 0x4800040b, 0xb40003f4, "e,f,g", 0 },
+{ "m12ttpa.sd", 0x4800048b, 0xb4000374, "e,f,g", 0 },
+{ "m12ttpa.dd", 0x4800058b, 0xb4000274, "e,f,g", 0 },
+{ "iat1p2.ss", 0x4800040c, 0xb40003f3, "e,f,g", 0 },
+{ "iat1p2.sd", 0x4800048c, 0xb4000373, "e,f,g", 0 },
+{ "iat1p2.dd", 0x4800058c, 0xb4000273, "e,f,g", 0 },
+{ "m12tpm.ss", 0x4800040d, 0xb40003f2, "e,f,g", 0 },
+{ "m12tpm.sd", 0x4800048d, 0xb4000372, "e,f,g", 0 },
+{ "m12tpm.dd", 0x4800058d, 0xb4000272, "e,f,g", 0 },
+{ "ia1p2.ss", 0x4800040e, 0xb40003f1, "e,f,g", 0 },
+{ "ia1p2.sd", 0x4800048e, 0xb4000371, "e,f,g", 0 },
+{ "ia1p2.dd", 0x4800058e, 0xb4000271, "e,f,g", 0 },
+{ "m12tpa.ss", 0x4800040f, 0xb40003f0, "e,f,g", 0 },
+{ "m12tpa.sd", 0x4800048f, 0xb4000370, "e,f,g", 0 },
+{ "m12tpa.dd", 0x4800058f, 0xb4000270, "e,f,g", 0 },
+
+/* Floating Point Escape Instruction Format - pfsm.p fsrc1,fsrc2,fdest */
+{ "r2s1.ss", 0x48000410, 0xb40003ef, "e,f,g", 0 },
+{ "r2s1.sd", 0x48000490, 0xb400036f, "e,f,g", 0 },
+{ "r2s1.dd", 0x48000590, 0xb400026f, "e,f,g", 0 },
+{ "r2st.ss", 0x48000411, 0xb40003ee, "e,f,g", 0 },
+{ "r2st.sd", 0x48000491, 0xb400036e, "e,f,g", 0 },
+{ "r2st.dd", 0x48000591, 0xb400026e, "e,f,g", 0 },
+{ "r2as1.ss", 0x48000412, 0xb40003ed, "e,f,g", 0 },
+{ "r2as1.sd", 0x48000492, 0xb400036d, "e,f,g", 0 },
+{ "r2as1.dd", 0x48000592, 0xb400026d, "e,f,g", 0 },
+{ "r2ast.ss", 0x48000413, 0xb40003ec, "e,f,g", 0 },
+{ "r2ast.sd", 0x48000493, 0xb400036c, "e,f,g", 0 },
+{ "r2ast.dd", 0x48000593, 0xb400026c, "e,f,g", 0 },
+{ "i2s1.ss", 0x48000414, 0xb40003eb, "e,f,g", 0 },
+{ "i2s1.sd", 0x48000494, 0xb400036b, "e,f,g", 0 },
+{ "i2s1.dd", 0x48000594, 0xb400026b, "e,f,g", 0 },
+{ "i2st.ss", 0x48000415, 0xb40003ea, "e,f,g", 0 },
+{ "i2st.sd", 0x48000495, 0xb400036a, "e,f,g", 0 },
+{ "i2st.dd", 0x48000595, 0xb400026a, "e,f,g", 0 },
+{ "i2as1.ss", 0x48000416, 0xb40003e9, "e,f,g", 0 },
+{ "i2as1.sd", 0x48000496, 0xb4000369, "e,f,g", 0 },
+{ "i2as1.dd", 0x48000596, 0xb4000269, "e,f,g", 0 },
+{ "i2ast.ss", 0x48000417, 0xb40003e8, "e,f,g", 0 },
+{ "i2ast.sd", 0x48000497, 0xb4000368, "e,f,g", 0 },
+{ "i2ast.dd", 0x48000597, 0xb4000268, "e,f,g", 0 },
+{ "rat1s2.ss", 0x48000418, 0xb40003e7, "e,f,g", 0 },
+{ "rat1s2.sd", 0x48000498, 0xb4000367, "e,f,g", 0 },
+{ "rat1s2.dd", 0x48000598, 0xb4000267, "e,f,g", 0 },
+{ "m12asm.ss", 0x48000419, 0xb40003e6, "e,f,g", 0 },
+{ "m12asm.sd", 0x48000499, 0xb4000366, "e,f,g", 0 },
+{ "m12asm.dd", 0x48000599, 0xb4000266, "e,f,g", 0 },
+{ "ra1s2.ss", 0x4800041a, 0xb40003e5, "e,f,g", 0 },
+{ "ra1s2.sd", 0x4800049a, 0xb4000365, "e,f,g", 0 },
+{ "ra1s2.dd", 0x4800059a, 0xb4000265, "e,f,g", 0 },
+{ "m12ttsa.ss", 0x4800041b, 0xb40003e4, "e,f,g", 0 },
+{ "m12ttsa.sd", 0x4800049b, 0xb4000364, "e,f,g", 0 },
+{ "m12ttsa.dd", 0x4800059b, 0xb4000264, "e,f,g", 0 },
+{ "iat1s2.ss", 0x4800041c, 0xb40003e3, "e,f,g", 0 },
+{ "iat1s2.sd", 0x4800049c, 0xb4000363, "e,f,g", 0 },
+{ "iat1s2.dd", 0x4800059c, 0xb4000263, "e,f,g", 0 },
+{ "m12tsm.ss", 0x4800041d, 0xb40003e2, "e,f,g", 0 },
+{ "m12tsm.sd", 0x4800049d, 0xb4000362, "e,f,g", 0 },
+{ "m12tsm.dd", 0x4800059d, 0xb4000262, "e,f,g", 0 },
+{ "ia1s2.ss", 0x4800041e, 0xb40003e1, "e,f,g", 0 },
+{ "ia1s2.sd", 0x4800049e, 0xb4000361, "e,f,g", 0 },
+{ "ia1s2.dd", 0x4800059e, 0xb4000261, "e,f,g", 0 },
+{ "m12tsa.ss", 0x4800041f, 0xb40003e0, "e,f,g", 0 },
+{ "m12tsa.sd", 0x4800049f, 0xb4000360, "e,f,g", 0 },
+{ "m12tsa.dd", 0x4800059f, 0xb4000260, "e,f,g", 0 },
+
+/* Floating Point Escape Instruction Format - pfmam.p fsrc1,fsrc2,fdest */
+{ "mr2p1.ss", 0x48000000, 0xb40007ff, "e,f,g", 0 },
+{ "mr2p1.sd", 0x48000080, 0xb400077f, "e,f,g", 0 },
+{ "mr2p1.dd", 0x48000180, 0xb400067f, "e,f,g", 0 },
+{ "mr2pt.ss", 0x48000001, 0xb40007fe, "e,f,g", 0 },
+{ "mr2pt.sd", 0x48000081, 0xb400077e, "e,f,g", 0 },
+{ "mr2pt.dd", 0x48000181, 0xb400067e, "e,f,g", 0 },
+{ "mr2mp1.ss", 0x48000002, 0xb40007fd, "e,f,g", 0 },
+{ "mr2mp1.sd", 0x48000082, 0xb400077d, "e,f,g", 0 },
+{ "mr2mp1.dd", 0x48000182, 0xb400067d, "e,f,g", 0 },
+{ "mr2mpt.ss", 0x48000003, 0xb40007fc, "e,f,g", 0 },
+{ "mr2mpt.sd", 0x48000083, 0xb400077c, "e,f,g", 0 },
+{ "mr2mpt.dd", 0x48000183, 0xb400067c, "e,f,g", 0 },
+{ "mi2p1.ss", 0x48000004, 0xb40007fb, "e,f,g", 0 },
+{ "mi2p1.sd", 0x48000084, 0xb400077b, "e,f,g", 0 },
+{ "mi2p1.dd", 0x48000184, 0xb400067b, "e,f,g", 0 },
+{ "mi2pt.ss", 0x48000005, 0xb40007fa, "e,f,g", 0 },
+{ "mi2pt.sd", 0x48000085, 0xb400077a, "e,f,g", 0 },
+{ "mi2pt.dd", 0x48000185, 0xb400067a, "e,f,g", 0 },
+{ "mi2mp1.ss", 0x48000006, 0xb40007f9, "e,f,g", 0 },
+{ "mi2mp1.sd", 0x48000086, 0xb4000779, "e,f,g", 0 },
+{ "mi2mp1.dd", 0x48000186, 0xb4000679, "e,f,g", 0 },
+{ "mi2mpt.ss", 0x48000007, 0xb40007f8, "e,f,g", 0 },
+{ "mi2mpt.sd", 0x48000087, 0xb4000778, "e,f,g", 0 },
+{ "mi2mpt.dd", 0x48000187, 0xb4000678, "e,f,g", 0 },
+{ "mrmt1p2.ss", 0x48000008, 0xb40007f7, "e,f,g", 0 },
+{ "mrmt1p2.sd", 0x48000088, 0xb4000777, "e,f,g", 0 },
+{ "mrmt1p2.dd", 0x48000188, 0xb4000677, "e,f,g", 0 },
+{ "mm12mpm.ss", 0x48000009, 0xb40007f6, "e,f,g", 0 },
+{ "mm12mpm.sd", 0x48000089, 0xb4000776, "e,f,g", 0 },
+{ "mm12mpm.dd", 0x48000189, 0xb4000676, "e,f,g", 0 },
+{ "mrm1p2.ss", 0x4800000a, 0xb40007f5, "e,f,g", 0 },
+{ "mrm1p2.sd", 0x4800008a, 0xb4000775, "e,f,g", 0 },
+{ "mrm1p2.dd", 0x4800018a, 0xb4000675, "e,f,g", 0 },
+{ "mm12ttpm.ss",0x4800000b, 0xb40007f4, "e,f,g", 0 },
+{ "mm12ttpm.sd",0x4800008b, 0xb4000774, "e,f,g", 0 },
+{ "mm12ttpm.dd",0x4800018b, 0xb4000674, "e,f,g", 0 },
+{ "mimt1p2.ss", 0x4800000c, 0xb40007f3, "e,f,g", 0 },
+{ "mimt1p2.sd", 0x4800008c, 0xb4000773, "e,f,g", 0 },
+{ "mimt1p2.dd", 0x4800018c, 0xb4000673, "e,f,g", 0 },
+{ "mm12tpm.ss", 0x4800000d, 0xb40007f2, "e,f,g", 0 },
+{ "mm12tpm.sd", 0x4800008d, 0xb4000772, "e,f,g", 0 },
+{ "mm12tpm.dd", 0x4800018d, 0xb4000672, "e,f,g", 0 },
+{ "mim1p2.ss", 0x4800000e, 0xb40007f1, "e,f,g", 0 },
+{ "mim1p2.sd", 0x4800008e, 0xb4000771, "e,f,g", 0 },
+{ "mim1p2.dd", 0x4800018e, 0xb4000671, "e,f,g", 0 },
+
+/* Floating Point Escape Instruction Format - pfmsm.p fsrc1,fsrc2,fdest */
+{ "mr2s1.ss", 0x48000010, 0xb40007ef, "e,f,g", 0 },
+{ "mr2s1.sd", 0x48000090, 0xb400076f, "e,f,g", 0 },
+{ "mr2s1.dd", 0x48000190, 0xb400066f, "e,f,g", 0 },
+{ "mr2st.ss", 0x48000011, 0xb40007ee, "e,f,g", 0 },
+{ "mr2st.sd", 0x48000091, 0xb400076e, "e,f,g", 0 },
+{ "mr2st.dd", 0x48000191, 0xb400066e, "e,f,g", 0 },
+{ "mr2ms1.ss", 0x48000012, 0xb40007ed, "e,f,g", 0 },
+{ "mr2ms1.sd", 0x48000092, 0xb400076d, "e,f,g", 0 },
+{ "mr2ms1.dd", 0x48000192, 0xb400066d, "e,f,g", 0 },
+{ "mr2mst.ss", 0x48000013, 0xb40007ec, "e,f,g", 0 },
+{ "mr2mst.sd", 0x48000093, 0xb400076c, "e,f,g", 0 },
+{ "mr2mst.dd", 0x48000193, 0xb400066c, "e,f,g", 0 },
+{ "mi2s1.ss", 0x48000014, 0xb40007eb, "e,f,g", 0 },
+{ "mi2s1.sd", 0x48000094, 0xb400076b, "e,f,g", 0 },
+{ "mi2s1.dd", 0x48000194, 0xb400066b, "e,f,g", 0 },
+{ "mi2st.ss", 0x48000015, 0xb40007ea, "e,f,g", 0 },
+{ "mi2st.sd", 0x48000095, 0xb400076a, "e,f,g", 0 },
+{ "mi2st.dd", 0x48000195, 0xb400066a, "e,f,g", 0 },
+{ "mi2ms1.ss", 0x48000016, 0xb40007e9, "e,f,g", 0 },
+{ "mi2ms1.sd", 0x48000096, 0xb4000769, "e,f,g", 0 },
+{ "mi2ms1.dd", 0x48000196, 0xb4000669, "e,f,g", 0 },
+{ "mi2mst.ss", 0x48000017, 0xb40007e8, "e,f,g", 0 },
+{ "mi2mst.sd", 0x48000097, 0xb4000768, "e,f,g", 0 },
+{ "mi2mst.dd", 0x48000197, 0xb4000668, "e,f,g", 0 },
+{ "mrmt1s2.ss", 0x48000018, 0xb40007e7, "e,f,g", 0 },
+{ "mrmt1s2.sd", 0x48000098, 0xb4000767, "e,f,g", 0 },
+{ "mrmt1s2.dd", 0x48000198, 0xb4000667, "e,f,g", 0 },
+{ "mm12msm.ss", 0x48000019, 0xb40007e6, "e,f,g", 0 },
+{ "mm12msm.sd", 0x48000099, 0xb4000766, "e,f,g", 0 },
+{ "mm12msm.dd", 0x48000199, 0xb4000666, "e,f,g", 0 },
+{ "mrm1s2.ss", 0x4800001a, 0xb40007e5, "e,f,g", 0 },
+{ "mrm1s2.sd", 0x4800009a, 0xb4000765, "e,f,g", 0 },
+{ "mrm1s2.dd", 0x4800019a, 0xb4000665, "e,f,g", 0 },
+{ "mm12ttsm.ss",0x4800001b, 0xb40007e4, "e,f,g", 0 },
+{ "mm12ttsm.sd",0x4800009b, 0xb4000764, "e,f,g", 0 },
+{ "mm12ttsm.dd",0x4800019b, 0xb4000664, "e,f,g", 0 },
+{ "mimt1s2.ss", 0x4800001c, 0xb40007e3, "e,f,g", 0 },
+{ "mimt1s2.sd", 0x4800009c, 0xb4000763, "e,f,g", 0 },
+{ "mimt1s2.dd", 0x4800019c, 0xb4000663, "e,f,g", 0 },
+{ "mm12tsm.ss", 0x4800001d, 0xb40007e2, "e,f,g", 0 },
+{ "mm12tsm.sd", 0x4800009d, 0xb4000762, "e,f,g", 0 },
+{ "mm12tsm.dd", 0x4800019d, 0xb4000662, "e,f,g", 0 },
+{ "mim1s2.ss", 0x4800001e, 0xb40007e1, "e,f,g", 0 },
+{ "mim1s2.sd", 0x4800009e, 0xb4000761, "e,f,g", 0 },
+{ "mim1s2.dd", 0x4800019e, 0xb4000661, "e,f,g", 0 },
+
+
+{ "fmul.ss", 0x48000020, 0xb40007df, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */
+{ "fmul.sd", 0x480000a0, 0xb400075f, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */
+{ "fmul.dd", 0x480001a0, 0xb400065f, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */
+{ "pfmul.ss", 0x48000420, 0xb40003df, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */
+{ "pfmul.sd", 0x480004a0, 0xb400035f, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */
+{ "pfmul.dd", 0x480005a0, 0xb400025f, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */
+{ "pfmul3.dd", 0x480005a4, 0xb400025b, "e,f,g", 0 }, /* pfmul3.p fsrc1,fsrc2,fdest */
+{ "fmlow.dd", 0x480001a1, 0xb400065e, "e,f,g", 0 }, /* fmlow.dd fsrc1,fsrc2,fdest */
+{ "frcp.ss", 0x48000022, 0xb40007dd, "f,g", 0 }, /* frcp.p fsrc2,fdest */
+{ "frcp.sd", 0x480000a2, 0xb400075d, "f,g", 0 }, /* frcp.p fsrc2,fdest */
+{ "frcp.dd", 0x480001a2, 0xb400065d, "f,g", 0 }, /* frcp.p fsrc2,fdest */
+{ "frsqr.ss", 0x48000023, 0xb40007dc, "f,g", 0 }, /* frsqr.p fsrc2,fdest */
+{ "frsqr.sd", 0x480000a3, 0xb400075c, "f,g", 0 }, /* frsqr.p fsrc2,fdest */
+{ "frsqr.dd", 0x480001a3, 0xb400065c, "f,g", 0 }, /* frsqr.p fsrc2,fdest */
+{ "fadd.ss", 0x48000030, 0xb40007cf, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */
+{ "fadd.sd", 0x480000b0, 0xb400074f, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */
+{ "fadd.dd", 0x480001b0, 0xb400064f, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */
+{ "pfadd.ss", 0x48000430, 0xb40003cf, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */
+{ "pfadd.sd", 0x480004b0, 0xb400034f, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */
+{ "pfadd.dd", 0x480005b0, 0xb400024f, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */
+{ "fsub.ss", 0x48000031, 0xb40007ce, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */
+{ "fsub.sd", 0x480000b1, 0xb400074e, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */
+{ "fsub.dd", 0x480001b1, 0xb400064e, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */
+{ "pfsub.ss", 0x48000431, 0xb40003ce, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */
+{ "pfsub.sd", 0x480004b1, 0xb400034e, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */
+{ "pfsub.dd", 0x480005b1, 0xb400024e, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */
+{ "fix.ss", 0x48000032, 0xb40007cd, "e,g", 0 }, /* fix.p fsrc1,fdest */
+{ "fix.sd", 0x480000b2, 0xb400074d, "e,g", 0 }, /* fix.p fsrc1,fdest */
+{ "fix.dd", 0x480001b2, 0xb400064d, "e,g", 0 }, /* fix.p fsrc1,fdest */
+{ "pfix.ss", 0x48000432, 0xb40003cd, "e,g", 0 }, /* pfix.p fsrc1,fdest */
+{ "pfix.sd", 0x480004b2, 0xb400034d, "e,g", 0 }, /* pfix.p fsrc1,fdest */
+{ "pfix.dd", 0x480005b2, 0xb400024d, "e,g", 0 }, /* pfix.p fsrc1,fdest */
+{ "famov.ss", 0x48000033, 0xb40007cc, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "famov.ds", 0x48000133, 0xb40006cc, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "famov.sd", 0x480000b3, 0xb400074c, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "famov.dd", 0x480001b3, 0xb400064c, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "pfamov.ss", 0x48000433, 0xb40003cc, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+{ "pfamov.ds", 0x48000533, 0xb40002cc, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+{ "pfamov.sd", 0x480004b3, 0xb400034c, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+{ "pfamov.dd", 0x480005b3, 0xb400024c, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+/* pfgt has R bit cleared; pfle has R bit set */
+{ "pfgt.ss", 0x48000434, 0xb40003cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */
+{ "pfgt.sd", 0x48000434, 0xb40003cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */
+{ "pfgt.dd", 0x48000534, 0xb40002cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */
+/* pfgt has R bit cleared; pfle has R bit set */
+{ "pfle.ss", 0x480004b4, 0xb400034b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */
+{ "pfle.sd", 0x480004b4, 0xb400034b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */
+{ "pfle.dd", 0x480005b4, 0xb400024b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */
+{ "ftrunc.ss", 0x4800003a, 0xb40007c5, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */
+{ "ftrunc.sd", 0x480000ba, 0xb4000745, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */
+{ "ftrunc.dd", 0x480001ba, 0xb4000645, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */
+{ "pftrunc.ss", 0x4800043a, 0xb40003c5, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */
+{ "pftrunc.sd", 0x480004ba, 0xb4000345, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */
+{ "pftrunc.dd", 0x480005ba, 0xb4000245, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */
+{ "fxfr", 0x48000040, 0xb40007bf, "e,d", 0 }, /* fxfr fsrc1,idest */
+{ "fiadd.ss", 0x48000049, 0xb40007b6, "e,f,g", 0 }, /* fiadd.w fsrc1,fsrc2,fdest */
+{ "fiadd.dd", 0x480001c9, 0xb4000636, "e,f,g", 0 }, /* fiadd.w fsrc1,fsrc2,fdest */
+{ "pfiadd.ss", 0x48000449, 0xb40003b6, "e,f,g", 0 }, /* pfiadd.w fsrc1,fsrc2,fdest */
+{ "pfiadd.dd", 0x480005c9, 0xb4000236, "e,f,g", 0 }, /* pfiadd.w fsrc1,fsrc2,fdest */
+{ "fisub.ss", 0x4800004d, 0xb40007b2, "e,f,g", 0 }, /* fisub.w fsrc1,fsrc2,fdest */
+{ "fisub.dd", 0x480001cd, 0xb4000632, "e,f,g", 0 }, /* fisub.w fsrc1,fsrc2,fdest */
+{ "pfisub.ss", 0x4800044d, 0xb40003b2, "e,f,g", 0 }, /* pfisub.w fsrc1,fsrc2,fdest */
+{ "pfisub.dd", 0x480005cd, 0xb4000232, "e,f,g", 0 }, /* pfisub.w fsrc1,fsrc2,fdest */
+{ "fzchkl", 0x48000057, 0xb40007a8, "e,f,g", 0 }, /* fzchkl fsrc1,fsrc2,fdest */
+{ "pfzchkl", 0x48000457, 0xb40003a8, "e,f,g", 0 }, /* pfzchkl fsrc1,fsrc2,fdest */
+{ "fzchks", 0x4800005f, 0xb40007a0, "e,f,g", 0 }, /* fzchks fsrc1,fsrc2,fdest */
+{ "pfzchks", 0x4800045f, 0xb40003a0, "e,f,g", 0 }, /* pfzchks fsrc1,fsrc2,fdest */
+{ "faddp", 0x48000050, 0xb40007af, "e,f,g", 0 }, /* faddp fsrc1,fsrc2,fdest */
+{ "pfaddp", 0x48000450, 0xb40003af, "e,f,g", 0 }, /* pfaddp fsrc1,fsrc2,fdest */
+{ "faddz", 0x48000051, 0xb40007ae, "e,f,g", 0 }, /* faddz fsrc1,fsrc2,fdest */
+{ "pfaddz", 0x48000451, 0xb40003ae, "e,f,g", 0 }, /* pfaddz fsrc1,fsrc2,fdest */
+{ "form", 0x4800005a, 0xb40007a5, "e,g", 0 }, /* form fsrc1,fdest */
+{ "pform", 0x4800045a, 0xb40003a5, "e,g", 0 }, /* pform fsrc1,fdest */
+
+/* Floating point pseudo-instructions */
+{ "fmov.ss", 0x48000049, 0xb7e007b6, "e,g", 0 }, /* fiadd.ss fsrc1,f0,fdest */
+{ "fmov.dd", 0x480001c9, 0xb7e00636, "e,g", 0 }, /* fiadd.dd fsrc1,f0,fdest */
+{ "fmov.sd", 0x480000b0, 0xb7e0074f, "e,g", 0 }, /* fadd.sd fsrc1,f0,fdest */
+{ "fmov.ds", 0x48000130, 0xb7e006cf, "e,g", 0 }, /* fadd.ds fsrc1,f0,fdest */
+{ "pfmov.ds", 0x48000530, 0xb73002cf, "e,g", 0 }, /* pfadd.ds fsrc1,f0,fdest */
+{ "pfmov.dd", 0x480005c9, 0xb7e00236, "e,g", 0 }, /* pfiadd.dd fsrc1,f0,fdest */
+
+
+};
+
+#define NUMOPCODES ((sizeof i860_opcodes)/(sizeof i860_opcodes[0]))
+
+
diff --git a/gnu/usr.bin/as/opcode/i960.h b/gnu/usr.bin/as/opcode/i960.h
new file mode 100644
index 0000000..20b10a8
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/i960.h
@@ -0,0 +1,434 @@
+/* Basic 80960 instruction formats.
+ *
+ * The 'COJ' instructions are actually COBR instructions with the 'b' in
+ * the mnemonic replaced by a 'j'; they are ALWAYS "de-optimized" if necessary:
+ * if the displacement will not fit in 13 bits, the assembler will replace them
+ * with the corresponding compare and branch instructions.
+ *
+ * All of the 'MEMn' instructions are the same format; the 'n' in the name
+ * indicates the default index scale factor (the size of the datum operated on).
+ *
+ * The FBRA formats are not actually an instruction format. They are the
+ * "convenience directives" for branching on floating-point comparisons,
+ * each of which generates 2 instructions (a 'bno' and one other branch).
+ *
+ * The CALLJ format is not actually an instruction format. It indicates that
+ * the instruction generated (a CTRL-format 'call') should have its relocation
+ * specially flagged for link-time replacement with a 'bal' or 'calls' if
+ * appropriate.
+ */
+
+/* $FreeBSD$ */
+
+#define CTRL 0
+#define COBR 1
+#define COJ 2
+#define REG 3
+#define MEM1 4
+#define MEM2 5
+#define MEM4 6
+#define MEM8 7
+#define MEM12 8
+#define MEM16 9
+#define FBRA 10
+#define CALLJ 11
+
+/* Masks for the mode bits in REG format instructions */
+#define M1 0x0800
+#define M2 0x1000
+#define M3 0x2000
+
+/* Generate the 12-bit opcode for a REG format instruction by placing the
+ * high 8 bits in instruction bits 24-31, the low 4 bits in instruction bits
+ * 7-10.
+ */
+
+#define REG_OPC(opc) ((opc & 0xff0) << 20) | ((opc & 0xf) << 7)
+
+/* Generate a template for a REG format instruction: place the opcode bits
+ * in the appropriate fields and OR in mode bits for the operands that will not
+ * be used. I.e.,
+ * set m1=1, if src1 will not be used
+ * set m2=1, if src2 will not be used
+ * set m3=1, if dst will not be used
+ *
+ * Setting the "unused" mode bits to 1 speeds up instruction execution(!).
+ * The information is also useful to us because some 1-operand REG instructions
+ * use the src1 field, others the dst field; and some 2-operand REG instructions
+ * use src1/src2, others src1/dst. The set mode bits enable us to distinguish.
+ */
+#define R_0(opc) ( REG_OPC(opc) | M1 | M2 | M3 ) /* No operands */
+#define R_1(opc) ( REG_OPC(opc) | M2 | M3 ) /* 1 operand: src1 */
+#define R_1D(opc) ( REG_OPC(opc) | M1 | M2 ) /* 1 operand: dst */
+#define R_2(opc) ( REG_OPC(opc) | M3 ) /* 2 ops: src1/src2 */
+#define R_2D(opc) ( REG_OPC(opc) | M2 ) /* 2 ops: src1/dst */
+#define R_3(opc) ( REG_OPC(opc) ) /* 3 operands */
+
+/* DESCRIPTOR BYTES FOR REGISTER OPERANDS
+ *
+ * Interpret names as follows:
+ * R: global or local register only
+ * RS: global, local, or (if target allows) special-function register only
+ * RL: global or local register, or integer literal
+ * RSL: global, local, or (if target allows) special-function register;
+ * or integer literal
+ * F: global, local, or floating-point register
+ * FL: global, local, or floating-point register; or literal (including
+ * floating point)
+ *
+ * A number appended to a name indicates that registers must be aligned,
+ * as follows:
+ * 2: register number must be multiple of 2
+ * 4: register number must be multiple of 4
+ */
+
+#define SFR 0x10 /* Mask for the "sfr-OK" bit */
+#define LIT 0x08 /* Mask for the "literal-OK" bit */
+#define FP 0x04 /* Mask for "floating-point-OK" bit */
+
+/* This macro ors the bits together. Note that 'align' is a mask
+ * for the low 0, 1, or 2 bits of the register number, as appropriate.
+ */
+#define OP(align,lit,fp,sfr) ( align | lit | fp | sfr )
+
+#define R OP( 0, 0, 0, 0 )
+#define RS OP( 0, 0, 0, SFR )
+#define RL OP( 0, LIT, 0, 0 )
+#define RSL OP( 0, LIT, 0, SFR )
+#define F OP( 0, 0, FP, 0 )
+#define FL OP( 0, LIT, FP, 0 )
+#define R2 OP( 1, 0, 0, 0 )
+#define RL2 OP( 1, LIT, 0, 0 )
+#define F2 OP( 1, 0, FP, 0 )
+#define FL2 OP( 1, LIT, FP, 0 )
+#define R4 OP( 3, 0, 0, 0 )
+#define RL4 OP( 3, LIT, 0, 0 )
+#define F4 OP( 3, 0, FP, 0 )
+#define FL4 OP( 3, LIT, FP, 0 )
+
+#define M 0x7f /* Memory operand (MEMA & MEMB format instructions) */
+
+/* Macros to extract info from the register operand descriptor byte 'od'.
+ */
+#define SFR_OK(od) (od & SFR) /* TRUE if sfr operand allowed */
+#define LIT_OK(od) (od & LIT) /* TRUE if literal operand allowed */
+#define FP_OK(od) (od & FP) /* TRUE if floating-point op allowed */
+#define REG_ALIGN(od,n) ((od & 0x3 & n) == 0)
+ /* TRUE if reg #n is properly aligned */
+#define MEMOP(od) (od == M) /* TRUE if operand is a memory operand*/
+
+/* Description of a single i80960 instruction */
+struct i960_opcode {
+ long opcode; /* 32 bits, constant fields filled in, rest zeroed */
+ char *name; /* Assembler mnemonic */
+ short iclass; /* Class: see #defines below */
+ char format; /* REG, COBR, CTRL, MEMn, COJ, FBRA, or CALLJ */
+ char num_ops; /* Number of operands */
+ char operand[3];/* Operand descriptors; same order as assembler instr */
+};
+
+/* Classes of 960 intructions:
+ * - each instruction falls into one class.
+ * - each target architecture supports one or more classes.
+ *
+ * EACH CONSTANT MUST CONTAIN 1 AND ONLY 1 SET BIT!: see targ_has_iclass().
+ */
+#define I_BASE 0x01 /* 80960 base instruction set */
+#define I_CX 0x02 /* 80960Cx instruction */
+#define I_DEC 0x04 /* Decimal instruction */
+#define I_FP 0x08 /* Floating point instruction */
+#define I_KX 0x10 /* 80960Kx instruction */
+#define I_MIL 0x20 /* Military instruction */
+#define I_CASIM 0x40 /* CA simulator instruction */
+
+/******************************************************************************
+ *
+ * TABLE OF i960 INSTRUCTION DESCRIPTIONS
+ *
+ ******************************************************************************/
+
+const struct i960_opcode i960_opcodes[] = {
+
+ /* if a CTRL instruction has an operand, it's always a displacement */
+
+ { 0x09000000, "callj", I_BASE, CALLJ, 1 },/*default=='call'*/
+ { 0x08000000, "b", I_BASE, CTRL, 1 },
+ { 0x09000000, "call", I_BASE, CTRL, 1 },
+ { 0x0a000000, "ret", I_BASE, CTRL, 0 },
+ { 0x0b000000, "bal", I_BASE, CTRL, 1 },
+ { 0x10000000, "bno", I_BASE, CTRL, 1 },
+ { 0x10000000, "bf", I_BASE, CTRL, 1 }, /* same as bno */
+ { 0x10000000, "bru", I_BASE, CTRL, 1 }, /* same as bno */
+ { 0x11000000, "bg", I_BASE, CTRL, 1 },
+ { 0x11000000, "brg", I_BASE, CTRL, 1 }, /* same as bg */
+ { 0x12000000, "be", I_BASE, CTRL, 1 },
+ { 0x12000000, "bre", I_BASE, CTRL, 1 }, /* same as be */
+ { 0x13000000, "bge", I_BASE, CTRL, 1 },
+ { 0x13000000, "brge", I_BASE, CTRL, 1 }, /* same as bge */
+ { 0x14000000, "bl", I_BASE, CTRL, 1 },
+ { 0x14000000, "brl", I_BASE, CTRL, 1 }, /* same as bl */
+ { 0x15000000, "bne", I_BASE, CTRL, 1 },
+ { 0x15000000, "brlg", I_BASE, CTRL, 1 }, /* same as bne */
+ { 0x16000000, "ble", I_BASE, CTRL, 1 },
+ { 0x16000000, "brle", I_BASE, CTRL, 1 }, /* same as ble */
+ { 0x17000000, "bo", I_BASE, CTRL, 1 },
+ { 0x17000000, "bt", I_BASE, CTRL, 1 }, /* same as bo */
+ { 0x17000000, "bro", I_BASE, CTRL, 1 }, /* same as bo */
+ { 0x18000000, "faultno", I_BASE, CTRL, 0 },
+ { 0x18000000, "faultf", I_BASE, CTRL, 0 }, /*same as faultno*/
+ { 0x19000000, "faultg", I_BASE, CTRL, 0 },
+ { 0x1a000000, "faulte", I_BASE, CTRL, 0 },
+ { 0x1b000000, "faultge", I_BASE, CTRL, 0 },
+ { 0x1c000000, "faultl", I_BASE, CTRL, 0 },
+ { 0x1d000000, "faultne", I_BASE, CTRL, 0 },
+ { 0x1e000000, "faultle", I_BASE, CTRL, 0 },
+ { 0x1f000000, "faulto", I_BASE, CTRL, 0 },
+ { 0x1f000000, "faultt", I_BASE, CTRL, 0 }, /* syn for faulto */
+
+ { 0x01000000, "syscall", I_CASIM,CTRL, 0 },
+
+ /* If a COBR (or COJ) has 3 operands, the last one is always a
+ * displacement and does not appear explicitly in the table.
+ */
+
+ { 0x20000000, "testno", I_BASE, COBR, 1, R },
+ { 0x21000000, "testg", I_BASE, COBR, 1, R },
+ { 0x22000000, "teste", I_BASE, COBR, 1, R },
+ { 0x23000000, "testge", I_BASE, COBR, 1, R },
+ { 0x24000000, "testl", I_BASE, COBR, 1, R },
+ { 0x25000000, "testne", I_BASE, COBR, 1, R },
+ { 0x26000000, "testle", I_BASE, COBR, 1, R },
+ { 0x27000000, "testo", I_BASE, COBR, 1, R },
+ { 0x30000000, "bbc", I_BASE, COBR, 3, RL, RS },
+ { 0x31000000, "cmpobg", I_BASE, COBR, 3, RL, RS },
+ { 0x32000000, "cmpobe", I_BASE, COBR, 3, RL, RS },
+ { 0x33000000, "cmpobge", I_BASE, COBR, 3, RL, RS },
+ { 0x34000000, "cmpobl", I_BASE, COBR, 3, RL, RS },
+ { 0x35000000, "cmpobne", I_BASE, COBR, 3, RL, RS },
+ { 0x36000000, "cmpoble", I_BASE, COBR, 3, RL, RS },
+ { 0x37000000, "bbs", I_BASE, COBR, 3, RL, RS },
+ { 0x38000000, "cmpibno", I_BASE, COBR, 3, RL, RS },
+ { 0x39000000, "cmpibg", I_BASE, COBR, 3, RL, RS },
+ { 0x3a000000, "cmpibe", I_BASE, COBR, 3, RL, RS },
+ { 0x3b000000, "cmpibge", I_BASE, COBR, 3, RL, RS },
+ { 0x3c000000, "cmpibl", I_BASE, COBR, 3, RL, RS },
+ { 0x3d000000, "cmpibne", I_BASE, COBR, 3, RL, RS },
+ { 0x3e000000, "cmpible", I_BASE, COBR, 3, RL, RS },
+ { 0x3f000000, "cmpibo", I_BASE, COBR, 3, RL, RS },
+ { 0x31000000, "cmpojg", I_BASE, COJ, 3, RL, RS },
+ { 0x32000000, "cmpoje", I_BASE, COJ, 3, RL, RS },
+ { 0x33000000, "cmpojge", I_BASE, COJ, 3, RL, RS },
+ { 0x34000000, "cmpojl", I_BASE, COJ, 3, RL, RS },
+ { 0x35000000, "cmpojne", I_BASE, COJ, 3, RL, RS },
+ { 0x36000000, "cmpojle", I_BASE, COJ, 3, RL, RS },
+ { 0x38000000, "cmpijno", I_BASE, COJ, 3, RL, RS },
+ { 0x39000000, "cmpijg", I_BASE, COJ, 3, RL, RS },
+ { 0x3a000000, "cmpije", I_BASE, COJ, 3, RL, RS },
+ { 0x3b000000, "cmpijge", I_BASE, COJ, 3, RL, RS },
+ { 0x3c000000, "cmpijl", I_BASE, COJ, 3, RL, RS },
+ { 0x3d000000, "cmpijne", I_BASE, COJ, 3, RL, RS },
+ { 0x3e000000, "cmpijle", I_BASE, COJ, 3, RL, RS },
+ { 0x3f000000, "cmpijo", I_BASE, COJ, 3, RL, RS },
+
+ { 0x80000000, "ldob", I_BASE, MEM1, 2, M, R },
+ { 0x82000000, "stob", I_BASE, MEM1, 2, R , M },
+ { 0x84000000, "bx", I_BASE, MEM1, 1, M },
+ { 0x85000000, "balx", I_BASE, MEM1, 2, M, R },
+ { 0x86000000, "callx", I_BASE, MEM1, 1, M },
+ { 0x88000000, "ldos", I_BASE, MEM2, 2, M, R },
+ { 0x8a000000, "stos", I_BASE, MEM2, 2, R , M },
+ { 0x8c000000, "lda", I_BASE, MEM1, 2, M, R },
+ { 0x90000000, "ld", I_BASE, MEM4, 2, M, R },
+ { 0x92000000, "st", I_BASE, MEM4, 2, R , M },
+ { 0x98000000, "ldl", I_BASE, MEM8, 2, M, R2 },
+ { 0x9a000000, "stl", I_BASE, MEM8, 2, R2 ,M },
+ { 0xa0000000, "ldt", I_BASE, MEM12, 2, M, R4 },
+ { 0xa2000000, "stt", I_BASE, MEM12, 2, R4 ,M },
+ { 0xb0000000, "ldq", I_BASE, MEM16, 2, M, R4 },
+ { 0xb2000000, "stq", I_BASE, MEM16, 2, R4 ,M },
+ { 0xc0000000, "ldib", I_BASE, MEM1, 2, M, R },
+ { 0xc2000000, "stib", I_BASE, MEM1, 2, R , M },
+ { 0xc8000000, "ldis", I_BASE, MEM2, 2, M, R },
+ { 0xca000000, "stis", I_BASE, MEM2, 2, R , M },
+
+ { R_3(0x580), "notbit", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x581), "and", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x582), "andnot", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x583), "setbit", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x584), "notand", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x586), "xor", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x587), "or", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x588), "nor", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x589), "xnor", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_2D(0x58a), "not", I_BASE, REG, 2, RSL,RS },
+ { R_3(0x58b), "ornot", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x58c), "clrbit", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x58d), "notor", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x58e), "nand", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x58f), "alterbit", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x590), "addo", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x591), "addi", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x592), "subo", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x593), "subi", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x598), "shro", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x59a), "shrdi", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x59b), "shri", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x59c), "shlo", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x59d), "rotate", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x59e), "shli", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_2(0x5a0), "cmpo", I_BASE, REG, 2, RSL,RSL },
+ { R_2(0x5a1), "cmpi", I_BASE, REG, 2, RSL,RSL },
+ { R_2(0x5a2), "concmpo", I_BASE, REG, 2, RSL,RSL },
+ { R_2(0x5a3), "concmpi", I_BASE, REG, 2, RSL,RSL },
+ { R_3(0x5a4), "cmpinco", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x5a5), "cmpinci", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x5a6), "cmpdeco", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x5a7), "cmpdeci", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_2(0x5ac), "scanbyte", I_BASE, REG, 2, RSL,RSL },
+ { R_2(0x5ae), "chkbit", I_BASE, REG, 2, RSL,RSL },
+ { R_3(0x5b0), "addc", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x5b2), "subc", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_2D(0x5cc), "mov", I_BASE, REG, 2, RSL,RS },
+ { R_2D(0x5dc), "movl", I_BASE, REG, 2, RL2,R2 },
+ { R_2D(0x5ec), "movt", I_BASE, REG, 2, RL4,R4 },
+ { R_2D(0x5fc), "movq", I_BASE, REG, 2, RL4,R4 },
+ { R_3(0x610), "atmod", I_BASE, REG, 3, RS, RSL,R },
+ { R_3(0x612), "atadd", I_BASE, REG, 3, RS, RSL,RS },
+ { R_2D(0x640), "spanbit", I_BASE, REG, 2, RSL,RS },
+ { R_2D(0x641), "scanbit", I_BASE, REG, 2, RSL,RS },
+ { R_3(0x645), "modac", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x650), "modify", I_BASE, REG, 3, RSL,RSL,R },
+ { R_3(0x651), "extract", I_BASE, REG, 3, RSL,RSL,R },
+ { R_3(0x654), "modtc", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x655), "modpc", I_BASE, REG, 3, RSL,RSL,R },
+ { R_1(0x660), "calls", I_BASE, REG, 1, RSL },
+ { R_0(0x66b), "mark", I_BASE, REG, 0, },
+ { R_0(0x66c), "fmark", I_BASE, REG, 0, },
+ { R_0(0x66d), "flushreg", I_BASE, REG, 0, },
+ { R_0(0x66f), "syncf", I_BASE, REG, 0, },
+ { R_3(0x670), "emul", I_BASE, REG, 3, RSL,RSL,R2 },
+ { R_3(0x671), "ediv", I_BASE, REG, 3, RSL,RL2,RS },
+ { R_2D(0x672), "cvtadr", I_CASIM,REG, 2, RL, R2 },
+ { R_3(0x701), "mulo", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x708), "remo", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x70b), "divo", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x741), "muli", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x748), "remi", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x749), "modi", I_BASE, REG, 3, RSL,RSL,RS },
+ { R_3(0x74b), "divi", I_BASE, REG, 3, RSL,RSL,RS },
+
+ /* Floating-point instructions */
+
+ { R_2D(0x674), "cvtir", I_FP, REG, 2, RL, F },
+ { R_2D(0x675), "cvtilr", I_FP, REG, 2, RL, F },
+ { R_3(0x676), "scalerl", I_FP, REG, 3, RL, FL2,F2 },
+ { R_3(0x677), "scaler", I_FP, REG, 3, RL, FL, F },
+ { R_3(0x680), "atanr", I_FP, REG, 3, FL, FL, F },
+ { R_3(0x681), "logepr", I_FP, REG, 3, FL, FL, F },
+ { R_3(0x682), "logr", I_FP, REG, 3, FL, FL, F },
+ { R_3(0x683), "remr", I_FP, REG, 3, FL, FL, F },
+ { R_2(0x684), "cmpor", I_FP, REG, 2, FL, FL },
+ { R_2(0x685), "cmpr", I_FP, REG, 2, FL, FL },
+ { R_2D(0x688), "sqrtr", I_FP, REG, 2, FL, F },
+ { R_2D(0x689), "expr", I_FP, REG, 2, FL, F },
+ { R_2D(0x68a), "logbnr", I_FP, REG, 2, FL, F },
+ { R_2D(0x68b), "roundr", I_FP, REG, 2, FL, F },
+ { R_2D(0x68c), "sinr", I_FP, REG, 2, FL, F },
+ { R_2D(0x68d), "cosr", I_FP, REG, 2, FL, F },
+ { R_2D(0x68e), "tanr", I_FP, REG, 2, FL, F },
+ { R_1(0x68f), "classr", I_FP, REG, 1, FL },
+ { R_3(0x690), "atanrl", I_FP, REG, 3, FL2,FL2,F2 },
+ { R_3(0x691), "logeprl", I_FP, REG, 3, FL2,FL2,F2 },
+ { R_3(0x692), "logrl", I_FP, REG, 3, FL2,FL2,F2 },
+ { R_3(0x693), "remrl", I_FP, REG, 3, FL2,FL2,F2 },
+ { R_2(0x694), "cmporl", I_FP, REG, 2, FL2,FL2 },
+ { R_2(0x695), "cmprl", I_FP, REG, 2, FL2,FL2 },
+ { R_2D(0x698), "sqrtrl", I_FP, REG, 2, FL2,F2 },
+ { R_2D(0x699), "exprl", I_FP, REG, 2, FL2,F2 },
+ { R_2D(0x69a), "logbnrl", I_FP, REG, 2, FL2,F2 },
+ { R_2D(0x69b), "roundrl", I_FP, REG, 2, FL2,F2 },
+ { R_2D(0x69c), "sinrl", I_FP, REG, 2, FL2,F2 },
+ { R_2D(0x69d), "cosrl", I_FP, REG, 2, FL2,F2 },
+ { R_2D(0x69e), "tanrl", I_FP, REG, 2, FL2,F2 },
+ { R_1(0x69f), "classrl", I_FP, REG, 1, FL2 },
+ { R_2D(0x6c0), "cvtri", I_FP, REG, 2, FL, R },
+ { R_2D(0x6c1), "cvtril", I_FP, REG, 2, FL, R2 },
+ { R_2D(0x6c2), "cvtzri", I_FP, REG, 2, FL, R },
+ { R_2D(0x6c3), "cvtzril", I_FP, REG, 2, FL, R2 },
+ { R_2D(0x6c9), "movr", I_FP, REG, 2, FL, F },
+ { R_2D(0x6d9), "movrl", I_FP, REG, 2, FL2,F2 },
+ { R_2D(0x6e1), "movre", I_FP, REG, 2, FL4,F4 },
+ { R_3(0x6e2), "cpysre", I_FP, REG, 3, FL4,FL4,F4 },
+ { R_3(0x6e3), "cpyrsre", I_FP, REG, 3, FL4,FL4,F4 },
+ { R_3(0x78b), "divr", I_FP, REG, 3, FL, FL, F },
+ { R_3(0x78c), "mulr", I_FP, REG, 3, FL, FL, F },
+ { R_3(0x78d), "subr", I_FP, REG, 3, FL, FL, F },
+ { R_3(0x78f), "addr", I_FP, REG, 3, FL, FL, F },
+ { R_3(0x79b), "divrl", I_FP, REG, 3, FL2,FL2,F2 },
+ { R_3(0x79c), "mulrl", I_FP, REG, 3, FL2,FL2,F2 },
+ { R_3(0x79d), "subrl", I_FP, REG, 3, FL2,FL2,F2 },
+ { R_3(0x79f), "addrl", I_FP, REG, 3, FL2,FL2,F2 },
+
+ /* These are the floating point branch instructions. Each actually
+ * generates 2 branch instructions: the first a CTRL instruction with
+ * the indicated opcode, and the second a 'bno'.
+ */
+
+ { 0x12000000, "brue", I_FP, FBRA, 1 },
+ { 0x11000000, "brug", I_FP, FBRA, 1 },
+ { 0x13000000, "bruge", I_FP, FBRA, 1 },
+ { 0x14000000, "brul", I_FP, FBRA, 1 },
+ { 0x16000000, "brule", I_FP, FBRA, 1 },
+ { 0x15000000, "brulg", I_FP, FBRA, 1 },
+
+
+ /* Decimal instructions */
+
+ { R_3(0x642), "daddc", I_DEC, REG, 3, RSL,RSL,RS },
+ { R_3(0x643), "dsubc", I_DEC, REG, 3, RSL,RSL,RS },
+ { R_2D(0x644), "dmovt", I_DEC, REG, 2, RSL,RS },
+
+
+ /* KX extensions */
+
+ { R_2(0x600), "synmov", I_KX, REG, 2, R, R },
+ { R_2(0x601), "synmovl", I_KX, REG, 2, R, R },
+ { R_2(0x602), "synmovq", I_KX, REG, 2, R, R },
+ { R_2D(0x615), "synld", I_KX, REG, 2, R, R },
+
+
+ /* MC extensions */
+
+ { R_3(0x603), "cmpstr", I_MIL, REG, 3, R, R, RL },
+ { R_3(0x604), "movqstr", I_MIL, REG, 3, R, R, RL },
+ { R_3(0x605), "movstr", I_MIL, REG, 3, R, R, RL },
+ { R_2D(0x613), "inspacc", I_MIL, REG, 2, R, R },
+ { R_2D(0x614), "ldphy", I_MIL, REG, 2, R, R },
+ { R_3(0x617), "fill", I_MIL, REG, 3, R, RL, RL },
+ { R_2D(0x646), "condrec", I_MIL, REG, 2, R, R },
+ { R_2D(0x656), "receive", I_MIL, REG, 2, R, R },
+ { R_3(0x662), "send", I_MIL, REG, 3, R, RL, R },
+ { R_1(0x663), "sendserv", I_MIL, REG, 1, R },
+ { R_1(0x664), "resumprcs", I_MIL, REG, 1, R },
+ { R_1(0x665), "schedprcs", I_MIL, REG, 1, R },
+ { R_0(0x666), "saveprcs", I_MIL, REG, 0, },
+ { R_1(0x668), "condwait", I_MIL, REG, 1, R },
+ { R_1(0x669), "wait", I_MIL, REG, 1, R },
+ { R_1(0x66a), "signal", I_MIL, REG, 1, R },
+ { R_1D(0x673), "ldtime", I_MIL, REG, 1, R2 },
+
+
+ /* CX extensions */
+
+ { R_3(0x5d8), "eshro", I_CX, REG, 3, RSL,RSL,RS },
+ { R_3(0x630), "sdma", I_CX, REG, 3, RSL,RSL,RL },
+ { R_3(0x631), "udma", I_CX, REG, 0 },
+ { R_3(0x659), "sysctl", I_CX, REG, 3, RSL,RSL,RL },
+
+
+ /* END OF TABLE */
+
+ { 0, NULL, 0, 0 }
+};
+
+ /* end of i960-opcode.h */
diff --git a/gnu/usr.bin/as/opcode/m68k.h b/gnu/usr.bin/as/opcode/m68k.h
new file mode 100644
index 0000000..bd35495
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/m68k.h
@@ -0,0 +1,1998 @@
+/* Opcode table for m680[01234]0/m6888[12]/m68851.
+ Copyright (C) 1989, 1991 Free Software Foundation.
+
+This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.
+
+Both GDB and GAS are free software; you can redistribute and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB and GAS are distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB or GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* These are used as bit flags for arch below. */
+
+enum m68k_architecture {
+ m68000 = 0x01,
+ m68008 = m68000, /* synonym for -m68000. otherwise unused. */
+ m68010 = 0x02,
+ m68020 = 0x04,
+ m68030 = 0x08,
+ m68040 = 0x10,
+ m68881 = 0x20,
+ m68882 = m68881, /* synonym for -m68881. otherwise unused. */
+ m68851 = 0x40,
+
+ /* handy aliases */
+ m68040up = m68040,
+ m68030up = (m68030 | m68040up),
+ m68020up = (m68020 | m68030up),
+ m68010up = (m68010 | m68020up),
+ m68000up = (m68000 | m68010up),
+
+ mfloat = (m68881 | m68882 | m68040),
+ mmmu = (m68851 | m68030 | m68040)
+}; /* enum m68k_architecture */
+
+ /* note that differences in addressing modes that aren't distinguished
+ in the following table are handled explicitly by gas. */
+
+struct m68k_opcode {
+ char *name;
+ unsigned long opcode;
+ unsigned long match;
+ char *args;
+ enum m68k_architecture arch;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and is as much longer as necessary to
+ hold the operands it has.
+
+ The match component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing two characters
+ for each operand of the instruction. The first specifies
+ the kind of operand; the second, the place it is stored. */
+
+/* Kinds of operands:
+ D data register only. Stored as 3 bits.
+ A address register only. Stored as 3 bits.
+ a address register indirect only. Stored as 3 bits.
+ R either kind of register. Stored as 4 bits.
+ F floating point coprocessor register only. Stored as 3 bits.
+ O an offset (or width): immediate data 0-31 or data register.
+ Stored as 6 bits in special format for BF... insns.
+ + autoincrement only. Stored as 3 bits (number of the address register).
+ - autodecrement only. Stored as 3 bits (number of the address register).
+ Q quick immediate data. Stored as 3 bits.
+ This matches an immediate operand only when value is in range 1 .. 8.
+ M moveq immediate data. Stored as 8 bits.
+ This matches an immediate operand only when value is in range -128..127
+ T trap vector immediate data. Stored as 4 bits.
+
+ k K-factor for fmove.p instruction. Stored as a 7-bit constant or
+ a three bit register offset, depending on the field type.
+
+ # immediate data. Stored in special places (b, w or l)
+ which say how many bits to store.
+ ^ immediate data for floating point instructions. Special places
+ are offset by 2 bytes from '#'...
+ B pc-relative address, converted to an offset
+ that is treated as immediate data.
+ d displacement and register. Stores the register as 3 bits
+ and stores the displacement in the entire second word.
+
+ C the CCR. No need to store it; this is just for filtering validity.
+ S the SR. No need to store, just as with CCR.
+ U the USP. No need to store, just as with CCR.
+
+ I Coprocessor ID. Not printed if 1. The Coprocessor ID is always
+ extracted from the 'd' field of word one, which means that an extended
+ coprocessor opcode can be skipped using the 'i' place, if needed.
+
+ s System Control register for the floating point coprocessor.
+ S List of system control registers for floating point coprocessor.
+
+ J Misc register for movec instruction, stored in 'j' format.
+ Possible values:
+ 0x000 SFC Source Function Code reg [40, 30, 20, 10]
+ 0x001 DFC Data Function Code reg [40, 30, 20, 10]
+ 0x002 CACR Cache Control Register [40, 30, 20]
+ 0x800 USP User Stack Pointer [40, 30, 20, 10]
+ 0x801 VBR Vector Base reg [40, 30, 20, 10]
+ 0x802 CAAR Cache Address Register [ 30, 20]
+ 0x803 MSP Master Stack Pointer [40, 30, 20]
+ 0x804 ISP Interrupt Stack Pointer [40, 30, 20]
+ 0x003 TC MMU Translation Control [40]
+ 0x004 ITT0 Instruction Transparent
+ Translation reg 0 [40]
+ 0x005 ITT1 Instruction Transparent
+ Translation reg 1 [40]
+ 0x006 DTT0 Data Transparent
+ Translation reg 0 [40]
+ 0x007 DTT1 Data Transparent
+ Translation reg 1 [40]
+ 0x805 MMUSR MMU Status reg [40]
+ 0x806 URP User Root Pointer [40]
+ 0x807 SRP Supervisor Root Pointer [40]
+
+ L Register list of the type d0-d7/a0-a7 etc.
+ (New! Improved! Can also hold fp0-fp7, as well!)
+ The assembler tries to see if the registers match the insn by
+ looking at where the insn wants them stored.
+
+ l Register list like L, but with all the bits reversed.
+ Used for going the other way. . .
+
+ c cache identifier which may be "nc" for no cache, "ic"
+ for instruction cache, "dc" for data cache, or "bc"
+ for both caches. Used in cinv and cpush. Always
+ stored in position "d".
+
+ They are all stored as 6 bits using an address mode and a register number;
+ they differ in which addressing modes they match.
+
+ * all (modes 0-6,7.*)
+ ~ alterable memory (modes 2-6,7.0,7.1)(not 0,1,7.~)
+ % alterable (modes 0-6,7.0,7.1)(not 7.~)
+ ; data (modes 0,2-6,7.*)(not 1)
+ @ data, but not immediate (modes 0,2-6,7.? ? ?)(not 1,7.?) This may really be ;, the 68020 book says it is
+ ! control (modes 2,5,6,7.*-)(not 0,1,3,4,7.4)
+ & alterable control (modes 2,5,6,7.0,7.1)(not 0,1,7.? ? ?)
+ $ alterable data (modes 0,2-6,7.0,7.1)(not 1,7.~)
+ ? alterable control, or data register (modes 0,2,5,6,7.0,7.1)(not 1,3,4,7.~)
+ / control, or data register (modes 0,2,5,6,7.0,7.1,7.2,7.3)(not 1,3,4,7.4)
+*/
+
+/* JF: for the 68851 */
+/*
+ I didn't use much imagination in choosing the
+ following codes, so many of them aren't very
+ mnemonic. -rab
+
+ P pmmu register
+ Possible values:
+ 000 TC Translation Control reg
+ 100 CAL Current Access Level
+ 101 VAL Validate Access Level
+ 110 SCC Stack Change Control
+ 111 AC Access Control
+
+ W wide pmmu registers
+ Possible values:
+ 001 DRP Dma Root Pointer
+ 010 SRP Supervisor Root Pointer
+ 011 CRP Cpu Root Pointer
+
+ f function code register
+ 0 SFC
+ 1 DFC
+
+ V VAL register only
+
+ X BADx, BACx
+ 100 BAD Breakpoint Acknowledge Data
+ 101 BAC Breakpoint Acknowledge Control
+
+ Y PSR
+ Z PCSR
+
+ | memory (modes 2-6, 7.*)
+
+*/
+
+/* Places to put an operand, for non-general operands:
+ s source, low bits of first word.
+ d dest, shifted 9 in first word
+ 1 second word, shifted 12
+ 2 second word, shifted 6
+ 3 second word, shifted 0
+ 4 third word, shifted 12
+ 5 third word, shifted 6
+ 6 third word, shifted 0
+ 7 second word, shifted 7
+ 8 second word, shifted 10
+ D store in both place 1 and place 3; for divul and divsl.
+ B first word, low byte, for branch displacements
+ W second word (entire), for branch displacements
+ L second and third words (entire), for branch displacements (also overloaded for move16)
+ b second word, low byte
+ w second word (entire) [variable word/long branch offset for dbra]
+ l second and third word (entire)
+ g variable branch offset for bra and similar instructions.
+ The place to store depends on the magnitude of offset.
+ t store in both place 7 and place 8; for floating point operations
+ c branch offset for cpBcc operations.
+ The place to store is word two if bit six of word one is zero,
+ and words two and three if bit six of word one is one.
+ i Increment by two, to skip over coprocessor extended operands. Only
+ works with the 'I' format.
+ k Dynamic K-factor field. Bits 6-4 of word 2, used as a register number.
+ Also used for dynamic fmovem instruction.
+ C floating point coprocessor constant - 7 bits. Also used for static
+ K-factors...
+ j Movec register #, stored in 12 low bits of second word.
+
+ Places to put operand, for general operands:
+ d destination, shifted 6 bits in first word
+ b source, at low bit of first word, and immediate uses one byte
+ w source, at low bit of first word, and immediate uses two bytes
+ l source, at low bit of first word, and immediate uses four bytes
+ s source, at low bit of first word.
+ Used sometimes in contexts where immediate is not allowed anyway.
+ f single precision float, low bit of 1st word, immediate uses 4 bytes
+ F double precision float, low bit of 1st word, immediate uses 8 bytes
+ x extended precision float, low bit of 1st word, immediate uses 12 bytes
+ p packed float, low bit of 1st word, immediate uses 12 bytes
+*/
+
+#define one(x) ((x) << 16)
+#define two(x, y) (((x) << 16) + y)
+
+/*
+ *** DANGER WILL ROBINSON ***
+
+ The assembler requires that all instances of the same mnemonic must be
+ consecutive. If they aren't, the assembler will bomb at runtime
+ */
+struct m68k_opcode m68k_opcodes[] =
+{
+{"abcd", one(0140400), one(0170770), "DsDd", m68000up },
+{"abcd", one(0140410), one(0170770), "-s-d", m68000up },
+
+ /* Add instructions */
+{"addal", one(0150700), one(0170700), "*lAd", m68000up },
+{"addaw", one(0150300), one(0170700), "*wAd", m68000up },
+{"addib", one(0003000), one(0177700), "#b$b", m68000up },
+{"addil", one(0003200), one(0177700), "#l$l", m68000up },
+{"addiw", one(0003100), one(0177700), "#w$w", m68000up },
+{"addqb", one(0050000), one(0170700), "Qd$b", m68000up },
+{"addql", one(0050200), one(0170700), "Qd%l", m68000up },
+{"addqw", one(0050100), one(0170700), "Qd%w", m68000up },
+
+{"addb", one(0050000), one(0170700), "Qd$b", m68000up }, /* addq written as add */
+{"addb", one(0003000), one(0177700), "#b$b", m68000up }, /* addi written as add */
+{"addb", one(0150000), one(0170700), ";bDd", m68000up }, /* addb <ea>, Dd */
+{"addb", one(0150400), one(0170700), "Dd~b", m68000up }, /* addb Dd, <ea> */
+
+{"addw", one(0050100), one(0170700), "Qd%w", m68000up }, /* addq written as add */
+{"addw", one(0003100), one(0177700), "#w$w", m68000up }, /* addi written as add */
+{"addw", one(0150300), one(0170700), "*wAd", m68000up }, /* adda written as add */
+{"addw", one(0150100), one(0170700), "*wDd", m68000up }, /* addw <ea>, Dd */
+{"addw", one(0150500), one(0170700), "Dd~w", m68000up }, /* addw Dd, <ea> */
+
+{"addl", one(0050200), one(0170700), "Qd%l", m68000up }, /* addq written as add */
+{"addl", one(0003200), one(0177700), "#l$l", m68000up }, /* addi written as add */
+{"addl", one(0150700), one(0170700), "*lAd", m68000up }, /* adda written as add */
+{"addl", one(0150200), one(0170700), "*lDd", m68000up }, /* addl <ea>, Dd */
+{"addl", one(0150600), one(0170700), "Dd~l", m68000up }, /* addl Dd, <ea> */
+
+{"addxb", one(0150400), one(0170770), "DsDd", m68000up },
+{"addxb", one(0150410), one(0170770), "-s-d", m68000up },
+{"addxl", one(0150600), one(0170770), "DsDd", m68000up },
+{"addxl", one(0150610), one(0170770), "-s-d", m68000up },
+{"addxw", one(0150500), one(0170770), "DsDd", m68000up },
+{"addxw", one(0150510), one(0170770), "-s-d", m68000up },
+
+{"andib", one(0001000), one(0177700), "#b$b", m68000up },
+{"andib", one(0001074), one(0177777), "#bCb", m68000up }, /* andi to ccr */
+{"andiw", one(0001100), one(0177700), "#w$w", m68000up },
+{"andiw", one(0001174), one(0177777), "#wSw", m68000up }, /* andi to sr */
+{"andil", one(0001200), one(0177700), "#l$l", m68000up },
+
+{"andb", one(0001000), one(0177700), "#b$b", m68000up }, /* andi written as or */
+{"andb", one(0001074), one(0177777), "#bCb", m68000up }, /* andi to ccr */
+{"andb", one(0140000), one(0170700), ";bDd", m68000up }, /* memory to register */
+{"andb", one(0140400), one(0170700), "Dd~b", m68000up }, /* register to memory */
+{"andw", one(0001100), one(0177700), "#w$w", m68000up }, /* andi written as or */
+{"andw", one(0001174), one(0177777), "#wSw", m68000up }, /* andi to sr */
+{"andw", one(0140100), one(0170700), ";wDd", m68000up }, /* memory to register */
+{"andw", one(0140500), one(0170700), "Dd~w", m68000up }, /* register to memory */
+{"andl", one(0001200), one(0177700), "#l$l", m68000up }, /* andi written as or */
+{"andl", one(0140200), one(0170700), ";lDd", m68000up }, /* memory to register */
+{"andl", one(0140600), one(0170700), "Dd~l", m68000up }, /* register to memory */
+
+{"aslb", one(0160400), one(0170770), "QdDs", m68000up },
+{"aslb", one(0160440), one(0170770), "DdDs", m68000up },
+{"asll", one(0160600), one(0170770), "QdDs", m68000up },
+{"asll", one(0160640), one(0170770), "DdDs", m68000up },
+{"aslw", one(0160500), one(0170770), "QdDs", m68000up },
+{"aslw", one(0160540), one(0170770), "DdDs", m68000up },
+{"aslw", one(0160700), one(0177700), "~s", m68000up }, /* Shift memory */
+{"asrb", one(0160000), one(0170770), "QdDs", m68000up },
+{"asrb", one(0160040), one(0170770), "DdDs", m68000up },
+{"asrl", one(0160200), one(0170770), "QdDs", m68000up },
+{"asrl", one(0160240), one(0170770), "DdDs", m68000up },
+{"asrw", one(0160100), one(0170770), "QdDs", m68000up },
+{"asrw", one(0160140), one(0170770), "DdDs", m68000up },
+{"asrw", one(0160300), one(0177700), "~s", m68000up }, /* Shift memory */
+
+/* Fixed-size branches with 16-bit offsets */
+
+{"bhi", one(0061000), one(0177777), "BW", m68000up },
+{"bls", one(0061400), one(0177777), "BW", m68000up },
+{"bcc", one(0062000), one(0177777), "BW", m68000up },
+{"bcs", one(0062400), one(0177777), "BW", m68000up },
+{"bne", one(0063000), one(0177777), "BW", m68000up },
+{"beq", one(0063400), one(0177777), "BW", m68000up },
+{"bvc", one(0064000), one(0177777), "BW", m68000up },
+{"bvs", one(0064400), one(0177777), "BW", m68000up },
+{"bpl", one(0065000), one(0177777), "BW", m68000up },
+{"bmi", one(0065400), one(0177777), "BW", m68000up },
+{"bge", one(0066000), one(0177777), "BW", m68000up },
+{"blt", one(0066400), one(0177777), "BW", m68000up },
+{"bgt", one(0067000), one(0177777), "BW", m68000up },
+{"ble", one(0067400), one(0177777), "BW", m68000up },
+{"bra", one(0060000), one(0177777), "BW", m68000up },
+{"bsr", one(0060400), one(0177777), "BW", m68000up },
+
+/* Fixed-size branches with short (byte) offsets */
+
+{"bhis", one(0061000), one(0177400), "BB", m68000up },
+{"blss", one(0061400), one(0177400), "BB", m68000up },
+{"bccs", one(0062000), one(0177400), "BB", m68000up },
+{"bcss", one(0062400), one(0177400), "BB", m68000up },
+{"bnes", one(0063000), one(0177400), "BB", m68000up },
+{"beqs", one(0063400), one(0177400), "BB", m68000up },
+{"bvcs", one(0064000), one(0177400), "BB", m68000up },
+{"bvss", one(0064400), one(0177400), "BB", m68000up },
+{"bpls", one(0065000), one(0177400), "BB", m68000up },
+{"bmis", one(0065400), one(0177400), "BB", m68000up },
+{"bges", one(0066000), one(0177400), "BB", m68000up },
+{"blts", one(0066400), one(0177400), "BB", m68000up },
+{"bgts", one(0067000), one(0177400), "BB", m68000up },
+{"bles", one(0067400), one(0177400), "BB", m68000up },
+{"bras", one(0060000), one(0177400), "BB", m68000up },
+{"bsrs", one(0060400), one(0177400), "BB", m68000up },
+
+/* Fixed-size branches with long (32-bit) offsets */
+
+{"bhil", one(0061377), one(0177777), "BL", m68020up },
+{"blsl", one(0061777), one(0177777), "BL", m68020up },
+{"bccl", one(0062377), one(0177777), "BL", m68020up },
+{"bcsl", one(0062777), one(0177777), "BL", m68020up },
+{"bnel", one(0063377), one(0177777), "BL", m68020up },
+{"beql", one(0063777), one(0177777), "BL", m68020up },
+{"bvcl", one(0064377), one(0177777), "BL", m68020up },
+{"bvsl", one(0064777), one(0177777), "BL", m68020up },
+{"bpll", one(0065377), one(0177777), "BL", m68020up },
+{"bmil", one(0065777), one(0177777), "BL", m68020up },
+{"bgel", one(0066377), one(0177777), "BL", m68020up },
+{"bltl", one(0066777), one(0177777), "BL", m68020up },
+{"bgtl", one(0067377), one(0177777), "BL", m68020up },
+{"blel", one(0067777), one(0177777), "BL", m68020up },
+{"bral", one(0060377), one(0177777), "BL", m68020up },
+{"bsrl", one(0060777), one(0177777), "BL", m68020up },
+
+/* We now return you to our regularly scheduled instruction set */
+
+{"bchg", one(0000500), one(0170700), "Dd$s", m68000up },
+{"bchg", one(0004100), one(0177700), "#b$s", m68000up },
+{"bclr", one(0000600), one(0170700), "Dd$s", m68000up },
+{"bclr", one(0004200), one(0177700), "#b$s", m68000up },
+
+{"bfchg", two(0165300, 0), two(0177700, 0170000), "?sO2O3", m68020up },
+{"bfclr", two(0166300, 0), two(0177700, 0170000), "?sO2O3", m68020up },
+{"bfexts", two(0165700, 0), two(0177700, 0100000), "/sO2O3D1", m68020up },
+{"bfextu", two(0164700, 0), two(0177700, 0100000), "/sO2O3D1", m68020up },
+{"bfffo", two(0166700, 0), two(0177700, 0100000), "/sO2O3D1", m68020up },
+{"bfins", two(0167700, 0), two(0177700, 0100000), "D1?sO2O3", m68020up },
+{"bfset", two(0167300, 0), two(0177700, 0170000), "?sO2O3", m68020up },
+{"bftst", two(0164300, 0), two(0177700, 0170000), "/sO2O3", m68020up },
+{"bkpt", one(0044110), one(0177770), "Qs", m68020up },
+
+{"bset", one(0000700), one(0170700), "Dd$s", m68000up },
+{"bset", one(0004300), one(0177700), "#b$s", m68000up },
+{"btst", one(0000400), one(0170700), "Dd@s", m68000up },
+{"btst", one(0004000), one(0177700), "#b@s", m68000up },
+
+
+{"callm", one(0003300), one(0177700), "#b!s", m68020 },
+
+{"cas2l", two(0007374, 0), two(0177777, 0107070), "D3D6D2D5R1R4", m68020up }, /* JF FOO really a 3 word ins */
+{"cas2w", two(0006374, 0), two(0177777, 0107070), "D3D6D2D5R1R4", m68020up }, /* JF ditto */
+{"casb", two(0005300, 0), two(0177700, 0177070), "D3D2~s", m68020up },
+{"casl", two(0007300, 0), two(0177700, 0177070), "D3D2~s", m68020up },
+{"casw", two(0006300, 0), two(0177700, 0177070), "D3D2~s", m68020up },
+
+/* {"chk", one(0040600), one(0170700), ";wDd"}, JF FOO this looks wrong */
+{"chk2b", two(0000300, 0004000), two(0177700, 07777), "!sR1", m68020up },
+{"chk2l", two(0002300, 0004000), two(0177700, 07777), "!sR1", m68020up },
+{"chk2w", two(0001300, 0004000), two(0177700, 07777), "!sR1", m68020up },
+{"chkl", one(0040400), one(0170700), ";lDd", m68000up },
+{"chkw", one(0040600), one(0170700), ";wDd", m68000up },
+
+#define SCOPE_LINE (0x1 << 3)
+#define SCOPE_PAGE (0x2 << 3)
+#define SCOPE_ALL (0x3 << 3)
+{"cinva", one(0xf400|SCOPE_ALL), one(0xff38), "ce", m68040 },
+{"cinvl", one(0xf400|SCOPE_LINE), one(0xff38), "ceas", m68040 },
+{"cinvp", one(0xf400|SCOPE_PAGE), one(0xff38), "ceas", m68040 },
+
+{"cpusha", one(0xf420|SCOPE_ALL), one(0xff38), "ce", m68040 },
+{"cpushl", one(0xf420|SCOPE_LINE), one(0xff38), "ceas", m68040 },
+{"cpushp", one(0xf420|SCOPE_PAGE), one(0xff38), "ceas", m68040 },
+
+#undef SCOPE_LINE
+#undef SCOPE_PAGE
+#undef SCOPE_ALL
+
+{"clrb", one(0041000), one(0177700), "$s", m68000up },
+{"clrl", one(0041200), one(0177700), "$s", m68000up },
+{"clrw", one(0041100), one(0177700), "$s", m68000up },
+
+{"cmp2b", two(0000300, 0), two(0177700, 07777), "!sR1", m68020up },
+{"cmp2l", two(0002300, 0), two(0177700, 07777), "!sR1", m68020up },
+{"cmp2w", two(0001300, 0), two(0177700, 07777), "!sR1", m68020up },
+{"cmpal", one(0130700), one(0170700), "*lAd", m68000up },
+{"cmpaw", one(0130300), one(0170700), "*wAd", m68000up },
+{"cmpib", one(0006000), one(0177700), "#b;b", m68000up },
+{"cmpil", one(0006200), one(0177700), "#l;l", m68000up },
+{"cmpiw", one(0006100), one(0177700), "#w;w", m68000up },
+{"cmpb", one(0006000), one(0177700), "#b;b", m68000up }, /* cmpi written as cmp */
+{"cmpb", one(0130000), one(0170700), ";bDd", m68000up },
+{"cmpw", one(0006100), one(0177700), "#w;w", m68000up },
+{"cmpw", one(0130100), one(0170700), "*wDd", m68000up },
+{"cmpw", one(0130300), one(0170700), "*wAd", m68000up }, /* cmpa written as cmp */
+{"cmpl", one(0006200), one(0177700), "#l;l", m68000up },
+{"cmpl", one(0130200), one(0170700), "*lDd", m68000up },
+{"cmpl", one(0130700), one(0170700), "*lAd", m68000up },
+{"cmpmb", one(0130410), one(0170770), "+s+d", m68000up },
+{"cmpml", one(0130610), one(0170770), "+s+d", m68000up },
+{"cmpmw", one(0130510), one(0170770), "+s+d", m68000up },
+
+{"dbcc", one(0052310), one(0177770), "DsBw", m68000up },
+{"dbcs", one(0052710), one(0177770), "DsBw", m68000up },
+{"dbeq", one(0053710), one(0177770), "DsBw", m68000up },
+{"dbf", one(0050710), one(0177770), "DsBw", m68000up },
+{"dbge", one(0056310), one(0177770), "DsBw", m68000up },
+{"dbgt", one(0057310), one(0177770), "DsBw", m68000up },
+{"dbhi", one(0051310), one(0177770), "DsBw", m68000up },
+{"dble", one(0057710), one(0177770), "DsBw", m68000up },
+{"dbls", one(0051710), one(0177770), "DsBw", m68000up },
+{"dblt", one(0056710), one(0177770), "DsBw", m68000up },
+{"dbmi", one(0055710), one(0177770), "DsBw", m68000up },
+{"dbne", one(0053310), one(0177770), "DsBw", m68000up },
+{"dbpl", one(0055310), one(0177770), "DsBw", m68000up },
+{"dbra", one(0050710), one(0177770), "DsBw", m68000up },
+{"dbt", one(0050310), one(0177770), "DsBw", m68000up },
+{"dbvc", one(0054310), one(0177770), "DsBw", m68000up },
+{"dbvs", one(0054710), one(0177770), "DsBw", m68000up },
+
+{"divsl", two(0046100, 0006000), two(0177700, 0107770), ";lD3D1", m68020up },
+{"divsl", two(0046100, 0004000), two(0177700, 0107770), ";lDD", m68020up },
+{"divsll", two(0046100, 0004000), two(0177700, 0107770), ";lD3D1", m68020up },
+{"divsw", one(0100700), one(0170700), ";wDd", m68000up },
+{"divs", one(0100700), one(0170700), ";wDd", m68000up },
+{"divul", two(0046100, 0002000), two(0177700, 0107770), ";lD3D1", m68020up },
+{"divul", two(0046100, 0000000), two(0177700, 0107770), ";lDD", m68020up },
+{"divull", two(0046100, 0000000), two(0177700, 0107770), ";lD3D1", m68020up },
+{"divuw", one(0100300), one(0170700), ";wDd", m68000up },
+{"divu", one(0100300), one(0170700), ";wDd", m68000up },
+{"eorb", one(0005000), one(0177700), "#b$s", m68000up }, /* eori written as or */
+{"eorb", one(0005074), one(0177777), "#bCs", m68000up }, /* eori to ccr */
+{"eorb", one(0130400), one(0170700), "Dd$s", m68000up }, /* register to memory */
+{"eorib", one(0005000), one(0177700), "#b$s", m68000up },
+{"eorib", one(0005074), one(0177777), "#bCs", m68000up }, /* eori to ccr */
+{"eoril", one(0005200), one(0177700), "#l$s", m68000up },
+{"eoriw", one(0005100), one(0177700), "#w$s", m68000up },
+{"eoriw", one(0005174), one(0177777), "#wSs", m68000up }, /* eori to sr */
+{"eorl", one(0005200), one(0177700), "#l$s", m68000up },
+{"eorl", one(0130600), one(0170700), "Dd$s", m68000up },
+{"eorw", one(0005100), one(0177700), "#w$s", m68000up },
+{"eorw", one(0005174), one(0177777), "#wSs", m68000up }, /* eori to sr */
+{"eorw", one(0130500), one(0170700), "Dd$s", m68000up },
+
+{"exg", one(0140500), one(0170770), "DdDs", m68000up },
+{"exg", one(0140510), one(0170770), "AdAs", m68000up },
+{"exg", one(0140610), one(0170770), "DdAs", m68000up },
+{"exg", one(0140610), one(0170770), "AsDd", m68000up },
+
+{"extw", one(0044200), one(0177770), "Ds", m68000up },
+{"extl", one(0044300), one(0177770), "Ds", m68000up },
+{"extbl", one(0044700), one(0177770), "Ds", m68020up },
+{"extb.l", one(0044700), one(0177770), "Ds", m68020up }, /* Not sure we should support this one */
+
+/* float stuff starts here */
+{"fabsb", two(0xF000, 0x5818), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fabsd", two(0xF000, 0x5418), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fabsl", two(0xF000, 0x4018), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fabsp", two(0xF000, 0x4C18), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fabss", two(0xF000, 0x4418), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fabsw", two(0xF000, 0x5018), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fabsx", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fabsx", two(0xF000, 0x4818), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fabsx", two(0xF000, 0x0018), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+/* FIXME-NOW: The '040 book that I have claims that these should be
+ coded exactly like fadd. In fact, the table of opmodes calls them
+ fadd, fsadd, fdadd. That can't be right. If someone can give me the
+ right encoding, I'll fix it. By induction, I *think* the right
+ encoding is 38 & 3c, but I'm not sure.
+
+ in the mean time, if you know the encoding for the opmode field, you
+ can replace all of the "38),"'s and "3c),"'s below with the corrected
+ values and these guys should then just work. xoxorich. 31Aug91 */
+{"fsabsb", two(0xF000, 0x5858), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fsabsd", two(0xF000, 0x5458), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fsabsl", two(0xF000, 0x4058), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fsabsp", two(0xF000, 0x4C58), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fsabss", two(0xF000, 0x4458), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fsabsw", two(0xF000, 0x5058), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fsabsx", two(0xF000, 0x0058), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fsabsx", two(0xF000, 0x4858), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+{"fsabsx", two(0xF000, 0x0058), two(0xF1C0, 0xE07F), "IiFt", m68040 },
+
+{"fdabsb", two(0xF000, 0x585c), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040},
+{"fdabsd", two(0xF000, 0x545c), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040},
+{"fdabsl", two(0xF000, 0x405c), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040},
+{"fdabsp", two(0xF000, 0x4C5c), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040},
+{"fdabss", two(0xF000, 0x445c), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040},
+{"fdabsw", two(0xF000, 0x505c), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040},
+{"fdabsx", two(0xF000, 0x005c), two(0xF1C0, 0xE07F), "IiF8F7", m68040},
+{"fdabsx", two(0xF000, 0x485c), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040},
+{"fdabsx", two(0xF000, 0x005c), two(0xF1C0, 0xE07F), "IiFt", m68040},
+
+{"facosb", two(0xF000, 0x581C), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"facosd", two(0xF000, 0x541C), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"facosl", two(0xF000, 0x401C), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"facosp", two(0xF000, 0x4C1C), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"facoss", two(0xF000, 0x441C), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"facosw", two(0xF000, 0x501C), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"facosx", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"facosx", two(0xF000, 0x481C), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"facosx", two(0xF000, 0x001C), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"faddb", two(0xF000, 0x5822), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"faddd", two(0xF000, 0x5422), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"faddl", two(0xF000, 0x4022), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"faddp", two(0xF000, 0x4C22), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fadds", two(0xF000, 0x4422), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"faddw", two(0xF000, 0x5022), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"faddx", two(0xF000, 0x4822), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+/* {"faddx", two(0xF000, 0x0022), two(0xF1C0, 0xE07F), "IiFt", mfloat }, JF removed */
+{"fsaddb", two(0xF000, 0x5862), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fsaddd", two(0xF000, 0x5462), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fsaddl", two(0xF000, 0x4062), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fsaddp", two(0xF000, 0x4C62), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fsadds", two(0xF000, 0x4462), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fsaddw", two(0xF000, 0x5062), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fsaddx", two(0xF000, 0x0062), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fsaddx", two(0xF000, 0x4862), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+/* {"fsaddx", two(0xF000, 0x0062), two(0xF1C0, 0xE07F), "IiFt", m68040 }, JF removed */
+{"fdaddb", two(0xF000, 0x5866), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fdaddd", two(0xF000, 0x5466), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fdaddl", two(0xF000, 0x4066), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fdaddp", two(0xF000, 0x4C66), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fdadds", two(0xF000, 0x4466), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fdaddw", two(0xF000, 0x5066), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fdaddx", two(0xF000, 0x0066), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fdaddx", two(0xF000, 0x4866), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+/* {"faddx", two(0xF000, 0x0066), two(0xF1C0, 0xE07F), "IiFt", m68040 }, JF removed */
+
+{"fasinb", two(0xF000, 0x580C), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fasind", two(0xF000, 0x540C), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fasinl", two(0xF000, 0x400C), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fasinp", two(0xF000, 0x4C0C), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fasins", two(0xF000, 0x440C), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fasinw", two(0xF000, 0x500C), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fasinx", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fasinx", two(0xF000, 0x480C), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fasinx", two(0xF000, 0x000C), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fatanb", two(0xF000, 0x580A), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fatand", two(0xF000, 0x540A), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fatanl", two(0xF000, 0x400A), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fatanp", two(0xF000, 0x4C0A), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fatans", two(0xF000, 0x440A), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fatanw", two(0xF000, 0x500A), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fatanx", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fatanx", two(0xF000, 0x480A), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fatanx", two(0xF000, 0x000A), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fatanhb", two(0xF000, 0x580D), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fatanhd", two(0xF000, 0x540D), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fatanhl", two(0xF000, 0x400D), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fatanhp", two(0xF000, 0x4C0D), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fatanhs", two(0xF000, 0x440D), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fatanhw", two(0xF000, 0x500D), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fatanhx", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fatanhx", two(0xF000, 0x480D), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fatanhx", two(0xF000, 0x000D), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+/* Fixed-size Float branches */
+
+{"fbeq", one(0xF081), one(0xF1BF), "IdBW", mfloat },
+{"fbf", one(0xF080), one(0xF1BF), "IdBW", mfloat },
+{"fbge", one(0xF093), one(0xF1BF), "IdBW", mfloat },
+{"fbgl", one(0xF096), one(0xF1BF), "IdBW", mfloat },
+{"fbgle", one(0xF097), one(0xF1BF), "IdBW", mfloat },
+{"fbgt", one(0xF092), one(0xF1BF), "IdBW", mfloat },
+{"fble", one(0xF095), one(0xF1BF), "IdBW", mfloat },
+{"fblt", one(0xF094), one(0xF1BF), "IdBW", mfloat },
+{"fbne", one(0xF08E), one(0xF1BF), "IdBW", mfloat },
+{"fbnge", one(0xF09C), one(0xF1BF), "IdBW", mfloat },
+{"fbngl", one(0xF099), one(0xF1BF), "IdBW", mfloat },
+{"fbngle", one(0xF098), one(0xF1BF), "IdBW", mfloat },
+{"fbngt", one(0xF09D), one(0xF1BF), "IdBW", mfloat },
+{"fbnle", one(0xF09A), one(0xF1BF), "IdBW", mfloat },
+{"fbnlt", one(0xF09B), one(0xF1BF), "IdBW", mfloat },
+{"fboge", one(0xF083), one(0xF1BF), "IdBW", mfloat },
+{"fbogl", one(0xF086), one(0xF1BF), "IdBW", mfloat },
+{"fbogt", one(0xF082), one(0xF1BF), "IdBW", mfloat },
+{"fbole", one(0xF085), one(0xF1BF), "IdBW", mfloat },
+{"fbolt", one(0xF084), one(0xF1BF), "IdBW", mfloat },
+{"fbor", one(0xF087), one(0xF1BF), "IdBW", mfloat },
+{"fbseq", one(0xF091), one(0xF1BF), "IdBW", mfloat },
+{"fbsf", one(0xF090), one(0xF1BF), "IdBW", mfloat },
+{"fbsne", one(0xF09E), one(0xF1BF), "IdBW", mfloat },
+{"fbst", one(0xF09F), one(0xF1BF), "IdBW", mfloat },
+{"fbt", one(0xF08F), one(0xF1BF), "IdBW", mfloat },
+{"fbueq", one(0xF089), one(0xF1BF), "IdBW", mfloat },
+{"fbuge", one(0xF08B), one(0xF1BF), "IdBW", mfloat },
+{"fbugt", one(0xF08A), one(0xF1BF), "IdBW", mfloat },
+{"fbule", one(0xF08D), one(0xF1BF), "IdBW", mfloat },
+{"fbult", one(0xF08C), one(0xF1BF), "IdBW", mfloat },
+{"fbun", one(0xF088), one(0xF1BF), "IdBW", mfloat },
+
+/* Float branches -- long (32-bit) displacements */
+
+{"fbeql", one(0xF081), one(0xF1BF), "IdBC", mfloat },
+{"fbfl", one(0xF080), one(0xF1BF), "IdBC", mfloat },
+{"fbgel", one(0xF093), one(0xF1BF), "IdBC", mfloat },
+{"fbgll", one(0xF096), one(0xF1BF), "IdBC", mfloat },
+{"fbglel", one(0xF097), one(0xF1BF), "IdBC", mfloat },
+{"fbgtl", one(0xF092), one(0xF1BF), "IdBC", mfloat },
+{"fblel", one(0xF095), one(0xF1BF), "IdBC", mfloat },
+{"fbltl", one(0xF094), one(0xF1BF), "IdBC", mfloat },
+{"fbnel", one(0xF08E), one(0xF1BF), "IdBC", mfloat },
+{"fbngel", one(0xF09C), one(0xF1BF), "IdBC", mfloat },
+{"fbngll", one(0xF099), one(0xF1BF), "IdBC", mfloat },
+{"fbnglel", one(0xF098), one(0xF1BF), "IdBC", mfloat },
+{"fbngtl", one(0xF09D), one(0xF1BF), "IdBC", mfloat },
+{"fbnlel", one(0xF09A), one(0xF1BF), "IdBC", mfloat },
+{"fbnltl", one(0xF09B), one(0xF1BF), "IdBC", mfloat },
+{"fbogel", one(0xF083), one(0xF1BF), "IdBC", mfloat },
+{"fbogll", one(0xF086), one(0xF1BF), "IdBC", mfloat },
+{"fbogtl", one(0xF082), one(0xF1BF), "IdBC", mfloat },
+{"fbolel", one(0xF085), one(0xF1BF), "IdBC", mfloat },
+{"fboltl", one(0xF084), one(0xF1BF), "IdBC", mfloat },
+{"fborl", one(0xF087), one(0xF1BF), "IdBC", mfloat },
+{"fbseql", one(0xF091), one(0xF1BF), "IdBC", mfloat },
+{"fbsfl", one(0xF090), one(0xF1BF), "IdBC", mfloat },
+{"fbsnel", one(0xF09E), one(0xF1BF), "IdBC", mfloat },
+{"fbstl", one(0xF09F), one(0xF1BF), "IdBC", mfloat },
+{"fbtl", one(0xF08F), one(0xF1BF), "IdBC", mfloat },
+{"fbueql", one(0xF089), one(0xF1BF), "IdBC", mfloat },
+{"fbugel", one(0xF08B), one(0xF1BF), "IdBC", mfloat },
+{"fbugtl", one(0xF08A), one(0xF1BF), "IdBC", mfloat },
+{"fbulel", one(0xF08D), one(0xF1BF), "IdBC", mfloat },
+{"fbultl", one(0xF08C), one(0xF1BF), "IdBC", mfloat },
+{"fbunl", one(0xF088), one(0xF1BF), "IdBC", mfloat },
+
+{"fcmpb", two(0xF000, 0x5838), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fcmpd", two(0xF000, 0x5438), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fcmpl", two(0xF000, 0x4038), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fcmpp", two(0xF000, 0x4C38), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fcmps", two(0xF000, 0x4438), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fcmpw", two(0xF000, 0x5038), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fcmpx", two(0xF000, 0x4838), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+/* {"fcmpx", two(0xF000, 0x0038), two(0xF1C0, 0xE07F), "IiFt", mfloat }, JF removed */
+
+{"fcosb", two(0xF000, 0x581D), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fcosd", two(0xF000, 0x541D), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fcosl", two(0xF000, 0x401D), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fcosp", two(0xF000, 0x4C1D), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fcoss", two(0xF000, 0x441D), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fcosw", two(0xF000, 0x501D), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fcosx", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fcosx", two(0xF000, 0x481D), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fcosx", two(0xF000, 0x001D), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fcoshb", two(0xF000, 0x5819), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fcoshd", two(0xF000, 0x5419), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fcoshl", two(0xF000, 0x4019), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fcoshp", two(0xF000, 0x4C19), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fcoshs", two(0xF000, 0x4419), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fcoshw", two(0xF000, 0x5019), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fcoshx", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fcoshx", two(0xF000, 0x4819), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fcoshx", two(0xF000, 0x0019), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fdbeq", two(0xF048, 0x0001), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbf", two(0xF048, 0x0000), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbge", two(0xF048, 0x0013), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbgl", two(0xF048, 0x0016), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbgle", two(0xF048, 0x0017), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbgt", two(0xF048, 0x0012), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdble", two(0xF048, 0x0015), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdblt", two(0xF048, 0x0014), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbne", two(0xF048, 0x000E), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbnge", two(0xF048, 0x001C), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbngl", two(0xF048, 0x0019), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbngle", two(0xF048, 0x0018), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbngt", two(0xF048, 0x001D), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbnle", two(0xF048, 0x001A), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbnlt", two(0xF048, 0x001B), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdboge", two(0xF048, 0x0003), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbogl", two(0xF048, 0x0006), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbogt", two(0xF048, 0x0002), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbole", two(0xF048, 0x0005), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbolt", two(0xF048, 0x0004), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbor", two(0xF048, 0x0007), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbseq", two(0xF048, 0x0011), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbsf", two(0xF048, 0x0010), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbsne", two(0xF048, 0x001E), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbst", two(0xF048, 0x001F), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbt", two(0xF048, 0x000F), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbueq", two(0xF048, 0x0009), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbuge", two(0xF048, 0x000B), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbugt", two(0xF048, 0x000A), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbule", two(0xF048, 0x000D), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbult", two(0xF048, 0x000C), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+{"fdbun", two(0xF048, 0x0008), two(0xF1F8, 0xFFFF), "IiDsBw", mfloat },
+
+{"fdivb", two(0xF000, 0x5820), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fdivd", two(0xF000, 0x5420), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fdivl", two(0xF000, 0x4020), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fdivp", two(0xF000, 0x4C20), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fdivs", two(0xF000, 0x4420), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fdivw", two(0xF000, 0x5020), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fdivx", two(0xF000, 0x4820), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+/* {"fdivx", two(0xF000, 0x0020), two(0xF1C0, 0xE07F), "IiFt", mfloat }, JF */
+
+{"fsdivb", two(0xF000, 0x5860), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fsdivd", two(0xF000, 0x5460), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fsdivl", two(0xF000, 0x4060), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fsdivp", two(0xF000, 0x4C60), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fsdivs", two(0xF000, 0x4460), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fsdivw", two(0xF000, 0x5060), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fsdivx", two(0xF000, 0x0060), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fsdivx", two(0xF000, 0x4860), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+/* {"fsdivx", two(0xF000, 0x0060), two(0xF1C0, 0xE07F), "IiFt", m68040 }, JF */
+
+{"fddivb", two(0xF000, 0x5864), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fddivd", two(0xF000, 0x5464), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fddivl", two(0xF000, 0x4064), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fddivp", two(0xF000, 0x4C64), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fddivs", two(0xF000, 0x4464), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fddivw", two(0xF000, 0x5064), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fddivx", two(0xF000, 0x0064), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fddivx", two(0xF000, 0x4864), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+/* {"fddivx", two(0xF000, 0x0064), two(0xF1C0, 0xE07F), "IiFt", m68040 }, JF */
+
+{"fetoxb", two(0xF000, 0x5810), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fetoxd", two(0xF000, 0x5410), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fetoxl", two(0xF000, 0x4010), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fetoxp", two(0xF000, 0x4C10), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fetoxs", two(0xF000, 0x4410), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fetoxw", two(0xF000, 0x5010), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fetoxx", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fetoxx", two(0xF000, 0x4810), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fetoxx", two(0xF000, 0x0010), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fetoxm1b", two(0xF000, 0x5808), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fetoxm1d", two(0xF000, 0x5408), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fetoxm1l", two(0xF000, 0x4008), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fetoxm1p", two(0xF000, 0x4C08), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fetoxm1s", two(0xF000, 0x4408), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fetoxm1w", two(0xF000, 0x5008), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fetoxm1x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fetoxm1x", two(0xF000, 0x4808), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fetoxm1x", two(0xF000, 0x0008), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fgetexpb", two(0xF000, 0x581E), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fgetexpd", two(0xF000, 0x541E), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fgetexpl", two(0xF000, 0x401E), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fgetexpp", two(0xF000, 0x4C1E), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fgetexps", two(0xF000, 0x441E), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fgetexpw", two(0xF000, 0x501E), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fgetexpx", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fgetexpx", two(0xF000, 0x481E), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fgetexpx", two(0xF000, 0x001E), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fgetmanb", two(0xF000, 0x581F), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fgetmand", two(0xF000, 0x541F), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fgetmanl", two(0xF000, 0x401F), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fgetmanp", two(0xF000, 0x4C1F), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fgetmans", two(0xF000, 0x441F), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fgetmanw", two(0xF000, 0x501F), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fgetmanx", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fgetmanx", two(0xF000, 0x481F), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fgetmanx", two(0xF000, 0x001F), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fintb", two(0xF000, 0x5801), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fintd", two(0xF000, 0x5401), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fintl", two(0xF000, 0x4001), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fintp", two(0xF000, 0x4C01), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fints", two(0xF000, 0x4401), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fintw", two(0xF000, 0x5001), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fintx", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fintx", two(0xF000, 0x4801), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fintx", two(0xF000, 0x0001), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fintrzb", two(0xF000, 0x5803), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fintrzd", two(0xF000, 0x5403), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fintrzl", two(0xF000, 0x4003), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fintrzp", two(0xF000, 0x4C03), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fintrzs", two(0xF000, 0x4403), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fintrzw", two(0xF000, 0x5003), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fintrzx", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fintrzx", two(0xF000, 0x4803), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fintrzx", two(0xF000, 0x0003), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"flog10b", two(0xF000, 0x5815), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"flog10d", two(0xF000, 0x5415), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"flog10l", two(0xF000, 0x4015), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"flog10p", two(0xF000, 0x4C15), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"flog10s", two(0xF000, 0x4415), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"flog10w", two(0xF000, 0x5015), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"flog10x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"flog10x", two(0xF000, 0x4815), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"flog10x", two(0xF000, 0x0015), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"flog2b", two(0xF000, 0x5816), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"flog2d", two(0xF000, 0x5416), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"flog2l", two(0xF000, 0x4016), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"flog2p", two(0xF000, 0x4C16), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"flog2s", two(0xF000, 0x4416), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"flog2w", two(0xF000, 0x5016), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"flog2x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"flog2x", two(0xF000, 0x4816), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"flog2x", two(0xF000, 0x0016), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"flognb", two(0xF000, 0x5814), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"flognd", two(0xF000, 0x5414), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"flognl", two(0xF000, 0x4014), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"flognp", two(0xF000, 0x4C14), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"flogns", two(0xF000, 0x4414), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"flognw", two(0xF000, 0x5014), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"flognx", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"flognx", two(0xF000, 0x4814), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"flognx", two(0xF000, 0x0014), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"flognp1b", two(0xF000, 0x5806), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"flognp1d", two(0xF000, 0x5406), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"flognp1l", two(0xF000, 0x4006), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"flognp1p", two(0xF000, 0x4C06), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"flognp1s", two(0xF000, 0x4406), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"flognp1w", two(0xF000, 0x5006), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"flognp1x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"flognp1x", two(0xF000, 0x4806), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"flognp1x", two(0xF000, 0x0006), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fmodb", two(0xF000, 0x5821), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fmodd", two(0xF000, 0x5421), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fmodl", two(0xF000, 0x4021), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fmodp", two(0xF000, 0x4C21), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fmods", two(0xF000, 0x4421), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fmodw", two(0xF000, 0x5021), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fmodx", two(0xF000, 0x4821), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+/* {"fmodx", two(0xF000, 0x0021), two(0xF1C0, 0xE07F), "IiFt", mfloat }, JF */
+
+{"fmoveb", two(0xF000, 0x5800), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmoveb", two(0xF000, 0x7800), two(0xF1C0, 0xFC7F), "IiF7@b", mfloat }, /* fmove from fp<n> to <ea> */
+{"fmoved", two(0xF000, 0x5400), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmoved", two(0xF000, 0x7400), two(0xF1C0, 0xFC7F), "IiF7@F", mfloat }, /* fmove from fp<n> to <ea> */
+{"fmovel", two(0xF000, 0x4000), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmovel", two(0xF000, 0x6000), two(0xF1C0, 0xFC7F), "IiF7@l", mfloat }, /* fmove from fp<n> to <ea> */
+/* Warning: The addressing modes on these are probably not right:
+ esp, Areg direct is only allowed for FPI */
+ /* fmove.l from/to system control registers: */
+{"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s", mfloat },
+{"fmovel", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ls8", mfloat },
+
+/* {"fmovel", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s", mfloat },
+{"fmovel", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*ss8", mfloat }, */
+
+{"fmovep", two(0xF000, 0x4C00), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmovep", two(0xF000, 0x6C00), two(0xF1C0, 0xFC00), "IiF7@pkC", mfloat }, /* fmove.p with k-factors: */
+{"fmovep", two(0xF000, 0x7C00), two(0xF1C0, 0xFC0F), "IiF7@pDk", mfloat }, /* fmove.p with k-factors: */
+
+{"fmoves", two(0xF000, 0x4400), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmoves", two(0xF000, 0x6400), two(0xF1C0, 0xFC7F), "IiF7@f", mfloat }, /* fmove from fp<n> to <ea> */
+{"fmovew", two(0xF000, 0x5000), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmovew", two(0xF000, 0x7000), two(0xF1C0, 0xFC7F), "IiF7@w", mfloat }, /* fmove from fp<n> to <ea> */
+{"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiF8F7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmovex", two(0xF000, 0x4800), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat }, /* fmove from <ea> to fp<n> */
+{"fmovex", two(0xF000, 0x6800), two(0xF1C0, 0xFC7F), "IiF7@x", mfloat }, /* fmove from fp<n> to <ea> */
+/* JF removed {"fmovex", two(0xF000, 0x0000), two(0xF1C0, 0xE07F), "IiFt", mfloat }, / * fmove from <ea> to fp<n> */
+
+{"fsmoveb", two(0xF000, 0x5840), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fsmoved", two(0xF000, 0x5440), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fsmovel", two(0xF000, 0x4040), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fsmoves", two(0xF000, 0x4440), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fsmovew", two(0xF000, 0x5040), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fsmovex", two(0xF000, 0x0040), two(0xF1C0, 0xE07F), "IiF8F7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fsmovex", two(0xF000, 0x4840), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 }, /* fmove from <ea> to fp<n> */
+/* JF removed {"fsmovex", two(0xF000, 0x0040), two(0xF1C0, 0xE07F), "IiFt", m68040 }, / * fmove from <ea> to fp<n> */
+
+{"fdmoveb", two(0xF000, 0x5844), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fdmoved", two(0xF000, 0x5444), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fdmovel", two(0xF000, 0x4044), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fdmoves", two(0xF000, 0x4444), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fdmovew", two(0xF000, 0x5044), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fdmovex", two(0xF000, 0x0044), two(0xF1C0, 0xE07F), "IiF8F7", m68040 }, /* fmove from <ea> to fp<n> */
+{"fdmovex", two(0xF000, 0x4844), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 }, /* fmove from <ea> to fp<n> */
+/* JF removed {"fdmovex", two(0xF000, 0x0044), two(0xF1C0, 0xE07F), "IiFt", m68040 }, / * fmove from <ea> to fp<n> */
+
+{"fmovecrx", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7", mfloat }, /* fmovecr.x #ccc, FPn */
+{"fmovecr", two(0xF000, 0x5C00), two(0xF1FF, 0xFC00), "Ii#CF7", mfloat },
+
+/* Other fmovemx. */
+{"fmovemx", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s", mfloat }, /* reg to control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk", mfloat }, /* from control to reg, static and dynamic: */
+
+{"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s", mfloat }, /* to control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s", mfloat }, /* to control, static and dynamic: */
+
+{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3", mfloat }, /* from control, static and dynamic: */
+{"fmovemx", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3", mfloat }, /* from control, static and dynamic: */
+
+{"fmovemx", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s", mfloat }, /* reg to autodecrement, static and dynamic */
+{"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s", mfloat }, /* to autodecrement, static and dynamic */
+{"fmovemx", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s", mfloat }, /* to autodecrement, static and dynamic */
+
+{"fmovemx", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk", mfloat }, /* from autoinc to reg, static and dynamic: */
+{"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3", mfloat }, /* from autoincrement, static and dynamic: */
+{"fmovemx", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3", mfloat }, /* from autoincrement, static and dynamic: */
+
+{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s", mfloat },
+{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Ii#8@s", mfloat },
+{"fmoveml", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s", mfloat },
+
+{"fmoveml", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8", mfloat },
+{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*s#8", mfloat },
+{"fmoveml", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8", mfloat },
+
+/* fmovemx with register lists */
+{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "IdL3-s", mfloat }, /* to autodec, static & dynamic */
+{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Idl3&s", mfloat }, /* to control, static and dynamic */
+{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+sl3", mfloat }, /* from autoinc, static & dynamic */
+{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&sl3", mfloat }, /* from control, static and dynamic */
+
+ /* Alternate mnemonics for GNU as and GNU CC */
+{"fmovem", two(0xF020, 0xE000), two(0xF1F8, 0xFF00), "Id#3-s", mfloat }, /* to autodecrement, static and dynamic */
+{"fmovem", two(0xF020, 0xE800), two(0xF1F8, 0xFF8F), "IiDk-s", mfloat }, /* to autodecrement, static and dynamic */
+
+{"fmovem", two(0xF000, 0xF000), two(0xF1C0, 0xFF00), "Id#3&s", mfloat }, /* to control, static and dynamic: */
+{"fmovem", two(0xF000, 0xF800), two(0xF1C0, 0xFF8F), "IiDk&s", mfloat }, /* to control, static and dynamic: */
+
+{"fmovem", two(0xF018, 0xD000), two(0xF1F8, 0xFF00), "Id+s#3", mfloat }, /* from autoincrement, static and dynamic: */
+{"fmovem", two(0xF018, 0xD800), two(0xF1F8, 0xFF8F), "Ii+sDk", mfloat }, /* from autoincrement, static and dynamic: */
+
+{"fmovem", two(0xF000, 0xD000), two(0xF1C0, 0xFF00), "Id&s#3", mfloat }, /* from control, static and dynamic: */
+{"fmovem", two(0xF000, 0xD800), two(0xF1C0, 0xFF8F), "Ii&sDk", mfloat }, /* from control, static and dynamic: */
+
+/* fmoveml a FP-control register */
+{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "Iis8@s", mfloat },
+{"fmovem", two(0xF000, 0x8000), two(0xF1C0, 0xE3FF), "Ii*ss8", mfloat },
+
+/* fmoveml a FP-control reglist */
+{"fmovem", two(0xF000, 0xA000), two(0xF1C0, 0xE3FF), "IiL8@s", mfloat },
+{"fmovem", two(0xF000, 0x8000), two(0xF2C0, 0xE3FF), "Ii*sL8", mfloat },
+
+{"fmulb", two(0xF000, 0x5823), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fmuld", two(0xF000, 0x5423), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fmull", two(0xF000, 0x4023), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fmulp", two(0xF000, 0x4C23), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fmuls", two(0xF000, 0x4423), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fmulw", two(0xF000, 0x5023), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fmulx", two(0xF000, 0x4823), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+/* {"fmulx", two(0xF000, 0x0023), two(0xF1C0, 0xE07F), "IiFt", mfloat }, JF */
+
+{"fsmulb", two(0xF000, 0x5863), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fsmuld", two(0xF000, 0x5463), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fsmull", two(0xF000, 0x4063), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fsmulp", two(0xF000, 0x4C63), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fsmuls", two(0xF000, 0x4463), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fsmulw", two(0xF000, 0x5063), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fsmulx", two(0xF000, 0x0063), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fsmulx", two(0xF000, 0x4863), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+/* {"fsmulx", two(0xF000, 0x0063), two(0xF1C0, 0xE07F), "IiFt", m68040 }, JF */
+
+{"fdmulb", two(0xF000, 0x5867), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fdmuld", two(0xF000, 0x5467), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fdmull", two(0xF000, 0x4067), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fdmulp", two(0xF000, 0x4C67), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fdmuls", two(0xF000, 0x4467), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fdmulw", two(0xF000, 0x5067), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fdmulx", two(0xF000, 0x0067), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fdmulx", two(0xF000, 0x4867), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+/* {"dfmulx", two(0xF000, 0x0067), two(0xF1C0, 0xE07F), "IiFt", m68040 }, JF */
+
+{"fnegb", two(0xF000, 0x581A), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fnegd", two(0xF000, 0x541A), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fnegl", two(0xF000, 0x401A), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fnegp", two(0xF000, 0x4C1A), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fnegs", two(0xF000, 0x441A), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fnegw", two(0xF000, 0x501A), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fnegx", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fnegx", two(0xF000, 0x481A), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fnegx", two(0xF000, 0x001A), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fsnegb", two(0xF000, 0x585A), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fsnegd", two(0xF000, 0x545A), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fsnegl", two(0xF000, 0x405A), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fsnegp", two(0xF000, 0x4C5A), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fsnegs", two(0xF000, 0x445A), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fsnegw", two(0xF000, 0x505A), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fsnegx", two(0xF000, 0x005A), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fsnegx", two(0xF000, 0x485A), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+{"fsnegx", two(0xF000, 0x005A), two(0xF1C0, 0xE07F), "IiFt", m68040 },
+
+{"fdnegb", two(0xF000, 0x585E), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fdnegd", two(0xF000, 0x545E), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fdnegl", two(0xF000, 0x405E), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fdnegp", two(0xF000, 0x4C5E), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fdnegs", two(0xF000, 0x445E), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fdnegw", two(0xF000, 0x505E), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fdnegx", two(0xF000, 0x005E), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fdnegx", two(0xF000, 0x485E), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+{"fdnegx", two(0xF000, 0x005E), two(0xF1C0, 0xE07F), "IiFt", m68040 },
+
+{"fnop", two(0xF280, 0x0000), two(0xFFFF, 0xFFFF), "Ii", mfloat },
+
+{"fremb", two(0xF000, 0x5825), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fremd", two(0xF000, 0x5425), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"freml", two(0xF000, 0x4025), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fremp", two(0xF000, 0x4C25), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"frems", two(0xF000, 0x4425), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fremw", two(0xF000, 0x5025), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fremx", two(0xF000, 0x4825), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+/* {"fremx", two(0xF000, 0x0025), two(0xF1C0, 0xE07F), "IiFt", mfloat }, JF */
+
+{"frestore", one(0xF140), one(0xF1C0), "Id&s", mfloat },
+{"frestore", one(0xF158), one(0xF1F8), "Id+s", mfloat },
+{"fsave", one(0xF100), one(0xF1C0), "Id&s", mfloat },
+{"fsave", one(0xF120), one(0xF1F8), "Id-s", mfloat },
+
+{"fscaleb", two(0xF000, 0x5826), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fscaled", two(0xF000, 0x5426), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fscalel", two(0xF000, 0x4026), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fscalep", two(0xF000, 0x4C26), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fscales", two(0xF000, 0x4426), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fscalew", two(0xF000, 0x5026), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fscalex", two(0xF000, 0x4826), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+/* {"fscalex", two(0xF000, 0x0026), two(0xF1C0, 0xE07F), "IiFt", mfloat }, JF */
+
+/* $ is necessary to prevent the assembler from using PC-relative.
+ If @ were used, "label: fseq label" could produce "ftrapeq",
+ because "label" became "pc@label". */
+{"fseq", two(0xF040, 0x0001), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsf", two(0xF040, 0x0000), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsge", two(0xF040, 0x0013), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsgl", two(0xF040, 0x0016), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsgle", two(0xF040, 0x0017), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsgt", two(0xF040, 0x0012), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsle", two(0xF040, 0x0015), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fslt", two(0xF040, 0x0014), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsne", two(0xF040, 0x000E), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsnge", two(0xF040, 0x001C), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsngl", two(0xF040, 0x0019), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsngle", two(0xF040, 0x0018), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsngt", two(0xF040, 0x001D), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsnle", two(0xF040, 0x001A), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsnlt", two(0xF040, 0x001B), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsoge", two(0xF040, 0x0003), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsogl", two(0xF040, 0x0006), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsogt", two(0xF040, 0x0002), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsole", two(0xF040, 0x0005), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsolt", two(0xF040, 0x0004), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsor", two(0xF040, 0x0007), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsseq", two(0xF040, 0x0011), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fssf", two(0xF040, 0x0010), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fssne", two(0xF040, 0x001E), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsst", two(0xF040, 0x001F), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fst", two(0xF040, 0x000F), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsueq", two(0xF040, 0x0009), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsuge", two(0xF040, 0x000B), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsugt", two(0xF040, 0x000A), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsule", two(0xF040, 0x000D), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsult", two(0xF040, 0x000C), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+{"fsun", two(0xF040, 0x0008), two(0xF1C0, 0xFFFF), "Ii$s", mfloat },
+
+{"fsgldivb", two(0xF000, 0x5824), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fsgldivd", two(0xF000, 0x5424), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fsgldivl", two(0xF000, 0x4024), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fsgldivp", two(0xF000, 0x4C24), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fsgldivs", two(0xF000, 0x4424), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fsgldivw", two(0xF000, 0x5024), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fsgldivx", two(0xF000, 0x4824), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fsgldivx", two(0xF000, 0x0024), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fsglmulb", two(0xF000, 0x5827), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fsglmuld", two(0xF000, 0x5427), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fsglmull", two(0xF000, 0x4027), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fsglmulp", two(0xF000, 0x4C27), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fsglmuls", two(0xF000, 0x4427), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fsglmulw", two(0xF000, 0x5027), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fsglmulx", two(0xF000, 0x4827), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fsglmulx", two(0xF000, 0x0027), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fsinb", two(0xF000, 0x580E), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fsind", two(0xF000, 0x540E), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fsinl", two(0xF000, 0x400E), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fsinp", two(0xF000, 0x4C0E), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fsins", two(0xF000, 0x440E), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fsinw", two(0xF000, 0x500E), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fsinx", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fsinx", two(0xF000, 0x480E), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fsinx", two(0xF000, 0x000E), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fsinhb", two(0xF000, 0x5802), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fsinhd", two(0xF000, 0x5402), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fsinhl", two(0xF000, 0x4002), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fsinhp", two(0xF000, 0x4C02), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fsinhs", two(0xF000, 0x4402), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fsinhw", two(0xF000, 0x5002), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fsinhx", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fsinhx", two(0xF000, 0x4802), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fsinhx", two(0xF000, 0x0002), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fsincosb", two(0xF000, 0x5830), two(0xF1C0, 0xFC78), "Ii;bF3F7", mfloat },
+{"fsincosd", two(0xF000, 0x5430), two(0xF1C0, 0xFC78), "Ii;FF3F7", mfloat },
+{"fsincosl", two(0xF000, 0x4030), two(0xF1C0, 0xFC78), "Ii;lF3F7", mfloat },
+{"fsincosp", two(0xF000, 0x4C30), two(0xF1C0, 0xFC78), "Ii;pF3F7", mfloat },
+{"fsincoss", two(0xF000, 0x4430), two(0xF1C0, 0xFC78), "Ii;fF3F7", mfloat },
+{"fsincosw", two(0xF000, 0x5030), two(0xF1C0, 0xFC78), "Ii;wF3F7", mfloat },
+{"fsincosx", two(0xF000, 0x0030), two(0xF1C0, 0xE078), "IiF8F3F7", mfloat },
+{"fsincosx", two(0xF000, 0x4830), two(0xF1C0, 0xFC78), "Ii;xF3F7", mfloat },
+
+{"fsqrtb", two(0xF000, 0x5804), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fsqrtd", two(0xF000, 0x5404), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fsqrtl", two(0xF000, 0x4004), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fsqrtp", two(0xF000, 0x4C04), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fsqrts", two(0xF000, 0x4404), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fsqrtw", two(0xF000, 0x5004), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fsqrtx", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fsqrtx", two(0xF000, 0x4804), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fsqrtx", two(0xF000, 0x0004), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fssqrtb", two(0xF000, 0x5841), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fssqrtd", two(0xF000, 0x5441), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fssqrtl", two(0xF000, 0x4041), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fssqrtp", two(0xF000, 0x4C41), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fssqrts", two(0xF000, 0x4441), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fssqrtw", two(0xF000, 0x5041), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fssqrtx", two(0xF000, 0x0041), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fssqrtx", two(0xF000, 0x4841), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+{"fssqrtx", two(0xF000, 0x0041), two(0xF1C0, 0xE07F), "IiFt", m68040 },
+
+{"fdsqrtb", two(0xF000, 0x5845), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fdsqrtd", two(0xF000, 0x5445), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fdsqrtl", two(0xF000, 0x4045), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fdsqrtp", two(0xF000, 0x4C45), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fdsqrts", two(0xF000, 0x4445), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fdsqrtw", two(0xF000, 0x5045), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fdsqrtx", two(0xF000, 0x0045), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fdsqrtx", two(0xF000, 0x4845), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+{"fdsqrtx", two(0xF000, 0x0045), two(0xF1C0, 0xE07F), "IiFt", m68040 },
+
+{"fsubb", two(0xF000, 0x5828), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"fsubd", two(0xF000, 0x5428), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"fsubl", two(0xF000, 0x4028), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"fsubp", two(0xF000, 0x4C28), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"fsubs", two(0xF000, 0x4428), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"fsubw", two(0xF000, 0x5028), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"fsubx", two(0xF000, 0x4828), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"fsubx", two(0xF000, 0x0028), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"fssubb", two(0xF000, 0x5868), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fssubd", two(0xF000, 0x5468), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fssubl", two(0xF000, 0x4068), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fssubp", two(0xF000, 0x4C68), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fssubs", two(0xF000, 0x4468), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fssubw", two(0xF000, 0x5068), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fssubx", two(0xF000, 0x0068), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fssubx", two(0xF000, 0x4868), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+{"fssubx", two(0xF000, 0x0068), two(0xF1C0, 0xE07F), "IiFt", m68040 },
+
+{"fdsubb", two(0xF000, 0x586c), two(0xF1C0, 0xFC7F), "Ii;bF7", m68040 },
+{"fdsubd", two(0xF000, 0x546c), two(0xF1C0, 0xFC7F), "Ii;FF7", m68040 },
+{"fdsubl", two(0xF000, 0x406c), two(0xF1C0, 0xFC7F), "Ii;lF7", m68040 },
+{"fdsubp", two(0xF000, 0x4C6c), two(0xF1C0, 0xFC7F), "Ii;pF7", m68040 },
+{"fdsubs", two(0xF000, 0x446c), two(0xF1C0, 0xFC7F), "Ii;fF7", m68040 },
+{"fdsubw", two(0xF000, 0x506c), two(0xF1C0, 0xFC7F), "Ii;wF7", m68040 },
+{"fdsubx", two(0xF000, 0x006c), two(0xF1C0, 0xE07F), "IiF8F7", m68040 },
+{"fdsubx", two(0xF000, 0x486c), two(0xF1C0, 0xFC7F), "Ii;xF7", m68040 },
+{"fdsubx", two(0xF000, 0x006c), two(0xF1C0, 0xE07F), "IiFt", m68040 },
+
+{"ftanb", two(0xF000, 0x580F), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"ftand", two(0xF000, 0x540F), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"ftanl", two(0xF000, 0x400F), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"ftanp", two(0xF000, 0x4C0F), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"ftans", two(0xF000, 0x440F), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"ftanw", two(0xF000, 0x500F), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"ftanx", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"ftanx", two(0xF000, 0x480F), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"ftanx", two(0xF000, 0x000F), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"ftanhb", two(0xF000, 0x5809), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"ftanhd", two(0xF000, 0x5409), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"ftanhl", two(0xF000, 0x4009), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"ftanhp", two(0xF000, 0x4C09), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"ftanhs", two(0xF000, 0x4409), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"ftanhw", two(0xF000, 0x5009), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"ftanhx", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"ftanhx", two(0xF000, 0x4809), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"ftanhx", two(0xF000, 0x0009), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"ftentoxb", two(0xF000, 0x5812), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"ftentoxd", two(0xF000, 0x5412), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"ftentoxl", two(0xF000, 0x4012), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"ftentoxp", two(0xF000, 0x4C12), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"ftentoxs", two(0xF000, 0x4412), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"ftentoxw", two(0xF000, 0x5012), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"ftentoxx", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"ftentoxx", two(0xF000, 0x4812), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"ftentoxx", two(0xF000, 0x0012), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+{"ftrapeq", two(0xF07C, 0x0001), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapf", two(0xF07C, 0x0000), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapge", two(0xF07C, 0x0013), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapgl", two(0xF07C, 0x0016), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapgle", two(0xF07C, 0x0017), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapgt", two(0xF07C, 0x0012), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftraple", two(0xF07C, 0x0015), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftraplt", two(0xF07C, 0x0014), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapne", two(0xF07C, 0x000E), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapnge", two(0xF07C, 0x001C), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapngl", two(0xF07C, 0x0019), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapngle", two(0xF07C, 0x0018), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapngt", two(0xF07C, 0x001D), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapnle", two(0xF07C, 0x001A), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapnlt", two(0xF07C, 0x001B), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapoge", two(0xF07C, 0x0003), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapogl", two(0xF07C, 0x0006), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapogt", two(0xF07C, 0x0002), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapole", two(0xF07C, 0x0005), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapolt", two(0xF07C, 0x0004), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapor", two(0xF07C, 0x0007), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapseq", two(0xF07C, 0x0011), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapsf", two(0xF07C, 0x0010), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapsne", two(0xF07C, 0x001E), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapst", two(0xF07C, 0x001F), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapt", two(0xF07C, 0x000F), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapueq", two(0xF07C, 0x0009), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapuge", two(0xF07C, 0x000B), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapugt", two(0xF07C, 0x000A), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapule", two(0xF07C, 0x000D), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapult", two(0xF07C, 0x000C), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+{"ftrapun", two(0xF07C, 0x0008), two(0xF1FF, 0xFFFF), "Ii", mfloat },
+
+{"ftrapeqw", two(0xF07A, 0x0001), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapfw", two(0xF07A, 0x0000), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapgew", two(0xF07A, 0x0013), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapglw", two(0xF07A, 0x0016), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapglew", two(0xF07A, 0x0017), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapgtw", two(0xF07A, 0x0012), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftraplew", two(0xF07A, 0x0015), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapltw", two(0xF07A, 0x0014), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapnew", two(0xF07A, 0x000E), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapngew", two(0xF07A, 0x001C), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapnglw", two(0xF07A, 0x0019), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapnglew", two(0xF07A, 0x0018), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapngtw", two(0xF07A, 0x001D), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapnlew", two(0xF07A, 0x001A), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapnltw", two(0xF07A, 0x001B), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapogew", two(0xF07A, 0x0003), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapoglw", two(0xF07A, 0x0006), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapogtw", two(0xF07A, 0x0002), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapolew", two(0xF07A, 0x0005), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapoltw", two(0xF07A, 0x0004), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftraporw", two(0xF07A, 0x0007), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapseqw", two(0xF07A, 0x0011), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapsfw", two(0xF07A, 0x0010), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapsnew", two(0xF07A, 0x001E), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapstw", two(0xF07A, 0x001F), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftraptw", two(0xF07A, 0x000F), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapueqw", two(0xF07A, 0x0009), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapugew", two(0xF07A, 0x000B), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapugtw", two(0xF07A, 0x000A), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapulew", two(0xF07A, 0x000D), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapultw", two(0xF07A, 0x000C), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+{"ftrapunw", two(0xF07A, 0x0008), two(0xF1FF, 0xFFFF), "Ii^w", mfloat },
+
+{"ftrapeql", two(0xF07B, 0x0001), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapfl", two(0xF07B, 0x0000), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapgel", two(0xF07B, 0x0013), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapgll", two(0xF07B, 0x0016), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapglel", two(0xF07B, 0x0017), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapgtl", two(0xF07B, 0x0012), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftraplel", two(0xF07B, 0x0015), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapltl", two(0xF07B, 0x0014), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapnel", two(0xF07B, 0x000E), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapngel", two(0xF07B, 0x001C), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapngll", two(0xF07B, 0x0019), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapnglel", two(0xF07B, 0x0018), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapngtl", two(0xF07B, 0x001D), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapnlel", two(0xF07B, 0x001A), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapnltl", two(0xF07B, 0x001B), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapogel", two(0xF07B, 0x0003), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapogll", two(0xF07B, 0x0006), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapogtl", two(0xF07B, 0x0002), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapolel", two(0xF07B, 0x0005), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapoltl", two(0xF07B, 0x0004), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftraporl", two(0xF07B, 0x0007), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapseql", two(0xF07B, 0x0011), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapsfl", two(0xF07B, 0x0010), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapsnel", two(0xF07B, 0x001E), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapstl", two(0xF07B, 0x001F), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftraptl", two(0xF07B, 0x000F), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapueql", two(0xF07B, 0x0009), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapugel", two(0xF07B, 0x000B), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapugtl", two(0xF07B, 0x000A), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapulel", two(0xF07B, 0x000D), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapultl", two(0xF07B, 0x000C), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+{"ftrapunl", two(0xF07B, 0x0008), two(0xF1FF, 0xFFFF), "Ii^l", mfloat },
+
+{"ftstb", two(0xF000, 0x583A), two(0xF1C0, 0xFC7F), "Ii;b", mfloat },
+{"ftstd", two(0xF000, 0x543A), two(0xF1C0, 0xFC7F), "Ii;F", mfloat },
+{"ftstl", two(0xF000, 0x403A), two(0xF1C0, 0xFC7F), "Ii;l", mfloat },
+{"ftstp", two(0xF000, 0x4C3A), two(0xF1C0, 0xFC7F), "Ii;p", mfloat },
+{"ftsts", two(0xF000, 0x443A), two(0xF1C0, 0xFC7F), "Ii;f", mfloat },
+{"ftstw", two(0xF000, 0x503A), two(0xF1C0, 0xFC7F), "Ii;w", mfloat },
+{"ftstx", two(0xF000, 0x003A), two(0xF1C0, 0xE07F), "IiF8", mfloat },
+{"ftstx", two(0xF000, 0x483A), two(0xF1C0, 0xFC7F), "Ii;x", mfloat },
+
+{"ftwotoxb", two(0xF000, 0x5811), two(0xF1C0, 0xFC7F), "Ii;bF7", mfloat },
+{"ftwotoxd", two(0xF000, 0x5411), two(0xF1C0, 0xFC7F), "Ii;FF7", mfloat },
+{"ftwotoxl", two(0xF000, 0x4011), two(0xF1C0, 0xFC7F), "Ii;lF7", mfloat },
+{"ftwotoxp", two(0xF000, 0x4C11), two(0xF1C0, 0xFC7F), "Ii;pF7", mfloat },
+{"ftwotoxs", two(0xF000, 0x4411), two(0xF1C0, 0xFC7F), "Ii;fF7", mfloat },
+{"ftwotoxw", two(0xF000, 0x5011), two(0xF1C0, 0xFC7F), "Ii;wF7", mfloat },
+{"ftwotoxx", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiF8F7", mfloat },
+{"ftwotoxx", two(0xF000, 0x4811), two(0xF1C0, 0xFC7F), "Ii;xF7", mfloat },
+{"ftwotoxx", two(0xF000, 0x0011), two(0xF1C0, 0xE07F), "IiFt", mfloat },
+
+/* Variable-sized float branches */
+
+{"fjeq", one(0xF081), one(0xF1FF), "IdBc", mfloat },
+{"fjf", one(0xF080), one(0xF1FF), "IdBc", mfloat },
+{"fjge", one(0xF093), one(0xF1FF), "IdBc", mfloat },
+{"fjgl", one(0xF096), one(0xF1FF), "IdBc", mfloat },
+{"fjgle", one(0xF097), one(0xF1FF), "IdBc", mfloat },
+{"fjgt", one(0xF092), one(0xF1FF), "IdBc", mfloat },
+{"fjle", one(0xF095), one(0xF1FF), "IdBc", mfloat },
+{"fjlt", one(0xF094), one(0xF1FF), "IdBc", mfloat },
+{"fjne", one(0xF08E), one(0xF1FF), "IdBc", mfloat },
+{"fjnge", one(0xF09C), one(0xF1FF), "IdBc", mfloat },
+{"fjngl", one(0xF099), one(0xF1FF), "IdBc", mfloat },
+{"fjngle", one(0xF098), one(0xF1FF), "IdBc", mfloat },
+{"fjngt", one(0xF09D), one(0xF1FF), "IdBc", mfloat },
+{"fjnle", one(0xF09A), one(0xF1FF), "IdBc", mfloat },
+{"fjnlt", one(0xF09B), one(0xF1FF), "IdBc", mfloat },
+{"fjoge", one(0xF083), one(0xF1FF), "IdBc", mfloat },
+{"fjogl", one(0xF086), one(0xF1FF), "IdBc", mfloat },
+{"fjogt", one(0xF082), one(0xF1FF), "IdBc", mfloat },
+{"fjole", one(0xF085), one(0xF1FF), "IdBc", mfloat },
+{"fjolt", one(0xF084), one(0xF1FF), "IdBc", mfloat },
+{"fjor", one(0xF087), one(0xF1FF), "IdBc", mfloat },
+{"fjseq", one(0xF091), one(0xF1FF), "IdBc", mfloat },
+{"fjsf", one(0xF090), one(0xF1FF), "IdBc", mfloat },
+{"fjsne", one(0xF09E), one(0xF1FF), "IdBc", mfloat },
+{"fjst", one(0xF09F), one(0xF1FF), "IdBc", mfloat },
+{"fjt", one(0xF08F), one(0xF1FF), "IdBc", mfloat },
+{"fjueq", one(0xF089), one(0xF1FF), "IdBc", mfloat },
+{"fjuge", one(0xF08B), one(0xF1FF), "IdBc", mfloat },
+{"fjugt", one(0xF08A), one(0xF1FF), "IdBc", mfloat },
+{"fjule", one(0xF08D), one(0xF1FF), "IdBc", mfloat },
+{"fjult", one(0xF08C), one(0xF1FF), "IdBc", mfloat },
+{"fjun", one(0xF088), one(0xF1FF), "IdBc", mfloat },
+/* float stuff ends here */
+
+{"illegal", one(0045374), one(0177777), "", m68000up },
+{"jmp", one(0047300), one(0177700), "!s", m68000up },
+{"jsr", one(0047200), one(0177700), "!s", m68000up },
+{"lea", one(0040700), one(0170700), "!sAd", m68000up },
+{"linkw", one(0047120), one(0177770), "As#w", m68000up },
+{"linkl", one(0044010), one(0177770), "As#l", m68020up },
+{"link", one(0047120), one(0177770), "As#w", m68000up },
+{"link", one(0044010), one(0177770), "As#l", m68020up },
+
+{"lslb", one(0160410), one(0170770), "QdDs", m68000up }, /* lsrb #Q, Ds */
+{"lslb", one(0160450), one(0170770), "DdDs", m68000up }, /* lsrb Dd, Ds */
+{"lslw", one(0160510), one(0170770), "QdDs", m68000up }, /* lsrb #Q, Ds */
+{"lslw", one(0160550), one(0170770), "DdDs", m68000up }, /* lsrb Dd, Ds */
+{"lslw", one(0161700), one(0177700), "~s", m68000up }, /* Shift memory */
+{"lsll", one(0160610), one(0170770), "QdDs", m68000up }, /* lsrb #Q, Ds */
+{"lsll", one(0160650), one(0170770), "DdDs", m68000up }, /* lsrb Dd, Ds */
+
+{"lsrb", one(0160010), one(0170770), "QdDs", m68000up }, /* lsrb #Q, Ds */
+{"lsrb", one(0160050), one(0170770), "DdDs", m68000up }, /* lsrb Dd, Ds */
+{"lsrl", one(0160210), one(0170770), "QdDs", m68000up }, /* lsrb #Q, Ds */
+{"lsrl", one(0160250), one(0170770), "DdDs", m68000up }, /* lsrb #Q, Ds */
+{"lsrw", one(0160110), one(0170770), "QdDs", m68000up }, /* lsrb #Q, Ds */
+{"lsrw", one(0160150), one(0170770), "DdDs", m68000up }, /* lsrb #Q, Ds */
+{"lsrw", one(0161300), one(0177700), "~s", m68000up }, /* Shift memory */
+
+{"moveal", one(0020100), one(0170700), "*lAd", m68000up },
+{"moveaw", one(0030100), one(0170700), "*wAd", m68000up },
+{"moveb", one(0010000), one(0170000), ";b$d", m68000up }, /* move */
+{"movel", one(0070000), one(0170400), "MsDd", m68000up }, /* moveq written as move */
+{"movel", one(0020000), one(0170000), "*l$d", m68000up },
+{"movel", one(0020100), one(0170700), "*lAd", m68000up },
+{"movel", one(0047140), one(0177770), "AsUd", m68000up }, /* move to USP */
+{"movel", one(0047150), one(0177770), "UdAs", m68000up }, /* move from USP */
+
+{"movec", one(0047173), one(0177777), "R1Jj", m68010up },
+{"movec", one(0047173), one(0177777), "R1#j", m68010up },
+{"movec", one(0047172), one(0177777), "JjR1", m68010up },
+{"movec", one(0047172), one(0177777), "#jR1", m68010up },
+
+/* JF added these next four for the assembler */
+{"moveml", one(0044300), one(0177700), "Lw&s", m68000up }, /* movem reg to mem. */
+{"moveml", one(0044340), one(0177770), "lw-s", m68000up }, /* movem reg to autodecrement. */
+{"moveml", one(0046300), one(0177700), "!sLw", m68000up }, /* movem mem to reg. */
+{"moveml", one(0046330), one(0177770), "+sLw", m68000up }, /* movem autoinc to reg. */
+
+{"moveml", one(0044300), one(0177700), "#w&s", m68000up }, /* movem reg to mem. */
+{"moveml", one(0044340), one(0177770), "#w-s", m68000up }, /* movem reg to autodecrement. */
+{"moveml", one(0046300), one(0177700), "!s#w", m68000up }, /* movem mem to reg. */
+{"moveml", one(0046330), one(0177770), "+s#w", m68000up }, /* movem autoinc to reg. */
+
+/* JF added these next four for the assembler */
+{"movemw", one(0044200), one(0177700), "Lw&s", m68000up }, /* movem reg to mem. */
+{"movemw", one(0044240), one(0177770), "lw-s", m68000up }, /* movem reg to autodecrement. */
+{"movemw", one(0046200), one(0177700), "!sLw", m68000up }, /* movem mem to reg. */
+{"movemw", one(0046230), one(0177770), "+sLw", m68000up }, /* movem autoinc to reg. */
+
+{"movemw", one(0044200), one(0177700), "#w&s", m68000up }, /* movem reg to mem. */
+{"movemw", one(0044240), one(0177770), "#w-s", m68000up }, /* movem reg to autodecrement. */
+{"movemw", one(0046200), one(0177700), "!s#w", m68000up }, /* movem mem to reg. */
+{"movemw", one(0046230), one(0177770), "+s#w", m68000up }, /* movem autoinc to reg. */
+
+{"movepl", one(0000510), one(0170770), "dsDd", m68000up }, /* memory to register */
+{"movepl", one(0000710), one(0170770), "Ddds", m68000up }, /* register to memory */
+{"movepw", one(0000410), one(0170770), "dsDd", m68000up }, /* memory to register */
+{"movepw", one(0000610), one(0170770), "Ddds", m68000up }, /* register to memory */
+{"moveq", one(0070000), one(0170400), "MsDd", m68000up },
+{"movew", one(0030000), one(0170000), "*w$d", m68000up },
+{"movew", one(0030100), one(0170700), "*wAd", m68000up }, /* movea, written as move */
+{"movew", one(0040300), one(0177700), "Ss$s", m68000up }, /* Move from sr */
+{"movew", one(0041300), one(0177700), "Cs$s", m68010up }, /* Move from ccr */
+{"movew", one(0042300), one(0177700), ";wCd", m68000up }, /* move to ccr */
+{"movew", one(0043300), one(0177700), ";wSd", m68000up }, /* move to sr */
+
+{"movesb", two(0007000, 0), two(0177700, 07777), "~sR1", m68010up }, /* moves from memory */
+{"movesb", two(0007000, 04000), two(0177700, 07777), "R1~s", m68010up }, /* moves to memory */
+{"movesl", two(0007200, 0), two(0177700, 07777), "~sR1", m68010up }, /* moves from memory */
+{"movesl", two(0007200, 04000), two(0177700, 07777), "R1~s", m68010up }, /* moves to memory */
+{"movesw", two(0007100, 0), two(0177700, 07777), "~sR1", m68010up }, /* moves from memory */
+{"movesw", two(0007100, 04000), two(0177700, 07777), "R1~s", m68010up }, /* moves to memory */
+
+{"move16", two(0xf620, 0x8000), two(0xfff8, 0x8fff), "+s+1", m68040 },
+{"move16", one(0xf600), one(0xfff8), "+s_L", m68040 },
+{"move16", one(0xf608), one(0xfff8), "_L+s", m68040 },
+{"move16", one(0xf610), one(0xfff8), "as_L", m68040 },
+{"move16", one(0xf618), one(0xfff8), "_Las", m68040 },
+
+{"mulsl", two(0046000, 004000), two(0177700, 0107770), ";lD1", m68020up },
+{"mulsl", two(0046000, 006000), two(0177700, 0107770), ";lD3D1", m68020up },
+{"mulsw", one(0140700), one(0170700), ";wDd", m68000up },
+{"muls", one(0140700), one(0170700), ";wDd", m68000up },
+{"mulul", two(0046000, 000000), two(0177700, 0107770), ";lD1", m68020up },
+{"mulul", two(0046000, 002000), two(0177700, 0107770), ";lD3D1", m68020up },
+{"muluw", one(0140300), one(0170700), ";wDd", m68000up },
+{"mulu", one(0140300), one(0170700), ";wDd", m68000up },
+{"nbcd", one(0044000), one(0177700), "$s", m68000up },
+{"negb", one(0042000), one(0177700), "$s", m68000up },
+{"negl", one(0042200), one(0177700), "$s", m68000up },
+{"negw", one(0042100), one(0177700), "$s", m68000up },
+{"negxb", one(0040000), one(0177700), "$s", m68000up },
+{"negxl", one(0040200), one(0177700), "$s", m68000up },
+{"negxw", one(0040100), one(0177700), "$s", m68000up },
+{"nop", one(0047161), one(0177777), "", m68000up },
+{"notb", one(0043000), one(0177700), "$s", m68000up },
+{"notl", one(0043200), one(0177700), "$s", m68000up },
+{"notw", one(0043100), one(0177700), "$s", m68000up },
+
+{"orb", one(0000000), one(0177700), "#b$s", m68000up }, /* ori written as or */
+{"orb", one(0000074), one(0177777), "#bCs", m68000up }, /* ori to ccr */
+{"orb", one(0100000), one(0170700), ";bDd", m68000up }, /* memory to register */
+{"orb", one(0100400), one(0170700), "Dd~s", m68000up }, /* register to memory */
+{"orib", one(0000000), one(0177700), "#b$s", m68000up },
+{"orib", one(0000074), one(0177777), "#bCs", m68000up }, /* ori to ccr */
+{"oril", one(0000200), one(0177700), "#l$s", m68000up },
+{"oriw", one(0000100), one(0177700), "#w$s", m68000up },
+{"oriw", one(0000174), one(0177777), "#wSs", m68000up }, /* ori to sr */
+{"orl", one(0000200), one(0177700), "#l$s", m68000up },
+{"orl", one(0100200), one(0170700), ";lDd", m68000up }, /* memory to register */
+{"orl", one(0100600), one(0170700), "Dd~s", m68000up }, /* register to memory */
+{"orw", one(0000100), one(0177700), "#w$s", m68000up },
+{"orw", one(0000174), one(0177777), "#wSs", m68000up }, /* ori to sr */
+{"orw", one(0100100), one(0170700), ";wDd", m68000up }, /* memory to register */
+{"orw", one(0100500), one(0170700), "Dd~s", m68000up }, /* register to memory */
+
+{"pack", one(0100500), one(0170770), "DsDd#w", m68020up }, /* pack Ds, Dd, #w */
+{"pack", one(0100510), one(0170770), "-s-d#w", m68020up }, /* pack -(As), -(Ad), #w */
+
+#ifndef NO_68851
+{"pbac", one(0xf0c7), one(0xffbf), "Bc", m68851 },
+{"pbacw", one(0xf087), one(0xffbf), "Bc", m68851 },
+{"pbas", one(0xf0c6), one(0xffbf), "Bc", m68851 },
+{"pbasw", one(0xf086), one(0xffbf), "Bc", m68851 },
+{"pbbc", one(0xf0c1), one(0xffbf), "Bc", m68851 },
+{"pbbcw", one(0xf081), one(0xffbf), "Bc", m68851 },
+{"pbbs", one(0xf0c0), one(0xffbf), "Bc", m68851 },
+{"pbbsw", one(0xf080), one(0xffbf), "Bc", m68851 },
+{"pbcc", one(0xf0cf), one(0xffbf), "Bc", m68851 },
+{"pbccw", one(0xf08f), one(0xffbf), "Bc", m68851 },
+{"pbcs", one(0xf0ce), one(0xffbf), "Bc", m68851 },
+{"pbcsw", one(0xf08e), one(0xffbf), "Bc", m68851 },
+{"pbgc", one(0xf0cd), one(0xffbf), "Bc", m68851 },
+{"pbgcw", one(0xf08d), one(0xffbf), "Bc", m68851 },
+{"pbgs", one(0xf0cc), one(0xffbf), "Bc", m68851 },
+{"pbgsw", one(0xf08c), one(0xffbf), "Bc", m68851 },
+{"pbic", one(0xf0cb), one(0xffbf), "Bc", m68851 },
+{"pbicw", one(0xf08b), one(0xffbf), "Bc", m68851 },
+{"pbis", one(0xf0ca), one(0xffbf), "Bc", m68851 },
+{"pbisw", one(0xf08a), one(0xffbf), "Bc", m68851 },
+{"pblc", one(0xf0c3), one(0xffbf), "Bc", m68851 },
+{"pblcw", one(0xf083), one(0xffbf), "Bc", m68851 },
+{"pbls", one(0xf0c2), one(0xffbf), "Bc", m68851 },
+{"pblsw", one(0xf082), one(0xffbf), "Bc", m68851 },
+{"pbsc", one(0xf0c5), one(0xffbf), "Bc", m68851 },
+{"pbscw", one(0xf085), one(0xffbf), "Bc", m68851 },
+{"pbss", one(0xf0c4), one(0xffbf), "Bc", m68851 },
+{"pbssw", one(0xf084), one(0xffbf), "Bc", m68851 },
+{"pbwc", one(0xf0c9), one(0xffbf), "Bc", m68851 },
+{"pbwcw", one(0xf089), one(0xffbf), "Bc", m68851 },
+{"pbws", one(0xf0c8), one(0xffbf), "Bc", m68851 },
+{"pbwsw", one(0xf088), one(0xffbf), "Bc", m68851 },
+
+{"pdbac", two(0xf048, 0x0007), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbas", two(0xf048, 0x0006), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbbc", two(0xf048, 0x0001), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbbs", two(0xf048, 0x0000), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbcc", two(0xf048, 0x000f), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbcs", two(0xf048, 0x000e), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbgc", two(0xf048, 0x000d), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbgs", two(0xf048, 0x000c), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbic", two(0xf048, 0x000b), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbis", two(0xf048, 0x000a), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdblc", two(0xf048, 0x0003), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbls", two(0xf048, 0x0002), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbsc", two(0xf048, 0x0005), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbss", two(0xf048, 0x0004), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbwc", two(0xf048, 0x0009), two(0xfff8, 0xffff), "DsBw", m68851 },
+{"pdbws", two(0xf048, 0x0008), two(0xfff8, 0xffff), "DsBw", m68851 },
+#endif /* NO_68851 */
+
+{"pea", one(0044100), one(0177700), "!s", m68000up },
+
+#ifndef NO_68851
+{"pflusha", two(0xf000, 0x2400), two(0xffff, 0xffff), "", m68030 | m68851 },
+{"pflusha", one(0xf518), one(0xfff8), "", m68040 },
+
+{"pflush", two(0xf000, 0x3010), two(0xffc0, 0xfe10), "T3T9", m68030 | m68851 },
+{"pflush", two(0xf000, 0x3810), two(0xffc0, 0xfe10), "T3T9&s", m68030 | m68851 },
+{"pflush", two(0xf000, 0x3008), two(0xffc0, 0xfe18), "D3T9", m68030 | m68851 },
+{"pflush", two(0xf000, 0x3808), two(0xffc0, 0xfe18), "D3T9&s", m68030 | m68851 },
+{"pflush", two(0xf000, 0x3000), two(0xffc0, 0xfe1e), "f3T9", m68030 | m68851 },
+{"pflush", two(0xf000, 0x3800), two(0xffc0, 0xfe1e), "f3T9&s", m68030 | m68851 },
+{"pflush", one(0xf508), one(0xfff8), "as", m68040 },
+{"pflush", one(0xf508), one(0xfff8), "As", m68040 },
+{"pflushan", one(0xf510), one(0xfff8), "", m68040 },
+{"pflushn", one(0xf500), one(0xfff8), "as", m68040 },
+{"pflushn", one(0xf500), one(0xfff8), "As", m68040 },
+
+{"pflushr", two(0xf000, 0xa000), two(0xffc0, 0xffff), "|s", m68851 },
+
+{"pflushs", two(0xf000, 0x3410), two(0xfff8, 0xfe10), "T3T9", m68851 },
+{"pflushs", two(0xf000, 0x3c10), two(0xfff8, 0xfe00), "T3T9&s", m68851 },
+{"pflushs", two(0xf000, 0x3408), two(0xfff8, 0xfe18), "D3T9", m68851 },
+{"pflushs", two(0xf000, 0x3c08), two(0xfff8, 0xfe18), "D3T9&s", m68851 },
+{"pflushs", two(0xf000, 0x3400), two(0xfff8, 0xfe1e), "f3T9", m68851 },
+{"pflushs", two(0xf000, 0x3c00), two(0xfff8, 0xfe1e), "f3T9&s", m68851 },
+
+{"ploadr", two(0xf000, 0x2210), two(0xffc0, 0xfff0), "T3&s", m68030 | m68851 },
+{"ploadr", two(0xf000, 0x2208), two(0xffc0, 0xfff8), "D3&s", m68030 | m68851 },
+{"ploadr", two(0xf000, 0x2200), two(0xffc0, 0xfffe), "f3&s", m68030 | m68851 },
+{"ploadw", two(0xf000, 0x2010), two(0xffc0, 0xfff0), "T3&s", m68030 | m68851 },
+{"ploadw", two(0xf000, 0x2008), two(0xffc0, 0xfff8), "D3&s", m68030 | m68851 },
+{"ploadw", two(0xf000, 0x2000), two(0xffc0, 0xfffe), "f3&s", m68030 | m68851 },
+
+/* TC, CRP, DRP, SRP, CAL, VAL, SCC, AC */
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "*sP8", m68030 | m68851 },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "P8%s", m68030 | m68851 },
+{"pmove", two(0xf000, 0x4000), two(0xffc0, 0xe3ff), "|sW8", m68030 | m68851 },
+{"pmove", two(0xf000, 0x4200), two(0xffc0, 0xe3ff), "W8~s", m68030 | m68851 },
+
+/* BADx, BACx */
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xe3e3), "*sX3", m68030 | m68851 },
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xe3e3), "X3%s", m68030 | m68851 },
+
+/* PSR, PCSR */
+/* {"pmove", two(0xf000, 0x6100), two(oxffc0, oxffff), "*sZ8", m68030 | m68851 }, */
+{"pmove", two(0xf000, 0x6000), two(0xffc0, 0xffff), "*sY8", m68030 | m68851 },
+{"pmove", two(0xf000, 0x6200), two(0xffc0, 0xffff), "Y8%s", m68030 | m68851 },
+{"pmove", two(0xf000, 0x6600), two(0xffc0, 0xffff), "Z8%s", m68030 | m68851 },
+
+{"prestore", one(0xf140), one(0xffc0), "&s", m68851 },
+{"prestore", one(0xf158), one(0xfff8), "+s", m68851 },
+{"psave", one(0xf100), one(0xffc0), "&s", m68851 },
+{"psave", one(0xf100), one(0xffc0), "+s", m68851 },
+
+{"psac", two(0xf040, 0x0007), two(0xffc0, 0xffff), "@s", m68851 },
+{"psas", two(0xf040, 0x0006), two(0xffc0, 0xffff), "@s", m68851 },
+{"psbc", two(0xf040, 0x0001), two(0xffc0, 0xffff), "@s", m68851 },
+{"psbs", two(0xf040, 0x0000), two(0xffc0, 0xffff), "@s", m68851 },
+{"pscc", two(0xf040, 0x000f), two(0xffc0, 0xffff), "@s", m68851 },
+{"pscs", two(0xf040, 0x000e), two(0xffc0, 0xffff), "@s", m68851 },
+{"psgc", two(0xf040, 0x000d), two(0xffc0, 0xffff), "@s", m68851 },
+{"psgs", two(0xf040, 0x000c), two(0xffc0, 0xffff), "@s", m68851 },
+{"psic", two(0xf040, 0x000b), two(0xffc0, 0xffff), "@s", m68851 },
+{"psis", two(0xf040, 0x000a), two(0xffc0, 0xffff), "@s", m68851 },
+{"pslc", two(0xf040, 0x0003), two(0xffc0, 0xffff), "@s", m68851 },
+{"psls", two(0xf040, 0x0002), two(0xffc0, 0xffff), "@s", m68851 },
+{"pssc", two(0xf040, 0x0005), two(0xffc0, 0xffff), "@s", m68851 },
+{"psss", two(0xf040, 0x0004), two(0xffc0, 0xffff), "@s", m68851 },
+{"pswc", two(0xf040, 0x0009), two(0xffc0, 0xffff), "@s", m68851 },
+{"psws", two(0xf040, 0x0008), two(0xffc0, 0xffff), "@s", m68851 },
+
+{"ptestr", two(0xf000, 0x8210), two(0xffc0, 0xe3f0), "T3&sQ8", m68030 | m68851 },
+{"ptestr", two(0xf000, 0x8310), two(0xffc0, 0xe310), "T3&sQ8A9", m68030 | m68851 },
+{"ptestr", two(0xf000, 0x8208), two(0xffc0, 0xe3f8), "D3&sQ8", m68030 | m68851 },
+{"ptestr", two(0xf000, 0x8308), two(0xffc0, 0xe318), "D3&sQ8A9", m68030 | m68851 },
+{"ptestr", two(0xf000, 0x8200), two(0xffc0, 0xe3fe), "f3&sQ8", m68030 | m68851 },
+{"ptestr", two(0xf000, 0x8300), two(0xffc0, 0xe31e), "f3&sQ8A9", m68030 | m68851 },
+
+{"ptestr", one(0xf568), one(0xfff8), "as", m68040 },
+
+{"ptestw", two(0xf000, 0x8010), two(0xffc0, 0xe3f0), "T3&sQ8", m68030 | m68851 },
+{"ptestw", two(0xf000, 0x8110), two(0xffc0, 0xe310), "T3&sQ8A9", m68030 | m68851 },
+{"ptestw", two(0xf000, 0x8008), two(0xffc0, 0xe3f8), "D3&sQ8", m68030 | m68851 },
+{"ptestw", two(0xf000, 0x8108), two(0xffc0, 0xe318), "D3&sQ8A9", m68030 | m68851 },
+{"ptestw", two(0xf000, 0x8000), two(0xffc0, 0xe3fe), "f3&sQ8", m68030 | m68851 },
+{"ptestw", two(0xf000, 0x8100), two(0xffc0, 0xe31e), "f3&sQ8A9", m68030 | m68851 },
+
+{"ptestw", one(0xf548), one(0xfff8), "as", m68040 },
+
+{"ptrapacw", two(0xf07a, 0x0007), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapacl", two(0xf07b, 0x0007), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapac", two(0xf07c, 0x0007), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapasw", two(0xf07a, 0x0006), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapasl", two(0xf07b, 0x0006), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapas", two(0xf07c, 0x0006), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapbcw", two(0xf07a, 0x0001), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapbcl", two(0xf07b, 0x0001), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapbc", two(0xf07c, 0x0001), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapbsw", two(0xf07a, 0x0000), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapbsl", two(0xf07b, 0x0000), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapbs", two(0xf07c, 0x0000), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapccw", two(0xf07a, 0x000f), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapccl", two(0xf07b, 0x000f), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapcc", two(0xf07c, 0x000f), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapcsw", two(0xf07a, 0x000e), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapcsl", two(0xf07b, 0x000e), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapcs", two(0xf07c, 0x000e), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapgcw", two(0xf07a, 0x000d), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapgcl", two(0xf07b, 0x000d), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapgc", two(0xf07c, 0x000d), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapgsw", two(0xf07a, 0x000c), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapgsl", two(0xf07b, 0x000c), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapgs", two(0xf07c, 0x000c), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapicw", two(0xf07a, 0x000b), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapicl", two(0xf07b, 0x000b), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapic", two(0xf07c, 0x000b), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapisw", two(0xf07a, 0x000a), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapisl", two(0xf07b, 0x000a), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapis", two(0xf07c, 0x000a), two(0xffff, 0xffff), "", m68851 },
+
+{"ptraplcw", two(0xf07a, 0x0003), two(0xffff, 0xffff), "#w", m68851 },
+{"ptraplcl", two(0xf07b, 0x0003), two(0xffff, 0xffff), "#l", m68851 },
+{"ptraplc", two(0xf07c, 0x0003), two(0xffff, 0xffff), "", m68851 },
+
+{"ptraplsw", two(0xf07a, 0x0002), two(0xffff, 0xffff), "#w", m68851 },
+{"ptraplsl", two(0xf07b, 0x0002), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapls", two(0xf07c, 0x0002), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapscw", two(0xf07a, 0x0005), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapscl", two(0xf07b, 0x0005), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapsc", two(0xf07c, 0x0005), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapssw", two(0xf07a, 0x0004), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapssl", two(0xf07b, 0x0004), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapss", two(0xf07c, 0x0004), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapwcw", two(0xf07a, 0x0009), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapwcl", two(0xf07b, 0x0009), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapwc", two(0xf07c, 0x0009), two(0xffff, 0xffff), "", m68851 },
+
+{"ptrapwsw", two(0xf07a, 0x0008), two(0xffff, 0xffff), "#w", m68851 },
+{"ptrapwsl", two(0xf07b, 0x0008), two(0xffff, 0xffff), "#l", m68851 },
+{"ptrapws", two(0xf07c, 0x0008), two(0xffff, 0xffff), "", m68851 },
+
+{"pvalid", two(0xf000, 0x2800), two(0xffc0, 0xffff), "Vs&s", m68851 },
+{"pvalid", two(0xf000, 0x2c00), two(0xffc0, 0xfff8), "A3&s", m68851 },
+
+#endif /* NO_68851 */
+
+{"reset", one(0047160), one(0177777), "", m68000up },
+
+{"rolb", one(0160430), one(0170770), "QdDs", m68000up }, /* rorb #Q, Ds */
+{"rolb", one(0160470), one(0170770), "DdDs", m68000up }, /* rorb Dd, Ds */
+{"roll", one(0160630), one(0170770), "QdDs", m68000up }, /* rorb #Q, Ds */
+{"roll", one(0160670), one(0170770), "DdDs", m68000up }, /* rorb Dd, Ds */
+{"rolw", one(0160530), one(0170770), "QdDs", m68000up }, /* rorb #Q, Ds */
+{"rolw", one(0160570), one(0170770), "DdDs", m68000up }, /* rorb Dd, Ds */
+{"rolw", one(0163700), one(0177700), "~s", m68000up }, /* Rotate memory */
+{"rorb", one(0160030), one(0170770), "QdDs", m68000up }, /* rorb #Q, Ds */
+{"rorb", one(0160070), one(0170770), "DdDs", m68000up }, /* rorb Dd, Ds */
+{"rorl", one(0160230), one(0170770), "QdDs", m68000up }, /* rorb #Q, Ds */
+{"rorl", one(0160270), one(0170770), "DdDs", m68000up }, /* rorb Dd, Ds */
+{"rorw", one(0160130), one(0170770), "QdDs", m68000up }, /* rorb #Q, Ds */
+{"rorw", one(0160170), one(0170770), "DdDs", m68000up }, /* rorb Dd, Ds */
+{"rorw", one(0163300), one(0177700), "~s", m68000up }, /* Rotate memory */
+
+{"roxlb", one(0160420), one(0170770), "QdDs", m68000up }, /* roxrb #Q, Ds */
+{"roxlb", one(0160460), one(0170770), "DdDs", m68000up }, /* roxrb Dd, Ds */
+{"roxll", one(0160620), one(0170770), "QdDs", m68000up }, /* roxrb #Q, Ds */
+{"roxll", one(0160660), one(0170770), "DdDs", m68000up }, /* roxrb Dd, Ds */
+{"roxlw", one(0160520), one(0170770), "QdDs", m68000up }, /* roxrb #Q, Ds */
+{"roxlw", one(0160560), one(0170770), "DdDs", m68000up }, /* roxrb Dd, Ds */
+{"roxlw", one(0162700), one(0177700), "~s", m68000up }, /* Rotate memory */
+{"roxrb", one(0160020), one(0170770), "QdDs", m68000up }, /* roxrb #Q, Ds */
+{"roxrb", one(0160060), one(0170770), "DdDs", m68000up }, /* roxrb Dd, Ds */
+{"roxrl", one(0160220), one(0170770), "QdDs", m68000up }, /* roxrb #Q, Ds */
+{"roxrl", one(0160260), one(0170770), "DdDs", m68000up }, /* roxrb Dd, Ds */
+{"roxrw", one(0160120), one(0170770), "QdDs", m68000up }, /* roxrb #Q, Ds */
+{"roxrw", one(0160160), one(0170770), "DdDs", m68000up }, /* roxrb Dd, Ds */
+{"roxrw", one(0162300), one(0177700), "~s", m68000up }, /* Rotate memory */
+
+{"rtd", one(0047164), one(0177777), "#w", m68010up },
+{"rte", one(0047163), one(0177777), "", m68000up },
+{"rtm", one(0003300), one(0177760), "Rs", m68020 },
+{"rtr", one(0047167), one(0177777), "", m68000up },
+{"rts", one(0047165), one(0177777), "", m68000up },
+
+{"sbcd", one(0100400), one(0170770), "DsDd", m68000up },
+{"sbcd", one(0100410), one(0170770), "-s-d", m68000up },
+
+{"scc", one(0052300), one(0177700), "$s", m68000up },
+{"scs", one(0052700), one(0177700), "$s", m68000up },
+{"seq", one(0053700), one(0177700), "$s", m68000up },
+{"sf", one(0050700), one(0177700), "$s", m68000up },
+{"sge", one(0056300), one(0177700), "$s", m68000up },
+{"sfge", one(0056300), one(0177700), "$s", m68000up },
+{"sgt", one(0057300), one(0177700), "$s", m68000up },
+{"sfgt", one(0057300), one(0177700), "$s", m68000up },
+{"shi", one(0051300), one(0177700), "$s", m68000up },
+{"sle", one(0057700), one(0177700), "$s", m68000up },
+{"sfle", one(0057700), one(0177700), "$s", m68000up },
+{"sls", one(0051700), one(0177700), "$s", m68000up },
+{"slt", one(0056700), one(0177700), "$s", m68000up },
+{"sflt", one(0056700), one(0177700), "$s", m68000up },
+{"smi", one(0055700), one(0177700), "$s", m68000up },
+{"sne", one(0053300), one(0177700), "$s", m68000up },
+{"sfneq", one(0053300), one(0177700), "$s", m68000up },
+{"spl", one(0055300), one(0177700), "$s", m68000up },
+{"st", one(0050300), one(0177700), "$s", m68000up },
+{"svc", one(0054300), one(0177700), "$s", m68000up },
+{"svs", one(0054700), one(0177700), "$s", m68000up },
+
+{"stop", one(0047162), one(0177777), "#w", m68000up },
+
+{"subal", one(0110700), one(0170700), "*lAd", m68000up },
+{"subaw", one(0110300), one(0170700), "*wAd", m68000up },
+{"subb", one(0050400), one(0170700), "Qd%s", m68000up }, /* subq written as sub */
+{"subb", one(0002000), one(0177700), "#b$s", m68000up }, /* subi written as sub */
+{"subb", one(0110000), one(0170700), ";bDd", m68000up }, /* subb ? ?, Dd */
+{"subb", one(0110400), one(0170700), "Dd~s", m68000up }, /* subb Dd, ? ? */
+{"subib", one(0002000), one(0177700), "#b$s", m68000up },
+{"subil", one(0002200), one(0177700), "#l$s", m68000up },
+{"subiw", one(0002100), one(0177700), "#w$s", m68000up },
+{"subl", one(0050600), one(0170700), "Qd%s", m68000up },
+{"subl", one(0002200), one(0177700), "#l$s", m68000up },
+{"subl", one(0110700), one(0170700), "*lAd", m68000up },
+{"subl", one(0110200), one(0170700), "*lDd", m68000up },
+{"subl", one(0110600), one(0170700), "Dd~s", m68000up },
+{"subqb", one(0050400), one(0170700), "Qd%s", m68000up },
+{"subql", one(0050600), one(0170700), "Qd%s", m68000up },
+{"subqw", one(0050500), one(0170700), "Qd%s", m68000up },
+{"subw", one(0050500), one(0170700), "Qd%s", m68000up },
+{"subw", one(0002100), one(0177700), "#w$s", m68000up },
+{"subw", one(0110100), one(0170700), "*wDd", m68000up },
+{"subw", one(0110300), one(0170700), "*wAd", m68000up }, /* suba written as sub */
+{"subw", one(0110500), one(0170700), "Dd~s", m68000up },
+{"subxb", one(0110400), one(0170770), "DsDd", m68000up }, /* subxb Ds, Dd */
+{"subxb", one(0110410), one(0170770), "-s-d", m68000up }, /* subxb -(As), -(Ad) */
+{"subxl", one(0110600), one(0170770), "DsDd", m68000up },
+{"subxl", one(0110610), one(0170770), "-s-d", m68000up },
+{"subxw", one(0110500), one(0170770), "DsDd", m68000up },
+{"subxw", one(0110510), one(0170770), "-s-d", m68000up },
+
+{"swap", one(0044100), one(0177770), "Ds", m68000up },
+
+{"tas", one(0045300), one(0177700), "$s", m68000up },
+{"trap", one(0047100), one(0177760), "Ts", m68000up },
+
+{"trapcc", one(0052374), one(0177777), "", m68020up },
+{"trapcs", one(0052774), one(0177777), "", m68020up },
+{"trapeq", one(0053774), one(0177777), "", m68020up },
+{"trapf", one(0050774), one(0177777), "", m68020up },
+{"trapge", one(0056374), one(0177777), "", m68020up },
+{"trapgt", one(0057374), one(0177777), "", m68020up },
+{"traphi", one(0051374), one(0177777), "", m68020up },
+{"traple", one(0057774), one(0177777), "", m68020up },
+{"trapls", one(0051774), one(0177777), "", m68020up },
+{"traplt", one(0056774), one(0177777), "", m68020up },
+{"trapmi", one(0055774), one(0177777), "", m68020up },
+{"trapne", one(0053374), one(0177777), "", m68020up },
+{"trappl", one(0055374), one(0177777), "", m68020up },
+{"trapt", one(0050374), one(0177777), "", m68020up },
+{"trapvc", one(0054374), one(0177777), "", m68020up },
+{"trapvs", one(0054774), one(0177777), "", m68020up },
+
+{"trapcc.w", one(0052372), one(0177777), "", m68020up },
+{"trapcs.w", one(0052772), one(0177777), "", m68020up },
+{"trapeq.w", one(0053772), one(0177777), "", m68020up },
+{"trapf.w", one(0050772), one(0177777), "", m68020up },
+{"trapge.w", one(0056372), one(0177777), "", m68020up },
+{"trapgt.w", one(0057372), one(0177777), "", m68020up },
+{"traphi.w", one(0051372), one(0177777), "", m68020up },
+{"traple.w", one(0057772), one(0177777), "", m68020up },
+{"trapls.w", one(0051772), one(0177777), "", m68020up },
+{"traplt.w", one(0056772), one(0177777), "", m68020up },
+{"trapmi.w", one(0055772), one(0177777), "", m68020up },
+{"trapne.w", one(0053372), one(0177777), "", m68020up },
+{"trappl.w", one(0055372), one(0177777), "", m68020up },
+{"trapt.w", one(0050372), one(0177777), "", m68020up },
+{"trapvc.w", one(0054372), one(0177777), "", m68020up },
+{"trapvs.w", one(0054772), one(0177777), "", m68020up },
+
+{"trapcc.l", one(0052373), one(0177777), "", m68020up },
+{"trapcs.l", one(0052773), one(0177777), "", m68020up },
+{"trapeq.l", one(0053773), one(0177777), "", m68020up },
+{"trapf.l", one(0050773), one(0177777), "", m68020up },
+{"trapge.l", one(0056373), one(0177777), "", m68020up },
+{"trapgt.l", one(0057373), one(0177777), "", m68020up },
+{"traphi.l", one(0051373), one(0177777), "", m68020up },
+{"traple.l", one(0057773), one(0177777), "", m68020up },
+{"trapls.l", one(0051773), one(0177777), "", m68020up },
+{"traplt.l", one(0056773), one(0177777), "", m68020up },
+{"trapmi.l", one(0055773), one(0177777), "", m68020up },
+{"trapne.l", one(0053373), one(0177777), "", m68020up },
+{"trappl.l", one(0055373), one(0177777), "", m68020up },
+{"trapt.l", one(0050373), one(0177777), "", m68020up },
+{"trapvc.l", one(0054373), one(0177777), "", m68020up },
+{"trapvs.l", one(0054773), one(0177777), "", m68020up },
+
+{"trapv", one(0047166), one(0177777), "", m68000up },
+
+{"tstb", one(0045000), one(0177700), ";b", m68000up },
+{"tstw", one(0045100), one(0177700), "*w", m68000up },
+{"tstl", one(0045200), one(0177700), "*l", m68000up },
+
+{"unlk", one(0047130), one(0177770), "As", m68000up },
+{"unpk", one(0100600), one(0170770), "DsDd#w", m68020up },
+{"unpk", one(0100610), one(0170770), "-s-d#w", m68020up },
+
+/* Variable-sized branches */
+
+{"jbsr", one(0060400), one(0177400), "Bg", m68000up },
+{"jbsr", one(0047200), one(0177700), "!s", m68000up },
+#ifdef PIC
+{"jbsr", one(0060400), one(0177400), "Bg ", m68020up },
+#endif /* PIC */
+
+{"jra", one(0060000), one(0177400), "Bg", m68000up },
+{"jra", one(0047300), one(0177700), "!s", m68000up },
+#ifdef PIC
+{"jra", one(0060000), one(0177400), "Bg ", m68000up },
+#endif /* PIC */
+
+{"jhi", one(0061000), one(0177400), "Bg", m68000up },
+{"jls", one(0061400), one(0177400), "Bg", m68000up },
+{"jcc", one(0062000), one(0177400), "Bg", m68000up },
+{"jfnlt", one(0062000), one(0177400), "Bg", m68000up }, /* apparently a sun alias */
+{"jcs", one(0062400), one(0177400), "Bg", m68000up },
+{"jne", one(0063000), one(0177400), "Bg", m68000up },
+{"jeq", one(0063400), one(0177400), "Bg", m68000up },
+{"jfeq", one(0063400), one(0177400), "Bg", m68000up }, /* apparently a sun alias */
+{"jvc", one(0064000), one(0177400), "Bg", m68000up },
+{"jvs", one(0064400), one(0177400), "Bg", m68000up },
+{"jpl", one(0065000), one(0177400), "Bg", m68000up },
+{"jmi", one(0065400), one(0177400), "Bg", m68000up },
+{"jge", one(0066000), one(0177400), "Bg", m68000up },
+{"jlt", one(0066400), one(0177400), "Bg", m68000up },
+{"jgt", one(0067000), one(0177400), "Bg", m68000up },
+{"jle", one(0067400), one(0177400), "Bg", m68000up },
+{"jfngt", one(0067400), one(0177400), "Bg", m68000up }, /* apparently a sun alias */
+
+/* aliases */
+
+{"movql", one(0070000), one(0170400), "MsDd", m68000up },
+{"moveql", one(0070000), one(0170400), "MsDd", m68000up },
+{"moval", one(0020100), one(0170700), "*lAd", m68000up },
+{"movaw", one(0030100), one(0170700), "*wAd", m68000up },
+{"movb", one(0010000), one(0170000), ";b$d", m68000up }, /* mov */
+{"movl", one(0070000), one(0170400), "MsDd", m68000up }, /* movq written as mov */
+{"movl", one(0020000), one(0170000), "*l$d", m68000up },
+{"movl", one(0020100), one(0170700), "*lAd", m68000up },
+{"movl", one(0047140), one(0177770), "AsUd", m68000up }, /* mov to USP */
+{"movl", one(0047150), one(0177770), "UdAs", m68000up }, /* mov from USP */
+{"movc", one(0047173), one(0177777), "R1Jj", m68010up },
+{"movc", one(0047173), one(0177777), "R1#j", m68010up },
+{"movc", one(0047172), one(0177777), "JjR1", m68010up },
+{"movc", one(0047172), one(0177777), "#jR1", m68010up },
+{"movml", one(0044300), one(0177700), "#w&s", m68000up }, /* movm reg to mem. */
+{"movml", one(0044340), one(0177770), "#w-s", m68000up }, /* movm reg to autodecrement. */
+{"movml", one(0046300), one(0177700), "!s#w", m68000up }, /* movm mem to reg. */
+{"movml", one(0046330), one(0177770), "+s#w", m68000up }, /* movm autoinc to reg. */
+{"movml", one(0044300), one(0177700), "Lw&s", m68000up }, /* movm reg to mem. */
+{"movml", one(0044340), one(0177770), "lw-s", m68000up }, /* movm reg to autodecrement. */
+{"movml", one(0046300), one(0177700), "!sLw", m68000up }, /* movm mem to reg. */
+{"movml", one(0046330), one(0177770), "+sLw", m68000up }, /* movm autoinc to reg. */
+{"movmw", one(0044200), one(0177700), "#w&s", m68000up }, /* movm reg to mem. */
+{"movmw", one(0044240), one(0177770), "#w-s", m68000up }, /* movm reg to autodecrement. */
+{"movmw", one(0046200), one(0177700), "!s#w", m68000up }, /* movm mem to reg. */
+{"movmw", one(0046230), one(0177770), "+s#w", m68000up }, /* movm autoinc to reg. */
+{"movmw", one(0044200), one(0177700), "Lw&s", m68000up }, /* movm reg to mem. */
+{"movmw", one(0044240), one(0177770), "lw-s", m68000up }, /* movm reg to autodecrement. */
+{"movmw", one(0046200), one(0177700), "!sLw", m68000up }, /* movm mem to reg. */
+{"movmw", one(0046230), one(0177770), "+sLw", m68000up }, /* movm autoinc to reg. */
+{"movpl", one(0000510), one(0170770), "dsDd", m68000up }, /* memory to register */
+{"movpl", one(0000710), one(0170770), "Ddds", m68000up }, /* register to memory */
+{"movpw", one(0000410), one(0170770), "dsDd", m68000up }, /* memory to register */
+{"movpw", one(0000610), one(0170770), "Ddds", m68000up }, /* register to memory */
+{"movq", one(0070000), one(0170400), "MsDd", m68000up },
+{"movw", one(0030000), one(0170000), "*w$d", m68000up },
+{"movw", one(0030100), one(0170700), "*wAd", m68000up }, /* mova, written as mov */
+{"movw", one(0040300), one(0177700), "Ss$s", m68000up }, /* Move from sr */
+{"movw", one(0041300), one(0177700), "Cs$s", m68010up }, /* Move from ccr */
+{"movw", one(0042300), one(0177700), ";wCd", m68000up }, /* mov to ccr */
+{"movw", one(0043300), one(0177700), ";wSd", m68000up }, /* mov to sr */
+
+{"movsb", two(0007000, 0), two(0177700, 07777), "~sR1", m68010up },
+{"movsb", two(0007000, 04000), two(0177700, 07777), "R1~s", m68010up },
+{"movsl", two(0007200, 0), two(0177700, 07777), "~sR1", m68010up },
+{"movsl", two(0007200, 04000), two(0177700, 07777), "R1~s", m68010up },
+{"movsw", two(0007100, 0), two(0177700, 07777), "~sR1", m68010up },
+{"movsw", two(0007100, 04000), two(0177700, 07777), "R1~s", m68010up },
+
+};
+
+int numopcodes=sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);
+
+struct m68k_opcode *endop = m68k_opcodes+sizeof(m68k_opcodes)/sizeof(m68k_opcodes[0]);
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * End:
+ */
+
+/* end of m68k-opcode.h */
diff --git a/gnu/usr.bin/as/opcode/m88k.h b/gnu/usr.bin/as/opcode/m88k.h
new file mode 100644
index 0000000..5f685b9
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/m88k.h
@@ -0,0 +1,282 @@
+/* m88k-opcode.h -- Instruction information for the Motorola 88000
+ Contributed by Devon Bowen of Buffalo University
+ and Torbjorn Granlund of the Swedish Institute of Computer Science.
+ Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ Character codes for op_spec field below.
+ Reserved for direct matching: x , [ ]
+
+ d = GRF Destination register (21:5)
+ 1 = Source register 1 (16:5)
+ 2 = Source register 2 (0:5)
+ 3 = Both source registers (same value) (0:5 and 16:5)
+ I = IMM16 (0:16)
+ b = bit field spec. (0:10)
+ p = 16 bit pc displ. (0:16)
+ P = 26 bit pc displ. (0:26)
+ B = bb0/bb1 condition (21:5)
+ M = bcnd condition (21:5)
+ f = fcr (5:6)
+ c = cr (5:6)
+ V = VEC9 (0:9)
+ ? = Give warning for this insn/operand combination
+ */
+
+/* instruction descriptor structure */
+
+struct m88k_opcode
+{
+ unsigned int opcode;
+ char *name;
+ char *op_spec;
+};
+
+/* and introducing... the Motorola 88100 instruction sets... */
+
+/* These macros may seem silly, but they are in preparation
+ for future versions of the 88000 family. */
+
+#define _MC88100(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC},
+#define _MC88xxx(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC},
+
+/* Equal mnemonics must be adjacent.
+ More specific operand specification must go before more general.
+ For example, "d,1,2" must go before "d,1,I" as a register for s2
+ would otherwise be considered a variable name. */
+
+static struct m88k_opcode m88k_opcodes[] =
+{
+ /* Opcode Mnemonic Opspec */
+
+ _MC88xxx(0xf4007000, "add", "d,1,2")
+ _MC88xxx(0x70000000, "add", "d,1,I")
+ _MC88xxx(0xf4007200, "add.ci", "d,1,2")
+ _MC88xxx(0xf4007300, "add.cio", "d,1,2")
+ _MC88xxx(0xf4007100, "add.co", "d,1,2")
+ _MC88xxx(0xf4006000, "addu", "d,1,2")
+ _MC88xxx(0x60000000, "addu", "d,1,I")
+ _MC88xxx(0xf4006200, "addu.ci", "d,1,2")
+ _MC88xxx(0xf4006300, "addu.cio", "d,1,2")
+ _MC88xxx(0xf4006100, "addu.co", "d,1,2")
+ _MC88xxx(0xf4004000, "and", "d,1,2")
+ _MC88xxx(0x40000000, "and", "d,1,I")
+ _MC88xxx(0xf4004400, "and.c", "d,1,2")
+ _MC88xxx(0x44000000, "and.u", "d,1,I")
+ _MC88xxx(0xd0000000, "bb0", "B,1,p")
+ _MC88xxx(0xd4000000, "bb0.n", "B,1,p")
+ _MC88xxx(0xd8000000, "bb1", "B,1,p")
+ _MC88xxx(0xdc000000, "bb1.n", "B,1,p")
+ _MC88xxx(0xe8000000, "bcnd", "M,1,p")
+ _MC88xxx(0xec000000, "bcnd.n", "M,1,p")
+ _MC88xxx(0xc0000000, "br", "P")
+ _MC88xxx(0xc4000000, "br.n", "P")
+ _MC88xxx(0xc8000000, "bsr", "P")
+ _MC88xxx(0xcc000000, "bsr.n", "P")
+ _MC88xxx(0xf4008000, "clr", "d,1,2")
+ _MC88xxx(0xf0008000, "clr", "d,1,b")
+ _MC88xxx(0xf4007c00, "cmp", "d,1,2")
+ _MC88xxx(0x7c000000, "cmp", "d,1,I")
+ _MC88xxx(0xf4007800, "div", "d,1,2")
+ _MC88xxx(0x78000000, "div", "d,1,I")
+ _MC88xxx(0xf4007800, "divs", "d,1,2")
+ _MC88xxx(0x78000000, "divs", "d,1,I")
+ _MC88xxx(0xf4006800, "divu", "d,1,2")
+ _MC88xxx(0x68000000, "divu", "d,1,I")
+ _MC88xxx(0xf4009000, "ext", "d,1,2")
+ _MC88xxx(0xf0009000, "ext", "d,1,b")
+ _MC88xxx(0xf4009800, "extu", "d,1,2")
+ _MC88xxx(0xf0009800, "extu", "d,1,b")
+ _MC88xxx(0x84002800, "fadd.sss", "d,1,2")
+ _MC88xxx(0x84002880, "fadd.ssd", "d,1,2")
+ _MC88xxx(0x84002a00, "fadd.sds", "d,1,2")
+ _MC88xxx(0x84002a80, "fadd.sdd", "d,1,2")
+ _MC88xxx(0x84002820, "fadd.dss", "d,1,2")
+ _MC88xxx(0x840028a0, "fadd.dsd", "d,1,2")
+ _MC88xxx(0x84002a20, "fadd.dds", "d,1,2")
+ _MC88xxx(0x84002aa0, "fadd.ddd", "d,1,2")
+ _MC88xxx(0x84003a80, "fcmp.sdd", "d,1,2")
+ _MC88xxx(0x84003a00, "fcmp.sds", "d,1,2")
+ _MC88xxx(0x84003880, "fcmp.ssd", "d,1,2")
+ _MC88xxx(0x84003800, "fcmp.sss", "d,1,2")
+ _MC88xxx(0x84007000, "fdiv.sss", "d,1,2")
+ _MC88xxx(0x84007080, "fdiv.ssd", "d,1,2")
+ _MC88xxx(0x84007200, "fdiv.sds", "d,1,2")
+ _MC88xxx(0x84007280, "fdiv.sdd", "d,1,2")
+ _MC88xxx(0x84007020, "fdiv.dss", "d,1,2")
+ _MC88xxx(0x840070a0, "fdiv.dsd", "d,1,2")
+ _MC88xxx(0x84007220, "fdiv.dds", "d,1,2")
+ _MC88xxx(0x840072a0, "fdiv.ddd", "d,1,2")
+ _MC88xxx(0xf400ec00, "ff0", "d,2")
+ _MC88xxx(0xf400e800, "ff1", "d,2")
+ _MC88xxx(0x80004800, "fldcr", "d,f")
+ _MC88xxx(0x84002020, "flt.ds", "d,2")
+ _MC88xxx(0x84002000, "flt.ss", "d,2")
+ _MC88xxx(0x84000000, "fmul.sss", "d,1,2")
+ _MC88xxx(0x84000080, "fmul.ssd", "d,1,2")
+ _MC88xxx(0x84000200, "fmul.sds", "d,1,2")
+ _MC88xxx(0x84000280, "fmul.sdd", "d,1,2")
+ _MC88xxx(0x84000020, "fmul.dss", "d,1,2")
+ _MC88xxx(0x840000a0, "fmul.dsd", "d,1,2")
+ _MC88xxx(0x84000220, "fmul.dds", "d,1,2")
+ _MC88xxx(0x840002a0, "fmul.ddd", "d,1,2")
+ _MC88xxx(0x80008800, "fstcr", "3,f")
+ _MC88xxx(0x84003000, "fsub.sss", "d,1,2")
+ _MC88xxx(0x84003080, "fsub.ssd", "d,1,2")
+ _MC88xxx(0x84003200, "fsub.sds", "d,1,2")
+ _MC88xxx(0x84003280, "fsub.sdd", "d,1,2")
+ _MC88xxx(0x84003020, "fsub.dss", "d,1,2")
+ _MC88xxx(0x840030a0, "fsub.dsd", "d,1,2")
+ _MC88xxx(0x84003220, "fsub.dds", "d,1,2")
+ _MC88xxx(0x840032a0, "fsub.ddd", "d,1,2")
+ _MC88xxx(0x8000c800, "fxcr", "d,3,f")
+ _MC88xxx(0x8400fc01, "illop1", "")
+ _MC88xxx(0x8400fc02, "illop2", "")
+ _MC88xxx(0x8400fc03, "illop3", "")
+ _MC88xxx(0x84004880, "int.sd", "d,2")
+ _MC88xxx(0x84004800, "int.ss", "d,2")
+ _MC88xxx(0xf400c000, "jmp", "2")
+ _MC88xxx(0xf400c400, "jmp.n", "2")
+ _MC88xxx(0xf400c800, "jsr", "2")
+ _MC88xxx(0xf400cc00, "jsr.n", "2")
+ _MC88xxx(0xf4001400, "ld", "d,1,2")
+ _MC88xxx(0xf4001600, "ld", "d,1[2]")
+ _MC88xxx(0x14000000, "ld", "d,1,I")
+ _MC88xxx(0xf4001e00, "ld.b", "d,1[2]")
+ _MC88xxx(0xf4001c00, "ld.b", "d,1,2")
+ _MC88xxx(0x1c000000, "ld.b", "d,1,I")
+ _MC88xxx(0xf4001d00, "ld.b.usr", "d,1,2")
+ _MC88xxx(0xf4001f00, "ld.b.usr", "d,1[2]")
+ _MC88xxx(0xf4000e00, "ld.bu", "d,1[2]")
+ _MC88xxx(0xf4000c00, "ld.bu", "d,1,2")
+ _MC88xxx(0x0c000000, "ld.bu", "d,1,I")
+ _MC88xxx(0xf4000d00, "ld.bu.usr", "d,1,2")
+ _MC88xxx(0xf4000f00, "ld.bu.usr", "d,1[2]")
+ _MC88xxx(0xf4001200, "ld.d", "d,1[2]")
+ _MC88xxx(0xf4001000, "ld.d", "d,1,2")
+ _MC88xxx(0x10000000, "ld.d", "d,1,I")
+ _MC88xxx(0xf4001100, "ld.d.usr", "d,1,2")
+ _MC88xxx(0xf4001300, "ld.d.usr", "d,1[2]")
+ _MC88xxx(0xf4001a00, "ld.h", "d,1[2]")
+ _MC88xxx(0xf4001800, "ld.h", "d,1,2")
+ _MC88xxx(0x18000000, "ld.h", "d,1,I")
+ _MC88xxx(0xf4001900, "ld.h.usr", "d,1,2")
+ _MC88xxx(0xf4001b00, "ld.h.usr", "d,1[2]")
+ _MC88xxx(0xf4000a00, "ld.hu", "d,1[2]")
+ _MC88xxx(0xf4000800, "ld.hu", "d,1,2")
+ _MC88xxx(0x08000000, "ld.hu", "d,1,I")
+ _MC88xxx(0xf4000900, "ld.hu.usr", "d,1,2")
+ _MC88xxx(0xf4000b00, "ld.hu.usr", "d,1[2]")
+ _MC88xxx(0xf4001500, "ld.usr", "d,1,2")
+ _MC88xxx(0xf4001700, "ld.usr", "d,1[2]")
+ _MC88xxx(0xf4003600, "lda", "d,1[2]")
+ _MC88xxx(0xf4006000, "lda", "?d,1,2") /* Output addu */
+ _MC88xxx(0x60000000, "lda", "?d,1,I") /* Output addu */
+ _MC88xxx(0xf4006000, "lda.b", "?d,1[2]") /* Output addu */
+ _MC88xxx(0xf4006000, "lda.b", "?d,1,2") /* Output addu */
+ _MC88xxx(0x60000000, "lda.b", "?d,1,I") /* Output addu */
+ _MC88xxx(0xf4003200, "lda.d", "d,1[2]")
+ _MC88xxx(0xf4006000, "lda.d", "?d,1,2") /* Output addu */
+ _MC88xxx(0x60000000, "lda.d", "?d,1,I") /* Output addu */
+ _MC88xxx(0xf4003a00, "lda.h", "d,1[2]")
+ _MC88xxx(0xf4006000, "lda.h", "?d,1,2") /* Output addu */
+ _MC88xxx(0x60000000, "lda.h", "?d,1,I") /* Output addu */
+ _MC88xxx(0x80004000, "ldcr", "d,c")
+ _MC88xxx(0xf400a000, "mak", "d,1,2")
+ _MC88xxx(0xf000a000, "mak", "d,1,b")
+ _MC88xxx(0x48000000, "mask", "d,1,I")
+ _MC88xxx(0x4c000000, "mask.u", "d,1,I")
+ _MC88xxx(0xf4006c00, "mul", "d,1,2")
+ _MC88xxx(0x6c000000, "mul", "d,1,I")
+ _MC88xxx(0xf4006c00, "mulu", "d,1,2") /* synonym for mul */
+ _MC88xxx(0x6c000000, "mulu", "d,1,I") /* synonym for mul */
+ _MC88xxx(0x84005080, "nint.sd", "d,2")
+ _MC88xxx(0x84005000, "nint.ss", "d,2")
+ _MC88xxx(0xf4005800, "or", "d,1,2")
+ _MC88xxx(0x58000000, "or", "d,1,I")
+ _MC88xxx(0xf4005c00, "or.c", "d,1,2")
+ _MC88xxx(0x5c000000, "or.u", "d,1,I")
+ _MC88xxx(0xf000a800, "rot", "d,1,b")
+ _MC88xxx(0xf400a800, "rot", "d,1,2")
+ _MC88xxx(0xf400fc00, "rte", "")
+ _MC88xxx(0xf4008800, "set", "d,1,2")
+ _MC88xxx(0xf0008800, "set", "d,1,b")
+ _MC88xxx(0xf4002600, "st", "d,1[2]")
+ _MC88xxx(0xf4002400, "st", "d,1,2")
+ _MC88xxx(0x24000000, "st", "d,1,I")
+ _MC88xxx(0xf4002e00, "st.b", "d,1[2]")
+ _MC88xxx(0xf4002c00, "st.b", "d,1,2")
+ _MC88xxx(0x2c000000, "st.b", "d,1,I")
+ _MC88xxx(0xf4002d00, "st.b.usr", "d,1,2")
+ _MC88xxx(0xf4002f00, "st.b.usr", "d,1[2]")
+ _MC88xxx(0xf4002200, "st.d", "d,1[2]")
+ _MC88xxx(0xf4002000, "st.d", "d,1,2")
+ _MC88xxx(0x20000000, "st.d", "d,1,I")
+ _MC88xxx(0xf4002100, "st.d.usr", "d,1,2")
+ _MC88xxx(0xf4002300, "st.d.usr", "d,1[2]")
+ _MC88xxx(0xf4002a00, "st.h", "d,1[2]")
+ _MC88xxx(0xf4002800, "st.h", "d,1,2")
+ _MC88xxx(0x28000000, "st.h", "d,1,I")
+ _MC88xxx(0xf4002900, "st.h.usr", "d,1,2")
+ _MC88xxx(0xf4002b00, "st.h.usr", "d,1[2]")
+ _MC88xxx(0xf4002500, "st.usr", "d,1,2")
+ _MC88xxx(0xf4002700, "st.usr", "d,1[2]")
+ _MC88xxx(0x80008000, "stcr", "3,c")
+ _MC88xxx(0xf4007400, "sub", "d,1,2")
+ _MC88xxx(0x74000000, "sub", "d,1,I")
+ _MC88xxx(0xf4007600, "sub.ci", "d,1,2")
+ _MC88xxx(0xf4007700, "sub.cio", "d,1,2")
+ _MC88xxx(0xf4007500, "sub.co", "d,1,2")
+ _MC88xxx(0xf4006400, "subu", "d,1,2")
+ _MC88xxx(0x64000000, "subu", "d,1,I")
+ _MC88xxx(0xf4006600, "subu.ci", "d,1,2")
+ _MC88xxx(0xf4006700, "subu.cio", "d,1,2")
+ _MC88xxx(0xf4006500, "subu.co", "d,1,2")
+ _MC88xxx(0xf000d000, "tb0", "B,1,V")
+ _MC88xxx(0xf000d800, "tb1", "B,1,V")
+ _MC88xxx(0xf400f800, "tbnd", "1,2")
+ _MC88xxx(0xf8000000, "tbnd", "1,I")
+ _MC88xxx(0xf000e800, "tcnd", "M,1,V")
+ _MC88xxx(0x84005880, "trnc.sd", "d,2")
+ _MC88xxx(0x84005800, "trnc.ss", "d,2")
+ _MC88xxx(0x8000c000, "xcr", "d,1,c")
+ _MC88xxx(0xf4000600, "xmem", "d,1[2]")
+ _MC88xxx(0xf4000400, "xmem", "d,1,2")
+ _MC88100(0x04000000, "xmem", "?d,1,I")
+ _MC88xxx(0xf4000200, "xmem.bu", "d,1[2]")
+ _MC88xxx(0xf4000000, "xmem.bu", "d,1,2")
+ _MC88100(0x00000000, "xmem.bu", "?d,1,I")
+ _MC88xxx(0xf4000300, "xmem.bu.usr", "d,1[2]")
+ _MC88xxx(0xf4000100, "xmem.bu.usr", "d,1,2")
+ _MC88100(0x00000100, "xmem.bu.usr", "?d,1,I")
+ _MC88xxx(0xf4000700, "xmem.usr", "d,1[2]")
+ _MC88xxx(0xf4000500, "xmem.usr", "d,1,2")
+ _MC88100(0x04000100, "xmem.usr", "?d,1,I")
+ _MC88xxx(0xf4005000, "xor", "d,1,2")
+ _MC88xxx(0x50000000, "xor", "d,1,I")
+ _MC88xxx(0xf4005400, "xor.c", "d,1,2")
+ _MC88xxx(0x54000000, "xor.u", "d,1,I")
+ _MC88xxx(0x00000000, "", 0)
+};
+
+#define NUMOPCODES ((sizeof m88k_opcodes)/(sizeof m88k_opcodes[0]))
diff --git a/gnu/usr.bin/as/opcode/mips.h b/gnu/usr.bin/as/opcode/mips.h
new file mode 100644
index 0000000..796ed47
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/mips.h
@@ -0,0 +1,363 @@
+/* Mips opcde list for GDB, the GNU debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ Contributed by Nobuyuki Hikichi(hikichi@sra.junet)
+ Made to work for little-endian machines, and debugged
+ by Per Bothner (bothner@cs.wisc.edu).
+ Many fixes contributed by Frank Yellin (fy@lucid.com).
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if BITS_BIG_ENDIAN
+#define BIT_FIELDS_2(a,b) a;b;
+#define BIT_FIELDS_4(a,b,c,d) a;b;c;d;
+#define BIT_FIELDS_6(a,b,c,d,e,f) a;b;c;d;e;f;
+#else
+#define BIT_FIELDS_2(a,b) b;a;
+#define BIT_FIELDS_4(a,b,c,d) d;c;b;a;
+#define BIT_FIELDS_6(a,b,c,d,e,f) f;e;d;c;b;a;
+#endif
+
+struct op_i_fmt
+{
+BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned immediate : 16)
+};
+
+struct op_j_fmt
+{
+BIT_FIELDS_2(
+ unsigned op : 6,
+ unsigned target : 26)
+};
+
+struct op_r_fmt
+{
+BIT_FIELDS_6(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned rd : 5,
+ unsigned shamt : 5,
+ unsigned funct : 6)
+};
+
+
+struct fop_i_fmt
+{
+BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ unsigned immediate : 16)
+};
+
+struct op_b_fmt
+{
+BIT_FIELDS_4(
+ unsigned op : 6,
+ unsigned rs : 5,
+ unsigned rt : 5,
+ short delta : 16)
+};
+
+struct fop_r_fmt
+{
+BIT_FIELDS_6(
+ unsigned op : 6,
+ unsigned fmt : 5,
+ unsigned ft : 5,
+ unsigned fs : 5,
+ unsigned fd : 5,
+ unsigned funct : 6)
+};
+
+struct mips_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long match;
+ char *args;
+ int bdelay; /* Nonzero if delayed branch. */
+};
+
+/* args format;
+
+ "s" rs: source register specifier
+ "t" rt: target register
+ "i" immediate
+ "a" target address
+ "c" branch condition
+ "d" rd: destination register specifier
+ "h" shamt: shift amount
+ "f" funct: function field
+
+ for fpu
+ "S" fs source 1 register
+ "T" ft source 2 register
+ "D" distination register
+*/
+
+#define one(x) (x << 26)
+#define op_func(x, y) ((x << 26) | y)
+#define op_cond(x, y) ((x << 26) | (y << 16))
+#define op_rs_func(x, y, z) ((x << 26) | (y << 21) | z)
+#define op_rs_b11(x, y, z) ((x << 26) | (y << 21) | z)
+#define op_o16(x, y) ((x << 26) | (y << 16))
+#define op_bc(x, y, z) ((x << 26) | (y << 21) | (z << 16))
+
+struct mips_opcode mips_opcodes[] =
+{
+/* These first opcodes are special cases of the ones in the comments */
+ {"nop", 0, 0xffffffff, /*li*/ "", 0},
+ {"li", op_bc(9,0,0), op_bc(0x3f,31,0), /*addiu*/ "t,j", 0},
+ {"b", one(4), 0xffff0000, /*beq*/ "b", 1},
+ {"move", op_func(0, 33), op_cond(0x3f,31)|0x7ff,/*addu*/ "d,s", 0},
+
+ {"sll", op_func(0, 0), op_func(0x3f, 0x3f), "d,t,h", 0},
+ {"srl", op_func(0, 2), op_func(0x3f, 0x3f), "d,t,h", 0},
+ {"sra", op_func(0, 3), op_func(0x3f, 0x3f), "d,t,h", 0},
+ {"sllv", op_func(0, 4), op_func(0x3f, 0x7ff), "d,t,s", 0},
+ {"srlv", op_func(0, 6), op_func(0x3f, 0x7ff), "d,t,s", 0},
+ {"srav", op_func(0, 7), op_func(0x3f, 0x7ff), "d,t,s", 0},
+ {"jr", op_func(0, 8), op_func(0x3f, 0x1fffff), "s", 1},
+ {"jalr", op_func(0, 9), op_func(0x3f, 0x1f07ff), "d,s", 1},
+ {"syscall", op_func(0, 12), op_func(0x3f, 0x3f), "", 0},
+ {"break", op_func(0, 13), op_func(0x3f, 0x3f), "", 0},
+ {"mfhi", op_func(0, 16), op_func(0x3f, 0x03ff07ff), "d", 0},
+ {"mthi", op_func(0, 17), op_func(0x3f, 0x1fffff), "s", 0},
+ {"mflo", op_func(0, 18), op_func(0x3f, 0x03ff07ff), "d", 0},
+ {"mtlo", op_func(0, 19), op_func(0x3f, 0x1fffff), "s", 0},
+ {"mult", op_func(0, 24), op_func(0x3f, 0xffff), "s,t", 0},
+ {"multu", op_func(0, 25), op_func(0x3f, 0xffff), "s,t", 0},
+ {"div", op_func(0, 26), op_func(0x3f, 0xffff), "s,t", 0},
+ {"divu", op_func(0, 27), op_func(0x3f, 0xffff), "s,t", 0},
+ {"add", op_func(0, 32), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"addu", op_func(0, 33), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"sub", op_func(0, 34), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"subu", op_func(0, 35), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"and", op_func(0, 36), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"or", op_func(0, 37), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"xor", op_func(0, 38), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"nor", op_func(0, 39), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"slt", op_func(0, 42), op_func(0x3f, 0x7ff), "d,s,t", 0},
+ {"sltu", op_func(0, 43), op_func(0x3f, 0x7ff), "d,s,t", 0},
+
+ {"bltz", op_cond (1, 0), op_cond(0x3f, 0x1f), "s,b", 1},
+ {"bgez", op_cond (1, 1), op_cond(0x3f, 0x1f), "s,b", 1},
+ {"bltzal", op_cond (1, 16),op_cond(0x3f, 0x1f), "s,b", 1},
+ {"bgezal", op_cond (1, 17),op_cond(0x3f, 0x1f), "s,b", 1},
+
+
+ {"j", one(2), one(0x3f), "a", 1},
+ {"jal", one(3), one(0x3f), "a", 1},
+ {"beq", one(4), one(0x3f), "s,t,b", 1},
+ {"bne", one(5), one(0x3f), "s,t,b", 1},
+ {"blez", one(6), one(0x3f) | 0x1f0000, "s,b", 1},
+ {"bgtz", one(7), one(0x3f) | 0x1f0000, "s,b", 1},
+ {"addi", one(8), one(0x3f), "t,s,j", 0},
+ {"addiu", one(9), one(0x3f), "t,s,j", 0},
+ {"slti", one(10), one(0x3f), "t,s,j", 0},
+ {"sltiu", one(11), one(0x3f), "t,s,j", 0},
+ {"andi", one(12), one(0x3f), "t,s,i", 0},
+ {"ori", one(13), one(0x3f), "t,s,i", 0},
+ {"xori", one(14), one(0x3f), "t,s,i", 0},
+ /* rs field is don't care field? */
+ {"lui", one(15), one(0x3f), "t,i", 0},
+
+/* co processor 0 instruction */
+ {"mfc0", op_rs_b11 (16, 0, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"cfc0", op_rs_b11 (16, 2, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"mtc0", op_rs_b11 (16, 4, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"ctc0", op_rs_b11 (16, 6, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+
+ {"bc0f", op_o16(16, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc0f", op_o16(16, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc0t", op_o16(16, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc0t", op_o16(16, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+ {"tlbr", op_rs_func(16, 0x10, 1), ~0, "", 0},
+ {"tlbwi", op_rs_func(16, 0x10, 2), ~0, "", 0},
+ {"tlbwr", op_rs_func(16, 0x10, 6), ~0, "", 0},
+ {"tlbp", op_rs_func(16, 0x10, 8), ~0, "", 0},
+ {"rfe", op_rs_func(16, 0x10, 16), ~0, "", 0},
+
+ {"mfc1", op_rs_b11 (17, 0, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+ {"cfc1", op_rs_b11 (17, 2, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+ {"mtc1", op_rs_b11 (17, 4, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+ {"ctc1", op_rs_b11 (17, 6, 0), op_rs_b11(0x3f, 0x1f, 0),"t,S", 0},
+
+ {"bc1f", op_o16(17, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc1f", op_o16(17, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc1t", op_o16(17, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc1t", op_o16(17, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+/* fpu instruction */
+ {"add.s", op_rs_func(17, 0x10, 0),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"add.d", op_rs_func(17, 0x11, 0),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"sub.s", op_rs_func(17, 0x10, 1),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"sub.d", op_rs_func(17, 0x11, 1),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"mul.s", op_rs_func(17, 0x10, 2),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"mul.d", op_rs_func(17, 0x11, 2),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"div.s", op_rs_func(17, 0x10, 3),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"div.d", op_rs_func(17, 0x11, 3),
+ op_rs_func(0x3f, 0x1f, 0x3f), "D,S,T", 0},
+ {"abs.s", op_rs_func(17, 0x10, 5),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"abs.d", op_rs_func(17, 0x11, 5),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"mov.s", op_rs_func(17, 0x10, 6),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"mov.d", op_rs_func(17, 0x11, 6),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"neg.s", op_rs_func(17, 0x10, 7),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"neg.d", op_rs_func(17, 0x11, 7),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.s.s", op_rs_func(17, 0x10, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.s.d", op_rs_func(17, 0x11, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.s.w", op_rs_func(17, 0x14, 32),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.d.s", op_rs_func(17, 0x10, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.d.d", op_rs_func(17, 0x11, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.d.w", op_rs_func(17, 0x14, 33),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.w.s", op_rs_func(17, 0x10, 36),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"cvt.w.d", op_rs_func(17, 0x11, 36),
+ op_rs_func(0x3f, 0x1f, 0x1f003f), "D,S", 0},
+ {"c.f.s", op_rs_func(17, 0x10, 48),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.f.d", op_rs_func(17, 0x11, 48),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.un.s", op_rs_func(17, 0x10, 49),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.un.d", op_rs_func(17, 0x11, 49),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.eq.s", op_rs_func(17, 0x10, 50),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.eq.d", op_rs_func(17, 0x11, 50),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ueq.s", op_rs_func(17, 0x10, 51),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ueq.d", op_rs_func(17, 0x11, 51),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.olt.s", op_rs_func(17, 0x10, 52),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.olt.d", op_rs_func(17, 0x11, 52),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ult.s", op_rs_func(17, 0x10, 53),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ult.d", op_rs_func(17, 0x11, 53),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ole.s", op_rs_func(17, 0x10, 54),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ole.d", op_rs_func(17, 0x11, 54),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ule.s", op_rs_func(17, 0x10, 55),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ule.d", op_rs_func(17, 0x11, 55),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.sf.s", op_rs_func(17, 0x10, 56),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.sf.d", op_rs_func(17, 0x11, 56),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngle.s", op_rs_func(17, 0x10, 57),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngle.d", op_rs_func(17, 0x11, 57),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.seq.s", op_rs_func(17, 0x10, 58),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.seq.d", op_rs_func(17, 0x11, 58),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngl.s", op_rs_func(17, 0x10, 59),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngl.d", op_rs_func(17, 0x11, 59),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.lt.s", op_rs_func(17, 0x10, 60),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.lt.d", op_rs_func(17, 0x11, 60),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.nge.s", op_rs_func(17, 0x10, 61),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.nge.d", op_rs_func(17, 0x11, 61),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.le.s", op_rs_func(17, 0x10, 62),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.le.d", op_rs_func(17, 0x11, 62),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngt.s", op_rs_func(17, 0x10, 63),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+ {"c.ngt.d", op_rs_func(17, 0x11, 63),
+ op_rs_func(0x3f, 0x1f, 0x7ff), "S,T", 0},
+
+/* co processor 2 instruction */
+ {"mfc2", op_rs_b11 (18, 0, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"cfc2", op_rs_b11 (18, 2, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"mtc2", op_rs_b11 (18, 4, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"ctc2", op_rs_b11 (18, 6, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"bc2f", op_o16(18, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc2f", op_o16(18, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc2f", op_o16(18, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc2t", op_o16(18, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+/* co processor 3 instruction */
+ {"mtc3", op_rs_b11 (19, 0, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"cfc3", op_rs_b11 (19, 2, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"mtc3", op_rs_b11 (19, 4, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"ctc3", op_rs_b11 (19, 6, 0), op_rs_b11(0x3f, 0x1f, 0x1ffff), "t,d", 0},
+ {"bc3f", op_o16(19, 0x100), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc3f", op_o16(19, 0x180), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc3t", op_o16(19, 0x101), op_o16(0x3f, 0x3ff), "b", 1},
+ {"bc3t", op_o16(19, 0x181), op_o16(0x3f, 0x3ff), "b", 1},
+
+ {"lb", one(32), one(0x3f), "t,j(s)", 0},
+ {"lh", one(33), one(0x3f), "t,j(s)", 0},
+ {"lwl", one(34), one(0x3f), "t,j(s)", 0},
+ {"lw", one(35), one(0x3f), "t,j(s)", 0},
+ {"lbu", one(36), one(0x3f), "t,j(s)", 0},
+ {"lhu", one(37), one(0x3f), "t,j(s)", 0},
+ {"lwr", one(38), one(0x3f), "t,j(s)", 0},
+ {"sb", one(40), one(0x3f), "t,j(s)", 0},
+ {"sh", one(41), one(0x3f), "t,j(s)", 0},
+ {"swl", one(42), one(0x3f), "t,j(s)", 0},
+ {"swr", one(46), one(0x3f), "t,j(s)", 0},
+ {"sw", one(43), one(0x3f), "t,j(s)", 0},
+ {"lwc0", one(48), one(0x3f), "t,j(s)", 0},
+/* for fpu */
+ {"lwc1", one(49), one(0x3f), "T,j(s)", 0},
+ {"lwc2", one(50), one(0x3f), "t,j(s)", 0},
+ {"lwc3", one(51), one(0x3f), "t,j(s)", 0},
+ {"swc0", one(56), one(0x3f), "t,j(s)", 0},
+/* for fpu */
+ {"swc1", one(57), one(0x3f), "T,j(s)", 0},
+ {"swc2", one(58), one(0x3f), "t,j(s)", 0},
+ {"swc3", one(59), one(0x3f), "t,j(s)", 0},
+};
diff --git a/gnu/usr.bin/as/opcode/np1.h b/gnu/usr.bin/as/opcode/np1.h
new file mode 100644
index 0000000..6546825
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/np1.h
@@ -0,0 +1,422 @@
+/* Print GOULD NPL instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct gld_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long mask;
+ char *args;
+ int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and at most four. The length of the
+ instruction is based on the opcode.
+
+ The mask component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing characters
+ that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+ r Register in first field
+ R Register in second field
+ b Base register in first field
+ B Base register in second field
+ v Vector register in first field
+ V Vector register in first field
+ A Optional address register (base register)
+ X Optional index register
+ I Immediate data (16bits signed)
+ O Offset field (16bits signed)
+ h Offset field (15bits signed)
+ d Offset field (14bits signed)
+ S Shift count field
+
+ any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "lb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lbs", 0xec080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lnh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ld", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lnd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "li", 0xf8000000, 0xfc7f0000, "r,I", 4 },
+{ "lpa", 0x50080000, 0xfc080000, "r,xOA,X", 4 },
+{ "la", 0x50000000, 0xfc080000, "r,xOA,X", 4 },
+{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lbp", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lhp", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lwp", 0x90000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ldp", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
+{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
+{ "lf", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lfbr", 0xbc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
+{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stfbr", 0xdc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "zmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "zmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stbp", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sthp", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stwp", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stdp", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lil", 0xf80b0000, 0xfc7f0000, "r,D", 4 },
+{ "lwsl1", 0xec000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwsl2", 0xfc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwsl3", 0xfc080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "lvb", 0xb0080000, 0xfc080000, "v,xOA,X", 4 },
+{ "lvh", 0xb0000001, 0xfc080001, "v,xOA,X", 4 },
+{ "lvw", 0xb0000000, 0xfc080000, "v,xOA,X", 4 },
+{ "lvd", 0xb0000002, 0xfc080002, "v,xOA,X", 4 },
+{ "liv", 0x3c040000, 0xfc0f0000, "v,R", 2 },
+{ "livf", 0x3c080000, 0xfc0f0000, "v,R", 2 },
+{ "stvb", 0xd0080000, 0xfc080000, "v,xOA,X", 4 },
+{ "stvh", 0xd0000001, 0xfc080001, "v,xOA,X", 4 },
+{ "stvw", 0xd0000000, 0xfc080000, "v,xOA,X", 4 },
+{ "stvd", 0xd0000002, 0xfc080002, "v,xOA,X", 4 },
+
+{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
+{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
+{ "trnd", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
+{ "trabs", 0x2c010000, 0xfc0f0000, "r,R", 2 },
+{ "trabsd", 0x2c090000, 0xfc0f0000, "r,R", 2 },
+{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
+{ "xcr", 0x28040000, 0xfc0f0000, "r,R", 2 },
+{ "cxcr", 0x2c060000, 0xfc0f0000, "r,R", 2 },
+{ "cxcrd", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
+{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
+{ "trbr", 0x28030000, 0xfc0f0000, "b,R", 2 },
+{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
+{ "tbrbr", 0x28010000, 0xfc0f0000, "b,B", 2 },
+
+{ "trvv", 0x28050000, 0xfc0f0000, "v,V", 2 },
+{ "trvvn", 0x2c050000, 0xfc0f0000, "v,V", 2 },
+{ "trvvnd", 0x2c0d0000, 0xfc0f0000, "v,V", 2 },
+{ "trvab", 0x2c070000, 0xfc0f0000, "v,V", 2 },
+{ "trvabd", 0x2c0f0000, 0xfc0f0000, "v,V", 2 },
+{ "cmpv", 0x14060000, 0xfc0f0000, "v,V", 2 },
+{ "expv", 0x14070000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvlt", 0x10030000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvle", 0x10040000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvgt", 0x14030000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvge", 0x14040000, 0xfc0f0000, "v,V", 2 },
+{ "mrvveq", 0x10050000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvne", 0x10050000, 0xfc0f0000, "v,V", 2 },
+{ "mrvrlt", 0x100d0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrle", 0x100e0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrgt", 0x140d0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrge", 0x140e0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvreq", 0x100f0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrne", 0x140f0000, 0xfc0f0000, "v,R", 2 },
+{ "trvr", 0x140b0000, 0xfc0f0000, "r,V", 2 },
+{ "trrv", 0x140c0000, 0xfc0f0000, "v,R", 2 },
+
+{ "bu", 0x40000000, 0xff880000, "xOA,X", 4 },
+{ "bns", 0x70080000, 0xff880000, "xOA,X", 4 },
+{ "bnco", 0x70880000, 0xff880000, "xOA,X", 4 },
+{ "bge", 0x71080000, 0xff880000, "xOA,X", 4 },
+{ "bne", 0x71880000, 0xff880000, "xOA,X", 4 },
+{ "bunge", 0x72080000, 0xff880000, "xOA,X", 4 },
+{ "bunle", 0x72880000, 0xff880000, "xOA,X", 4 },
+{ "bgt", 0x73080000, 0xff880000, "xOA,X", 4 },
+{ "bnany", 0x73880000, 0xff880000, "xOA,X", 4 },
+{ "bs" , 0x70000000, 0xff880000, "xOA,X", 4 },
+{ "bco", 0x70800000, 0xff880000, "xOA,X", 4 },
+{ "blt", 0x71000000, 0xff880000, "xOA,X", 4 },
+{ "beq", 0x71800000, 0xff880000, "xOA,X", 4 },
+{ "buge", 0x72000000, 0xff880000, "xOA,X", 4 },
+{ "bult", 0x72800000, 0xff880000, "xOA,X", 4 },
+{ "ble", 0x73000000, 0xff880000, "xOA,X", 4 },
+{ "bany", 0x73800000, 0xff880000, "xOA,X", 4 },
+{ "brlnk", 0x44000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bib", 0x48000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bih", 0x48080000, 0xfc080000, "r,xOA,X", 4 },
+{ "biw", 0x4c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bid", 0x4c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivb", 0x60000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivh", 0x60080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivw", 0x64000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivd", 0x64080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsb", 0x68000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsh", 0x68080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsw", 0x6c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsd", 0x6c080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "camb", 0x80080000, 0xfc080000, "r,xOA,X", 4 },
+{ "camh", 0x80000001, 0xfc080001, "r,xOA,X", 4 },
+{ "camw", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
+{ "camd", 0x80000002, 0xfc080002, "r,xOA,X", 4 },
+{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
+{ "card", 0x14000000, 0xfc0f0000, "r,R", 2 },
+{ "ci", 0xf8050000, 0xfc7f0000, "r,I", 4 },
+{ "chkbnd", 0x5c080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "cavv", 0x10010000, 0xfc0f0000, "v,V", 2 },
+{ "cavr", 0x10020000, 0xfc0f0000, "v,R", 2 },
+{ "cavvd", 0x10090000, 0xfc0f0000, "v,V", 2 },
+{ "cavrd", 0x100b0000, 0xfc0f0000, "v,R", 2 },
+
+{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
+{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
+{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
+{ "ani", 0xf8080000, 0xfc7f0000, "r,I", 4 },
+{ "ormb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "ormw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
+{ "oi", 0xf8090000, 0xfc7f0000, "r,I", 4 },
+{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
+{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
+{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
+{ "eoi", 0xf80a0000, 0xfc7f0000, "r,I", 4 },
+
+{ "anvv", 0x04010000, 0xfc0f0000, "v,V", 2 },
+{ "anvr", 0x04020000, 0xfc0f0000, "v,R", 2 },
+{ "orvv", 0x08010000, 0xfc0f0000, "v,V", 2 },
+{ "orvr", 0x08020000, 0xfc0f0000, "v,R", 2 },
+{ "eovv", 0x0c010000, 0xfc0f0000, "v,V", 2 },
+{ "eovr", 0x0c020000, 0xfc0f0000, "v,R", 2 },
+
+{ "sacz", 0x100c0000, 0xfc0f0000, "r,R", 2 },
+{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
+{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
+{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
+{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
+{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
+{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
+{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
+{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
+{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
+{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
+{ "sda", 0x3c030000, 0xfc0f0000, "r,R", 2 },
+{ "sdl", 0x3c020000, 0xfc0f0000, "r,R", 2 },
+{ "sdc", 0x3c010000, 0xfc0f0000, "r,R", 2 },
+{ "sdad", 0x3c0b0000, 0xfc0f0000, "r,R", 2 },
+{ "sdld", 0x3c0a0000, 0xfc0f0000, "r,R", 2 },
+
+{ "svda", 0x3c070000, 0xfc0f0000, "v,R", 2 },
+{ "svdl", 0x3c060000, 0xfc0f0000, "v,R", 2 },
+{ "svdc", 0x3c050000, 0xfc0f0000, "v,R", 2 },
+{ "svdad", 0x3c0e0000, 0xfc0f0000, "v,R", 2 },
+{ "svdld", 0x3c0d0000, 0xfc0f0000, "v,R", 2 },
+
+{ "sbm", 0xac080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zbm", 0xac000000, 0xfc080000, "f,xOA,X", 4 },
+{ "tbm", 0xa8080000, 0xfc080000, "f,xOA,X", 4 },
+{ "incmb", 0xa0000000, 0xfc080000, "xOA,X", 4 },
+{ "incmh", 0xa0080000, 0xfc080000, "xOA,X", 4 },
+{ "incmw", 0xa4000000, 0xfc080000, "xOA,X", 4 },
+{ "incmd", 0xa4080000, 0xfc080000, "xOA,X", 4 },
+{ "sbmd", 0x7c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zbmd", 0x7c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "tbmd", 0x78080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "ssm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zsm", 0x9c000000, 0xfc080000, "f,xOA,X", 4 },
+{ "tsm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
+
+{ "admb", 0xc8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "admh", 0xc8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "admw", 0xc8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "admd", 0xc8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
+{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "adi", 0xf8010000, 0xfc0f0000, "r,I", 4 },
+{ "sumb", 0xcc080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumh", 0xcc000001, 0xfc080001, "r,xOA,X", 4 },
+{ "sumw", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumd", 0xcc000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
+{ "sui", 0xf8020000, 0xfc0f0000, "r,I", 4 },
+{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
+{ "mprd", 0x3c0f0000, 0xfc0f0000, "r,R", 2 },
+{ "mpi", 0xf8030000, 0xfc0f0000, "r,I", 4 },
+{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
+{ "dvi", 0xf8040000, 0xfc0f0000, "r,I", 4 },
+{ "exs", 0x38080000, 0xfc0f0000, "r,R", 2 },
+
+{ "advv", 0x30000000, 0xfc0f0000, "v,V", 2 },
+{ "advvd", 0x30080000, 0xfc0f0000, "v,V", 2 },
+{ "adrv", 0x34000000, 0xfc0f0000, "v,R", 2 },
+{ "adrvd", 0x34080000, 0xfc0f0000, "v,R", 2 },
+{ "suvv", 0x30010000, 0xfc0f0000, "v,V", 2 },
+{ "suvvd", 0x30090000, 0xfc0f0000, "v,V", 2 },
+{ "surv", 0x34010000, 0xfc0f0000, "v,R", 2 },
+{ "survd", 0x34090000, 0xfc0f0000, "v,R", 2 },
+{ "mpvv", 0x30020000, 0xfc0f0000, "v,V", 2 },
+{ "mprv", 0x34020000, 0xfc0f0000, "v,R", 2 },
+
+{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
+{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
+{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
+{ "surfw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "surfd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
+{ "surfd", 0x380b0000, 0xfc0f0000, "r,R", 2 },
+{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
+{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
+{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
+{ "rfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "rfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "rrfw", 0x0c0e0000, 0xfc0f0000, "r", 2 },
+{ "rrfd", 0x0c0f0000, 0xfc0f0000, "r", 2 },
+
+{ "advvfw", 0x30040000, 0xfc0f0000, "v,V", 2 },
+{ "advvfd", 0x300c0000, 0xfc0f0000, "v,V", 2 },
+{ "adrvfw", 0x34040000, 0xfc0f0000, "v,R", 2 },
+{ "adrvfd", 0x340c0000, 0xfc0f0000, "v,R", 2 },
+{ "suvvfw", 0x30050000, 0xfc0f0000, "v,V", 2 },
+{ "suvvfd", 0x300d0000, 0xfc0f0000, "v,V", 2 },
+{ "survfw", 0x34050000, 0xfc0f0000, "v,R", 2 },
+{ "survfd", 0x340d0000, 0xfc0f0000, "v,R", 2 },
+{ "mpvvfw", 0x30060000, 0xfc0f0000, "v,V", 2 },
+{ "mpvvfd", 0x300e0000, 0xfc0f0000, "v,V", 2 },
+{ "mprvfw", 0x34060000, 0xfc0f0000, "v,R", 2 },
+{ "mprvfd", 0x340e0000, 0xfc0f0000, "v,R", 2 },
+{ "rvfw", 0x30070000, 0xfc0f0000, "v", 2 },
+{ "rvfd", 0x300f0000, 0xfc0f0000, "v", 2 },
+
+{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
+{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
+{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
+{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
+{ "cfpds", 0x3c090000, 0xfc0f0000, "r,R", 2 },
+
+{ "fltvw", 0x080d0000, 0xfc0f0000, "v,V", 2 },
+{ "fltvd", 0x080f0000, 0xfc0f0000, "v,V", 2 },
+{ "fixvw", 0x080c0000, 0xfc0f0000, "v,V", 2 },
+{ "fixvd", 0x080e0000, 0xfc0f0000, "v,V", 2 },
+{ "cfpvds", 0x0c0d0000, 0xfc0f0000, "v,V", 2 },
+
+{ "orvrn", 0x000a0000, 0xfc0f0000, "r,V", 2 },
+{ "andvrn", 0x00080000, 0xfc0f0000, "r,V", 2 },
+{ "frsteq", 0x04090000, 0xfc0f0000, "r,V", 2 },
+{ "sigma", 0x0c080000, 0xfc0f0000, "r,V", 2 },
+{ "sigmad", 0x0c0a0000, 0xfc0f0000, "r,V", 2 },
+{ "sigmf", 0x08080000, 0xfc0f0000, "r,V", 2 },
+{ "sigmfd", 0x080a0000, 0xfc0f0000, "r,V", 2 },
+{ "prodf", 0x04080000, 0xfc0f0000, "r,V", 2 },
+{ "prodfd", 0x040a0000, 0xfc0f0000, "r,V", 2 },
+{ "maxv", 0x10080000, 0xfc0f0000, "r,V", 2 },
+{ "maxvd", 0x100a0000, 0xfc0f0000, "r,V", 2 },
+{ "minv", 0x14080000, 0xfc0f0000, "r,V", 2 },
+{ "minvd", 0x140a0000, 0xfc0f0000, "r,V", 2 },
+
+{ "lpsd", 0xf0000000, 0xfc080000, "xOA,X", 4 },
+{ "ldc", 0xf0080000, 0xfc080000, "xOA,X", 4 },
+{ "spm", 0x040c0000, 0xfc0f0000, "r", 2 },
+{ "rpm", 0x040d0000, 0xfc0f0000, "r", 2 },
+{ "tritr", 0x00070000, 0xfc0f0000, "r", 2 },
+{ "trrit", 0x00060000, 0xfc0f0000, "r", 2 },
+{ "rpswt", 0x04080000, 0xfc0f0000, "r", 2 },
+{ "exr", 0xf8070000, 0xfc0f0000, "", 4 },
+{ "halt", 0x00000000, 0xfc0f0000, "", 2 },
+{ "wait", 0x00010000, 0xfc0f0000, "", 2 },
+{ "nop", 0x00020000, 0xfc0f0000, "", 2 },
+{ "eiae", 0x00030000, 0xfc0f0000, "", 2 },
+{ "efae", 0x000d0000, 0xfc0f0000, "", 2 },
+{ "diae", 0x000e0000, 0xfc0f0000, "", 2 },
+{ "dfae", 0x000f0000, 0xfc0f0000, "", 2 },
+{ "spvc", 0xf8060000, 0xfc0f0000, "r,T,N", 4 },
+{ "rdsts", 0x00090000, 0xfc0f0000, "r", 2 },
+{ "setcpu", 0x000c0000, 0xfc0f0000, "r", 2 },
+{ "cmc", 0x000b0000, 0xfc0f0000, "r", 2 },
+{ "trrcu", 0x00040000, 0xfc0f0000, "r", 2 },
+{ "attnio", 0x00050000, 0xfc0f0000, "", 2 },
+{ "fudit", 0x28080000, 0xfc0f0000, "", 2 },
+{ "break", 0x28090000, 0xfc0f0000, "", 2 },
+{ "frzss", 0x280a0000, 0xfc0f0000, "", 2 },
+{ "ripi", 0x04040000, 0xfc0f0000, "r,R", 2 },
+{ "xcp", 0x04050000, 0xfc0f0000, "r", 2 },
+{ "block", 0x04060000, 0xfc0f0000, "", 2 },
+{ "unblock", 0x04070000, 0xfc0f0000, "", 2 },
+{ "trsc", 0x08060000, 0xfc0f0000, "r,R", 2 },
+{ "tscr", 0x08070000, 0xfc0f0000, "r,R", 2 },
+{ "fq", 0x04080000, 0xfc0f0000, "r", 2 },
+{ "flupte", 0x2c080000, 0xfc0f0000, "r", 2 },
+{ "rviu", 0x040f0000, 0xfc0f0000, "", 2 },
+{ "ldel", 0x280c0000, 0xfc0f0000, "r,R", 2 },
+{ "ldu", 0x280d0000, 0xfc0f0000, "r,R", 2 },
+{ "stdecc", 0x280b0000, 0xfc0f0000, "r,R", 2 },
+{ "trpc", 0x08040000, 0xfc0f0000, "r", 2 },
+{ "tpcr", 0x08050000, 0xfc0f0000, "r", 2 },
+{ "ghalt", 0x0c050000, 0xfc0f0000, "r", 2 },
+{ "grun", 0x0c040000, 0xfc0f0000, "", 2 },
+{ "tmpr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
+{ "trmp", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
+
+{ "trrve", 0x28060000, 0xfc0f0000, "r", 2 },
+{ "trver", 0x28070000, 0xfc0f0000, "r", 2 },
+{ "trvlr", 0x280f0000, 0xfc0f0000, "r", 2 },
+
+{ "linkfl", 0x18000000, 0xfc0f0000, "r,R", 2 },
+{ "linkbl", 0x18020000, 0xfc0f0000, "r,R", 2 },
+{ "linkfp", 0x18010000, 0xfc0f0000, "r,R", 2 },
+{ "linkbp", 0x18030000, 0xfc0f0000, "r,R", 2 },
+{ "linkpl", 0x18040000, 0xfc0f0000, "r,R", 2 },
+{ "ulinkl", 0x18080000, 0xfc0f0000, "r,R", 2 },
+{ "ulinkp", 0x18090000, 0xfc0f0000, "r,R", 2 },
+{ "ulinktl", 0x180a0000, 0xfc0f0000, "r,R", 2 },
+{ "ulinktp", 0x180b0000, 0xfc0f0000, "r,R", 2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+ sizeof(gld_opcodes[0]);
diff --git a/gnu/usr.bin/as/opcode/ns32k.h b/gnu/usr.bin/as/opcode/ns32k.h
new file mode 100644
index 0000000..e513e64
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/ns32k.h
@@ -0,0 +1,491 @@
+/* ns32k-opcode.h -- Opcode table for National Semi 32k processor
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#ifdef TE_SEQUENT
+#define DEF_MODEC 20
+#define DEF_MODEL 21
+#endif
+
+#ifndef DEF_MODEC
+#define DEF_MODEC 20
+#endif
+
+#ifndef DEF_MODEL
+#define DEF_MODEL 20
+#endif
+/*
+ After deciding the instruction entry (via hash.c) the instruction parser
+ will try to match the operands after the instruction to the required set
+ given in the entry operandfield. Every operand will result in a change in
+ the opcode or the addition of data to the opcode.
+ The operands in the source instruction are checked for inconsistent
+ semantics.
+
+ F : 32 bit float general form
+ L : 64 bit float "
+ B : byte "
+ W : word "
+ D : double-word "
+ Q : quad-word "
+ A : double-word gen-address-form ie no regs allowed
+ d : displacement
+ b : displacement - pc relative addressing acb
+ p : displacement - pc relative addressing br bcond bsr cxp
+ q : quick
+ i : immediate (8 bits)
+ This is not a standard ns32k operandtype, it is used to build
+ instructions like svc arg1,arg2
+ Svc is the instruction SuperVisorCall and is sometimes used to
+ call OS-routines from usermode. Some args might be handy!
+ r : register number (3 bits)
+ O : setcfg instruction optionslist
+ C : cinv instruction optionslist
+ S : stringinstruction optionslist
+ U : registerlist save,enter
+ u : registerlist restore,exit
+ M : mmu register
+ P : cpu register
+ g : 3:rd operand of inss or exts instruction
+ G : 4:th operand of inss or exts instruction
+ Those operands are encoded in the same byte.
+ This byte is placed last in the instruction.
+ f : operand of sfsr
+ H : sequent-hack for bsr (Warning)
+
+column 1 instructions
+ 2 number of bits in opcode.
+ 3 number of bits in opcode explicitly
+ determined by the instruction type.
+ 4 opcodeseed, the number we build our opcode
+ from.
+ 5 operandtypes, used by operandparser.
+ 6 size in bytes of immediate
+*/
+struct ns32k_opcode {
+ char *name;
+ unsigned char opcode_id_size; /* not used by the assembler */
+ unsigned char opcode_size;
+ unsigned long opcode_seed;
+ char *operands;
+ unsigned char im_size; /* not used by dissassembler */
+ char *default_args; /* default to those args when none given */
+ char default_modec; /* default to this addr-mode when ambigous
+ ie when the argument of a general addr-mode
+ is a plain constant */
+ char default_model; /* is a plain label */
+};
+
+#ifdef comment
+/* This section was from the gdb version of this file. */
+
+#ifndef ns32k_opcodeT
+#define ns32k_opcodeT int
+#endif /* no ns32k_opcodeT */
+
+struct not_wot /* ns32k opcode table: wot to do with this */
+ /* particular opcode */
+{
+ int obits; /* number of opcode bits */
+ int ibits; /* number of instruction bits */
+ ns32k_opcodeT code; /* op-code (may be > 8 bits!) */
+ char *args; /* how to compile said opcode */
+};
+
+struct not /* ns32k opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct not_wot detail; /* rest of opcode table [datum] */
+};
+
+/* Instructions look like this:
+
+ basic instruction--1, 2, or 3 bytes
+ index byte for operand A, if operand A is indexed--1 byte
+ index byte for operand B, if operand B is indexed--1 byte
+ addressing extension for operand A
+ addressing extension for operand B
+ implied operands
+
+ Operand A is the operand listed first in the following opcode table.
+ Operand B is the operand listed second in the following opcode table.
+ All instructions have at most 2 general operands, so this is enough.
+ The implied operands are associated with operands other than A and B.
+
+ Each operand has a digit and a letter.
+
+ The digit gives the position in the assembly language. The letter,
+ one of the following, tells us what kind of operand it is. */
+
+/* F : 32 bit float
+ * L : 64 bit float
+ * B : byte
+ * W : word
+ * D : double-word
+ * Q : quad-word
+ * d : displacement
+ * q : quick
+ * i : immediate (8 bits)
+ * r : register number (3 bits)
+ * p : displacement - pc relative addressing
+*/
+
+
+#endif /* comment */
+
+static const struct ns32k_opcode ns32k_opcodes[]=
+{
+ { "absf", 14,24, 0x35be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "absl", 14,24, 0x34be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "absb", 14,24, 0x304e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "absw", 14,24, 0x314e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "absd", 14,24, 0x334e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "acbb", 7,16, 0x4c, "2B1q3p", 1, "", DEF_MODEC,DEF_MODEL },
+ { "acbw", 7,16, 0x4d, "2W1q3p", 2, "", DEF_MODEC,DEF_MODEL },
+ { "acbd", 7,16, 0x4f, "2D1q3p", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addf", 14,24, 0x01be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addl", 14,24, 0x00be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "addb", 6,16, 0x00, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addw", 6,16, 0x01, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addd", 6,16, 0x03, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addcb", 6,16, 0x10, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addcw", 6,16, 0x11, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addcd", 6,16, 0x13, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addpb", 14,24, 0x3c4e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addpw", 14,24, 0x3d4e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addpd", 14,24, 0x3f4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addqb", 7,16, 0x0c, "2B1q", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addqw", 7,16, 0x0d, "2W1q", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addqd", 7,16, 0x0f, "2D1q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addr", 6,16, 0x27, "1A2D", 4, "", 21,21 },
+ { "adjspb", 11,16, 0x057c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "adjspw", 11,16, 0x057d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "adjspd", 11,16, 0x057f, "1D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "andb", 6,16, 0x28, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "andw", 6,16, 0x29, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "andd", 6,16, 0x2b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "ashb", 14,24, 0x044e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ashw", 14,24, 0x054e, "1B2W", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ashd", 14,24, 0x074e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "beq", 8,8, 0x0a, "1p", 0, "", 21,21 },
+ { "bne", 8,8, 0x1a, "1p", 0, "", 21,21 },
+ { "bcs", 8,8, 0x2a, "1p", 0, "", 21,21 },
+ { "bcc", 8,8, 0x3a, "1p", 0, "", 21,21 },
+ { "bhi", 8,8, 0x4a, "1p", 0, "", 21,21 },
+ { "bls", 8,8, 0x5a, "1p", 0, "", 21,21 },
+ { "bgt", 8,8, 0x6a, "1p", 0, "", 21,21 },
+ { "ble", 8,8, 0x7a, "1p", 0, "", 21,21 },
+ { "bfs", 8,8, 0x8a, "1p", 0, "", 21,21 },
+ { "bfc", 8,8, 0x9a, "1p", 0, "", 21,21 },
+ { "blo", 8,8, 0xaa, "1p", 0, "", 21,21 },
+ { "bhs", 8,8, 0xba, "1p", 0, "", 21,21 },
+ { "blt", 8,8, 0xca, "1p", 0, "", 21,21 },
+ { "bge", 8,8, 0xda, "1p", 0, "", 21,21 },
+ { "but", 8,8, 0xea, "1p", 0, "", 21,21 },
+ { "buf", 8,8, 0xfa, "1p", 0, "", 21,21 },
+ { "bicb", 6,16, 0x08, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "bicw", 6,16, 0x09, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "bicd", 6,16, 0x0b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "bicpsrb", 11,16, 0x17c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "bicpsrw", 11,16, 0x17d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "bispsrb", 11,16, 0x37c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "bispsrw", 11,16, 0x37d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "bpt", 8,8, 0xf2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "br", 8,8, 0xea, "1p", 0, "", 21,21 },
+#ifdef TE_SEQUENT
+ { "bsr", 8,8, 0x02, "1H", 0, "", 21,21 },
+#else
+ { "bsr", 8,8, 0x02, "1p", 0, "", 21,21 },
+#endif
+ { "caseb", 11,16, 0x77c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "casew", 11,16, 0x77d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cased", 11,16, 0x77f, "1D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cbitb", 14,24, 0x084e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cbitw", 14,24, 0x094e, "1W2D", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cbitd", 14,24, 0x0b4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cbitib", 14,24, 0x0c4e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cbitiw", 14,24, 0x0d4e, "1W2D", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cbitid", 14,24, 0x0f4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "checkb", 11,24, 0x0ee, "2A3B1r", 1, "", DEF_MODEC,DEF_MODEL },
+ { "checkw", 11,24, 0x1ee, "2A3W1r", 2, "", DEF_MODEC,DEF_MODEL },
+ { "checkd", 11,24, 0x3ee, "2A3D1r", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cinv", 14,24, 0x271e, "2D1C", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpf", 14,24, 0x09be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpl", 14,24, 0x08be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "cmpb", 6,16, 0x04, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cmpw", 6,16, 0x05, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cmpd", 6,16, 0x07, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpmb", 14,24, 0x04ce, "1A2A3b", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cmpmw", 14,24, 0x05ce, "1A2A3b", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cmpmd", 14,24, 0x07ce, "1A2A3b", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpqb", 7,16, 0x1c, "2B1q", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cmpqw", 7,16, 0x1d, "2W1q", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cmpqd", 7,16, 0x1f, "2D1q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpsb", 16,24, 0x040e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "cmpsw", 16,24, 0x050e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "cmpsd", 16,24, 0x070e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "cmpst", 16,24, 0x840e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "comb", 14,24, 0x344e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "comw", 14,24, 0x354e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "comd", 14,24, 0x374e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cvtp", 11,24, 0x036e, "2A3D1r", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cxp", 8,8, 0x22, "1p", 0, "", 21,21 },
+ { "cxpd", 11,16, 0x07f, "1A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "deib", 14,24, 0x2cce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL },
+ { "deiw", 14,24, 0x2dce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL },
+ { "deid", 14,24, 0x2fce, "1D2Q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "dia", 8,8, 0xc2, "", 1, "", DEF_MODEC,DEF_MODEL },
+ { "divf", 14,24, 0x21be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "divl", 14,24, 0x20be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "divb", 14,24, 0x3cce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "divw", 14,24, 0x3dce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "divd", 14,24, 0x3fce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "enter", 8,8, 0x82, "1U2d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "exit", 8,8, 0x92, "1u", 0, "", DEF_MODEC,DEF_MODEL },
+ { "extb", 11,24, 0x02e, "2D3B1r4d", 1, "", DEF_MODEC,DEF_MODEL },
+ { "extw", 11,24, 0x12e, "2D3W1r4d", 2, "", DEF_MODEC,DEF_MODEL },
+ { "extd", 11,24, 0x32e, "2D3D1r4d", 4, "", DEF_MODEC,DEF_MODEL },
+ { "extsb", 14,24, 0x0cce, "1D2B3g4G", 1, "", DEF_MODEC,DEF_MODEL },
+ { "extsw", 14,24, 0x0dce, "1D2W3g4G", 2, "", DEF_MODEC,DEF_MODEL },
+ { "extsd", 14,24, 0x0fce, "1D2D3g4G", 4, "", DEF_MODEC,DEF_MODEL },
+ { "ffsb", 14,24, 0x046e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ffsw", 14,24, 0x056e, "1W2B", 2, "", DEF_MODEC,DEF_MODEL },
+ { "ffsd", 14,24, 0x076e, "1D2B", 4, "", DEF_MODEC,DEF_MODEL },
+ { "flag", 8,8, 0xd2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "floorfb", 14,24, 0x3c3e, "1F2B", 4, "", DEF_MODEC,DEF_MODEL },
+ { "floorfw", 14,24, 0x3d3e, "1F2W", 4, "", DEF_MODEC,DEF_MODEL },
+ { "floorfd", 14,24, 0x3f3e, "1F2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "floorlb", 14,24, 0x383e, "1L2B", 8, "", DEF_MODEC,DEF_MODEL },
+ { "floorlw", 14,24, 0x393e, "1L2W", 8, "", DEF_MODEC,DEF_MODEL },
+ { "floorld", 14,24, 0x3b3e, "1L2D", 8, "", DEF_MODEC,DEF_MODEL },
+ { "ibitb", 14,24, 0x384e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ibitw", 14,24, 0x394e, "1W2D", 2, "", DEF_MODEC,DEF_MODEL },
+ { "ibitd", 14,24, 0x3b4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "indexb", 11,24, 0x42e, "2B3B1r", 1, "", DEF_MODEC,DEF_MODEL },
+ { "indexw", 11,24, 0x52e, "2W3W1r", 2, "", DEF_MODEC,DEF_MODEL },
+ { "indexd", 11,24, 0x72e, "2D3D1r", 4, "", DEF_MODEC,DEF_MODEL },
+ { "insb", 11,24, 0x0ae, "2B3B1r4d", 1, "", DEF_MODEC,DEF_MODEL },
+ { "insw", 11,24, 0x1ae, "2W3W1r4d", 2, "", DEF_MODEC,DEF_MODEL },
+ { "insd", 11,24, 0x3ae, "2D3D1r4d", 4, "", DEF_MODEC,DEF_MODEL },
+ { "inssb", 14,24, 0x08ce, "1B2D3g4G", 1, "", DEF_MODEC,DEF_MODEL },
+ { "inssw", 14,24, 0x09ce, "1W2D3g4G", 2, "", DEF_MODEC,DEF_MODEL },
+ { "inssd", 14,24, 0x0bce, "1D2D3g4G", 4, "", DEF_MODEC,DEF_MODEL },
+ { "jsr", 11,16, 0x67f, "1A", 4, "", 21,21 },
+ { "jump", 11,16, 0x27f, "1A", 4, "", 21,21 },
+ { "lfsr", 19,24, 0x00f3e,"1D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "lmr", 15,24, 0x0b1e, "2D1M", 4, "", DEF_MODEC,DEF_MODEL },
+ { "lprb", 7,16, 0x6c, "2B1P", 1, "", DEF_MODEC,DEF_MODEL },
+ { "lprw", 7,16, 0x6d, "2W1P", 2, "", DEF_MODEC,DEF_MODEL },
+ { "lprd", 7,16, 0x6f, "2D1P", 4, "", DEF_MODEC,DEF_MODEL },
+ { "lshb", 14,24, 0x144e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "lshw", 14,24, 0x154e, "1B2W", 1, "", DEF_MODEC,DEF_MODEL },
+ { "lshd", 14,24, 0x174e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "meib", 14,24, 0x24ce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL },
+ { "meiw", 14,24, 0x25ce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL },
+ { "meid", 14,24, 0x27ce, "1D2Q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "modb", 14,24, 0x38ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "modw", 14,24, 0x39ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "modd", 14,24, 0x3bce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movf", 14,24, 0x05be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movl", 14,24, 0x04be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "movb", 6,16, 0x14, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movw", 6,16, 0x15, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movd", 6,16, 0x17, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movbf", 14,24, 0x043e, "1B2F", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movwf", 14,24, 0x053e, "1W2F", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movdf", 14,24, 0x073e, "1D2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movbl", 14,24, 0x003e, "1B2L", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movwl", 14,24, 0x013e, "1W2L", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movdl", 14,24, 0x033e, "1D2L", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movfl", 14,24, 0x1b3e, "1F2L", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movlf", 14,24, 0x163e, "1L2F", 8, "", DEF_MODEC,DEF_MODEL },
+ { "movmb", 14,24, 0x00ce, "1A2A3b", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movmw", 14,24, 0x01ce, "1A2A3b", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movmd", 14,24, 0x03ce, "1A2A3b", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movqb", 7,16, 0x5c, "2B1q", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movqw", 7,16, 0x5d, "2B1q", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movqd", 7,16, 0x5f, "2B1q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movsb", 16,24, 0x000e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movsw", 16,24, 0x010e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movsd", 16,24, 0x030e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movst", 16,24, 0x800e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movsub", 14,24, 0x0cae, "1A2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movsuw", 14,24, 0x0dae, "1A2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movsud", 14,24, 0x0fae, "1A2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movusb", 14,24, 0x1cae, "1A2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movusw", 14,24, 0x1dae, "1A2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movusd", 14,24, 0x1fae, "1A2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movxbd", 14,24, 0x1cce, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movxwd", 14,24, 0x1dce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movxbw", 14,24, 0x10ce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movzbd", 14,24, 0x18ce, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movzwd", 14,24, 0x19ce, "1W2D", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movzbw", 14,24, 0x14ce, "1B2W", 1, "", DEF_MODEC,DEF_MODEL },
+ { "mulf", 14,24, 0x31be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "mull", 14,24, 0x30be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "mulb", 14,24, 0x20ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "mulw", 14,24, 0x21ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "muld", 14,24, 0x23ce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "negf", 14,24, 0x15be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "negl", 14,24, 0x14be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "negb", 14,24, 0x204e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "negw", 14,24, 0x214e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "negd", 14,24, 0x234e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "nop", 8,8, 0xa2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "notb", 14,24, 0x244e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "notw", 14,24, 0x254e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "notd", 14,24, 0x274e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "orb", 6,16, 0x18, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "orw", 6,16, 0x19, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "ord", 6,16, 0x1b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "quob", 14,24, 0x30ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "quow", 14,24, 0x31ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "quod", 14,24, 0x33ce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "rdval", 19,24, 0x0031e,"1A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "remb", 14,24, 0x34ce, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "remw", 14,24, 0x35ce, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "remd", 14,24, 0x37ce, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "restore", 8,8, 0x72, "1u", 0, "", DEF_MODEC,DEF_MODEL },
+ { "ret", 8,8, 0x12, "1d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "reti", 8,8, 0x52, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "rett", 8,8, 0x42, "1d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "rotb", 14,24, 0x004e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "rotw", 14,24, 0x014e, "1B2W", 1, "", DEF_MODEC,DEF_MODEL },
+ { "rotd", 14,24, 0x034e, "1B2D", 1, "", DEF_MODEC,DEF_MODEL },
+ { "roundfb", 14,24, 0x243e, "1F2B", 4, "", DEF_MODEC,DEF_MODEL },
+ { "roundfw", 14,24, 0x253e, "1F2W", 4, "", DEF_MODEC,DEF_MODEL },
+ { "roundfd", 14,24, 0x273e, "1F2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "roundlb", 14,24, 0x203e, "1L2B", 8, "", DEF_MODEC,DEF_MODEL },
+ { "roundlw", 14,24, 0x213e, "1L2W", 8, "", DEF_MODEC,DEF_MODEL },
+ { "roundld", 14,24, 0x233e, "1L2D", 8, "", DEF_MODEC,DEF_MODEL },
+ { "rxp", 8,8, 0x32, "1d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "seqb", 11,16, 0x3c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "seqw", 11,16, 0x3d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "seqd", 11,16, 0x3f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sneb", 11,16, 0xbc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "snew", 11,16, 0xbd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sned", 11,16, 0xbf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "scsb", 11,16, 0x13c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "scsw", 11,16, 0x13d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "scsd", 11,16, 0x13f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sccb", 11,16, 0x1bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sccw", 11,16, 0x1bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sccd", 11,16, 0x1bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shib", 11,16, 0x23c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shiw", 11,16, 0x23d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shid", 11,16, 0x23f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slsb", 11,16, 0x2bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slsw", 11,16, 0x2bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slsd", 11,16, 0x2bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgtb", 11,16, 0x33c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgtw", 11,16, 0x33d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgtd", 11,16, 0x33f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sleb", 11,16, 0x3bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slew", 11,16, 0x3bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sled", 11,16, 0x3bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsb", 11,16, 0x43c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsw", 11,16, 0x43d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsd", 11,16, 0x43f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfcb", 11,16, 0x4bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfcw", 11,16, 0x4bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfcd", 11,16, 0x4bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slob", 11,16, 0x53c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slow", 11,16, 0x53d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slod", 11,16, 0x53f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shsb", 11,16, 0x5bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shsw", 11,16, 0x5bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shsd", 11,16, 0x5bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sltb", 11,16, 0x63c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sltw", 11,16, 0x63d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sltd", 11,16, 0x63f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgeb", 11,16, 0x6bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgew", 11,16, 0x6bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sged", 11,16, 0x6bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sutb", 11,16, 0x73c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sutw", 11,16, 0x73d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sutd", 11,16, 0x73f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sufb", 11,16, 0x7bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sufw", 11,16, 0x7bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sufd", 11,16, 0x7bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "save", 8,8, 0x62, "1U", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sbitb", 14,24, 0x184e, "1B2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "sbitw", 14,24, 0x194e, "1W2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "sbitd", 14,24, 0x1b4e, "1D2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "sbitib", 14,24, 0x1c4e, "1B2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "sbitiw", 14,24, 0x1d4e, "1W2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "sbitid", 14,24, 0x1f4e, "1D2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "setcfg", 15,24, 0x0b0e, "1O", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsr", 14,24, 0x373e, "1f", 0, "", DEF_MODEC,DEF_MODEL },
+ { "skpsb", 16,24, 0x0c0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "skpsw", 16,24, 0x0d0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "skpsd", 16,24, 0x0f0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "skpst", 16,24, 0x8c0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "smr", 15,24, 0x0f1e, "2D1M", 4, "", DEF_MODEC,DEF_MODEL },
+ { "sprb", 7,16, 0x2c, "2B1P", 1, "", DEF_MODEC,DEF_MODEL },
+ { "sprw", 7,16, 0x2d, "2W1P", 2, "", DEF_MODEC,DEF_MODEL },
+ { "sprd", 7,16, 0x2f, "2D1P", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subf", 14,24, 0x11be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subl", 14,24, 0x10be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "subb", 6,16, 0x20, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "subw", 6,16, 0x21, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "subd", 6,16, 0x23, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subcb", 6,16, 0x30, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "subcw", 6,16, 0x31, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "subcd", 6,16, 0x33, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subpb", 14,24, 0x2c4e, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "subpw", 14,24, 0x2d4e, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "subpd", 14,24, 0x2f4e, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+#ifdef NS32K_SVC_IMMED_OPERANDS
+ { "svc", 8,8, 0xe2, "2i1i", 1, "", DEF_MODEC,DEF_MODEL }, /* not really, but unix uses it */
+#else
+ { "svc", 8,8, 0xe2, "", 0, "", DEF_MODEC,DEF_MODEL },
+#endif
+ { "tbitb", 6,16, 0x34, "1B2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "tbitw", 6,16, 0x35, "1W2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "tbitd", 6,16, 0x37, "1D2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "truncfb", 14,24, 0x2c3e, "1F2B", 4, "", DEF_MODEC,DEF_MODEL },
+ { "truncfw", 14,24, 0x2d3e, "1F2W", 4, "", DEF_MODEC,DEF_MODEL },
+ { "truncfd", 14,24, 0x2f3e, "1F2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "trunclb", 14,24, 0x283e, "1L2B", 8, "", DEF_MODEC,DEF_MODEL },
+ { "trunclw", 14,24, 0x293e, "1L2W", 8, "", DEF_MODEC,DEF_MODEL },
+ { "truncld", 14,24, 0x2b3e, "1L2D", 8, "", DEF_MODEC,DEF_MODEL },
+ { "wait", 8,8, 0xb2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "wrval", 19,24, 0x0071e,"1A", 0, "", DEF_MODEC,DEF_MODEL },
+ { "xorb", 6,16, 0x38, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "xorw", 6,16, 0x39, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "xord", 6,16, 0x3b, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+#if defined(NS32381) /* I'm not too sure of these */
+ { "dotf", 14,24, 0x0dfe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "dotl", 14,24, 0x0cfe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "logbf", 14,24, 0x15fe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "logbl", 14,24, 0x14fe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "polyf", 14,24, 0x09fe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "polyl", 14,24, 0x08fe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "scalbf", 14,24, 0x11fe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "scalbl", 14,24, 0x10fe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+#endif
+};
+
+static const int numopcodes=sizeof(ns32k_opcodes)/sizeof(ns32k_opcodes[0]);
+
+static const struct ns32k_opcode *endop = ns32k_opcodes+sizeof(ns32k_opcodes)/sizeof(ns32k_opcodes[0]);
+
+#define MAX_ARGS 4
+#define ARG_LEN 50
+
diff --git a/gnu/usr.bin/as/opcode/pn.h b/gnu/usr.bin/as/opcode/pn.h
new file mode 100644
index 0000000..fde4764
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/pn.h
@@ -0,0 +1,282 @@
+/* Print GOULD PN (PowerNode) instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+struct gld_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long mask;
+ char *args;
+ int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and at most four. The length of the
+ instruction is based on the opcode.
+
+ The mask component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing characters
+ that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+ r Register in first field
+ R Register in second field
+ b Base register in first field
+ B Base register in second field
+ v Vector register in first field
+ V Vector register in first field
+ A Optional address register (base register)
+ X Optional index register
+ I Immediate data (16bits signed)
+ O Offset field (16bits signed)
+ h Offset field (15bits signed)
+ d Offset field (14bits signed)
+ S Shift count field
+
+ any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "abm", 0xa0080000, 0xfc080000, "f,xOA,X", 4 },
+{ "abr", 0x18080000, 0xfc0c0000, "r,f", 2 },
+{ "aci", 0xfc770000, 0xfc7f8000, "r,I", 4 },
+{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
+{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "adi", 0xc8010000, 0xfc7f0000, "r,I", 4 },
+{ "admb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "admd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "admh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "admw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
+{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
+{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
+{ "adrm", 0x38080000, 0xfc0f0000, "r,R", 2 },
+{ "ai", 0xfc030000, 0xfc07ffff, "I", 4 },
+{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
+{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
+{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
+{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
+{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bcf", 0xf0000000, 0xfc080000, "I,xOA,X", 4 },
+{ "bct", 0xec000000, 0xfc080000, "I,xOA,X", 4 },
+{ "bei", 0x00060000, 0xffff0000, "", 2 },
+{ "bft", 0xf0000000, 0xff880000, "xOA,X", 4 },
+{ "bib", 0xf4000000, 0xfc780000, "r,xOA", 4 },
+{ "bid", 0xf4600000, 0xfc780000, "r,xOA", 4 },
+{ "bih", 0xf4200000, 0xfc780000, "r,xOA", 4 },
+{ "biw", 0xf4400000, 0xfc780000, "r,xOA", 4 },
+{ "bl", 0xf8800000, 0xff880000, "xOA,X", 4 },
+{ "bsub", 0x5c080000, 0xff8f0000, "", 2 },
+{ "bsubm", 0x28080000, 0xfc080000, "", 4 },
+{ "bu", 0xec000000, 0xff880000, "xOA,X", 4 },
+{ "call", 0x28080000, 0xfc0f0000, "", 2 },
+{ "callm", 0x5c080000, 0xff880000, "", 4 },
+{ "camb", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
+{ "camd", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
+{ "camh", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
+{ "camw", 0x90000000, 0xfc080000, "r.xOA,X", 4 },
+{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
+{ "cd", 0xfc060000, 0xfc070000, "r,f", 4 },
+{ "cea", 0x000f0000, 0xffff0000, "", 2 },
+{ "ci", 0xc8050000, 0xfc7f0000, "r,I", 4 },
+{ "cmc", 0x040a0000, 0xfc7f0000, "r", 2 },
+{ "cmmb", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
+{ "cmmd", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
+{ "cmmh", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
+{ "cmmw", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
+{ "cmr", 0x14000000, 0xfc0f0000, "r,R", 2 },
+{ "daci", 0xfc7f0000, 0xfc7f8000, "r,I", 4 },
+{ "dae", 0x000e0000, 0xffff0000, "", 2 },
+{ "dai", 0xfc040000, 0xfc07ffff, "I", 4 },
+{ "dci", 0xfc6f0000, 0xfc7f8000, "r,I", 4 },
+{ "di", 0xfc010000, 0xfc07ffff, "I", 4 },
+{ "dvfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "dvfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvi", 0xc8040000, 0xfc7f0000, "r,I", 4 },
+{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
+{ "dvrfd", 0x380c0000, 0xfc0f0000, "r,R", 4 },
+{ "dvrfw", 0x38040000, 0xfc0f0000, "r,xOA,X", 4 },
+{ "eae", 0x00080000, 0xffff0000, "", 2 },
+{ "eci", 0xfc670000, 0xfc7f8080, "r,I", 4 },
+{ "ecwcs", 0xfc4f0000, 0xfc7f8000, "", 4 },
+{ "ei", 0xfc000000, 0xfc07ffff, "I", 4 },
+{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
+{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
+{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
+{ "eorm", 0x0c080000, 0xfc0f0000, "r,R", 2 },
+{ "es", 0x00040000, 0xfc7f0000, "r", 2 },
+{ "exm", 0xa8000000, 0xff880000, "xOA,X", 4 },
+{ "exr", 0xc8070000, 0xfc7f0000, "r", 2 },
+{ "exrr", 0xc8070002, 0xfc7f0002, "r", 2 },
+{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
+{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
+{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
+{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
+{ "grio", 0xfc3f0000, 0xfc7f8000, "r,I", 4 },
+{ "halt", 0x00000000, 0xffff0000, "", 2 },
+{ "hio", 0xfc370000, 0xfc7f8000, "r,I", 4 },
+{ "jwcs", 0xfa080000, 0xff880000, "xOA,X", 4 },
+{ "la", 0x50000000, 0xfc000000, "r,xOA,X", 4 },
+{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lb", 0xac080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lcs", 0x00030000, 0xfc7f0000, "r", 2 },
+{ "ld", 0xac000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lear", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lf", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lfbr", 0xcc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lh", 0xac000001, 0xfc080001, "r,xOA,X", 4 },
+{ "li", 0xc8000000, 0xfc7f0000, "r,I", 4 },
+{ "lmap", 0x2c070000, 0xfc7f0000, "r", 2 },
+{ "lmb", 0xb0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lmd", 0xb0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lmh", 0xb0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lmw", 0xb0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnd", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lnh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lnw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lpsd", 0xf9800000, 0xff880000, "r,xOA,X", 4 },
+{ "lpsdcm", 0xfa800000, 0xff880000, "r,xOA,X", 4 },
+{ "lw", 0xac000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
+{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
+{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpi", 0xc8030000, 0xfc7f0000, "r,I", 4 },
+{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
+{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
+{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
+{ "nop", 0x00020000, 0xffff0000, "", 2 },
+{ "ormb", 0x88080000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormd", 0x88000002, 0xfc080002, "r,xOA,X", 4 },
+{ "ormh", 0x88000001, 0xfc080001, "r,xOA,X", 4 },
+{ "ormw", 0x88000000, 0xfc080000, "r,xOA,X", 4 },
+{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
+{ "orrm", 0x08080000, 0xfc0f0000, "r,R", 2 },
+{ "rdsts", 0x00090000, 0xfc7f0000, "r", 2 },
+{ "return", 0x280e0000, 0xfc7f0000, "", 2 },
+{ "ri", 0xfc020000, 0xfc07ffff, "I", 4 },
+{ "rnd", 0x00050000, 0xfc7f0000, "r", 2 },
+{ "rpswt", 0x040b0000, 0xfc7f0000, "r", 2 },
+{ "rschnl", 0xfc2f0000, 0xfc7f8000, "r,I", 4 },
+{ "rsctl", 0xfc470000, 0xfc7f8000, "r,I", 4 },
+{ "rwcs", 0x000b0000, 0xfc0f0000, "r,R", 2 },
+{ "sacz", 0x10080000, 0xfc0f0000, "r,R", 2 },
+{ "sbm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
+{ "sbr", 0x18000000, 0xfc0c0000, "r,f", 4 },
+{ "sea", 0x000d0000, 0xffff0000, "", 2 },
+{ "setcpu", 0x2c090000, 0xfc7f0000, "r", 2 },
+{ "sio", 0xfc170000, 0xfc7f8000, "r,I", 4 },
+{ "sipu", 0x000a0000, 0xffff0000, "", 2 },
+{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
+{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
+{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
+{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
+{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
+{ "smc", 0x04070000, 0xfc070000, "", 2 },
+{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
+{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
+{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
+{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
+{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
+{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stfbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "stmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stpio", 0xfc270000, 0xfc7f8000, "r,I", 4 },
+{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
+{ "sufd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sufw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sui", 0xc8020000, 0xfc7f0000, "r,I", 4 },
+{ "sumb", 0xbc080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumd", 0xbc000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sumh", 0xbc000001, 0xfc080001, "r,xOA,X", 4 },
+{ "sumw", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
+{ "surfd", 0x380b0000, 0xfc0f0000, "r,xOA,X", 4 },
+{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
+{ "surm", 0x3c080000, 0xfc0f0000, "r,R", 2 },
+{ "svc", 0xc8060000, 0xffff0000, "", 4 },
+{ "tbm", 0xa4080000, 0xfc080000, "f,xOA,X", 4 },
+{ "tbr", 0x180c0000, 0xfc0c0000, "r,f", 2 },
+{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
+{ "tccr", 0x28040000, 0xfc7f0000, "", 2 },
+{ "td", 0xfc050000, 0xfc070000, "r,f", 4 },
+{ "tio", 0xfc1f0000, 0xfc7f8000, "r,I", 4 },
+{ "tmapr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
+{ "tpcbr", 0x280c0000, 0xfc7f0000, "r", 2 },
+{ "trbr", 0x2c010000, 0xfc0f0000, "b,R", 2 },
+{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
+{ "trcc", 0x28050000, 0xfc7f0000, "", 2 },
+{ "trcm", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
+{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
+{ "trnm", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
+{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
+{ "trrm", 0x2c080000, 0xfc0f0000, "r,R", 2 },
+{ "trsc", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
+{ "trsw", 0x28000000, 0xfc7f0000, "r", 2 },
+{ "tscr", 0x2c0f0000, 0xfc0f0000, "r,R", 2 },
+{ "uei", 0x00070000, 0xffff0000, "", 2 },
+{ "wait", 0x00010000, 0xffff0000, "", 2 },
+{ "wcwcs", 0xfc5f0000, 0xfc7f8000, "", 4 },
+{ "wwcs", 0x000c0000, 0xfc0f0000, "r,R", 2 },
+{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
+{ "xcr", 0x2c050000, 0xfc0f0000, "r,R", 2 },
+{ "xcrm", 0x2c0d0000, 0xfc0f0000, "r,R", 2 },
+{ "zbm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zbr", 0x18040000, 0xfc0c0000, "r,f", 2 },
+{ "zmb", 0xf8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmd", 0xf8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "zmh", 0xf8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "zmw", 0xf8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "zr", 0x0c000000, 0xfc0f0000, "r", 2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+ sizeof(gld_opcodes[0]);
diff --git a/gnu/usr.bin/as/opcode/pyr.h b/gnu/usr.bin/as/opcode/pyr.h
new file mode 100644
index 0000000..ea5d84a
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/pyr.h
@@ -0,0 +1,287 @@
+/* pyramid.opcode.h -- gdb initial attempt. */
+
+/* pyramid opcode table: wot to do with this
+ particular opcode */
+
+struct pyr_datum
+{
+ char nargs;
+ char * args; /* how to compile said opcode */
+ unsigned long mask; /* Bit vector: which operand modes are valid
+ for this opcode */
+ unsigned char code; /* op-code (always 6(?) bits */
+};
+
+typedef struct pyr_insn_format {
+ unsigned int mode :4;
+ unsigned int operator :8;
+ unsigned int index_scale :2;
+ unsigned int index_reg :6;
+ unsigned int operand_1 :6;
+ unsigned int operand_2:6;
+} pyr_insn_format;
+
+
+/* We store four bytes of opcode for all opcodes.
+ Pyramid is sufficiently RISCy that:
+ - insns are always an integral number of words;
+ - the length of any insn can be told from the first word of
+ the insn. (ie, if there are zero, one, or two words of
+ immediate operand/offset).
+
+
+ The args component is a string containing two characters for each
+ operand of the instruction. The first specifies the kind of operand;
+ the second, the place it is stored. */
+
+/* Kinds of operands:
+ mask assembler syntax description
+ 0x0001: movw Rn,Rn register to register
+ 0x0002: movw K,Rn quick immediate to register
+ 0x0004: movw I,Rn long immediate to register
+ 0x0008: movw (Rn),Rn register indirect to register
+ movw (Rn)[x],Rn register indirect to register
+ 0x0010: movw I(Rn),Rn offset register indirect to register
+ movw I(Rn)[x],Rn offset register indirect, indexed, to register
+
+ 0x0020: movw Rn,(Rn) register to register indirect
+ 0x0040: movw K,(Rn) quick immediate to register indirect
+ 0x0080: movw I,(Rn) long immediate to register indirect
+ 0x0100: movw (Rn),(Rn) register indirect to-register indirect
+ 0x0100: movw (Rn),(Rn) register indirect to-register indirect
+ 0x0200: movw I(Rn),(Rn) register indirect+offset to register indirect
+ 0x0200: movw I(Rn),(Rn) register indirect+offset to register indirect
+
+ 0x0400: movw Rn,I(Rn) register to register indirect+offset
+ 0x0800: movw K,I(Rn) quick immediate to register indirect+offset
+ 0x1000: movw I,I(Rn) long immediate to register indirect+offset
+ 0x1000: movw (Rn),I(Rn) register indirect to-register indirect+offset
+ 0x1000: movw I(Rn),I(Rn) register indirect+offset to register indirect
+ +offset
+ 0x0000: (irregular) ???
+
+
+ Each insn has a four-bit field encoding the type(s) of its operands.
+*/
+
+/* Some common combinations
+ */
+
+/* the first 5,(0x1|0x2|0x4|0x8|0x10) ie (1|2|4|8|16), ie ( 32 -1)*/
+#define GEN_TO_REG (31)
+
+#define UNKNOWN ((unsigned long)-1)
+#define ANY (GEN_TO_REG | (GEN_TO_REG << 5) | (GEN_TO_REG << 15))
+
+#define CONVERT (1|8|0x10|0x20|0x200)
+
+#define K_TO_REG (2)
+#define I_TO_REG (4)
+#define NOTK_TO_REG (GEN_TO_REG & ~K_TO_REG)
+#define NOTI_TO_REG (GEN_TO_REG & ~I_TO_REG)
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+
+struct pyr_opcode /* pyr opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct pyr_datum datum; /* rest of opcode table [datum] */
+};
+
+#define pyr_how args
+#define pyr_nargs nargs
+#define pyr_mask mask
+#define pyr_name name
+
+struct pyr_opcode pyr_opcodes[] =
+{
+ {"movb", { 2, "", UNKNOWN, 0x11}, },
+ {"movh", { 2, "", UNKNOWN, 0x12} },
+ {"movw", { 2, "", ANY, 0x10} },
+ {"movl", { 2, "", ANY, 0x13} },
+ {"mnegw", { 2, "", (0x1|0x8|0x10), 0x14} },
+ {"mnegf", { 2, "", 0x1, 0x15} },
+ {"mnegd", { 2, "", 0x1, 0x16} },
+ {"mcomw", { 2, "", (0x1|0x8|0x10), 0x17} },
+ {"mabsw", { 2, "", (0x1|0x8|0x10), 0x18} },
+ {"mabsf", { 2, "", 0x1, 0x19} },
+ {"mabsd", { 2, "", 0x1, 0x1a} },
+ {"mtstw", { 2, "", (0x1|0x8|0x10), 0x1c} },
+ {"mtstf", { 2, "", 0x1, 0x1d} },
+ {"mtstd", { 2, "", 0x1, 0x1e} },
+ {"mova", { 2, "", 0x8|0x10, 0x1f} },
+ {"movzbw", { 2, "", (0x1|0x8|0x10), 0x20} },
+ {"movzhw", { 2, "", (0x1|0x8|0x10), 0x21} },
+ /* 2 insns out of order here */
+ {"movbl", { 2, "", 1, 0x4f} },
+ {"filbl", { 2, "", 1, 0x4e} },
+
+ {"cvtbw", { 2, "", CONVERT, 0x22} },
+ {"cvthw", { 2, "", CONVERT, 0x23} },
+ {"cvtwb", { 2, "", CONVERT, 0x24} },
+ {"cvtwh", { 2, "", CONVERT, 0x25} },
+ {"cvtwf", { 2, "", CONVERT, 0x26} },
+ {"cvtwd", { 2, "", CONVERT, 0x27} },
+ {"cvtfw", { 2, "", CONVERT, 0x28} },
+ {"cvtfd", { 2, "", CONVERT, 0x29} },
+ {"cvtdw", { 2, "", CONVERT, 0x2a} },
+ {"cvtdf", { 2, "", CONVERT, 0x2b} },
+
+ {"addw", { 2, "", GEN_TO_REG, 0x40} },
+ {"addwc", { 2, "", GEN_TO_REG, 0x41} },
+ {"subw", { 2, "", GEN_TO_REG, 0x42} },
+ {"subwb", { 2, "", GEN_TO_REG, 0x43} },
+ {"rsubw", { 2, "", GEN_TO_REG, 0x44} },
+ {"mulw", { 2, "", GEN_TO_REG, 0x45} },
+ {"emul", { 2, "", GEN_TO_REG, 0x47} },
+ {"umulw", { 2, "", GEN_TO_REG, 0x46} },
+ {"divw", { 2, "", GEN_TO_REG, 0x48} },
+ {"ediv", { 2, "", GEN_TO_REG, 0x4a} },
+ {"rdivw", { 2, "", GEN_TO_REG, 0x4b} },
+ {"udivw", { 2, "", GEN_TO_REG, 0x49} },
+ {"modw", { 2, "", GEN_TO_REG, 0x4c} },
+ {"umodw", { 2, "", GEN_TO_REG, 0x4d} },
+
+
+ {"addf", { 2, "", 1, 0x50} },
+ {"addd", { 2, "", 1, 0x51} },
+ {"subf", { 2, "", 1, 0x52} },
+ {"subd", { 2, "", 1, 0x53} },
+ {"mulf", { 2, "", 1, 0x56} },
+ {"muld", { 2, "", 1, 0x57} },
+ {"divf", { 2, "", 1, 0x58} },
+ {"divd", { 2, "", 1, 0x59} },
+
+
+ {"cmpb", { 2, "", UNKNOWN, 0x61} },
+ {"cmph", { 2, "", UNKNOWN, 0x62} },
+ {"cmpw", { 2, "", UNKNOWN, 0x60} },
+ {"ucmpb", { 2, "", UNKNOWN, 0x66} },
+ /* WHY no "ucmph"??? */
+ {"ucmpw", { 2, "", UNKNOWN, 0x65} },
+ {"xchw", { 2, "", UNKNOWN, 0x0f} },
+
+
+ {"andw", { 2, "", GEN_TO_REG, 0x30} },
+ {"orw", { 2, "", GEN_TO_REG, 0x31} },
+ {"xorw", { 2, "", GEN_TO_REG, 0x32} },
+ {"bicw", { 2, "", GEN_TO_REG, 0x33} },
+ {"lshlw", { 2, "", GEN_TO_REG, 0x38} },
+ {"ashlw", { 2, "", GEN_TO_REG, 0x3a} },
+ {"ashll", { 2, "", GEN_TO_REG, 0x3c} },
+ {"ashrw", { 2, "", GEN_TO_REG, 0x3b} },
+ {"ashrl", { 2, "", GEN_TO_REG, 0x3d} },
+ {"rotlw", { 2, "", GEN_TO_REG, 0x3e} },
+ {"rotrw", { 2, "", GEN_TO_REG, 0x3f} },
+
+ /* push and pop insns are "going away next release". */
+ {"pushw", { 2, "", GEN_TO_REG, 0x0c} },
+ {"popw", { 2, "", (0x1|0x8|0x10), 0x0d} },
+ {"pusha", { 2, "", (0x8|0x10), 0x0e} },
+
+ {"bitsw", { 2, "", UNKNOWN, 0x35} },
+ {"bitcw", { 2, "", UNKNOWN, 0x36} },
+ /* some kind of ibra/dbra insns??*/
+ {"icmpw", { 2, "", UNKNOWN, 0x67} },
+ {"dcmpw", { 2, "", (1|4|0x20|0x80|0x400|0x1000), 0x69} },/*FIXME*/
+ {"acmpw", { 2, "", 1, 0x6b} },
+
+ /* Call is written as a 1-op insn, but is always (dis)assembled as a 2-op
+ insn with a 2nd op of tr14. The assembler will have to grok this. */
+ {"call", { 2, "", GEN_TO_REG, 0x04} },
+ {"call", { 1, "", GEN_TO_REG, 0x04} },
+
+ {"callk", { 1, "", UNKNOWN, 0x06} },/* system call?*/
+ /* Ret is usually written as a 0-op insn, but gets disassembled as a
+ 1-op insn. The operand is always tr15. */
+ {"ret", { 0, "", UNKNOWN, 0x09} },
+ {"ret", { 1, "", UNKNOWN, 0x09} },
+ {"adsf", { 2, "", (1|2|4), 0x08} },
+ {"retd", { 2, "", UNKNOWN, 0x0a} },
+ {"btc", { 2, "", UNKNOWN, 0x01} },
+ {"bfc", { 2, "", UNKNOWN, 0x02} },
+ /* Careful: halt is 0x00000000. Jump must have some other (mode?)bit set?? */
+ {"jump", { 1, "", UNKNOWN, 0x00} },
+ {"btp", { 2, "", UNKNOWN, 0xf00} },
+ /* read control-stack pointer is another 1-or-2 operand insn. */
+ {"rcsp", { 2, "", UNKNOWN, 0x01f} },
+ {"rcsp", { 1, "", UNKNOWN, 0x01f} }
+};
+
+/* end: pyramid.opcode.h */
+/* One day I will have to take the time to find out what operands
+ are valid for these insns, and guess at what they mean.
+
+ I can't imagine what the "I???" insns (iglob, etc) do.
+
+ the arithmetic-sounding insns ending in "p" sound awfully like BCD
+ arithmetic insns:
+ dshlp -> Decimal SHift Left Packed
+ dshrp -> Decimal SHift Right Packed
+ and cvtlp would be convert long to packed.
+ I have no idea how the operands are interpreted; but having them be
+ a long register with (address, length) of an in-memory packed BCD operand
+ would not be surprising.
+ They are unlikely to be a packed bcd string: 64 bits of long give
+ is only 15 digits+sign, which isn't enough for COBOL.
+ */
+#if 0
+ {"wcsp", { 2, "", UNKNOWN, 0x00} }, /*write csp?*/
+ /* The OSx Operating System Porting Guide claims SSL does things
+ with tr12 (a register reserved to it) to do with static block-structure
+ references. SSL=Set Static Link? It's "Going away next release". */
+ {"ssl", { 2, "", UNKNOWN, 0x00} },
+ {"ccmps", { 2, "", UNKNOWN, 0x00} },
+ {"lcd", { 2, "", UNKNOWN, 0x00} },
+ {"uemul", { 2, "", UNKNOWN, 0x00} }, /*unsigned emul*/
+ {"srf", { 2, "", UNKNOWN, 0x00} }, /*Gidget time???*/
+ {"mnegp", { 2, "", UNKNOWN, 0x00} }, /move-neg phys?*/
+ {"ldp", { 2, "", UNKNOWN, 0x00} }, /*load phys?*/
+ {"ldti", { 2, "", UNKNOWN, 0x00} },
+ {"ldb", { 2, "", UNKNOWN, 0x00} },
+ {"stp", { 2, "", UNKNOWN, 0x00} },
+ {"stti", { 2, "", UNKNOWN, 0x00} },
+ {"stb", { 2, "", UNKNOWN, 0x00} },
+ {"stu", { 2, "", UNKNOWN, 0x00} },
+ {"addp", { 2, "", UNKNOWN, 0x00} },
+ {"subp", { 2, "", UNKNOWN, 0x00} },
+ {"mulp", { 2, "", UNKNOWN, 0x00} },
+ {"divp", { 2, "", UNKNOWN, 0x00} },
+ {"dshlp", { 2, "", UNKNOWN, 0x00} }, /* dec shl packed? */
+ {"dshrp", { 2, "", UNKNOWN, 0x00} }, /* dec shr packed? */
+ {"movs", { 2, "", UNKNOWN, 0x00} }, /*move (string?)?*/
+ {"cmpp", { 2, "", UNKNOWN, 0x00} }, /* cmp phys?*/
+ {"cmps", { 2, "", UNKNOWN, 0x00} }, /* cmp (string?)?*/
+ {"cvtlp", { 2, "", UNKNOWN, 0x00} }, /* cvt long to p??*/
+ {"cvtpl", { 2, "", UNKNOWN, 0x00} }, /* cvt p to l??*/
+ {"dintr", { 2, "", UNKNOWN, 0x00} }, /* ?? intr ?*/
+ {"rphysw", { 2, "", UNKNOWN, 0x00} }, /* read phys word?*/
+ {"wphysw", { 2, "", UNKNOWN, 0x00} }, /* write phys word?*/
+ {"cmovs", { 2, "", UNKNOWN, 0x00} },
+ {"rsubw", { 2, "", UNKNOWN, 0x00} },
+ {"bicpsw", { 2, "", UNKNOWN, 0x00} }, /* clr bit in psw? */
+ {"bispsw", { 2, "", UNKNOWN, 0x00} }, /* set bit in psw? */
+ {"eio", { 2, "", UNKNOWN, 0x00} }, /* ?? ?io ? */
+ {"callp", { 2, "", UNKNOWN, 0x00} }, /* call phys?*/
+ {"callr", { 2, "", UNKNOWN, 0x00} },
+ {"lpcxt", { 2, "", UNKNOWN, 0x00} }, /*load proc context*/
+ {"rei", { 2, "", UNKNOWN, 0x00} }, /*ret from intrpt*/
+ {"rport", { 2, "", UNKNOWN, 0x00} }, /*read-port?*/
+ {"rtod", { 2, "", UNKNOWN, 0x00} }, /*read-time-of-day?*/
+ {"ssi", { 2, "", UNKNOWN, 0x00} },
+ {"vtpa", { 2, "", UNKNOWN, 0x00} }, /*virt-to-phys-addr?*/
+ {"wicl", { 2, "", UNKNOWN, 0x00} }, /* write icl ? */
+ {"wport", { 2, "", UNKNOWN, 0x00} }, /*write-port?*/
+ {"wtod", { 2, "", UNKNOWN, 0x00} }, /*write-time-of-day?*/
+ {"flic", { 2, "", UNKNOWN, 0x00} },
+ {"iglob", { 2, "", UNKNOWN, 0x00} }, /* I global? */
+ {"iphys", { 2, "", UNKNOWN, 0x00} }, /* I physical? */
+ {"ipid", { 2, "", UNKNOWN, 0x00} }, /* I pid? */
+ {"ivect", { 2, "", UNKNOWN, 0x00} }, /* I vector? */
+ {"lamst", { 2, "", UNKNOWN, 0x00} },
+ {"tio", { 2, "", UNKNOWN, 0x00} },
+#endif
diff --git a/gnu/usr.bin/as/opcode/sparc.h b/gnu/usr.bin/as/opcode/sparc.h
new file mode 100644
index 0000000..cd032c2
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/sparc.h
@@ -0,0 +1,885 @@
+
+/* Table of opcodes for the sparc.
+ Copyright 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler, GDB, the GNU debugger, and
+the GNU Binutils.
+
+GAS/GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+ /* FIXME-someday: perhaps the ,a's and such should be embedded in the
+ instruction's name rather than the args. This would make gas faster, pinsn
+ slower, but would mess up some macros a bit. xoxorich. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+enum sparc_architecture {
+ v6 = 0,
+ v7,
+ v8,
+};
+
+static const char *architecture_pname[] = {
+ "v6",
+ "v7",
+ "v8",
+ NULL,
+};
+
+struct sparc_opcode {
+ const char *name;
+ unsigned long match; /* Bits that must be set. */
+ unsigned long lose; /* Bits that must not be set. */
+ const char *args;
+ /* This was called "delayed" in versions before the flags. */
+ char flags;
+ enum sparc_architecture architecture;
+};
+
+#define F_DELAYED 1 /* Delayed branch */
+#define F_ALIAS 2 /* Alias for a "real" instruction */
+
+/*
+
+All sparc opcodes are 32 bits, except for the `set' instruction (really a
+macro), which is 64 bits. It is handled as a special case.
+
+The match component is a mask saying which bits must match a particular
+opcode in order for an instruction to be an instance of that opcode.
+
+The args component is a string containing one character for each operand of the
+instruction.
+
+Kinds of operands:
+ # Number used by optimizer. It is ignored.
+ 1 rs1 register.
+ 2 rs2 register.
+ d rd register.
+ e frs1 floating point register.
+ v frs1 floating point register (double/even).
+ V frs1 floating point register (quad/multiple of 4).
+ f frs2 floating point register.
+ B frs2 floating point register (double/even).
+ R frs2 floating point register (quad/multiple of 4).
+ g frsd floating point register.
+ H frsd floating point register (double/even).
+ J frsd floating point register (quad/multiple of 4).
+ b crs1 coprocessor register
+ c crs2 coprocessor register
+ D crsd coprocessor register
+ m alternate space register (asr) in rd
+ M alternate space register (asr) in rs1
+ h 22 high bits.
+ i 13 bit Immediate.
+ n 22 bit immediate.
+ l 22 bit PC relative immediate.
+ L 30 bit PC relative immediate.
+ a Annul. The annul bit is set.
+ A Alternate address space. Stored as 8 bits.
+ C Coprocessor state register.
+ F floating point state register.
+ p Processor state register.
+ q Floating point queue.
+ r Single register that is both rs1 and rsd.
+ Q Coprocessor queue.
+ S Special case.
+ x Single register that is both rs2 and rsd.
+ t Trap base register.
+ w Window invalid mask register.
+ y Y register.
+
+The following chars are unused: (note: ,[] are used as punctuation)
+[oOX3450]
+
+*/
+
+/* The order of the opcodes in this table is significant:
+
+ * The assembler requires that all instances of the same mnemonic must
+ be consecutive. If they aren't, the assembler will bomb at runtime.
+
+ * The disassembler should not care about the order of the opcodes.
+
+*/
+
+#define OP2(x) (((x)&0x7) << 22) /* op2 field of format2 insns */
+#define OP3(x) (((x)&0x3f) << 19) /* op3 field of format3 insns */
+#define OP(x) (((x)&0x3) << 30) /* op field of all insns */
+#define OPF(x) (((x)&0x1ff) << 5) /* opf field of float insns */
+#define F3F(x, y, z) (OP(x) | OP3(y) | OPF(z)) /* format3 float insns */
+#define F3I(x) (((x)&0x1) << 13) /* immediate field of format 3 insns */
+#define F2(x, y) (OP(x) | OP2(y)) /* format 2 insns */
+#define F3(x, y, z) (OP(x) | OP3(y) | F3I(z)) /* format3 insns */
+#define F1(x) (OP(x))
+#define DISP30(x) ((x)&0x3fffffff)
+#define ASI(x) (((x)&0xff) << 5) /* asi field of format3 insns */
+#define RS2(x) ((x)&0x1f) /* rs2 field */
+#define SIMM13(x) ((x)&0x1fff) /* simm13 field */
+#define RD(x) (((x)&0x1f) << 25) /* destination register field */
+#define RS1(x) (((x)&0x1f) << 14) /* rs1 field */
+#define ASI_RS2(x) (SIMM13(x))
+
+#define ANNUL (1<<29)
+#define IMMED F3I(1)
+#define RD_G0 RD(~0)
+#define RS1_G0 RS1(~0)
+#define RS2_G0 RS2(~0)
+
+#define COND(x) (((x)&0xf)<<25)
+
+#define CONDA (COND(0x8))
+#define CONDCC (COND(0xd))
+#define CONDCS (COND(0x5))
+#define CONDE (COND(0x1))
+#define CONDG (COND(0xa))
+#define CONDGE (COND(0xb))
+#define CONDGU (COND(0xc))
+#define CONDL (COND(0x3))
+#define CONDLE (COND(0x2))
+#define CONDLEU (COND(0x4))
+#define CONDN (COND(0x0))
+#define CONDNE (COND(0x9))
+#define CONDNEG (COND(0x6))
+#define CONDPOS (COND(0xe))
+#define CONDVC (COND(0xf))
+#define CONDVS (COND(0x7))
+
+#define CONDNZ CONDNE
+#define CONDZ CONDE
+#define CONDGEU CONDCC
+#define CONDLU CONDCS
+
+#define FCONDA (COND(0x8))
+#define FCONDE (COND(0x9))
+#define FCONDG (COND(0x6))
+#define FCONDGE (COND(0xb))
+#define FCONDL (COND(0x4))
+#define FCONDLE (COND(0xd))
+#define FCONDLG (COND(0x2))
+#define FCONDN (COND(0x0))
+#define FCONDNE (COND(0x1))
+#define FCONDO (COND(0xf))
+#define FCONDU (COND(0x7))
+#define FCONDUE (COND(0xa))
+#define FCONDUG (COND(0x5))
+#define FCONDUGE (COND(0xc))
+#define FCONDUL (COND(0x3))
+#define FCONDULE (COND(0xe))
+
+#define FCONDNZ FCONDNE
+#define FCONDZ FCONDE
+
+
+static const struct sparc_opcode sparc_opcodes[] = {
+
+{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", 0, v6 },
+{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0), "[1+2],g", 0, v6 },
+{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0)|RS2_G0, "[1],g", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[1+i],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[i+1],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|RS1_G0, "[i],g", 0, v6 },
+{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|SIMM13(~0), "[1],g", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0), "[1+2],F", 0, v6 },
+{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RS2_G0, "[1],F", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1), "[1+i],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1), "[i+1],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0, "[i],F", 0, v6 },
+{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0), "[1],F", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2],D", 0, v6 },
+{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1],D", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i],D", 0, v6 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1],D", 0, v6 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i],D", 0, v6 },
+{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1],D", 0, v6 }, /* ld [rs1+0],d */
+{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0), "[1+2],C", 0, v6 },
+{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0, "[1],C", 0, v6 }, /* ld [rs1+%g0],d */
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[1+i],C", 0, v6 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[i+1],C", 0, v6 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0, "[i],C", 0, v6 },
+{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0), "[1],C", 0, v6 }, /* ld [rs1+0],d */
+
+
+
+{ "lda", F3(3, 0x10, 0), F3(~3, ~0x10, ~0), "[1+2]A,d", 0, v6 },
+{ "lda", F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lda [rs1+%g0],d */
+
+{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI(~0), "[1+2],d", 0, v6 },
+{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldd [rs1+%g0],d */
+{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[1+i],d", 0, v6 },
+{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[i+1],d", 0, v6 },
+{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldd [rs1+0],d */
+{ "ldd", F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI(~0), "[1+2],g", 0, v6 },
+{ "ldd", F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI_RS2(~0), "[1],g", 0, v6 }, /* ldd [rs1+%g0],d */
+{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1), "[1+i],g", 0, v6 },
+{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1), "[i+1],g", 0, v6 },
+{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|RS1_G0, "[i],g", 0, v6 },
+{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|SIMM13(~0), "[1],g", 0, v6 }, /* ldd [rs1+0],d */
+{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI(~0), "[1+2],D", 0, v6 },
+{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI_RS2(~0), "[1],D", 0, v6 }, /* ldd [rs1+%g0],d */
+{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[1+i],D", 0, v6 },
+{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[i+1],D", 0, v6 },
+{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0, "[i],D", 0, v6 },
+{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0), "[1],D", 0, v6 }, /* ldd [rs1+0],d */
+{ "ldsb", F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI(~0), "[1+2],d", 0, v6 },
+{ "ldsb", F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldsb [rs1+%g0],d */
+{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1), "[1+i],d", 0, v6 },
+{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1), "[i+1],d", 0, v6 },
+{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldsb [rs1+0],d */
+{ "ldsh", F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldsh [rs1+%g0],d */
+{ "ldsh", F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI(~0), "[1+2],d", 0, v6 },
+{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1), "[1+i],d", 0, v6 },
+{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1), "[i+1],d", 0, v6 },
+{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldsh [rs1+0],d */
+{ "ldstub", F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI(~0), "[1+2],d", 0, v6 },
+{ "ldstub", F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldstub [rs1+%g0],d */
+{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1), "[1+i],d", 0, v6 },
+{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1), "[i+1],d", 0, v6 },
+{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "ldub", F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI(~0), "[1+2],d", 0, v6 },
+{ "ldub", F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldub [rs1+%g0],d */
+{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1), "[1+i],d", 0, v6 },
+{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1), "[i+1],d", 0, v6 },
+{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldub [rs1+0],d */
+{ "lduh", F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI(~0), "[1+2],d", 0, v6 },
+{ "lduh", F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* lduh [rs1+%g0],d */
+{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1), "[1+i],d", 0, v6 },
+{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1), "[i+1],d", 0, v6 },
+{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|RS1_G0, "[i],d", 0, v6 },
+{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* lduh [rs1+0],d */
+
+
+{ "ldda", F3(3, 0x13, 0), F3(~3, ~0x13, ~0), "[1+2]A,d", 0, v6 },
+{ "ldda", F3(3, 0x13, 0), F3(~3, ~0x13, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldda [rs1+%g0],d */
+{ "ldsba", F3(3, 0x19, 0), F3(~3, ~0x19, ~0), "[1+2]A,d", 0, v6 },
+{ "ldsba", F3(3, 0x19, 0), F3(~3, ~0x19, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldsba [rs1+%g0],d */
+{ "ldsha", F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0), "[1+2]A,d", 0, v6 },
+{ "ldsha", F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldsha [rs1+%g0],d */
+{ "ldstuba", F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0), "[1+2]A,d", 0, v6 },
+{ "ldstuba", F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldstuba [rs1+%g0],d */
+{ "lduba", F3(3, 0x11, 0), F3(~3, ~0x11, ~0), "[1+2]A,d", 0, v6 },
+{ "lduba", F3(3, 0x11, 0), F3(~3, ~0x11, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lduba [rs1+%g0],d */
+{ "lduha", F3(3, 0x12, 0), F3(~3, ~0x12, ~0), "[1+2]A,d", 0, v6 },
+{ "lduha", F3(3, 0x12, 0), F3(~3, ~0x12, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lduha [rs1+%g0],d */
+
+{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", 0, v6 },
+{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", 0, v6 },
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", 0, v6 },
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", 0, v6 },
+{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI(~0), "g,[1+2]", 0, v6 },
+{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI_RS2(~0), "g,[1]", 0, v6 }, /* st d[rs1+%g0] */
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1), "g,[1+i]", 0, v6 },
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1), "g,[i+1]", 0, v6 },
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|RS1_G0, "g,[i]", 0, v6 },
+{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|SIMM13(~0), "g,[1]", 0, v6 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI(~0), "D,[1+2]", 0, v6 },
+{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI_RS2(~0), "D,[1]", 0, v6 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[1+i]", 0, v6 },
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[i+1]", 0, v6 },
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0, "D,[i]", 0, v6 },
+{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0), "D,[1]", 0, v6 }, /* st d,[rs1+0] */
+{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI(~0), "C,[1+2]", 0, v6 },
+{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI_RS2(~0), "C,[1]", 0, v6 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[1+i]", 0, v6 },
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[i+1]", 0, v6 },
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0, "C,[i]", 0, v6 },
+{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0), "C,[1]", 0, v6 }, /* st d,[rs1+0] */
+
+{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI(~0), "F,[1+2]", 0, v6 },
+{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI_RS2(~0), "F,[1]", 0, v6 }, /* st d,[rs1+%g0] */
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[1+i]", 0, v6 },
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[i+1]", 0, v6 },
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|RS1_G0, "F,[i]", 0, v6 },
+{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|SIMM13(~0), "F,[1]", 0, v6 }, /* st d,[rs1+0] */
+
+
+
+
+{ "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", 0, v6 },
+{ "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* sta d,[rs1+%g0] */
+
+
+
+
+{ "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0), "d,[1+2]", 0, v6 },
+{ "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+%g0] */
+{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[1+i]", 0, v6 },
+{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[i+1]", 0, v6 },
+{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0, "d,[i]", 0, v6 },
+{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+0] */
+
+
+
+{ "stba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0), "d,[1+2]A", 0, v6 },
+{ "stba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stba d,[rs1+%g0] */
+
+
+
+{ "std", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0), "d,[1+2]", 0, v6 },
+{ "std", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* std d,[rs1+%g0] */
+{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[1+i]", 0, v6 },
+{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[i+1]", 0, v6 },
+{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0, "d,[i]", 0, v6 },
+{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* std d,[rs1+0] */
+{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0), "q,[1+2]", 0, v6 },
+{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0), "q,[1]", 0, v6 }, /* std d,[rs1+%g0] */
+{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[1+i]", 0, v6 },
+{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[i+1]", 0, v6 },
+{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0, "q,[i]", 0, v6 },
+{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0), "q,[1]", 0, v6 }, /* std d,[rs1+0] */
+{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI(~0), "g,[1+2]", 0, v6 },
+{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI_RS2(~0), "g,[1]", 0, v6 }, /* std d,[rs1+%g0] */
+{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "g,[1+i]", 0, v6 },
+{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "g,[i+1]", 0, v6 },
+{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|RS1_G0, "g,[i]", 0, v6 },
+{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|SIMM13(~0), "g,[1]", 0, v6 }, /* std d,[rs1+0] */
+{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0), "Q,[1+2]", 0, v6 },
+{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0), "Q,[1]", 0, v6 }, /* std d,[rs1+%g0] */
+{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[1+i]", 0, v6 },
+{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[i+1]", 0, v6 },
+{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0, "Q,[i]", 0, v6 },
+{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0), "Q,[1]", 0, v6 }, /* std d,[rs1+0] */
+{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI(~0), "D,[1+2]", 0, v6 },
+{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI_RS2(~0), "D,[1]", 0, v6 }, /* std d,[rs1+%g0] */
+{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[1+i]", 0, v6 },
+{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[i+1]", 0, v6 },
+{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0, "D,[i]", 0, v6 },
+{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0), "D,[1]", 0, v6 }, /* std d,[rs1+0] */
+
+{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0), "d,[1+2]A", 0, v6 },
+{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stda d,[rs1+%g0] */
+
+{ "sth", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0), "d,[1+2]", 0, v6 },
+{ "sth", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* sth d,[rs1+%g0] */
+{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[1+i]", 0, v6 },
+{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[i+1]", 0, v6 },
+{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0, "d,[i]", 0, v6 },
+{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* sth d,[+] */
+
+
+
+{ "stha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0), "d,[1+2]A", 0, v6 },
+{ "stha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stha ,[+%] */
+
+
+
+
+
+{ "swap", F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI(~0), "[1+2],d", 0, v7 },
+{ "swap", F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI_RS2(~0), "[1],d", 0, v7 }, /* swap [rs1+%g0],d */
+{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1), "[1+i],d", 0, v7 },
+{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1), "[i+1],d", 0, v7 },
+{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|RS1_G0, "[i],d", 0, v7 },
+{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|SIMM13(~0), "[1],d", 0, v7 }, /* swap [rs1+0],d */
+
+{ "swapa", F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0), "[1+2]A,d", 0, v7 },
+{ "swapa", F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0)|RS2(~0), "[1]A,d", 0, v7 }, /* swapa [rs1+%g0],d */
+
+{ "restore", F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "restore", F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "", 0, v6 }, /* restore %g0,%g0,%g0 */
+{ "restore", F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1), "1,i,d", 0, v6 },
+{ "restore", F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1)|RD_G0|RS1_G0|SIMM13(~0), "", 0, v6 }, /* restore %g0,0,%g0 */
+
+{ "rett", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI(~0), "1+2", F_DELAYED, v6 }, /* rett rs1+rs2 */
+{ "rett", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI_RS2(~0), "1", F_DELAYED, v6 }, /* rett rs1,%g0 */
+{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0, "1+i", F_DELAYED, v6 }, /* rett rs1+X */
+{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0, "i+1", F_DELAYED, v6 }, /* rett X+rs1 */
+{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0,"i", F_DELAYED, v6 }, /* rett X+rs1 */
+{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0, "i", F_DELAYED, v6 }, /* rett X */
+{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|SIMM13(~0), "1", F_DELAYED, v6 }, /* rett rs1+0 */
+
+{ "save", F3(2, 0x3c, 0), F3(~2, ~0x3c, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "save", F3(2, 0x3c, 1), F3(~2, ~0x3c, ~1), "1,i,d", 0, v6 },
+
+{ "ret", F3(2, 0x38, 1)|RS1(0x1f)|SIMM13(8), F3(~2, ~0x38, ~1)|SIMM13(~8), "", F_DELAYED, v6 }, /* jmpl %i7+8,%g0 */
+{ "retl", F3(2, 0x38, 1)|RS1(0x0f)|SIMM13(8), F3(~2, ~0x38, ~1)|RS1(~0x0f)|SIMM13(~8), "", F_DELAYED, v6 }, /* jmpl %o7+8,%g0 */
+
+{ "jmpl", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI(~0), "1+2,d", F_DELAYED, v6 },
+{ "jmpl", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI_RS2(~0), "1,d", F_DELAYED, v6 }, /* jmpl rs1+%g0,d */
+{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|SIMM13(~0), "1,d", F_DELAYED, v6 }, /* jmpl rs1+0,d */
+{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RS1_G0, "i,d", F_DELAYED, v6 }, /* jmpl %g0+i,d */
+{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "1+i,d", F_DELAYED, v6 },
+{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "i+1,d", F_DELAYED, v6 },
+{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RS1_G0, "i,d", F_DELAYED, v6 },
+
+ /* The 1<<12 is a long story. It is necessary. For more info, please contact rich@cygnus.com */
+{ "sll", F3(2, 0x25, 0), F3(~2, ~0x25, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 },
+{ "sll", F3(2, 0x25, 1), F3(~2, ~0x25, ~1)|(1<<12), "1,i,d", 0, v6 },
+{ "sra", F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 },
+{ "sra", F3(2, 0x27, 1), F3(~2, ~0x27, ~1)|(1<<12), "1,i,d", 0, v6 },
+{ "srl", F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0), "1,2,d", 0, v6 },
+{ "srl", F3(2, 0x26, 1), F3(~2, ~0x26, ~1)|(1<<12), "1,i,d", 0, v6 },
+
+
+
+{ "mulscc", F3(2, 0x24, 0), F3(~2, ~0x24, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "mulscc", F3(2, 0x24, 1), F3(~2, ~0x24, ~1), "1,i,d", 0, v6 },
+
+{ "clr", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "d", F_ALIAS, v6 }, /* or %g0,%g0,d */
+{ "clr", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0|SIMM13(~0), "d", F_ALIAS, v6 }, /* or %g0,0,d */
+{ "clr", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 },
+{ "clr", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+%g0] */
+{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 },
+{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 },
+{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 },
+{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+0] */
+
+{ "clrb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 },
+{ "clrb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+%g0] */
+{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 },
+{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 },
+{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 },
+
+{ "clrh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 },
+{ "clrh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+%g0] */
+{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 },
+{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 },
+{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 },
+
+{ "orcc", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "orcc", F3(2, 0x12, 1), F3(~2, ~0x12, ~1), "1,i,d", 0, v6 },
+{ "orcc", F3(2, 0x12, 1), F3(~2, ~0x12, ~1), "i,1,d", 0, v6 },
+
+{ "orncc", F3(2, 0x16, 0), F3(~2, ~0x16, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "orncc", F3(2, 0x16, 1), F3(~2, ~0x16, ~1), "1,i,d", 0, v6 },
+{ "orncc", F3(2, 0x16, 1), F3(~2, ~0x16, ~1), "i,1,d", 0, v6 },
+
+{ "orn", F3(2, 0x06, 0), F3(~2, ~0x06, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "orn", F3(2, 0x06, 1), F3(~2, ~0x06, ~1), "1,i,d", 0, v6 },
+{ "orn", F3(2, 0x06, 1), F3(~2, ~0x06, ~1), "i,1,d", 0, v6 },
+
+{ "tst", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|ASI_RS2(~0), "1", 0, v6 }, /* orcc rs1, %g0, %g0 */
+{ "tst", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|RS1_G0|ASI(~0), "2", 0, v6 }, /* orcc %g0, rs2, %g0 */
+{ "tst", F3(2, 0x12, 1), F3(~2, ~0x12, ~1)|RD_G0|SIMM13(~0), "1", 0, v6 }, /* orcc rs1, 0, %g0 */
+
+{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0), "1,2,m", 0, v8 }, /* wr r,r,%asrX */
+{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0), "1,2,y", 0, v6 }, /* wr r,r,%y */
+{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "1,i,m", 0, v8 }, /* wr r,i,%asrX */
+{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0, "1,i,y", 0, v6 }, /* wr r,i,%y */
+{ "wr", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", 0, v6 }, /* wr r,r,%psr */
+{ "wr", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", 0, v6 }, /* wr r,i,%psr */
+{ "wr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", 0, v6 }, /* wr r,r,%wim */
+{ "wr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", 0, v6 }, /* wr r,i,%wim */
+{ "wr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", 0, v6 }, /* wr r,r,%tbr */
+{ "wr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", 0, v6 }, /* wr r,i,%tbr */
+
+
+{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", 0, v8 }, /* rd %asr1,r */
+{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", 0, v6 }, /* rd %y,r */
+{ "rd", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", 0, v6 }, /* rd %tbr,r */
+
+{ "rd", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", 0, v6 }, /* rd %psr,r */
+{ "rd", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", 0, v6 }, /* rd %wim,r */
+
+{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0), "1,2,m", F_ALIAS, v8 }, /* wr r,r,%asrX */
+{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0), "1,2,y", F_ALIAS, v6 }, /* wr r,r,%y */
+{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "1,i,m", F_ALIAS, v8 }, /* wr r,i,%asrX */
+{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0, "1,i,y", F_ALIAS, v6 }, /* wr r,i,%y */
+{ "mov", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", F_ALIAS, v6 }, /* wr r,r,%psr */
+{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", F_ALIAS, v6 }, /* wr r,i,%psr */
+{ "mov", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", F_ALIAS, v6 }, /* wr r,r,%wim */
+{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", F_ALIAS, v6 }, /* wr r,i,%wim */
+{ "mov", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", F_ALIAS, v6 }, /* wr r,r,%tbr */
+{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", F_ALIAS, v6 }, /* wr r,i,%tbr */
+
+{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", F_ALIAS, v8 }, /* rd %asr1,r */
+{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", F_ALIAS, v6 }, /* rd %y,r */
+{ "mov", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", F_ALIAS, v6 }, /* rd %psr,r */
+{ "mov", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", F_ALIAS, v6 }, /* rd %wim,r */
+{ "mov", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", F_ALIAS, v6 }, /* rd %tbr,r */
+
+{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI_RS2(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */
+{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "i,y", F_ALIAS, v6 },
+{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|SIMM13(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,0,%y */
+{ "mov", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|ASI_RS2(~0), "1,p", F_ALIAS, v6 }, /* wr rs1,%g0,%psr */
+{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1), "i,p", F_ALIAS, v6 },
+{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|SIMM13(~0), "1,p", F_ALIAS, v6 }, /* wr rs1,0,%psr */
+{ "mov", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|ASI_RS2(~0), "1,w", F_ALIAS, v6 }, /* wr rs1,%g0,%wim */
+{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1), "i,w", F_ALIAS, v6 },
+{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|SIMM13(~0), "1,w", F_ALIAS, v6 }, /* wr rs1,0,%wim */
+{ "mov", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|ASI_RS2(~0), "1,t", F_ALIAS, v6 }, /* wr rs1,%g0,%tbr */
+{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1), "i,t", F_ALIAS, v6 },
+{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|SIMM13(~0), "1,t", F_ALIAS, v6 }, /* wr rs1,0,%tbr */
+
+{ "mov", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RS1_G0|ASI(~0), "2,d", 0, v6 }, /* or %g0,rs2,d */
+{ "mov", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0, "i,d", 0, v6 }, /* or %g0,i,d */
+{ "mov", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI_RS2(~0), "1,d", 0, v6 }, /* or rs1,%g0,d */
+{ "mov", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|SIMM13(~0), "1,d", 0, v6 }, /* or rs1,0,d */
+
+{ "or", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "1,i,d", 0, v6 },
+{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "i,1,d", 0, v6 },
+
+{ "bset", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* or rd,rs2,rd */
+{ "bset", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "i,r", F_ALIAS, v6 }, /* or rd,i,rd */
+
+{ "andn", F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "andn", F3(2, 0x05, 1), F3(~2, ~0x05, ~1), "1,i,d", 0, v6 },
+{ "andn", F3(2, 0x05, 1), F3(~2, ~0x05, ~1), "i,1,d", 0, v6 },
+
+{ "andncc", F3(2, 0x15, 0), F3(~2, ~0x15, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "andncc", F3(2, 0x15, 1), F3(~2, ~0x15, ~1), "1,i,d", 0, v6 },
+{ "andncc", F3(2, 0x15, 1), F3(~2, ~0x15, ~1), "i,1,d", 0, v6 },
+
+{ "bclr", F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* andn rd,rs2,rd */
+{ "bclr", F3(2, 0x05, 1), F3(~2, ~0x05, ~1), "i,r", F_ALIAS, v6 }, /* andn rd,i,rd */
+
+{ "cmp", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|RD_G0|ASI(~0), "1,2", 0, v6 }, /* subcc rs1,rs2,%g0 */
+{ "cmp", F3(2, 0x14, 1), F3(~2, ~0x14, ~1)|RD_G0, "1,i", 0, v6 }, /* subcc rs1,i,%g0 */
+
+{ "sub", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "sub", F3(2, 0x04, 1), F3(~2, ~0x04, ~1), "1,i,d", 0, v6 },
+
+{ "subcc", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "subcc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "1,i,d", 0, v6 },
+
+{ "subx", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "subx", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v6 },
+
+{ "subxcc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "subxcc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v6 },
+
+{ "and", F3(2, 0x01, 0), F3(~2, ~0x01, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "and", F3(2, 0x01, 1), F3(~2, ~0x01, ~1), "1,i,d", 0, v6 },
+{ "and", F3(2, 0x01, 1), F3(~2, ~0x01, ~1), "i,1,d", 0, v6 },
+
+{ "andcc", F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "andcc", F3(2, 0x11, 1), F3(~2, ~0x11, ~1), "1,i,d", 0, v6 },
+{ "andcc", F3(2, 0x11, 1), F3(~2, ~0x11, ~1), "i,1,d", 0, v6 },
+
+{ "dec", F3(2, 0x04, 1)|SIMM13(0x1), F3(~2, ~0x04, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* sub rd,1,rd */
+{ "dec", F3(2, 0x04, 1), F3(~2, ~0x04, ~1), "i,r", F_ALIAS, v6 }, /* sub rd,i,rd */
+{ "deccc", F3(2, 0x14, 1)|SIMM13(0x1), F3(~2, ~0x14, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* subcc rd,1,rd */
+{ "deccc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "i,r", F_ALIAS, v6 }, /* subcc rd,i,rd */
+{ "inc", F3(2, 0x00, 1)|SIMM13(0x1), F3(~2, ~0x00, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* add rs1,1,rsd */
+{ "inc", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "i,r", F_ALIAS, v6 }, /* add rs1,i,rsd */
+{ "inccc", F3(2, 0x10, 1)|SIMM13(0x1), F3(~2, ~0x10, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* addcc rd,1,rd */
+{ "inccc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,r", F_ALIAS, v6 }, /* addcc rd,i,rd */
+
+{ "btst", F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|RD_G0|ASI(~0), "1,2", F_ALIAS, v6 }, /* andcc rs1,rs2,%g0 */
+{ "btst", F3(2, 0x11, 1), F3(~2, ~0x11, ~1)|RD_G0, "i,1", F_ALIAS, v6 }, /* andcc rs1,i,%g0 */
+
+{ "neg", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "2,d", F_ALIAS, v6 }, /* sub %g0,rs2,rd */
+{ "neg", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "x", F_ALIAS, v6 }, /* sub %g0,rd,rd */
+
+{ "add", F3(2, 0x00, 0), F3(~2, ~0x00, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "add", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "1,i,d", 0, v6 },
+{ "add", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "i,1,d", 0, v6 },
+{ "addcc", F3(2, 0x10, 0), F3(~2, ~0x10, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "1,i,d", 0, v6 },
+{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,1,d", 0, v6 },
+{ "addx", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v6 },
+{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v6 },
+{ "addxcc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v6 },
+{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v6 },
+
+{ "smul", F3(2, 0x0b, 0), F3(~2, ~0x0b, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "smul", F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1), "1,i,d", 0, v8 },
+{ "smul", F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1), "i,1,d", 0, v8 },
+{ "smulcc", F3(2, 0x1b, 0), F3(~2, ~0x1b, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "smulcc", F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1), "1,i,d", 0, v8 },
+{ "smulcc", F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1), "i,1,d", 0, v8 },
+{ "umul", F3(2, 0x0a, 0), F3(~2, ~0x0a, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "umul", F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1), "1,i,d", 0, v8 },
+{ "umul", F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1), "i,1,d", 0, v8 },
+{ "umulcc", F3(2, 0x1a, 0), F3(~2, ~0x1a, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "umulcc", F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1), "1,i,d", 0, v8 },
+{ "umulcc", F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1), "i,1,d", 0, v8 },
+{ "sdiv", F3(2, 0x0f, 0), F3(~2, ~0x0f, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "sdiv", F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1), "1,i,d", 0, v8 },
+{ "sdiv", F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1), "i,1,d", 0, v8 },
+{ "sdivcc", F3(2, 0x1f, 0), F3(~2, ~0x1f, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "sdivcc", F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1), "1,i,d", 0, v8 },
+{ "sdivcc", F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1), "i,1,d", 0, v8 },
+{ "udiv", F3(2, 0x0e, 0), F3(~2, ~0x0e, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "udiv", F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1), "1,i,d", 0, v8 },
+{ "udiv", F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1), "i,1,d", 0, v8 },
+{ "udivcc", F3(2, 0x1e, 0), F3(~2, ~0x1e, ~0)|ASI(~0), "1,2,d", 0, v8 },
+{ "udivcc", F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1), "1,i,d", 0, v8 },
+{ "udivcc", F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1), "i,1,d", 0, v8 },
+
+{ "call", F1(0x1), F1(~0x1), "L", F_DELAYED, v6 },
+{ "call", F1(0x1), F1(~0x1), "L,#", F_DELAYED, v6 },
+{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1", F_DELAYED, v6 }, /* jmpl rs1+%g0, %o7 */
+{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1,#", F_DELAYED, v6 },
+
+{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf),
+"1+2", F_DELAYED, v6 }, /* jmpl rs1+rs2,%o7 */
+{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf),
+"1+2,#", F_DELAYED, v6 }, /* jmpl rs1+rs2,%o7 */
+
+{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),
+"1+i", F_DELAYED, v6 }, /* jmpl rs1+i,%o7 */
+{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),
+"1+i,#", F_DELAYED, v6 }, /* jmpl rs1+i,%o7 */
+{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),
+"i+1", F_DELAYED, v6 }, /* jmpl i+rs1,%o7 */
+{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf),
+"i+1,#", F_DELAYED, v6 }, /* jmpl i+rs1,%o7 */
+
+/* Conditional instructions.
+
+ Because this part of the table was such a mess earlier, I have
+ macrofied it so that all the branches and traps are generated from
+ a single-line description of each condition value. John Gilmore. */
+
+/* Define branches -- one annulled, one without, etc. */
+#define br(opcode, mask, lose, flags) \
+ { opcode, (mask)|ANNUL, (lose), ",a l", (flags), v6 }, \
+ { opcode, (mask) , (lose)|ANNUL, "l", (flags), v6 }
+
+
+/* Define four traps: reg+reg, reg + immediate, immediate alone, reg alone. */
+#define tr(opcode, mask, lose, flags) \
+ { opcode, (mask)|IMMED, (lose)|RS1_G0, "i", (flags), v6 }, /* %g0 + imm */ \
+ { opcode, (mask)|IMMED, (lose), "1+i", (flags), v6 }, /* rs1 + imm */ \
+ { opcode, (mask), IMMED|(lose), "1+2", (flags), v6 }, /* rs1 + rs2 */ \
+ { opcode, (mask), IMMED|(lose)|RS2_G0, "1", (flags), v6 } /* rs1 + %g0 */
+
+/* Define both branches and traps based on condition mask */
+#define cond(bop, top, mask, flags) \
+ br(bop, F2(0, 2)|(mask), F2(~0, ~2)|((~mask)&COND(~0)), F_DELAYED|(flags)), \
+ tr(top, F3(2, 0x3a, 0)|(mask), F3(~2, ~0x3a, 0)|((~mask)&COND(~0)), (flags))
+
+/* Define all the conditions, all the branches, all the traps. */
+
+cond ("b", "t", CONDA, 0),
+cond ("ba", "ta", CONDA, F_ALIAS), /* for nothing */
+cond ("bcc", "tcc", CONDCC, 0),
+cond ("bcs", "tcs", CONDCS, 0),
+cond ("be", "te", CONDE, 0),
+cond ("beq", "teq", CONDE, F_ALIAS), /* for be */
+cond ("bg", "tg", CONDG, 0),
+cond ("bgt", "tgt", CONDG, F_ALIAS),
+cond ("bge", "tge", CONDGE, 0),
+cond ("bgeu", "tgeu", CONDGEU, F_ALIAS), /* for cc */
+cond ("bgu", "tgu", CONDGU, 0),
+cond ("bl", "tl", CONDL, 0),
+cond ("blt", "tlt", CONDL, F_ALIAS),
+cond ("ble", "tle", CONDLE, 0),
+cond ("bleu", "tleu", CONDLEU, 0),
+cond ("blu", "tlu", CONDLU, F_ALIAS), /* for cs */
+cond ("bn", "tn", CONDN, 0),
+cond ("bne", "tne", CONDNE, 0),
+cond ("bneg", "tneg", CONDNEG, 0),
+cond ("bnz", "tnz", CONDNZ, F_ALIAS), /* for ne */
+cond ("bpos", "tpos", CONDPOS, 0),
+cond ("bvc", "tvc", CONDVC, 0),
+cond ("bvs", "tvs", CONDVS, 0),
+cond ("bz", "tz", CONDZ, F_ALIAS), /* for e */
+
+#undef cond
+#undef br
+#undef tr
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define brfc(opcode, mask, lose, flags) \
+ { opcode, (mask), ANNUL|(lose), "l", flags|F_DELAYED, v6 }, \
+ { opcode, (mask)|ANNUL, (lose), ",a l", flags|F_DELAYED, v6 }
+
+
+#define condfc(fop, cop, mask, flags) \
+ brfc(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags), \
+ brfc(cop, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)), flags) \
+
+condfc("fb", "cb", 0x8, 0),
+condfc("fba", "cba", 0x8, F_ALIAS),
+condfc("fbe", "cb0", 0x9, 0),
+condfc("fbg", "cb2", 0x6, 0),
+condfc("fbge", "cb02", 0xb, 0),
+condfc("fbl", "cb1", 0x4, 0),
+condfc("fble", "cb01", 0xd, 0),
+condfc("fblg", "cb12", 0x2, 0),
+condfc("fbn", "cbn", 0x0, 0),
+condfc("fbne", "cb123", 0x1, 0),
+condfc("fbo", "cb012", 0xf, 0),
+condfc("fbu", "cb3", 0x7, 0),
+condfc("fbue", "cb03", 0xa, 0),
+condfc("fbug", "cb23", 0x5, 0),
+condfc("fbuge", "cb023", 0xc, 0),
+condfc("fbul", "cb13", 0x3, 0),
+condfc("fbule", "cb013", 0xe, 0),
+
+#undef condfc
+#undef brfc
+
+{ "jmp", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI(~0), "1+2", F_DELAYED, v6 }, /* jmpl rs1+rs2,%g0 */
+{ "jmp", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI_RS2(~0), "1", F_DELAYED, v6 }, /* jmpl rs1+%g0,%g0 */
+{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0, "1+i", F_DELAYED, v6 }, /* jmpl rs1+i,%g0 */
+{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0, "i+1", F_DELAYED, v6 }, /* jmpl i+rs1,%g0 */
+{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|RS1_G0, "i", F_DELAYED, v6 }, /* jmpl %g0+i,%g0 */
+
+{ "nop", F2(0, 4), 0xfeffffff, "", 0, v6 }, /* sethi 0, %g0 */
+
+{ "set", F2(0x0, 0x4), F2(~0x0, ~0x4), "Sh,d", F_ALIAS, v6 },
+
+{ "sethi", F2(0x0, 0x4), F2(~0x0, ~0x4), "h,d", 0, v6 },
+
+{ "taddcc", F3(2, 0x20, 0), F3(~2, ~0x20, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "taddcc", F3(2, 0x20, 1), F3(~2, ~0x20, ~1), "1,i,d", 0, v6 },
+{ "taddcc", F3(2, 0x20, 1), F3(~2, ~0x20, ~1), "i,1,d", 0, v6 },
+{ "taddcctv", F3(2, 0x22, 0), F3(~2, ~0x22, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "taddcctv", F3(2, 0x22, 1), F3(~2, ~0x22, ~1), "1,i,d", 0, v6 },
+{ "taddcctv", F3(2, 0x22, 1), F3(~2, ~0x22, ~1), "i,1,d", 0, v6 },
+
+{ "tsubcc", F3(2, 0x21, 0), F3(~2, ~0x21, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "tsubcc", F3(2, 0x21, 1), F3(~2, ~0x21, ~1), "1,i,d", 0, v6 },
+{ "tsubcctv", F3(2, 0x23, 0), F3(~2, ~0x23, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "tsubcctv", F3(2, 0x23, 1), F3(~2, ~0x23, ~1), "1,i,d", 0, v6 },
+
+{ "unimp", F2(0x0, 0x0), 0xffc00000, "n", 0, v6 },
+
+{ "iflush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0), "1+2", 0, v6 },
+{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "1+i", 0, v6 },
+{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "i+1", 0, v6 },
+{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0, "i", 0, v6 },
+
+{ "xnor", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "xnor", F3(2, 0x07, 1), F3(~2, ~0x07, ~1), "1,i,d", 0, v6 },
+{ "xnor", F3(2, 0x07, 1), F3(~2, ~0x07, ~1), "i,1,d", 0, v6 },
+{ "xnorcc", F3(2, 0x17, 0), F3(~2, ~0x17, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "xnorcc", F3(2, 0x17, 1), F3(~2, ~0x17, ~1), "1,i,d", 0, v6 },
+{ "xnorcc", F3(2, 0x17, 1), F3(~2, ~0x17, ~1), "i,1,d", 0, v6 },
+{ "xor", F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "xor", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "1,i,d", 0, v6 },
+{ "xor", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "i,1,d", 0, v6 },
+{ "xorcc", F3(2, 0x13, 0), F3(~2, ~0x13, ~0)|ASI(~0), "1,2,d", 0, v6 },
+{ "xorcc", F3(2, 0x13, 1), F3(~2, ~0x13, ~1), "1,i,d", 0, v6 },
+{ "xorcc", F3(2, 0x13, 1), F3(~2, ~0x13, ~1), "i,1,d", 0, v6 },
+
+{ "not", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,d", F_ALIAS, v6 }, /* xnor rs1,%0,rd */
+{ "not", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "r", F_ALIAS, v6 }, /* xnor rd,%0,rd */
+
+{ "btog", F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* xor rd,rs2,rd */
+{ "btog", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "i,r", F_ALIAS, v6 }, /* xor rd,i,rd */
+
+{ "fpop1", F3F(2, 0x34, 0), F3F(~2, ~0x34, ~1), "[1+2],d", 0, v6 },
+{ "fpop2", F3F(2, 0x35, 0), F3F(~2, ~0x35, ~1), "[1+2],d", 0, v6 },
+
+/* float-start */
+{ "fdtoi", F3F(2, 0x34, 0x0d2), F3F(~2, ~0x34, ~0x0d2)|RS1_G0, "B,g", 0, v6 },
+{ "fstoi", F3F(2, 0x34, 0x0d1), F3F(~2, ~0x34, ~0x0d1)|RS1_G0, "f,g", 0, v6 },
+
+ /* all of these conversions are confused and probably wrong. */
+{ "fitod", F3F(2, 0x34, 0x0c8), F3F(~2, ~0x34, ~0x0c8)|RS1_G0, "f,H", 0, v6 },
+{ "fitos", F3F(2, 0x34, 0x0c4), F3F(~2, ~0x34, ~0x0c4)|RS1_G0, "f,g", 0, v6 },
+
+{ "fitoq", F3F(2, 0x34, 0x0cc), F3F(~2, ~0x34, ~0x0cc)|RS1_G0, "f,J", 0, v8 },
+
+
+{ "fdtoq", F3F(2, 0x34, 0x0ce), F3F(~2, ~0x34, ~0x0ce)|RS1_G0, "B,J", 0, v8 },
+{ "fdtos", F3F(2, 0x34, 0x0c6), F3F(~2, ~0x34, ~0x0c6)|RS1_G0, "B,g", 0, v6 },
+{ "fqtod", F3F(2, 0x34, 0x0cb), F3F(~2, ~0x34, ~0x0cb)|RS1_G0, "R,H", 0, v8 },
+{ "fqtos", F3F(2, 0x34, 0x0c7), F3F(~2, ~0x34, ~0x0c7)|RS1_G0, "R,g", 0, v8 },
+{ "fstod", F3F(2, 0x34, 0x0c9), F3F(~2, ~0x34, ~0x0c9)|RS1_G0, "f,H", 0, v6 },
+{ "fstoq", F3F(2, 0x34, 0x0cd), F3F(~2, ~0x34, ~0x0cd)|RS1_G0, "f,J", 0, v8 },
+
+
+
+
+
+{ "fqtoi", F3F(2, 0x34, 0x0d3), F3F(~2, ~0x34, ~0x0d3)|RS1_G0, "R,g", 0, v8 },
+
+
+{ "fdivd", F3F(2, 0x34, 0x04e), F3F(~2, ~0x34, ~0x04e), "v,B,H", 0, v6 },
+{ "fdivq", F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", 0, v8 },
+{ "fdivs", F3F(2, 0x34, 0x04d), F3F(~2, ~0x34, ~0x04d), "e,f,g", 0, v6 },
+{ "fmuld", F3F(2, 0x34, 0x04a), F3F(~2, ~0x34, ~0x04a), "v,B,H", 0, v6 },
+{ "fmulq", F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", 0, v8 },
+{ "fmuls", F3F(2, 0x34, 0x049), F3F(~2, ~0x34, ~0x049), "e,f,g", 0, v6 },
+
+{ "fdmulq", F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", 0, v8 },
+{ "fsmuld", F3F(2, 0x34, 0x069), F3F(~2, ~0x34, ~0x069), "e,f,H", 0, v8 },
+
+{ "fsqrtd", F3F(2, 0x34, 0x02a), F3F(~2, ~0x34, ~0x02a)|RS1_G0, "B,H", 0, v7 },
+{ "fsqrtq", F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", 0, v8 },
+{ "fsqrts", F3F(2, 0x34, 0x029), F3F(~2, ~0x34, ~0x029)|RS1_G0, "f,g", 0, v7 },
+
+{ "fabsq", F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", 0, v6 },
+{ "fabss", F3F(2, 0x34, 0x009), F3F(~2, ~0x34, ~0x009)|RS1_G0, "f,g", 0, v6 },
+{ "fmovq", F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", 0, v6 },
+{ "fmovs", F3F(2, 0x34, 0x001), F3F(~2, ~0x34, ~0x001)|RS1_G0, "f,g", 0, v6 },
+{ "fnegq", F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", 0, v6 },
+{ "fnegs", F3F(2, 0x34, 0x005), F3F(~2, ~0x34, ~0x005)|RS1_G0, "f,g", 0, v6 },
+
+
+{ "faddd", F3F(2, 0x34, 0x042), F3F(~2, ~0x34, ~0x042), "v,B,H", 0, v6 },
+{ "faddq", F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", 0, v8 },
+{ "fadds", F3F(2, 0x34, 0x041), F3F(~2, ~0x34, ~0x041), "e,f,g", 0, v6 },
+{ "fsubd", F3F(2, 0x34, 0x046), F3F(~2, ~0x34, ~0x046), "v,B,H", 0, v6 },
+{ "fsubq", F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", 0, v8 },
+{ "fsubs", F3F(2, 0x34, 0x045), F3F(~2, ~0x34, ~0x045), "e,f,g", 0, v6 },
+
+#define CMPFCC(x) (((x)&0x3)<<25)
+
+{ "fcmpd", F3F(2, 0x35, 0x052), F3F(~2, ~0x35, ~0x052)|RS1_G0, "v,B", 0, v6 },
+{ "fcmped", F3F(2, 0x35, 0x056), F3F(~2, ~0x35, ~0x056)|RS1_G0, "v,B", 0, v6 },
+{ "fcmpeq", F3F(2, 0x34, 0x057), F3F(~2, ~0x34, ~0x057), "V,R", 0, v8 },
+{ "fcmpes", F3F(2, 0x35, 0x055), F3F(~2, ~0x35, ~0x055)|RS1_G0, "e,f", 0, v6 },
+{ "fcmpq", F3F(2, 0x34, 0x053), F3F(~2, ~0x34, ~0x053), "V,R", 0, v8 },
+{ "fcmps", F3F(2, 0x35, 0x051), F3F(~2, ~0x35, ~0x051)|RS1_G0, "e,f", 0, v6 },
+
+{ "cpop1", F3(2, 0x36, 0), F3(~2, ~0x36, ~1), "[1+2],d", 0, v6 },
+{ "cpop2", F3(2, 0x37, 0), F3(~2, ~0x37, ~1), "[1+2],d", 0, v6 },
+
+
+
+};
+
+#define NUMOPCODES ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]))
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * comment-column: 0
+ * End:
+ */
+
+/* end of sparc-opcode.h */
diff --git a/gnu/usr.bin/as/opcode/tahoe.h b/gnu/usr.bin/as/opcode/tahoe.h
new file mode 100644
index 0000000..72b0082
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/tahoe.h
@@ -0,0 +1,247 @@
+/* tahoe-opcode.h - tahoe-specific
+ * Not part of GAS yet
+ *
+ * Ported by the State University of New York at Buffalo by the Distributed
+ * Computer Systems Lab, Department of Computer Science, 1991. (And by Dale
+ * Wiles who was unemployed at the time.)
+ */
+
+struct tot_wot /* tahoe opcode table: wot to do with this */
+ /* particular opcode */
+{
+ char *args; /* how to compile said opcode */
+ tahoe_opcodeT code; /* The opcode. */
+};
+
+struct tot /* tahoe opcode text */
+{
+ char *name; /* opcode name: lowercase string [key] */
+ struct tot_wot detail; /* rest of opcode table [datum] */
+};
+
+static struct tot
+totstrs[] =
+{
+{ "halt", {"", 0x00 } },
+{ "sinf", {"", 0x05 } },
+{ "ldf", {"rl", 0x06 } },
+{ "ldd", {"rq", 0x07 } },
+{ "addb2", {"rbmb", 0x08 } },
+{ "movb", {"rbwb", 0x09 } },
+{ "addw2", {"rwmw", 0x0a } },
+{ "movw", {"rwww", 0x0b } },
+{ "addl2", {"rlml", 0x0c } },
+{ "movl", {"rlwl", 0x0d } },
+{ "bbs", {"rlvlbw", 0x0e } },
+{ "nop", {"", 0x10 } },
+{ "brb", {"bb", 0x11 } },
+{ "brw", {"bw", 0x13 } },
+{ "cosf", {"", 0x15 } },
+{ "lnf", {"rl", 0x16 } },
+{ "lnd", {"rq", 0x17 } },
+{ "addb3", {"rbrbwb", 0x18 } },
+ /* cmpb is wrong in the "offical" (what a joke!) text. It's not "rbwb" */
+{ "cmpb", {"rbrb", 0x19 } },
+{ "addw3", {"rwrwww", 0x1a } },
+ /* cmpw is wrong in the "offical" text. It's not "rwww" */
+{ "cmpw", {"rwrw", 0x1b } },
+{ "addl3", {"rlrlwl", 0x1c } },
+ /* cmpl is wrong in the "offical" text. It's not "rlwl" */
+{ "cmpl", {"rlrl", 0x1d } },
+{ "bbc", {"rlvlbw", 0x1e } },
+{ "rei", {"", 0x20 } },
+{ "bneq", {"bb", 0x21 } },
+{ "bnequ", {"bb", 0x21 } },
+{ "cvtwl", {"rwwl", 0x23 } },
+{ "stf", {"wl", 0x26 } },
+{ "std", {"wq", 0x27 } },
+{ "subb2", {"rbmb", 0x28 } },
+{ "mcomb", {"rbwb", 0x29 } },
+{ "subw2", {"rwmw", 0x2a } },
+{ "mcomw", {"rwww", 0x2b } },
+{ "subl2", {"rlml", 0x2c } },
+{ "mcoml", {"rlwl", 0x2d } },
+{ "emul", {"rlrlrlwq", 0x2e } },
+{ "aoblss", {"rlmlbw", 0x2f } },
+{ "bpt", {"", 0x30 } },
+{ "beql", {"bb", 0x31 } },
+{ "beqlu", {"bb", 0x31 } },
+{ "cvtwb", {"rwwb", 0x33 } },
+{ "logf", {"", 0x35 } },
+{ "cmpf", {"rl", 0x36 } },
+{ "cmpd", {"rq", 0x37 } },
+{ "subb3", {"rbrbwb", 0x38 } },
+{ "bitb", {"rbrb", 0x39 } },
+{ "subw3", {"rwrwww", 0x3a } },
+{ "bitw", {"rwrw", 0x3b } },
+{ "subl3", {"rlrlwl", 0x3c } },
+{ "bitl", {"rlrl", 0x3d } },
+{ "ediv", {"rlrqwlwl", 0x3e } },
+{ "aobleq", {"rlmlbw", 0x3f } },
+{ "ret", {"", 0x40 } },
+{ "bgtr", {"bb", 0x41 } },
+{ "sqrtf", {"", 0x45 } },
+{ "cmpf2", {"rlrl", 0x46 } },
+{ "cmpd2", {"rqrq", 0x47 } },
+{ "shll", {"rbrlwl", 0x48 } },
+{ "clrb", {"wb", 0x49 } },
+{ "shlq", {"rbrqwq", 0x4a } },
+{ "clrw", {"ww", 0x4b } },
+{ "mull2", {"rlml", 0x4c } },
+{ "clrl", {"wl", 0x4d } },
+{ "shal", {"rbrlwl", 0x4e } },
+{ "bleq", {"bb", 0x51 } },
+{ "expf", {"", 0x55 } },
+{ "tstf", {"", 0x56 } },
+{ "tstd", {"", 0x57 } },
+{ "shrl", {"rbrlwl", 0x58 } },
+{ "tstb", {"rb", 0x59 } },
+{ "shrq", {"rbrqwq", 0x5a } },
+{ "tstw", {"rw", 0x5b } },
+{ "mull3", {"rlrlwl", 0x5c } },
+{ "tstl", {"rl", 0x5d } },
+{ "shar", {"rbrlwl", 0x5e } },
+{ "bbssi", {"rlmlbw", 0x5f } },
+{ "ldpctx", {"", 0x60 } },
+{ "pushd", {"", 0x67 } },
+{ "incb", {"mb", 0x69 } },
+{ "incw", {"mw", 0x6b } },
+{ "divl2", {"rlml", 0x6c } },
+{ "incl", {"ml", 0x6d } },
+{ "cvtlb", {"rlwb", 0x6f } },
+{ "svpctx", {"", 0x70 } },
+{ "jmp", {"ab", 0x71 } },
+{ "cvlf", {"rl", 0x76 } },
+{ "cvld", {"rl", 0x77 } },
+{ "decb", {"mb", 0x79 } },
+{ "decw", {"mw", 0x7b } },
+{ "divl3", {"rlrlwl", 0x7c } },
+{ "decl", {"ml", 0x7d } },
+{ "cvtlw", {"rlww", 0x7f } },
+{ "bgeq", {"bb", 0x81 } },
+{ "movs2", {"abab", 0x82 } },
+{ "cvfl", {"wl", 0x86 } },
+{ "cvdl", {"wl", 0x87 } },
+{ "orb2", {"rbmb", 0x88 } },
+{ "cvtbl", {"rbwl", 0x89 } },
+{ "orw2", {"rwmw", 0x8a } },
+{ "bispsw", {"rw", 0x8b } },
+{ "orl2", {"rlml", 0x8c } },
+{ "adwc", {"rlml", 0x8d } },
+{ "adda", {"rlml", 0x8e } },
+{ "blss", {"bb", 0x91 } },
+{ "cmps2", {"abab", 0x92 } },
+{ "ldfd", {"rl", 0x97 } },
+{ "orb3", {"rbrbwb", 0x98 } },
+{ "cvtbw", {"rbww", 0x99 } },
+{ "orw3", {"rwrwww", 0x9a } },
+{ "bicpsw", {"rw", 0x9b } },
+{ "orl3", {"rlrlwl", 0x9c } },
+{ "sbwc", {"rlml", 0x9d } },
+{ "suba", {"rlml", 0x9e } },
+{ "bgtru", {"bb", 0xa1 } },
+{ "cvdf", {"", 0xa6 } },
+{ "andb2", {"rbmb", 0xa8 } },
+{ "movzbl", {"rbwl", 0xa9 } },
+{ "andw2", {"rwmw", 0xaa } },
+{ "loadr", {"rwal", 0xab } },
+{ "andl2", {"rlml", 0xac } },
+{ "mtpr", {"rlrl", 0xad } },
+{ "ffs", {"rlwl", 0xae } },
+{ "blequ", {"bb", 0xb1 } },
+{ "negf", {"", 0xb6 } },
+{ "negd", {"", 0xb7 } },
+{ "andb3", {"rbrbwb", 0xb8 } },
+{ "movzbw", {"rbww", 0xb9 } },
+{ "andw3", {"rwrwww", 0xba } },
+{ "storer", {"rwal", 0xbb } },
+{ "andl3", {"rlrlwl", 0xbc } },
+{ "mfpr", {"rlwl", 0xbd } },
+{ "ffc", {"rlwl", 0xbe } },
+{ "calls", {"rbab", 0xbf } },
+{ "prober", {"rbabrl", 0xc0 } },
+{ "bvc", {"bb", 0xc1 } },
+{ "movs3", {"ababrw", 0xc2 } },
+{ "movzwl", {"rwwl", 0xc3 } },
+{ "addf", {"rl", 0xc6 } },
+{ "addd", {"rq", 0xc7 } },
+{ "xorb2", {"rbmb", 0xc8 } },
+{ "movob", {"rbwb", 0xc9 } },
+{ "xorw2", {"rwmw", 0xca } },
+{ "movow", {"rwww", 0xcb } },
+{ "xorl2", {"rlml", 0xcc } },
+{ "movpsl", {"wl", 0xcd } },
+{ "kcall", {"rw", 0xcf } },
+{ "probew", {"rbabrl", 0xd0 } },
+{ "bvs", {"bb", 0xd1 } },
+{ "cmps3", {"ababrw", 0xd2 } },
+{ "subf", {"rq", 0xd6 } },
+{ "subd", {"rq", 0xd7 } },
+{ "xorb3", {"rbrbwb", 0xd8 } },
+{ "pushb", {"rb", 0xd9 } },
+{ "xorw3", {"rwrwww", 0xda } },
+{ "pushw", {"rw", 0xdb } },
+{ "xorl3", {"rlrlwl", 0xdc } },
+{ "pushl", {"rl", 0xdd } },
+{ "insque", {"abab", 0xe0 } },
+{ "bcs", {"bb", 0xe1 } },
+{ "bgequ", {"bb", 0xe1 } },
+{ "mulf", {"rq", 0xe6 } },
+{ "muld", {"rq", 0xe7 } },
+{ "mnegb", {"rbwb", 0xe8 } },
+{ "movab", {"abwl", 0xe9 } },
+{ "mnegw", {"rwww", 0xea } },
+{ "movaw", {"awwl", 0xeb } },
+{ "mnegl", {"rlwl", 0xec } },
+{ "moval", {"alwl", 0xed } },
+{ "remque", {"ab", 0xf0 } },
+{ "bcc", {"bb", 0xf1 } },
+{ "blssu", {"bb", 0xf1 } },
+{ "divf", {"rq", 0xf6 } },
+{ "divd", {"rq", 0xf7 } },
+ /* movblk is really "alalrw" but 'as' won't accept it,
+ 'cc' and 'gcc' also produce code this way. */
+{ "movblk", {"", 0xf8 } },
+{ "pushab", {"ab", 0xf9 } },
+{ "pushaw", {"aw", 0xfb } },
+{ "casel", {"rlrlrl", 0xfc } },
+{ "pushal", {"al", 0xfd } },
+{ "callf", {"rbab", 0xfe } },
+{ "", "" } /* empty is end sentinel */
+};
+
+/* These are synthetic instructions, where the assembler will munge
+ the addressings modes for you. */
+static struct tot
+synthetic_totstrs[] =
+{
+{ "jr", {"b-", 0x11 } },
+{ "jbr", {"b-", 0x11 } },
+
+{ "jneq", {"b?", 0x21 } },
+{ "jnequ", {"b?", 0x21 } },
+{ "jeql", {"b?", 0x31 } },
+{ "jeqlu", {"b?", 0x31 } },
+{ "jgtr", {"b?", 0x41 } },
+{ "jleq", {"b?", 0x51 } },
+{ "jgeq", {"b?", 0x81 } },
+{ "jlss", {"b?", 0x91 } },
+{ "jgtru", {"b?", 0xa1 } },
+{ "jlequ", {"b?", 0xb1 } },
+{ "jvc", {"b?", 0xc1 } },
+{ "jvs", {"b?", 0xd1 } },
+{ "jcs", {"b?", 0xe1 } },
+{ "jgequ", {"b?", 0xe1 } },
+{ "jcc", {"b?", 0xf1 } },
+{ "jlssu", {"b?", 0xf1 } },
+
+{ "jbs", {"rlvlb!", 0x0e } },
+{ "jbc", {"rlvlb!", 0x1e } },
+
+{ "aojlss", {"rlmlb:", 0x2f } },
+{ "jaoblss", {"rlmlb:", 0x2f } },
+{ "aojleq", {"rlmlb:", 0x3f } },
+{ "jaobleq", {"rlmlb:", 0x3f } },
+{ "jbssi", {"rlmlb:", 0x5f } },
+ { "", "" } /* empty is end sentinel */
+};
diff --git a/gnu/usr.bin/as/opcode/vax.h b/gnu/usr.bin/as/opcode/vax.h
new file mode 100644
index 0000000..d604e3f
--- /dev/null
+++ b/gnu/usr.bin/as/opcode/vax.h
@@ -0,0 +1,382 @@
+/* Vax opcde list.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+GDB and GAS are free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB and GAS are distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB or GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef vax_opcodeT
+#define vax_opcodeT int
+#endif /* no vax_opcodeT */
+
+struct vot_wot /* vax opcode table: wot to do with this */
+ /* particular opcode */
+{
+ char * args; /* how to compile said opcode */
+ vax_opcodeT code; /* op-code (may be > 8 bits!) */
+};
+
+struct vot /* vax opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct vot_wot detail; /* rest of opcode table [datum] */
+};
+
+#define vot_how args
+#define vot_code code
+#define vot_detail detail
+#define vot_name name
+
+static const struct vot
+votstrs[] =
+{
+{ "halt", {"", 0x00 } },
+{ "nop", {"", 0x01 } },
+{ "rei", {"", 0x02 } },
+{ "bpt", {"", 0x03 } },
+{ "ret", {"", 0x04 } },
+{ "rsb", {"", 0x05 } },
+{ "ldpctx", {"", 0x06 } },
+{ "svpctx", {"", 0x07 } },
+{ "cvtps", {"rwabrwab", 0x08 } },
+{ "cvtsp", {"rwabrwab", 0x09 } },
+{ "index", {"rlrlrlrlrlwl", 0x0a } },
+{ "crc", {"abrlrwab", 0x0b } },
+{ "prober", {"rbrwab", 0x0c } },
+{ "probew", {"rbrwab", 0x0d } },
+{ "insque", {"abab", 0x0e } },
+{ "remque", {"abwl", 0x0f } },
+{ "bsbb", {"bb", 0x10 } },
+{ "brb", {"bb", 0x11 } },
+{ "bneq", {"bb", 0x12 } },
+{ "bnequ", {"bb", 0x12 } },
+{ "beql", {"bb", 0x13 } },
+{ "beqlu", {"bb", 0x13 } },
+{ "bgtr", {"bb", 0x14 } },
+{ "bleq", {"bb", 0x15 } },
+{ "jsb", {"ab", 0x16 } },
+{ "jmp", {"ab", 0x17 } },
+{ "bgeq", {"bb", 0x18 } },
+{ "blss", {"bb", 0x19 } },
+{ "bgtru", {"bb", 0x1a } },
+{ "blequ", {"bb", 0x1b } },
+{ "bvc", {"bb", 0x1c } },
+{ "bvs", {"bb", 0x1d } },
+{ "bcc", {"bb", 0x1e } },
+{ "bgequ", {"bb", 0x1e } },
+{ "blssu", {"bb", 0x1f } },
+{ "bcs", {"bb", 0x1f } },
+{ "addp4", {"rwabrwab", 0x20 } },
+{ "addp6", {"rwabrwabrwab", 0x21 } },
+{ "subp4", {"rwabrwab", 0x22 } },
+{ "subp6", {"rwabrwabrwab", 0x23 } },
+{ "cvtpt", {"rwababrwab", 0x24 } },
+{ "mulp", {"rwabrwabrwab", 0x25 } },
+{ "cvttp", {"rwababrwab", 0x26 } },
+{ "divp", {"rwabrwabrwab", 0x27 } },
+{ "movc3", {"rwabab", 0x28 } },
+{ "cmpc3", {"rwabab", 0x29 } },
+{ "scanc", {"rwababrb", 0x2a } },
+{ "spanc", {"rwababrb", 0x2b } },
+{ "movc5", {"rwabrbrwab", 0x2c } },
+{ "cmpc5", {"rwabrbrwab", 0x2d } },
+{ "movtc", {"rwabrbabrwab", 0x2e } },
+{ "movtuc", {"rwabrbabrwab", 0x2f } },
+{ "bsbw", {"bw", 0x30 } },
+{ "brw", {"bw", 0x31 } },
+{ "cvtwl", {"rwwl", 0x32 } },
+{ "cvtwb", {"rwwb", 0x33 } },
+{ "movp", {"rwabab", 0x34 } },
+{ "cmpp3", {"rwabab", 0x35 } },
+{ "cvtpl", {"rwabwl", 0x36 } },
+{ "cmpp4", {"rwabrwab", 0x37 } },
+{ "editpc", {"rwababab", 0x38 } },
+{ "matchc", {"rwabrwab", 0x39 } },
+{ "locc", {"rbrwab", 0x3a } },
+{ "skpc", {"rbrwab", 0x3b } },
+{ "movzwl", {"rwwl", 0x3c } },
+{ "acbw", {"rwrwmwbw", 0x3d } },
+{ "movaw", {"awwl", 0x3e } },
+{ "pushaw", {"aw", 0x3f } },
+{ "addf2", {"rfmf", 0x40 } },
+{ "addf3", {"rfrfwf", 0x41 } },
+{ "subf2", {"rfmf", 0x42 } },
+{ "subf3", {"rfrfwf", 0x43 } },
+{ "mulf2", {"rfmf", 0x44 } },
+{ "mulf3", {"rfrfwf", 0x45 } },
+{ "divf2", {"rfmf", 0x46 } },
+{ "divf3", {"rfrfwf", 0x47 } },
+{ "cvtfb", {"rfwb", 0x48 } },
+{ "cvtfw", {"rfww", 0x49 } },
+{ "cvtfl", {"rfwl", 0x4a } },
+{ "cvtrfl", {"rfwl", 0x4b } },
+{ "cvtbf", {"rbwf", 0x4c } },
+{ "cvtwf", {"rwwf", 0x4d } },
+{ "cvtlf", {"rlwf", 0x4e } },
+{ "acbf", {"rfrfmfbw", 0x4f } },
+{ "movf", {"rfwf", 0x50 } },
+{ "cmpf", {"rfrf", 0x51 } },
+{ "mnegf", {"rfwf", 0x52 } },
+{ "tstf", {"rf", 0x53 } },
+{ "emodf", {"rfrbrfwlwf", 0x54 } },
+{ "polyf", {"rfrwab", 0x55 } },
+{ "cvtfd", {"rfwd", 0x56 } },
+ /* opcode 57 is not defined yet */
+{ "adawi", {"rwmw", 0x58 } },
+ /* opcode 59 is not defined yet */
+ /* opcode 5a is not defined yet */
+ /* opcode 5b is not defined yet */
+{ "insqhi", {"abaq", 0x5c } },
+{ "insqti", {"abaq", 0x5d } },
+{ "remqhi", {"aqwl", 0x5e } },
+{ "remqti", {"aqwl", 0x5f } },
+{ "addd2", {"rdmd", 0x60 } },
+{ "addd3", {"rdrdwd", 0x61 } },
+{ "subd2", {"rdmd", 0x62 } },
+{ "subd3", {"rdrdwd", 0x63 } },
+{ "muld2", {"rdmd", 0x64 } },
+{ "muld3", {"rdrdwd", 0x65 } },
+{ "divd2", {"rdmd", 0x66 } },
+{ "divd3", {"rdrdwd", 0x67 } },
+{ "cvtdb", {"rdwb", 0x68 } },
+{ "cvtdw", {"rdww", 0x69 } },
+{ "cvtdl", {"rdwl", 0x6a } },
+{ "cvtrdl", {"rdwl", 0x6b } },
+{ "cvtbd", {"rbwd", 0x6c } },
+{ "cvtwd", {"rwwd", 0x6d } },
+{ "cvtld", {"rlwd", 0x6e } },
+{ "acbd", {"rdrdmdbw", 0x6f } },
+{ "movd", {"rdwd", 0x70 } },
+{ "cmpd", {"rdrd", 0x71 } },
+{ "mnegd", {"rdwd", 0x72 } },
+{ "tstd", {"rd", 0x73 } },
+{ "emodd", {"rdrbrdwlwd", 0x74 } },
+{ "polyd", {"rdrwab", 0x75 } },
+{ "cvtdf", {"rdwf", 0x76 } },
+ /* opcode 77 is not defined yet */
+{ "ashl", {"rbrlwl", 0x78 } },
+{ "ashq", {"rbrqwq", 0x79 } },
+{ "emul", {"rlrlrlwq", 0x7a } },
+{ "ediv", {"rlrqwlwl", 0x7b } },
+{ "clrd", {"wd", 0x7c } },
+{ "clrg", {"wg", 0x7c } },
+{ "clrq", {"wd", 0x7c } },
+{ "movq", {"rqwq", 0x7d } },
+{ "movaq", {"aqwl", 0x7e } },
+{ "movad", {"adwl", 0x7e } },
+{ "pushaq", {"aq", 0x7f } },
+{ "pushad", {"ad", 0x7f } },
+{ "addb2", {"rbmb", 0x80 } },
+{ "addb3", {"rbrbwb", 0x81 } },
+{ "subb2", {"rbmb", 0x82 } },
+{ "subb3", {"rbrbwb", 0x83 } },
+{ "mulb2", {"rbmb", 0x84 } },
+{ "mulb3", {"rbrbwb", 0x85 } },
+{ "divb2", {"rbmb", 0x86 } },
+{ "divb3", {"rbrbwb", 0x87 } },
+{ "bisb2", {"rbmb", 0x88 } },
+{ "bisb3", {"rbrbwb", 0x89 } },
+{ "bicb2", {"rbmb", 0x8a } },
+{ "bicb3", {"rbrbwb", 0x8b } },
+{ "xorb2", {"rbmb", 0x8c } },
+{ "xorb3", {"rbrbwb", 0x8d } },
+{ "mnegb", {"rbwb", 0x8e } },
+{ "caseb", {"rbrbrb", 0x8f } },
+{ "movb", {"rbwb", 0x90 } },
+{ "cmpb", {"rbrb", 0x91 } },
+{ "mcomb", {"rbwb", 0x92 } },
+{ "bitb", {"rbrb", 0x93 } },
+{ "clrb", {"wb", 0x94 } },
+{ "tstb", {"rb", 0x95 } },
+{ "incb", {"mb", 0x96 } },
+{ "decb", {"mb", 0x97 } },
+{ "cvtbl", {"rbwl", 0x98 } },
+{ "cvtbw", {"rbww", 0x99 } },
+{ "movzbl", {"rbwl", 0x9a } },
+{ "movzbw", {"rbww", 0x9b } },
+{ "rotl", {"rbrlwl", 0x9c } },
+{ "acbb", {"rbrbmbbw", 0x9d } },
+{ "movab", {"abwl", 0x9e } },
+{ "pushab", {"ab", 0x9f } },
+{ "addw2", {"rwmw", 0xa0 } },
+{ "addw3", {"rwrwww", 0xa1 } },
+{ "subw2", {"rwmw", 0xa2 } },
+{ "subw3", {"rwrwww", 0xa3 } },
+{ "mulw2", {"rwmw", 0xa4 } },
+{ "mulw3", {"rwrwww", 0xa5 } },
+{ "divw2", {"rwmw", 0xa6 } },
+{ "divw3", {"rwrwww", 0xa7 } },
+{ "bisw2", {"rwmw", 0xa8 } },
+{ "bisw3", {"rwrwww", 0xa9 } },
+{ "bicw2", {"rwmw", 0xaa } },
+{ "bicw3", {"rwrwww", 0xab } },
+{ "xorw2", {"rwmw", 0xac } },
+{ "xorw3", {"rwrwww", 0xad } },
+{ "mnegw", {"rwww", 0xae } },
+{ "casew", {"rwrwrw", 0xaf } },
+{ "movw", {"rwww", 0xb0 } },
+{ "cmpw", {"rwrw", 0xb1 } },
+{ "mcomw", {"rwww", 0xb2 } },
+{ "bitw", {"rwrw", 0xb3 } },
+{ "clrw", {"ww", 0xb4 } },
+{ "tstw", {"rw", 0xb5 } },
+{ "incw", {"mw", 0xb6 } },
+{ "decw", {"mw", 0xb7 } },
+{ "bispsw", {"rw", 0xb8 } },
+{ "bicpsw", {"rw", 0xb9 } },
+{ "popr", {"rw", 0xba } },
+{ "pushr", {"rw", 0xbb } },
+{ "chmk", {"rw", 0xbc } },
+{ "chme", {"rw", 0xbd } },
+{ "chms", {"rw", 0xbe } },
+{ "chmu", {"rw", 0xbf } },
+{ "addl2", {"rlml", 0xc0 } },
+{ "addl3", {"rlrlwl", 0xc1 } },
+{ "subl2", {"rlml", 0xc2 } },
+{ "subl3", {"rlrlwl", 0xc3 } },
+{ "mull2", {"rlml", 0xc4 } },
+{ "mull3", {"rlrlwl", 0xc5 } },
+{ "divl2", {"rlml", 0xc6 } },
+{ "divl3", {"rlrlwl", 0xc7 } },
+{ "bisl2", {"rlml", 0xc8 } },
+{ "bisl3", {"rlrlwl", 0xc9 } },
+{ "bicl2", {"rlml", 0xca } },
+{ "bicl3", {"rlrlwl", 0xcb } },
+{ "xorl2", {"rlml", 0xcc } },
+{ "xorl3", {"rlrlwl", 0xcd } },
+{ "mnegl", {"rlwl", 0xce } },
+{ "casel", {"rlrlrl", 0xcf } },
+{ "movl", {"rlwl", 0xd0 } },
+{ "cmpl", {"rlrl", 0xd1 } },
+{ "mcoml", {"rlwl", 0xd2 } },
+{ "bitl", {"rlrl", 0xd3 } },
+{ "clrf", {"wf", 0xd4 } },
+{ "clrl", {"wl", 0xd4 } },
+{ "tstl", {"rl", 0xd5 } },
+{ "incl", {"ml", 0xd6 } },
+{ "decl", {"ml", 0xd7 } },
+{ "adwc", {"rlml", 0xd8 } },
+{ "sbwc", {"rlml", 0xd9 } },
+{ "mtpr", {"rlrl", 0xda } },
+{ "mfpr", {"rlwl", 0xdb } },
+{ "movpsl", {"wl", 0xdc } },
+{ "pushl", {"rl", 0xdd } },
+{ "moval", {"alwl", 0xde } },
+{ "movaf", {"afwl", 0xde } },
+{ "pushal", {"al", 0xdf } },
+{ "pushaf", {"af", 0xdf } },
+{ "bbs", {"rlabbb", 0xe0 } },
+{ "bbc", {"rlabbb", 0xe1 } },
+{ "bbss", {"rlabbb", 0xe2 } },
+{ "bbcs", {"rlabbb", 0xe3 } },
+{ "bbsc", {"rlabbb", 0xe4 } },
+{ "bbcc", {"rlabbb", 0xe5 } },
+{ "bbssi", {"rlabbb", 0xe6 } },
+{ "bbcci", {"rlabbb", 0xe7 } },
+{ "blbs", {"rlbb", 0xe8 } },
+{ "blbc", {"rlbb", 0xe9 } },
+{ "ffs", {"rlrbvbwl", 0xea } },
+{ "ffc", {"rlrbvbwl", 0xeb } },
+{ "cmpv", {"rlrbvbrl", 0xec } },
+{ "cmpzv", {"rlrbvbrl", 0xed } },
+{ "extv", {"rlrbvbwl", 0xee } },
+{ "extzv", {"rlrbvbwl", 0xef } },
+{ "insv", {"rlrlrbvb", 0xf0 } },
+{ "acbl", {"rlrlmlbw", 0xf1 } },
+{ "aoblss", {"rlmlbb", 0xf2 } },
+{ "aobleq", {"rlmlbb", 0xf3 } },
+{ "sobgeq", {"mlbb", 0xf4 } },
+{ "sobgtr", {"mlbb", 0xf5 } },
+{ "cvtlb", {"rlwb", 0xf6 } },
+{ "cvtlw", {"rlww", 0xf7 } },
+{ "ashp", {"rbrwabrbrwab", 0xf8 } },
+{ "cvtlp", {"rlrwab", 0xf9 } },
+{ "callg", {"abab", 0xfa } },
+{ "calls", {"rlab", 0xfb } },
+{ "xfc", {"", 0xfc } },
+ /* undefined opcodes here */
+{ "cvtdh", {"rdwh", 0x32fd } },
+{ "cvtgf", {"rgwh", 0x33fd } },
+{ "addg2", {"rgmg", 0x40fd } },
+{ "addg3", {"rgrgwg", 0x41fd } },
+{ "subg2", {"rgmg", 0x42fd } },
+{ "subg3", {"rgrgwg", 0x43fd } },
+{ "mulg2", {"rgmg", 0x44fd } },
+{ "mulg3", {"rgrgwg", 0x45fd } },
+{ "divg2", {"rgmg", 0x46fd } },
+{ "divg3", {"rgrgwg", 0x47fd } },
+{ "cvtgb", {"rgwb", 0x48fd } },
+{ "cvtgw", {"rgww", 0x49fd } },
+{ "cvtgl", {"rgwl", 0x4afd } },
+{ "cvtrgl", {"rgwl", 0x4bfd } },
+{ "cvtbg", {"rbwg", 0x4cfd } },
+{ "cvtwg", {"rwwg", 0x4dfd } },
+{ "cvtlg", {"rlwg", 0x4efd } },
+{ "acbg", {"rgrgmgbw", 0x4ffd } },
+{ "movg", {"rgwg", 0x50fd } },
+{ "cmpg", {"rgrg", 0x51fd } },
+{ "mnegg", {"rgwg", 0x52fd } },
+{ "tstg", {"rg", 0x53fd } },
+{ "emodg", {"rgrwrgwlwg", 0x54fd } },
+{ "polyg", {"rgrwab", 0x55fd } },
+{ "cvtgh", {"rgwh", 0x56fd } },
+ /* undefined opcodes here */
+{ "addh2", {"rhmh", 0x60fd } },
+{ "addh3", {"rhrhwh", 0x61fd } },
+{ "subh2", {"rhmh", 0x62fd } },
+{ "subh3", {"rhrhwh", 0x63fd } },
+{ "mulh2", {"rhmh", 0x64fd } },
+{ "mulh3", {"rhrhwh", 0x65fd } },
+{ "divh2", {"rhmh", 0x66fd } },
+{ "divh3", {"rhrhwh", 0x67fd } },
+{ "cvthb", {"rhwb", 0x68fd } },
+{ "cvthw", {"rhww", 0x69fd } },
+{ "cvthl", {"rhwl", 0x6afd } },
+{ "cvtrhl", {"rhwl", 0x6bfd } },
+{ "cvtbh", {"rbwh", 0x6cfd } },
+{ "cvtwh", {"rwwh", 0x6dfd } },
+{ "cvtlh", {"rlwh", 0x6efd } },
+{ "acbh", {"rhrhmhbw", 0x6ffd } },
+{ "movh", {"rhwh", 0x70fd } },
+{ "cmph", {"rhrh", 0x71fd } },
+{ "mnegh", {"rhwh", 0x72fd } },
+{ "tsth", {"rh", 0x73fd } },
+{ "emodh", {"rhrwrhwlwh", 0x74fd } },
+{ "polyh", {"rhrwab", 0x75fd } },
+{ "cvthg", {"rhwg", 0x76fd } },
+ /* undefined opcodes here */
+{ "clrh", {"wh", 0x7cfd } },
+{ "clro", {"wo", 0x7cfd } },
+{ "movo", {"rowo", 0x7dfd } },
+{ "movah", {"ahwl", 0x7efd } },
+{ "movao", {"aowl", 0x7efd } },
+{ "pushah", {"ah", 0x7ffd } },
+{ "pushao", {"ao", 0x7ffd } },
+ /* undefined opcodes here */
+{ "cvtfh", {"rfwh", 0x98fd } },
+{ "cvtfg", {"rfwg", 0x99fd } },
+ /* undefined opcodes here */
+{ "cvthf", {"rhwf", 0xf6fd } },
+{ "cvthd", {"rhwd", 0xf7fd } },
+ /* undefined opcodes here */
+{ "bugl", {"rl", 0xfdff } },
+{ "bugw", {"rw", 0xfeff } },
+ /* undefined opcodes here */
+
+{ "" , "" } /* empty is end sentinel */
+
+}; /* votstrs */
+
+/* end: vax.opcode.h */
diff --git a/gnu/usr.bin/as/output-file.c b/gnu/usr.bin/as/output-file.c
new file mode 100644
index 0000000..0d913fd
--- /dev/null
+++ b/gnu/usr.bin/as/output-file.c
@@ -0,0 +1,122 @@
+/* output-file.c - Deal with the output file
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Confines all details of emitting object bytes to this module.
+ * All O/S specific crocks should live here.
+ * What we lose in "efficiency" we gain in modularity.
+ * Note we don't need to #include the "as.h" file. No common coupling!
+ */
+
+/* note that we do need config info. xoxorich. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <stdio.h>
+
+#include "as.h"
+
+#include "output-file.h"
+#ifdef BFD_HEADERS
+#include "bfd.h"
+bfd *stdoutput;
+void output_file_create(name)
+char *name;
+{
+ if (name[0] == '-' && name[1] == '\0') {
+ as_perror("FATAL: Can't open a bfd on stdout %s ", name);
+ }
+ else if ( ! (stdoutput = bfd_openw( name, TARGET_FORMAT )) )
+ {
+ as_perror ("FATAL: Can't create %s", name);
+ exit(42);
+ }
+ bfd_set_format(stdoutput, bfd_object);
+}
+/* output_file_create() */
+
+
+void output_file_close(filename)
+char *filename;
+{
+ /* Close the bfd without getting bfd to write out anything by itself */
+ if ( bfd_close_all_done( stdoutput ) == 0 )
+ {
+ as_perror ("FATAL: Can't close %s\n", filename);
+ exit(42);
+ }
+ stdoutput = NULL; /* Trust nobody! */
+} /* output_file_close() */
+
+void output_file_append(where, length, filename)
+char *where;
+long length;
+char *filename;
+{
+ abort(); /* Never do this */
+}
+
+#else
+
+static FILE *stdoutput;
+
+void output_file_create(name)
+char *name;
+{
+ if (name[0] == '-' && name[1] == '\0')
+ stdoutput=stdout;
+ else if (!(stdoutput = fopen(name, "wb"))) {
+ as_perror("FATAL: Can't create %s", name);
+ exit(42);
+ }
+} /* output_file_create() */
+
+
+
+void output_file_close(filename)
+char *filename;
+{
+ if (EOF == fclose(stdoutput)) {
+ as_perror ("FATAL: Can't close %s", filename);
+ exit(42);
+ }
+ stdoutput = NULL; /* Trust nobody! */
+} /* output_file_close() */
+
+void output_file_append(where, length, filename)
+char *where;
+long length;
+char *filename;
+{
+
+ for (; length; length--, where++) {
+ (void) putc(*where, stdoutput);
+ if (ferror(stdoutput))
+ /* if ( EOF == (putc( *where, stdoutput )) ) */
+ {
+ as_perror("Failed to emit an object byte", filename);
+ as_fatal("Can't continue");
+ }
+ }
+} /* output_file_append() */
+#endif
+
+/* end of output-file.c */
diff --git a/gnu/usr.bin/as/output-file.h b/gnu/usr.bin/as/output-file.h
new file mode 100644
index 0000000..7ef1677
--- /dev/null
+++ b/gnu/usr.bin/as/output-file.h
@@ -0,0 +1,40 @@
+/* This file is output-file.h
+
+ Copyright (C) 1987-1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+#ifdef __STDC__
+
+void output_file_append(char *where, long length, char *filename);
+void output_file_close(char *filename);
+void output_file_create(char *name);
+
+#else /* __STDC__ */
+
+void output_file_append();
+void output_file_close();
+void output_file_create();
+
+#endif /* __STDC__ */
+
+
+/* end of output-file.h */
diff --git a/gnu/usr.bin/as/read.c b/gnu/usr.bin/as/read.c
new file mode 100644
index 0000000..1b64ee6
--- /dev/null
+++ b/gnu/usr.bin/as/read.c
@@ -0,0 +1,2412 @@
+/* read.c - read a source file -
+
+ Copyright (C) 1986, 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#define MASK_CHAR (0xFF) /* If your chars aren't 8 bits, you will
+ change this a bit. But then, GNU isn't
+ spozed to run on your machine anyway.
+ (RMS is so shortsighted sometimes.)
+ */
+
+#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
+/* This is the largest known floating point */
+/* format (for now). It will grow when we */
+/* do 4361 style flonums. */
+
+
+/* Routines that read assembler source text to build spagetti in memory. */
+/* Another group of these functions is in the as-expr.c module */
+
+#include "as.h"
+
+#include "obstack.h"
+
+char *input_line_pointer; /*->next char of source file to parse. */
+
+#ifndef NOP_OPCODE
+# define NOP_OPCODE 0x00
+#endif
+
+#if BITS_PER_CHAR != 8
+The following table is indexed by [ (char) ] and will break if
+ a char does not have exactly 256 states (hopefully 0:255!) !
+#endif
+
+#ifdef ALLOW_ATSIGN
+#define AT 2
+#else
+#define AT 0
+#endif
+
+#ifndef PIC
+ const
+#endif
+ char /* used by is_... macros. our ctype[] */
+ lex_type[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
+ AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
+ 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+
+/*
+ * In: a character.
+ * Out: 1 if this character ends a line.
+ */
+#define _ (0)
+char is_end_of_line[256] = {
+#ifdef CR_EOL
+ _, _, _, _, _, _, _, _, _, _,99, _, _, 99, _, _,/* @abcdefghijklmno */
+#else
+ _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */
+#endif
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* */
+ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ /* */
+ };
+#undef _
+
+/* Functions private to this file. */
+
+extern const char line_comment_chars[];
+const char line_separator_chars[1];
+
+static char *buffer; /* 1st char of each buffer of lines is here. */
+static char *buffer_limit; /*->1 + last char in buffer. */
+
+static char *bignum_low; /* Lowest char of bignum. */
+static char *bignum_limit; /* 1st illegal address of bignum. */
+static char *bignum_high; /* Highest char of bignum. */
+/* May point to (bignum_start-1). */
+/* Never >= bignum_limit. */
+static char *old_buffer = 0; /* JF a hack */
+static char *old_input;
+static char *old_limit;
+
+/* Variables for handling include file directory list. */
+
+char **include_dirs; /* List of pointers to directories to
+ search for .include's */
+int include_dir_count; /* How many are in the list */
+int include_dir_maxlen = 1; /* Length of longest in list */
+
+#ifndef WORKING_DOT_WORD
+struct broken_word *broken_words;
+int new_broken_words = 0;
+#endif
+
+#if __STDC__ == 1
+
+static char *demand_copy_string(int *lenP);
+int is_it_end_of_statement(void);
+unsigned int next_char_of_string(void);
+static segT get_known_segmented_expression(expressionS *expP);
+static void grow_bignum(void);
+static void pobegin(void);
+void stringer(int append_zero);
+
+#else /* __STDC__ */
+
+static char *demand_copy_string();
+int is_it_end_of_statement();
+unsigned int next_char_of_string();
+static segT get_known_segmented_expression();
+static void grow_bignum();
+static void pobegin();
+void stringer();
+
+#endif /* not __STDC__ */
+
+extern int listing;
+
+
+void
+ read_begin()
+{
+ const char *p;
+
+ pobegin();
+ obj_read_begin_hook();
+
+ obstack_begin(&notes, 5000);
+ obstack_begin(&cond_obstack, 960);
+
+#define BIGNUM_BEGIN_SIZE (16)
+ bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE);
+ bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
+
+ /* Use machine dependent syntax */
+ for (p = line_separator_chars; *p; p++)
+ is_end_of_line[*p] = 1;
+ /* Use more. FIXME-SOMEDAY. */
+}
+
+/* set up pseudo-op tables */
+
+struct hash_control *
+ po_hash = NULL; /* use before set up: NULL->address error */
+
+static const pseudo_typeS
+ potable[] =
+{
+ { "abort", s_abort, 0 },
+ { "align", s_align_ptwo, 0 },
+ { "ascii", stringer, 0 },
+ { "asciz", stringer, 1 },
+ /* block */
+ { "byte", cons, 1 },
+ { "comm", s_comm, 0 },
+ { "data", s_data, 0 },
+ /* dim */
+ { "double", float_cons, 'd' },
+ /* dsect */
+#ifdef NO_LISTING
+ { "eject", s_ignore, 0 }, /* Formfeed listing */
+#else
+ { "eject", listing_eject, 0 }, /* Formfeed listing */
+#endif /* NO_LISTING */
+ { "else", s_else, 0 },
+ { "end", s_end, 0 },
+ { "endif", s_endif, 0 },
+ /* endef */
+ { "equ", s_set, 0 },
+ /* err */
+ /* extend */
+ { "extern", s_ignore, 0 }, /* We treat all undef as ext */
+ { "appline", s_app_line, 0 },
+ { "appfile", s_app_file, 1 },
+ { "file", s_app_file, 0 },
+ { "fill", s_fill, 0 },
+ { "float", float_cons, 'f' },
+ { "global", s_globl, 0 },
+ { "globl", s_globl, 0 },
+ { "hword", cons, 2 },
+ { "if", s_if, 0 },
+ { "ifdef", s_ifdef, 0 },
+ { "ifeqs", s_ifeqs, 0 },
+ { "ifndef", s_ifdef, 1 },
+ { "ifnes", s_ifeqs, 1 },
+ { "ifnotdef", s_ifdef, 1 },
+ { "include", s_include, 0 },
+ { "int", cons, 4 },
+ { "lcomm", s_lcomm, 0 },
+#ifdef NO_LISTING
+ { "lflags", s_ignore, 0 }, /* Listing flags */
+ { "list", s_ignore, 1 }, /* Turn listing on */
+#else
+ { "lflags", listing_flags, 0 }, /* Listing flags */
+ { "list", listing_list, 1 }, /* Turn listing on */
+#endif /* NO_LISTING */
+ { "long", cons, 4 },
+ { "lsym", s_lsym, 0 },
+#ifdef NO_LISTING
+ { "nolist", s_ignore, 0 }, /* Turn listing off */
+#else
+ { "nolist", listing_list, 0 }, /* Turn listing off */
+#endif /* NO_LISTING */
+ { "octa", big_cons, 16 },
+ { "org", s_org, 0 },
+ { "p2align", s_align_ptwo, 0 },
+ { "previous", s_previous, 0 },
+#ifdef NO_LISTING
+ { "psize", s_ignore, 0 }, /* set paper size */
+#else
+ { "psize", listing_psize, 0 }, /* set paper size */
+#endif /* NO_LISTING */
+ /* print */
+ { "quad", big_cons, 8 },
+#ifdef NO_LISTING
+ { "sbttl", s_ignore, 1 }, /* Subtitle of listing */
+#else
+ { "sbttl", listing_title, 1 }, /* Subtitle of listing */
+#endif /* NO_LISTING */
+ /* scl */
+ /* sect */
+#ifndef TC_M88K
+ { "set", s_set, 0 },
+#endif /* TC_M88K */
+ { "short", cons, 2 },
+ { "single", float_cons, 'f' },
+ /* size */
+ { "space", s_space, 0 },
+ /* tag */
+ { "text", s_text, 0 },
+#ifdef NO_LISTING
+ { "title", s_ignore, 0 }, /* Listing title */
+#else
+ { "title", listing_title, 0 }, /* Listing title */
+#endif /* NO_LISTING */
+ /* type */
+ /* use */
+ /* val */
+ { "word", cons, 2 },
+ { NULL} /* end sentinel */
+};
+
+static void pobegin() {
+ char *errtxt; /* error text */
+ const pseudo_typeS * pop;
+
+ po_hash = hash_new();
+
+ /* Do the target-specific pseudo ops. */
+ for (pop = md_pseudo_table; pop->poc_name; pop++) {
+ errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop);
+ if (errtxt && *errtxt) {
+ as_fatal("error constructing md pseudo-op table");
+ } /* on error */
+ } /* for each op */
+
+ /* Now object specific. Skip any that were in the target table. */
+ for (pop = obj_pseudo_table; pop->poc_name; pop++) {
+ errtxt = hash_insert(po_hash, pop->poc_name, (char *) pop);
+ if (errtxt && *errtxt) {
+ if (!strcmp(errtxt, "exists")) {
+#ifdef DIE_ON_OVERRIDES
+ as_fatal("pseudo op \".%s\" overridden.\n", pop->poc_name);
+#endif /* DIE_ON_OVERRIDES */
+ continue; /* OK if target table overrides. */
+ } else {
+ as_fatal("error constructing obj pseudo-op table");
+ } /* if overridden */
+ } /* on error */
+ } /* for each op */
+
+ /* Now portable ones. Skip any that we've seen already. */
+ for (pop = potable; pop->poc_name; pop++) {
+ errtxt = hash_insert(po_hash, pop->poc_name, (char *) pop);
+ if (errtxt && *errtxt) {
+ if (!strcmp (errtxt, "exists")) {
+#ifdef DIE_ON_OVERRIDES
+ as_fatal("pseudo op \".%s\" overridden.\n", pop->poc_name);
+#endif /* DIE_ON_OVERRIDES */
+ continue; /* OK if target table overrides. */
+ } else {
+ as_fatal("error constructing obj pseudo-op table");
+ } /* if overridden */
+ } /* on error */
+ } /* for each op */
+
+ return;
+} /* pobegin() */
+
+#define HANDLE_CONDITIONAL_ASSEMBLY() \
+ if (ignore_input ()) \
+{ \
+ while (! is_end_of_line[*input_line_pointer++]) \
+ if (input_line_pointer == buffer_limit) \
+ break; \
+ continue; \
+ }
+
+
+/* read_a_source_file()
+ *
+ * We read the file, putting things into a web that
+ * represents what we have been reading.
+ */
+void read_a_source_file(name)
+char *name;
+{
+ register char c;
+ register char * s; /* string of symbol, '\0' appended */
+ register int temp;
+ pseudo_typeS *pop = NULL;
+
+ buffer = input_scrub_new_file(name);
+
+ listing_file(name);
+ listing_newline("");
+
+ while ((buffer_limit = input_scrub_next_buffer(&input_line_pointer)) != 0) { /* We have another line to parse. */
+ know(buffer_limit[-1] == '\n'); /* Must have a sentinel. */
+ contin: /* JF this goto is my fault I admit it. Someone brave please re-write
+ the whole input section here? Pleeze??? */
+ while (input_line_pointer < buffer_limit) { /* We have more of this buffer to parse. */
+
+ /*
+ * We now have input_line_pointer->1st char of next line.
+ * If input_line_pointer[-1] == '\n' then we just
+ * scanned another line: so bump line counters.
+ */
+ if (input_line_pointer[-1] == '\n') {
+ bump_line_counters();
+ } /* just passed a newline */
+
+
+
+ /*
+ * We are at the begining of a line, or similar place.
+ * We expect a well-formed assembler statement.
+ * A "symbol-name:" is a statement.
+ *
+ * Depending on what compiler is used, the order of these tests
+ * may vary to catch most common case 1st.
+ * Each test is independent of all other tests at the (top) level.
+ * PLEASE make a compiler that doesn't use this assembler.
+ * It is crufty to waste a compiler's time encoding things for this
+ * assembler, which then wastes more time decoding it.
+ * (And communicating via (linear) files is silly!
+ * If you must pass stuff, please pass a tree!)
+ */
+ if ((c = *input_line_pointer++) == '\t' || c == ' ' || c == '\f' || c == 0) {
+ c = *input_line_pointer++;
+ }
+ know(c != ' '); /* No further leading whitespace. */
+ LISTING_NEWLINE();
+ /*
+ * C is the 1st significant character.
+ * Input_line_pointer points after that character.
+ */
+ if (is_name_beginner(c)) { /* want user-defined label or pseudo/opcode */
+ HANDLE_CONDITIONAL_ASSEMBLY();
+
+ s = input_line_pointer - 1;
+ c = get_symbol_end(); /* name's delimiter */
+ /*
+ * C is character after symbol.
+ * That character's place in the input line is now '\0'.
+ * S points to the beginning of the symbol.
+ * [In case of pseudo-op, s->'.'.]
+ * Input_line_pointer->'\0' where c was.
+ */
+ if (c == ':') {
+ colon(s); /* user-defined label */
+ * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */
+ /* Input_line_pointer->after ':'. */
+ SKIP_WHITESPACE();
+
+
+ } else if (c == '=' || input_line_pointer[1] == '=') { /* JF deal with FOO=BAR */
+ equals(s);
+ demand_empty_rest_of_line();
+ } else { /* expect pseudo-op or machine instruction */
+ if (*s == '.'
+#ifdef NO_DOT_PSEUDOS
+ || (pop= (pseudo_typeS *) hash_find(po_hash, s))
+#endif
+ ) {
+ /*
+ * PSEUDO - OP.
+ *
+ * WARNING: c has next char, which may be end-of-line.
+ * We lookup the pseudo-op table with s+1 because we
+ * already know that the pseudo-op begins with a '.'.
+ */
+
+#ifdef NO_DOT_PSEUDOS
+ if (*s == '.')
+#endif
+ pop = (pseudo_typeS *) hash_find(po_hash, s+1);
+
+ /* Print the error msg now, while we still can */
+ if (!pop) {
+ as_bad("Unknown pseudo-op: `%s'",s);
+ *input_line_pointer = c;
+ s_ignore(0);
+ break;
+ }
+
+ /* Put it back for error messages etc. */
+ *input_line_pointer = c;
+ /* The following skip of whitespace is compulsory. */
+ /* A well shaped space is sometimes all that separates keyword from operands. */
+ if (c == ' ' || c == '\t') {
+ input_line_pointer++;
+ } /* Skip seperator after keyword. */
+ /*
+ * Input_line is restored.
+ * Input_line_pointer->1st non-blank char
+ * after pseudo-operation.
+ */
+ if (!pop) {
+ ignore_rest_of_line();
+ break;
+ } else {
+ (*pop->poc_handler)(pop->poc_val);
+ } /* if we have one */
+ } else { /* machine instruction */
+ /* WARNING: c has char, which may be end-of-line. */
+ /* Also: input_line_pointer->`\0` where c was. */
+ * input_line_pointer = c;
+ while (!is_end_of_line[*input_line_pointer]) {
+ input_line_pointer++;
+ }
+ c = *input_line_pointer;
+ *input_line_pointer = '\0';
+ md_assemble(s); /* Assemble 1 instruction. */
+ *input_line_pointer++ = c;
+ /* We resume loop AFTER the end-of-line from this instruction */
+ } /* if (*s == '.') */
+
+ } /* if c == ':' */
+ continue;
+ } /* if (is_name_beginner(c) */
+
+
+ if (is_end_of_line[c]) {
+ continue;
+ } /* empty statement */
+
+
+ if (isdigit(c)) { /* local label ("4:") */
+ HANDLE_CONDITIONAL_ASSEMBLY ();
+
+ temp = c - '0';
+#ifdef LOCAL_LABELS_DOLLAR
+ if (*input_line_pointer == '$')
+ input_line_pointer++;
+#endif
+ if (*input_line_pointer++ == ':') {
+ local_colon (temp);
+ } else {
+ as_bad("Spurious digit %d.", temp);
+ input_line_pointer -- ;
+ ignore_rest_of_line();
+ }
+ continue;
+ } /* local label ("4:") */
+
+ if (c && strchr(line_comment_chars, c)) { /* Its a comment. Better say APP or NO_APP */
+ char *ends;
+ char *new_buf;
+ char *new_tmp;
+ int new_length;
+ char *tmp_buf = 0;
+ extern char *scrub_string, *scrub_last_string;
+
+ bump_line_counters();
+ s = input_line_pointer;
+ if (strncmp(s,"APP\n",4))
+ continue; /* We ignore it */
+ s += 4;
+
+ ends = strstr(s,"#NO_APP\n");
+
+ if (!ends) {
+ int tmp_len;
+ int num;
+
+ /* The end of the #APP wasn't in this buffer. We
+ keep reading in buffers until we find the #NO_APP
+ that goes with this #APP There is one. The specs
+ guarentee it... */
+ tmp_len = buffer_limit - s;
+ tmp_buf = xmalloc(tmp_len);
+ memcpy(tmp_buf, s, tmp_len);
+ do {
+ new_tmp = input_scrub_next_buffer(&buffer);
+ if (!new_tmp)
+ break;
+ else
+ buffer_limit = new_tmp;
+ input_line_pointer = buffer;
+ ends = strstr(buffer,"#NO_APP\n");
+ if (ends)
+ num = ends - buffer;
+ else
+ num = buffer_limit - buffer;
+
+ tmp_buf = xrealloc(tmp_buf, tmp_len + num);
+ memcpy(tmp_buf + tmp_len, buffer, num);
+ tmp_len += num;
+ } while (!ends);
+
+ input_line_pointer = ends ? ends + 8 : NULL;
+
+ s = tmp_buf;
+ ends = s + tmp_len;
+
+ } else {
+ input_line_pointer = ends + 8;
+ }
+ new_buf=xmalloc(100);
+ new_length=100;
+ new_tmp=new_buf;
+
+ scrub_string = s;
+ scrub_last_string = ends;
+ for (;;) {
+ int ch;
+
+ ch = do_scrub_next_char(scrub_from_string, scrub_to_string);
+ if (ch == EOF) break;
+ *new_tmp++ = ch;
+ if (new_tmp == new_buf + new_length) {
+ new_buf = xrealloc(new_buf, new_length + 100);
+ new_tmp = new_buf + new_length;
+ new_length += 100;
+ }
+ }
+
+ if (tmp_buf)
+ free(tmp_buf);
+ old_buffer = buffer;
+ old_input = input_line_pointer;
+ old_limit = buffer_limit;
+ buffer = new_buf;
+ input_line_pointer = new_buf;
+ buffer_limit = new_tmp;
+ continue;
+ }
+
+ HANDLE_CONDITIONAL_ASSEMBLY();
+
+ /* as_warn("Junk character %d.",c); Now done by ignore_rest */
+ input_line_pointer--; /* Report unknown char as ignored. */
+ ignore_rest_of_line();
+ } /* while (input_line_pointer<buffer_limit) */
+ if (old_buffer) {
+ bump_line_counters();
+ if (old_input != 0) {
+ buffer=old_buffer;
+ input_line_pointer=old_input;
+ buffer_limit=old_limit;
+ old_buffer = 0;
+ goto contin;
+ }
+ }
+ } /* while (more buffers to scan) */
+ input_scrub_close(); /* Close the input file */
+
+} /* read_a_source_file() */
+
+void s_abort() {
+ as_fatal(".abort detected. Abandoning ship.");
+} /* s_abort() */
+
+/* For machines where ".align 4" means align to a 4 byte boundary. */
+void s_align_bytes(arg)
+int arg;
+{
+ register unsigned int temp;
+ register long temp_fill;
+ unsigned int i = 0;
+ unsigned long max_alignment = 1 << 15;
+
+ if (is_end_of_line[*input_line_pointer])
+ temp = arg; /* Default value from pseudo-op table */
+ else
+ temp = get_absolute_expression();
+
+ if (temp > max_alignment) {
+ as_bad("Alignment too large: %d. assumed.", temp = max_alignment);
+ }
+
+ /*
+ * For the sparc, `.align (1<<n)' actually means `.align n'
+ * so we have to convert it.
+ */
+ if (temp != 0) {
+ for (i = 0; (temp & 1) == 0; temp >>= 1, ++i)
+ ;
+ }
+ if (temp != 1)
+ as_bad("Alignment not a power of 2");
+
+ temp = i;
+
+ if (*input_line_pointer == ',') {
+ input_line_pointer ++;
+ temp_fill = get_absolute_expression();
+ } else {
+ temp_fill = NOP_OPCODE;
+ }
+ /* Only make a frag if we HAVE to... */
+ if (temp && ! need_pass_2)
+ frag_align(temp, (int)temp_fill);
+
+ demand_empty_rest_of_line();
+} /* s_align_bytes() */
+
+/* For machines where ".align 4" means align to 2**4 boundary. */
+void s_align_ptwo() {
+ register int temp;
+ register long temp_fill;
+ long max_alignment = 15;
+
+ temp = get_absolute_expression();
+ if (temp > max_alignment)
+ as_bad("Alignment too large: %d. assumed.", temp = max_alignment);
+ else if (temp < 0) {
+ as_bad("Alignment negative. 0 assumed.");
+ temp = 0;
+ }
+ if (*input_line_pointer == ',') {
+ input_line_pointer ++;
+ temp_fill = get_absolute_expression();
+ } else
+ temp_fill = NOP_OPCODE;
+ /* Only make a frag if we HAVE to... */
+ if (temp && ! need_pass_2)
+ frag_align (temp, (int)temp_fill);
+
+ record_alignment(now_seg, temp);
+
+ demand_empty_rest_of_line();
+} /* s_align_ptwo() */
+
+void s_comm() {
+ register char *name;
+ register char c;
+ register char *p;
+ register int temp;
+ register symbolS *symbolP;
+
+ name = input_line_pointer;
+ c = get_symbol_end();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after symbol-name: rest of line ignored.");
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer ++; /* skip ',' */
+ if ((temp = get_absolute_expression()) < 0) {
+ as_warn(".COMMon length (%d.) <0! Ignored.", temp);
+ ignore_rest_of_line();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+ if (S_IS_DEFINED(symbolP)) {
+ as_bad("Ignoring attempt to re-define symbol");
+ ignore_rest_of_line();
+ return;
+ }
+ if (S_GET_VALUE(symbolP)) {
+ if (S_GET_VALUE(symbolP) != temp)
+ as_bad("Length of .comm \"%s\" is already %d. Not changed to %d.",
+ S_GET_NAME(symbolP),
+ S_GET_VALUE(symbolP),
+ temp);
+ } else {
+ S_SET_VALUE(symbolP, temp);
+ S_SET_EXTERNAL(symbolP);
+ }
+#ifdef OBJ_VMS
+ if ( (!temp) || !flagseen['1'])
+ S_GET_OTHER(symbolP) = const_flag;
+#endif /* not OBJ_VMS */
+ know(symbolP->sy_frag == &zero_address_frag);
+ demand_empty_rest_of_line();
+} /* s_comm() */
+
+void
+ s_data()
+{
+ register int temp;
+
+ prev_seg = now_seg;
+ prev_subseg = now_subseg;
+
+ temp = get_absolute_expression();
+ subseg_new (SEG_DATA, (subsegT)temp);
+
+#ifdef OBJ_VMS
+ const_flag = 0;
+#endif /* not OBJ_VMS */
+ demand_empty_rest_of_line();
+}
+
+void
+ s_previous()
+{
+ segT oprev_seg = now_seg;
+ subsegT oprev_subseg = now_subseg;
+
+ oprev_seg = now_seg;
+ oprev_subseg = now_subseg;
+
+ subseg_new (prev_seg, prev_subseg);
+
+ prev_seg = oprev_seg;
+ prev_subseg = oprev_subseg;
+
+#ifdef OBJ_VMS
+ const_flag = 0;
+#endif /* not OBJ_VMS */
+ demand_empty_rest_of_line();
+}
+
+
+/* Handle the .appfile pseudo-op. This is automatically generated by
+ do_scrub_next_char when a preprocessor # line comment is seen with
+ a file name. This default definition may be overridden by the
+ object or CPU specific pseudo-ops. This function is also the
+ default definition for .file; the APPFILE argument is 1 for
+ .appfile, 0 for .file. */
+
+void s_app_file(appfile)
+ int appfile;
+{
+ register char *s;
+ int length;
+
+ /* Some assemblers tolerate immediately following '"' */
+ if ((s = demand_copy_string(&length)) != 0) {
+ /* If this is a fake .appfile, a fake newline was inserted
+ * into the buffer. Passing -2 to new_logical_line tells it
+ * to account for it.
+ */
+ new_logical_line (s, appfile ? -2 : -1);
+ demand_empty_rest_of_line();
+#ifdef LISTING
+ if (listing)
+ listing_source_file (s);
+#endif
+ }
+#ifdef OBJ_COFF
+ c_dot_file_symbol(s);
+#endif /* OBJ_COFF */
+} /* s_app_file() */
+
+/* Handle the .appline pseudo-op. This is automatically generated by
+ do_scrub_next_char when a preprocessor # line comment is seen.
+ This default definition may be overridden by the object or CPU
+ specific pseudo-ops. */
+
+void
+s_app_line (ignore)
+ int ignore;
+{
+ int l;
+
+ /* The given number is that of the next line. */
+ l = get_absolute_expression () - 1;
+ new_logical_line ((char *) NULL, l);
+#ifdef LISTING
+ if (listing)
+ listing_source_line (l);
+#endif
+ demand_empty_rest_of_line ();
+}
+
+void s_fill() {
+ long temp_repeat;
+ long temp_size;
+ register long temp_fill;
+ char *p;
+
+ if (get_absolute_expression_and_terminator(& temp_repeat) != ',') {
+ input_line_pointer --; /* Backup over what was not a ','. */
+ as_bad("Expect comma after rep-size in .fill:");
+ ignore_rest_of_line();
+ return;
+ }
+ if (get_absolute_expression_and_terminator(& temp_size) != ',') {
+ input_line_pointer --; /* Backup over what was not a ','. */
+ as_bad("Expected comma after size in .fill");
+ ignore_rest_of_line();
+ return;
+ }
+ /*
+ * This is to be compatible with BSD 4.2 AS, not for any rational reason.
+ */
+#define BSD_FILL_SIZE_CROCK_8 (8)
+ if (temp_size > BSD_FILL_SIZE_CROCK_8) {
+ as_bad(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
+ temp_size = BSD_FILL_SIZE_CROCK_8 ;
+ } if (temp_size < 0) {
+ as_warn("Size negative: .fill ignored.");
+ temp_size = 0;
+ } else if (temp_repeat <= 0) {
+ as_warn("Repeat < 0, .fill ignored");
+ temp_size = 0;
+ }
+ temp_fill = get_absolute_expression();
+ if (temp_size && !need_pass_2) {
+ p = frag_var(rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0);
+ memset(p, '\0', (int) temp_size);
+ /*
+ * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS.
+ * The following bizzare behaviour is to be compatible with above.
+ * I guess they tried to take up to 8 bytes from a 4-byte expression
+ * and they forgot to sign extend. Un*x Sux.
+ */
+#define BSD_FILL_SIZE_CROCK_4 (4)
+ md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size);
+ /*
+ * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
+ * but emits no error message because it seems a legal thing to do.
+ * It is a degenerate case of .fill but could be emitted by a compiler.
+ */
+ }
+ demand_empty_rest_of_line();
+}
+
+void s_globl() {
+ register char *name;
+ register int c;
+ register symbolS * symbolP;
+
+ do {
+ name = input_line_pointer;
+ c = get_symbol_end();
+ symbolP = symbol_find_or_make(name);
+ * input_line_pointer = c;
+ SKIP_WHITESPACE();
+ S_SET_EXTERNAL(symbolP);
+ if (c == ',') {
+ input_line_pointer++;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer == '\n')
+ c='\n';
+ }
+ } while (c == ',');
+ demand_empty_rest_of_line();
+} /* s_globl() */
+
+void s_lcomm(needs_align)
+int needs_align; /* 1 if this was a ".bss" directive, which may require
+ * a 3rd argument (alignment).
+ * 0 if it was an ".lcomm" (2 args only)
+ */
+{
+ register char *name;
+ register char c;
+ register char *p;
+ register int temp;
+ register symbolS * symbolP;
+ const int max_alignment = 15;
+ int align = 0;
+
+ name = input_line_pointer;
+ c = get_symbol_end();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after name");
+ ignore_rest_of_line();
+ return;
+ }
+
+ ++input_line_pointer;
+
+ if (*input_line_pointer == '\n') {
+ as_bad("Missing size expression");
+ return;
+ }
+
+ if ((temp = get_absolute_expression()) < 0) {
+ as_warn("BSS length (%d.) <0! Ignored.", temp);
+ ignore_rest_of_line();
+ return;
+ }
+
+ if (needs_align) {
+ align = 0;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after size");
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer++;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer == '\n') {
+ as_bad("Missing alignment");
+ return;
+ }
+ align = get_absolute_expression();
+ if (align > max_alignment){
+ align = max_alignment;
+ as_warn("Alignment too large: %d. assumed.", align);
+ } else if (align < 0) {
+ align = 0;
+ as_warn("Alignment negative. 0 assumed.");
+ }
+ record_alignment(SEG_BSS, align);
+ } /* if needs align */
+
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+
+ if (
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ S_GET_OTHER(symbolP) == 0 &&
+ S_GET_DESC(symbolP) == 0 &&
+#endif /* OBJ_AOUT or OBJ_BOUT */
+ (((S_GET_SEGMENT(symbolP) == SEG_BSS) && (S_GET_VALUE(symbolP) == local_bss_counter))
+ || (!S_IS_DEFINED(symbolP) && S_GET_VALUE(symbolP) == 0))) {
+ if (needs_align){
+ /* Align */
+ align = ~ ((~0) << align); /* Convert to a mask */
+ local_bss_counter =
+ (local_bss_counter + align) & (~align);
+ }
+
+ S_SET_VALUE(symbolP, local_bss_counter);
+ S_SET_SEGMENT(symbolP, SEG_BSS);
+#ifdef OBJ_COFF
+ /* The symbol may already have been created with a preceding
+ * ".globl" directive -- be careful not to step on storage
+ * class in that case. Otherwise, set it to static.
+ */
+ if (S_GET_STORAGE_CLASS(symbolP) != C_EXT){
+ S_SET_STORAGE_CLASS(symbolP, C_STAT);
+ }
+#endif /* OBJ_COFF */
+ symbolP->sy_frag = &bss_address_frag;
+ local_bss_counter += temp;
+ } else {
+ as_bad("Ignoring attempt to re-define symbol from %d. to %d.",
+ S_GET_VALUE(symbolP), local_bss_counter);
+ }
+ demand_empty_rest_of_line();
+
+ return;
+} /* s_lcomm() */
+
+void
+ s_long()
+{
+ cons(4);
+}
+
+void
+ s_int()
+{
+ cons(4);
+}
+
+void s_lsym() {
+ register char *name;
+ register char c;
+ register char *p;
+ register segT segment;
+ expressionS exp;
+ register symbolS *symbolP;
+
+ /* we permit ANY defined expression: BSD4.2 demands constants */
+ name = input_line_pointer;
+ c = get_symbol_end();
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (* input_line_pointer != ',') {
+ *p = 0;
+ as_bad("Expected comma after name \"%s\"", name);
+ *p = c;
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer ++;
+ segment = expression(& exp);
+ if (segment != SEG_ABSOLUTE && !SEG_NORMAL(segment) &&
+ segment != SEG_REGISTER) {
+ as_bad("Bad expression: %s", segment_name(segment));
+ ignore_rest_of_line();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+
+ /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0
+ && symbolP->sy_desc == 0) out of this test
+ because coff doesn't have those fields, and I
+ can't see when they'd ever be tripped. I don't
+ think I understand why they were here so I may
+ have introduced a bug. As recently as 1.37 didn't
+ have this test anyway. xoxorich. */
+
+ if (S_GET_SEGMENT(symbolP) == SEG_UNKNOWN
+ && S_GET_VALUE(symbolP) == 0) {
+ /* The name might be an undefined .global symbol; be
+ sure to keep the "external" bit. */
+ S_SET_SEGMENT(symbolP, segment);
+ S_SET_VALUE(symbolP, (valueT)(exp.X_add_number));
+ } else {
+ as_bad("Symbol %s already defined", name);
+ }
+ *p = c;
+ demand_empty_rest_of_line();
+} /* s_lsym() */
+
+void s_org() {
+ register segT segment;
+ expressionS exp;
+ register long temp_fill;
+ register char *p;
+ /*
+ * Don't believe the documentation of BSD 4.2 AS.
+ * There is no such thing as a sub-segment-relative origin.
+ * Any absolute origin is given a warning, then assumed to be segment-relative.
+ * Any segmented origin expression ("foo+42") had better be in the right
+ * segment or the .org is ignored.
+ *
+ * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
+ * never know sub-segment sizes when we are reading code.
+ * BSD will crash trying to emit -ve numbers of filler bytes in certain
+ * .orgs. We don't crash, but see as-write for that code.
+ */
+ /*
+ * Don't make frag if need_pass_2 == 1.
+ */
+ segment = get_known_segmented_expression(&exp);
+ if (*input_line_pointer == ',') {
+ input_line_pointer ++;
+ temp_fill = get_absolute_expression();
+ } else
+ temp_fill = 0;
+ if (! need_pass_2) {
+ if (segment != now_seg && segment != SEG_ABSOLUTE)
+ as_bad("Invalid segment \"%s\". Segment \"%s\" assumed.",
+ segment_name(segment), segment_name(now_seg));
+ p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
+ exp.X_add_number, (char *)0);
+ * p = temp_fill;
+ } /* if (ok to make frag) */
+ demand_empty_rest_of_line();
+} /* s_org() */
+
+void s_set() {
+ register char *name;
+ register char delim;
+ register char *end_name;
+ register symbolS *symbolP;
+
+ /*
+ * Especial apologies for the random logic:
+ * this just grew, and could be parsed much more simply!
+ * Dean in haste.
+ */
+ name = input_line_pointer;
+ delim = get_symbol_end();
+ end_name = input_line_pointer;
+ *end_name = delim;
+ SKIP_WHITESPACE();
+
+ if (*input_line_pointer != ',') {
+ *end_name = 0;
+ as_bad("Expected comma after name \"%s\"", name);
+ *end_name = delim;
+ ignore_rest_of_line();
+ return;
+ }
+
+ input_line_pointer ++;
+ *end_name = 0;
+
+ if (name[0] == '.' && name[1] == '\0') {
+ /* Turn '. = mumble' into a .org mumble */
+ register segT segment;
+ expressionS exp;
+ register char *ptr;
+
+ segment = get_known_segmented_expression(& exp);
+
+ if (!need_pass_2) {
+ if (segment != now_seg && segment != SEG_ABSOLUTE)
+ as_bad("Invalid segment \"%s\". Segment \"%s\" assumed.",
+ segment_name(segment),
+ segment_name (now_seg));
+ ptr = frag_var(rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
+ exp.X_add_number, (char *)0);
+ *ptr= 0;
+ } /* if (ok to make frag) */
+
+ *end_name = delim;
+ return;
+ }
+
+ if ((symbolP = symbol_find(name)) == NULL
+ && (symbolP = md_undefined_symbol(name)) == NULL) {
+ symbolP = symbol_new(name,
+ SEG_UNKNOWN,
+ 0,
+ &zero_address_frag);
+#ifdef OBJ_COFF
+ /* "set" symbols are local unless otherwise specified. */
+ SF_SET_LOCAL(symbolP);
+#endif /* OBJ_COFF */
+
+ } /* make a new symbol */
+
+ symbol_table_insert(symbolP);
+
+ *end_name = delim;
+ pseudo_set(symbolP);
+ demand_empty_rest_of_line();
+} /* s_set() */
+
+void s_size() {
+ register char *name;
+ register char c;
+ register char *p;
+ register int temp;
+ register symbolS *symbolP;
+ expressionS *exp;
+ segT seg;
+
+ SKIP_WHITESPACE();
+ name = input_line_pointer;
+ c = get_symbol_end();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after symbol-name: rest of line ignored.");
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer ++; /* skip ',' */
+ if ((exp = (expressionS *)malloc(sizeof(expressionS))) == NULL) {
+ as_bad("Virtual memory exhausted");
+ return;
+ }
+ switch (get_known_segmented_expression(exp)) {
+ case SEG_ABSOLUTE:
+ break;
+ case SEG_DIFFERENCE:
+ if (exp->X_add_symbol == NULL || exp->X_subtract_symbol == NULL
+ || S_GET_SEGMENT(exp->X_add_symbol) !=
+ S_GET_SEGMENT(exp->X_subtract_symbol)) {
+ as_bad("Illegal .size expression");
+ ignore_rest_of_line();
+ return;
+ }
+ break;
+ default:
+ as_bad("Illegal .size expression");
+ ignore_rest_of_line();
+ return;
+ }
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+ if (symbolP->sy_sizexp) {
+ as_warn("\"%s\" already has a size", S_GET_NAME(symbolP));
+ } else
+ symbolP->sy_sizexp = (void *)exp;
+
+ demand_empty_rest_of_line();
+} /* s_size() */
+
+void s_type() {
+ register char *name, *type;
+ register char c, c1;
+ register char *p;
+ register symbolS *symbolP;
+ int aux;
+
+ SKIP_WHITESPACE();
+ name = input_line_pointer;
+ c = get_symbol_end();
+ /* just after name is now '\0' */
+ p = input_line_pointer;
+ *p = c;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != ',') {
+ as_bad("Expected comma after symbol-name: rest of line ignored.");
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer ++; /* skip ',' */
+ SKIP_WHITESPACE();
+ if (*input_line_pointer != TYPE_OPERAND_FMT) {
+ as_bad("Expected `%c' as start of operand: rest of line ignored.", TYPE_OPERAND_FMT);
+ ignore_rest_of_line();
+ return;
+ }
+ input_line_pointer ++; /* skip '@' */
+ type = input_line_pointer;
+ c1 = get_symbol_end();
+ if (strcmp(type, "function") == 0) {
+ aux = AUX_FUNC;
+ } else if (strcmp(type, "object") == 0) {
+ aux = AUX_OBJECT;
+ } else {
+ as_warn("Unrecognized .type operand: \"%s\": rest of line ignored.",
+ type);
+ ignore_rest_of_line();
+ return;
+ }
+ *input_line_pointer = c1;
+
+ *p = 0;
+ symbolP = symbol_find_or_make(name);
+ *p = c;
+
+ if (symbolP->sy_aux && symbolP->sy_aux != aux) {
+ as_bad("Type of \"%s\" is already %d. Not changed to %d.",
+ S_GET_NAME(symbolP), symbolP->sy_aux, aux);
+ } else
+ symbolP->sy_aux = aux;
+
+ demand_empty_rest_of_line();
+} /* s_type() */
+
+void s_weak() {
+ register char *name;
+ register int c;
+ register symbolS * symbolP;
+
+ do {
+ name = input_line_pointer;
+ c = get_symbol_end();
+ symbolP = symbol_find_or_make(name);
+ * input_line_pointer = c;
+ SKIP_WHITESPACE();
+ S_SET_EXTERNAL(symbolP);
+ symbolP->sy_bind = BIND_WEAK;
+ if (c == ',') {
+ input_line_pointer++;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer == '\n')
+ c='\n';
+ }
+ } while (c == ',');
+ demand_empty_rest_of_line();
+} /* s_weak() */
+
+void s_space() {
+ long temp_repeat;
+ register long temp_fill;
+ register char *p;
+
+ /* Just like .fill, but temp_size = 1 */
+ if (get_absolute_expression_and_terminator(& temp_repeat) == ',') {
+ temp_fill = get_absolute_expression();
+ } else {
+ input_line_pointer --; /* Backup over what was not a ','. */
+ temp_fill = 0;
+ }
+ if (temp_repeat <= 0) {
+ as_warn("Repeat < 0, .space ignored");
+ ignore_rest_of_line();
+ return;
+ }
+ if (! need_pass_2) {
+ p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
+ temp_repeat, (char *)0);
+ * p = temp_fill;
+ }
+ demand_empty_rest_of_line();
+} /* s_space() */
+
+void
+ s_text()
+{
+ register int temp;
+
+ prev_seg = now_seg;
+ prev_subseg = now_subseg;
+
+ temp = get_absolute_expression();
+ subseg_new (SEG_TEXT, (subsegT)temp);
+ demand_empty_rest_of_line();
+} /* s_text() */
+
+
+/*(JF was static, but can't be if machine dependent pseudo-ops are to use it */
+
+void demand_empty_rest_of_line() {
+ SKIP_WHITESPACE();
+ if (is_end_of_line[*input_line_pointer]) {
+ input_line_pointer++;
+ } else {
+ ignore_rest_of_line();
+ }
+ /* Return having already swallowed end-of-line. */
+} /* Return pointing just after end-of-line. */
+
+void
+ ignore_rest_of_line() /* For suspect lines: gives warning. */
+{
+ if (!is_end_of_line[*input_line_pointer])
+ {
+ if (isprint(*input_line_pointer))
+ as_bad("Rest of line ignored. First ignored character is `%c'.",
+ *input_line_pointer);
+ else
+ as_bad("Rest of line ignored. First ignored character valued 0x%x.",
+ *input_line_pointer);
+ while (input_line_pointer < buffer_limit
+ && !is_end_of_line[*input_line_pointer])
+ {
+ input_line_pointer ++;
+ }
+ }
+ input_line_pointer ++; /* Return pointing just after end-of-line. */
+ know(is_end_of_line[input_line_pointer[-1]]);
+}
+
+/*
+ * pseudo_set()
+ *
+ * In: Pointer to a symbol.
+ * Input_line_pointer->expression.
+ *
+ * Out: Input_line_pointer->just after any whitespace after expression.
+ * Tried to set symbol to value of expression.
+ * Will change symbols type, value, and frag;
+ * May set need_pass_2 == 1.
+ */
+void
+ pseudo_set (symbolP)
+symbolS * symbolP;
+{
+ expressionS exp;
+ register segT segment;
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ int ext;
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+ know(symbolP); /* NULL pointer is logic error. */
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ ext=S_IS_EXTERNAL(symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+ if ((segment = expression(& exp)) == SEG_ABSENT)
+ {
+ as_bad("Missing expression: absolute 0 assumed");
+ exp.X_seg = SEG_ABSOLUTE;
+ exp.X_add_number = 0;
+ }
+
+ switch (segment)
+ {
+ case SEG_BIG:
+ as_bad("%s number invalid. Absolute 0 assumed.",
+ exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
+ S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ ext ? S_SET_EXTERNAL(symbolP) :
+ S_CLEAR_EXTERNAL(symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+ S_SET_VALUE(symbolP, 0);
+ symbolP->sy_frag = & zero_address_frag;
+ break;
+
+ case SEG_ABSENT:
+ as_warn("No expression: Using absolute 0");
+ S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ ext ? S_SET_EXTERNAL(symbolP) :
+ S_CLEAR_EXTERNAL(symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+ S_SET_VALUE(symbolP, 0);
+ symbolP->sy_frag = & zero_address_frag;
+ break;
+
+ case SEG_DIFFERENCE:
+ if (exp.X_add_symbol && exp.X_subtract_symbol
+ && (S_GET_SEGMENT(exp.X_add_symbol) ==
+ S_GET_SEGMENT(exp.X_subtract_symbol))) {
+ if (exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag) {
+ as_bad("Unknown expression: symbols %s and %s are in different frags.",
+ S_GET_NAME(exp.X_add_symbol), S_GET_NAME(exp.X_subtract_symbol));
+ need_pass_2++;
+ }
+ exp.X_add_number+=S_GET_VALUE(exp.X_add_symbol) -
+ S_GET_VALUE(exp.X_subtract_symbol);
+ } else
+ as_bad("Complex expression. Absolute segment assumed.");
+ case SEG_ABSOLUTE:
+ S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ ext ? S_SET_EXTERNAL(symbolP) :
+ S_CLEAR_EXTERNAL(symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+ S_SET_VALUE(symbolP, exp.X_add_number);
+ symbolP->sy_frag = & zero_address_frag;
+ break;
+
+ default:
+ know(SEG_NORMAL(segment));
+ S_SET_SEGMENT(symbolP, segment);
+#if defined(OBJ_AOUT) | defined(OBJ_BOUT)
+ if (ext) {
+ S_SET_EXTERNAL(symbolP);
+ } else {
+ S_CLEAR_EXTERNAL(symbolP);
+ } /* if external */
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
+ S_SET_VALUE(symbolP, exp.X_add_number + S_GET_VALUE(exp.X_add_symbol));
+ symbolP->sy_frag = exp.X_add_symbol->sy_frag;
+ symbolP->sy_aux = exp.X_add_symbol->sy_aux;
+ break;
+
+ case SEG_PASS1: /* Not an error. Just try another pass. */
+ symbolP->sy_forward=exp.X_add_symbol;
+ as_bad("Unknown expression");
+ know(need_pass_2 == 1);
+ break;
+
+ case SEG_UNKNOWN:
+ symbolP->sy_forward=exp.X_add_symbol;
+ /* as_warn("unknown symbol"); */
+ /* need_pass_2 = 1; */
+ break;
+
+
+
+ }
+}
+
+/*
+ * cons()
+ *
+ * CONStruct more frag of .bytes, or .words etc.
+ * Should need_pass_2 be 1 then emit no frag(s).
+ * This understands EXPRESSIONS, as opposed to big_cons().
+ *
+ * Bug (?)
+ *
+ * This has a split personality. We use expression() to read the
+ * value. We can detect if the value won't fit in a byte or word.
+ * But we can't detect if expression() discarded significant digits
+ * in the case of a long. Not worth the crocks required to fix it.
+ */
+
+/* worker to do .byte etc statements */
+/* clobbers input_line_pointer, checks */
+/* end-of-line. */
+void cons(nbytes)
+register unsigned int nbytes; /* 1=.byte, 2=.word, 4=.long */
+{
+ register char c;
+ register long mask; /* High-order bits we will left-truncate, */
+ /* but includes sign bit also. */
+ register long get; /* what we get */
+ register long use; /* get after truncation. */
+ register long unmask; /* what bits we will store */
+ register char * p;
+ register segT segment;
+ expressionS exp;
+
+ /*
+ * Input_line_pointer->1st char after pseudo-op-code and could legally
+ * be a end-of-line. (Or, less legally an eof - which we cope with.)
+ */
+ /* JF << of >= number of bits in the object is undefined. In particular
+ SPARC (Sun 4) has problems */
+
+ if (nbytes >= sizeof(long)) {
+ mask = 0;
+ } else {
+ mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
+ } /* bigger than a long */
+
+ unmask = ~mask; /* Do store these bits. */
+
+#ifdef NEVER
+ "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
+ mask = ~ (unmask >> 1); /* Includes sign bit now. */
+#endif
+
+ /*
+ * The following awkward logic is to parse ZERO or more expressions,
+ * comma seperated. Recall an expression includes its leading &
+ * trailing blanks. We fake a leading ',' if there is (supposed to
+ * be) a 1st expression, and keep demanding 1 expression for each ','.
+ */
+ if (is_it_end_of_statement()) {
+ c = 0; /* Skip loop. */
+ input_line_pointer++; /* Matches end-of-loop 'correction'. */
+ } else {
+ c = ',';
+ } /* if the end else fake it */
+
+ /* Do loop. */
+ while (c == ',') {
+#ifdef WANT_BITFIELDS
+ unsigned int bits_available = BITS_PER_CHAR * nbytes;
+ /* used for error messages and rescanning */
+ char *hold = input_line_pointer;
+#endif /* WANT_BITFIELDS */
+
+ /* At least scan over the expression. */
+ segment = expression(&exp);
+
+#ifdef WANT_BITFIELDS
+ /* Some other assemblers, (eg, asm960), allow
+ bitfields after ".byte" as w:x,y:z, where w and
+ y are bitwidths and x and y are values. They
+ then pack them all together. We do a little
+ better in that we allow them in words, longs,
+ etc. and we'll pack them in target byte order
+ for you.
+
+ The rules are: pack least significat bit first,
+ if a field doesn't entirely fit, put it in the
+ next unit. Overflowing the bitfield is
+ explicitly *not* even a warning. The bitwidth
+ should be considered a "mask".
+
+ FIXME-SOMEDAY: If this is considered generally
+ useful, this logic should probably be reworked.
+ xoxorich. */
+
+ if (*input_line_pointer == ':') { /* bitfields */
+ long value = 0;
+
+ for (;;) {
+ unsigned long width;
+
+ if (*input_line_pointer != ':') {
+ input_line_pointer = hold;
+ break;
+ } /* next piece is not a bitfield */
+
+ /* In the general case, we can't allow
+ full expressions with symbol
+ differences and such. The relocation
+ entries for symbols not defined in this
+ assembly would require arbitrary field
+ widths, positions, and masks which most
+ of our current object formats don't
+ support.
+
+ In the specific case where a symbol
+ *is* defined in this assembly, we
+ *could* build fixups and track it, but
+ this could lead to confusion for the
+ backends. I'm lazy. I'll take any
+ SEG_ABSOLUTE. I think that means that
+ you can use a previous .set or
+ .equ type symbol. xoxorich. */
+
+ if (segment == SEG_ABSENT) {
+ as_warn("Using a bit field width of zero.");
+ exp.X_add_number = 0;
+ segment = SEG_ABSOLUTE;
+ } /* implied zero width bitfield */
+
+ if (segment != SEG_ABSOLUTE) {
+ *input_line_pointer = '\0';
+ as_bad("Field width \"%s\" too complex for a bitfield.\n", hold);
+ *input_line_pointer = ':';
+ demand_empty_rest_of_line();
+ return;
+ } /* too complex */
+
+ if ((width = exp.X_add_number) > (BITS_PER_CHAR * nbytes)) {
+ as_warn("Field width %d too big to fit in %d bytes: truncated to %d bits.",
+ width, nbytes, (BITS_PER_CHAR * nbytes));
+ width = BITS_PER_CHAR * nbytes;
+ } /* too big */
+
+ if (width > bits_available) {
+ /* FIXME-SOMEDAY: backing up and
+ reparsing is wasteful */
+ input_line_pointer = hold;
+ exp.X_add_number = value;
+ break;
+ } /* won't fit */
+
+ hold = ++input_line_pointer; /* skip ':' */
+
+ if ((segment = expression(&exp)) != SEG_ABSOLUTE) {
+ char cache = *input_line_pointer;
+
+ *input_line_pointer = '\0';
+ as_bad("Field value \"%s\" too complex for a bitfield.\n", hold);
+ *input_line_pointer = cache;
+ demand_empty_rest_of_line();
+ return;
+ } /* too complex */
+
+ value |= (~(-1 << width) & exp.X_add_number)
+ << ((BITS_PER_CHAR * nbytes) - bits_available);
+
+ if ((bits_available -= width) == 0
+ || is_it_end_of_statement()
+ || *input_line_pointer != ',') {
+ break;
+ } /* all the bitfields we're gonna get */
+
+ hold = ++input_line_pointer;
+ segment = expression(&exp);
+ } /* forever loop */
+
+ exp.X_add_number = value;
+ segment = SEG_ABSOLUTE;
+ } /* if looks like a bitfield */
+#endif /* WANT_BITFIELDS */
+
+ if (!need_pass_2) { /* Still worthwhile making frags. */
+
+ /* Don't call this if we are going to junk this pass anyway! */
+ know(segment != SEG_PASS1);
+
+ if (segment == SEG_DIFFERENCE && exp.X_add_symbol == NULL) {
+ as_bad("Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.",
+ S_GET_NAME(exp.X_subtract_symbol),
+ segment_name(S_GET_SEGMENT(exp.X_subtract_symbol)));
+ segment = SEG_ABSOLUTE;
+ /* Leave exp.X_add_number alone. */
+ }
+
+ p = frag_more(nbytes);
+
+ switch (segment) {
+ case SEG_BIG:
+ as_bad("%s number invalid. Absolute 0 assumed.",
+ exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
+ md_number_to_chars (p, (long)0, nbytes);
+ break;
+
+ case SEG_ABSENT:
+ as_warn("0 assumed for missing expression");
+ exp.X_add_number = 0;
+ know(exp.X_add_symbol == NULL);
+ /* fall into SEG_ABSOLUTE */
+ case SEG_ABSOLUTE:
+ get = exp.X_add_number;
+ use = get & unmask;
+ if ((get & mask) && (get & mask) != mask)
+ { /* Leading bits contain both 0s & 1s. */
+ as_warn("Value 0x%x truncated to 0x%x.", get, use);
+ }
+ md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
+ break;
+
+ case SEG_DIFFERENCE:
+#ifndef WORKING_DOT_WORD
+ if (nbytes == 2) {
+ struct broken_word *x;
+
+ x = (struct broken_word *) xmalloc(sizeof(struct broken_word));
+ x->next_broken_word = broken_words;
+ broken_words = x;
+ x->frag = frag_now;
+ x->word_goes_here = p;
+ x->dispfrag = 0;
+ x->add = exp.X_add_symbol;
+ x->sub = exp.X_subtract_symbol;
+ x->addnum = exp.X_add_number;
+ x->added = 0;
+ new_broken_words++;
+ break;
+ }
+ /* Else Fall through into... */
+#endif
+ default:
+ case SEG_UNKNOWN:
+#ifdef TC_NS32K
+ fix_new_ns32k(frag_now, p - frag_now->fr_literal, nbytes,
+ exp.X_add_symbol, exp.X_subtract_symbol,
+ exp.X_add_number, 0, 0, 2, 0, 0, RELOC_32);
+#else
+#ifdef PIC
+ fix_new(frag_now, p - frag_now->fr_literal, nbytes,
+ exp.X_add_symbol, exp.X_subtract_symbol,
+ exp.X_add_number, 0, RELOC_32,
+ exp.X_got_symbol);
+#else
+ fix_new(frag_now, p - frag_now->fr_literal, nbytes,
+ exp.X_add_symbol, exp.X_subtract_symbol,
+ exp.X_add_number, 0, RELOC_32);
+#endif
+#endif /* TC_NS32K */
+ break;
+ } /* switch (segment) */
+ } /* if (!need_pass_2) */
+ c = *input_line_pointer++;
+ } /* while (c == ',') */
+ input_line_pointer--; /* Put terminator back into stream. */
+ demand_empty_rest_of_line();
+} /* cons() */
+
+/*
+ * big_cons()
+ *
+ * CONStruct more frag(s) of .quads, or .octa etc.
+ * Makes 0 or more new frags.
+ * If need_pass_2 == 1, generate no frag.
+ * This understands only bignums, not expressions. Cons() understands
+ * expressions.
+ *
+ * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
+ *
+ * This creates objects with struct obstack_control objs, destroying
+ * any context objs held about a partially completed object. Beware!
+ *
+ *
+ * I think it sucks to have 2 different types of integers, with 2
+ * routines to read them, store them etc.
+ * It would be nicer to permit bignums in expressions and only
+ * complain if the result overflowed. However, due to "efficiency"...
+ */
+/* worker to do .quad etc statements */
+/* clobbers input_line_pointer, checks */
+/* end-of-line. */
+/* 8=.quad 16=.octa ... */
+
+void big_cons(nbytes)
+register int nbytes;
+{
+ register char c; /* input_line_pointer->c. */
+ register int radix;
+ register long length; /* Number of chars in an object. */
+ register int digit; /* Value of 1 digit. */
+ register int carry; /* For multi-precision arithmetic. */
+ register int work; /* For multi-precision arithmetic. */
+ register char * p; /* For multi-precision arithmetic. */
+
+ extern const char hex_value[]; /* In hex_value.c. */
+
+ /*
+ * The following awkward logic is to parse ZERO or more strings,
+ * comma seperated. Recall an expression includes its leading &
+ * trailing blanks. We fake a leading ',' if there is (supposed to
+ * be) a 1st expression, and keep demanding 1 expression for each ','.
+ */
+ if (is_it_end_of_statement())
+ {
+ c = 0; /* Skip loop. */
+ }
+ else
+ {
+ c = ','; /* Do loop. */
+ -- input_line_pointer;
+ }
+ while (c == ',')
+ {
+ ++ input_line_pointer;
+ SKIP_WHITESPACE();
+ c = * input_line_pointer;
+ /* C contains 1st non-blank character of what we hope is a number. */
+ if (c == '0')
+ {
+ c = * ++ input_line_pointer;
+ if (c == 'x' || c == 'X')
+ {
+ c = * ++ input_line_pointer;
+ radix = 16;
+ }
+ else
+ {
+ radix = 8;
+ }
+ }
+ else
+ {
+ radix = 10;
+ }
+ /*
+ * This feature (?) is here to stop people worrying about
+ * mysterious zero constants: which is what they get when
+ * they completely omit digits.
+ */
+ if (hex_value[c] >= radix) {
+ as_bad("Missing digits. 0 assumed.");
+ }
+ bignum_high = bignum_low - 1; /* Start constant with 0 chars. */
+ for (; (digit = hex_value[c]) < radix; c = *++input_line_pointer)
+ {
+ /* Multiply existing number by radix, then add digit. */
+ carry = digit;
+ for (p=bignum_low; p <= bignum_high; p++)
+ {
+ work = (*p & MASK_CHAR) * radix + carry;
+ *p = work & MASK_CHAR;
+ carry = work >> BITS_PER_CHAR;
+ }
+ if (carry)
+ {
+ grow_bignum();
+ * bignum_high = carry & MASK_CHAR;
+ know((carry & ~ MASK_CHAR) == 0);
+ }
+ }
+ length = bignum_high - bignum_low + 1;
+ if (length > nbytes)
+ {
+ as_warn("Most significant bits truncated in integer constant.");
+ }
+ else
+ {
+ register long leading_zeroes;
+
+ for (leading_zeroes = nbytes - length;
+ leading_zeroes;
+ leading_zeroes --)
+ {
+ grow_bignum();
+ * bignum_high = 0;
+ }
+ }
+ if (! need_pass_2)
+ {
+ p = frag_more (nbytes);
+ memcpy(p, bignum_low, (int) nbytes);
+ }
+ /* C contains character after number. */
+ SKIP_WHITESPACE();
+ c = *input_line_pointer;
+ /* C contains 1st non-blank character after number. */
+ }
+ demand_empty_rest_of_line();
+} /* big_cons() */
+
+/* Extend bignum by 1 char. */
+static void grow_bignum() {
+ register long length;
+
+ bignum_high ++;
+ if (bignum_high >= bignum_limit)
+ {
+ length = bignum_limit - bignum_low;
+ bignum_low = xrealloc(bignum_low, length + length);
+ bignum_high = bignum_low + length;
+ bignum_limit = bignum_low + length + length;
+ }
+} /* grow_bignum(); */
+
+/*
+ * float_cons()
+ *
+ * CONStruct some more frag chars of .floats .ffloats etc.
+ * Makes 0 or more new frags.
+ * If need_pass_2 == 1, no frags are emitted.
+ * This understands only floating literals, not expressions. Sorry.
+ *
+ * A floating constant is defined by atof_generic(), except it is preceded
+ * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
+ * reading, I decided to be incompatible. This always tries to give you
+ * rounded bits to the precision of the pseudo-op. Former AS did premature
+ * truncatation, restored noisy bits instead of trailing 0s AND gave you
+ * a choice of 2 flavours of noise according to which of 2 floating-point
+ * scanners you directed AS to use.
+ *
+ * In: input_line_pointer->whitespace before, or '0' of flonum.
+ *
+ */
+
+void /* JF was static, but can't be if VAX.C is goning to use it */
+ float_cons(float_type) /* Worker to do .float etc statements. */
+/* Clobbers input_line-pointer, checks end-of-line. */
+register int float_type; /* 'f':.ffloat ... 'F':.float ... */
+{
+ register char * p;
+ register char c;
+ int length; /* Number of chars in an object. */
+ register char * err; /* Error from scanning floating literal. */
+ char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
+
+ /*
+ * The following awkward logic is to parse ZERO or more strings,
+ * comma seperated. Recall an expression includes its leading &
+ * trailing blanks. We fake a leading ',' if there is (supposed to
+ * be) a 1st expression, and keep demanding 1 expression for each ','.
+ */
+ if (is_it_end_of_statement())
+ {
+ c = 0; /* Skip loop. */
+ ++ input_line_pointer; /*->past termintor. */
+ }
+ else
+ {
+ c = ','; /* Do loop. */
+ }
+ while (c == ',') {
+ /* input_line_pointer->1st char of a flonum (we hope!). */
+ SKIP_WHITESPACE();
+ /* Skip any 0{letter} that may be present. Don't even check if the
+ * letter is legal. Someone may invent a "z" format and this routine
+ * has no use for such information. Lusers beware: you get
+ * diagnostics if your input is ill-conditioned.
+ */
+
+ if (input_line_pointer[0] == '0' && isalpha(input_line_pointer[1]))
+ input_line_pointer+=2;
+
+ err = md_atof (float_type, temp, &length);
+ know(length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+ know(length > 0);
+ if (* err) {
+ as_bad("Bad floating literal: %s", err);
+ ignore_rest_of_line();
+ /* Input_line_pointer->just after end-of-line. */
+ c = 0; /* Break out of loop. */
+ } else {
+ if (! need_pass_2) {
+ p = frag_more (length);
+ memcpy(p, temp, length);
+ }
+ SKIP_WHITESPACE();
+ c = *input_line_pointer++;
+ /* C contains 1st non-white character after number. */
+ /* input_line_pointer->just after terminator (c). */
+ }
+ }
+ --input_line_pointer; /*->terminator (is not ','). */
+ demand_empty_rest_of_line();
+} /* float_cons() */
+
+/*
+ * stringer() Worker to do .ascii etc statements. Checks end-of-line.
+ *
+ * We read 0 or more ',' seperated, double-quoted strings.
+ *
+ * Caller should have checked need_pass_2 is FALSE because we don't check it.
+ */
+
+void stringer(append_zero)
+int append_zero; /* 0: don't append '\0', else 1 */
+{
+ unsigned int c;
+
+ /*
+ * The following awkward logic is to parse ZERO or more strings,
+ * comma seperated. Recall a string expression includes spaces
+ * before the opening '\"' and spaces after the closing '\"'.
+ * We fake a leading ',' if there is (supposed to be)
+ * a 1st, expression. We keep demanding expressions for each
+ * ','.
+ */
+ if (is_it_end_of_statement()) {
+ c = 0; /* Skip loop. */
+ ++ input_line_pointer; /* Compensate for end of loop. */
+ } else {
+ c = ','; /* Do loop. */
+ }
+
+ while (c == ',' || c == '<' || c == '"' || ('0' <= c && c <= '9')) {
+ int i;
+
+ SKIP_WHITESPACE();
+ switch (*input_line_pointer) {
+ case '\"':
+ ++input_line_pointer; /* ->1st char of string. */
+ while (is_a_char(c = next_char_of_string())) {
+ FRAG_APPEND_1_CHAR(c);
+ }
+ if (append_zero) {
+ FRAG_APPEND_1_CHAR(0);
+ }
+ know(input_line_pointer[-1] == '\"');
+ break;
+
+ case '<':
+ input_line_pointer++;
+ c = get_single_number();
+ FRAG_APPEND_1_CHAR(c);
+ if (*input_line_pointer != '>') {
+ as_bad("Expected <nn>");
+ }
+ input_line_pointer++;
+ break;
+
+ case ',':
+ input_line_pointer++;
+ break;
+
+ default:
+ i = get_absolute_expression();
+ FRAG_APPEND_1_CHAR(i);
+ break;
+ } /* switch on next char */
+
+ SKIP_WHITESPACE();
+ c = *input_line_pointer;
+ }
+
+ demand_empty_rest_of_line();
+} /* stringer() */
+
+/* FIXME-SOMEDAY: I had trouble here on characters with the
+ high bits set. We'll probably also have trouble with
+ multibyte chars, wide chars, etc. Also be careful about
+ returning values bigger than 1 byte. xoxorich. */
+
+unsigned int next_char_of_string() {
+ register unsigned int c;
+
+ c = *input_line_pointer++ & CHAR_MASK;
+ switch (c) {
+ case '\"':
+ c = NOT_A_CHAR;
+ break;
+
+ case '\\':
+ switch (c = *input_line_pointer++) {
+ case 'b':
+ c = '\b';
+ break;
+
+ case 'f':
+ c = '\f';
+ break;
+
+ case 'n':
+ c = '\n';
+ break;
+
+ case 'r':
+ c = '\r';
+ break;
+
+ case 't':
+ c = '\t';
+ break;
+
+#ifdef BACKSLASH_V
+ case 'v':
+ c = '\013';
+ break;
+#endif
+
+ case '\\':
+ case '"':
+ break; /* As itself. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ long number;
+
+ for (number = 0; isdigit(c); c = *input_line_pointer++) {
+ number = number * 8 + c - '0';
+ }
+ c = number & 0xff;
+ }
+ --input_line_pointer;
+ break;
+
+ case '\n':
+ /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
+ as_warn("Unterminated string: Newline inserted.");
+ c = '\n';
+ break;
+
+ default:
+
+#ifdef ONLY_STANDARD_ESCAPES
+ as_bad("Bad escaped character in string, '?' assumed");
+ c = '?';
+#endif /* ONLY_STANDARD_ESCAPES */
+
+ break;
+ } /* switch on escaped char */
+ break;
+
+ default:
+ break;
+ } /* switch on char */
+ return(c);
+} /* next_char_of_string() */
+
+static segT
+ get_segmented_expression (expP)
+register expressionS * expP;
+{
+ register segT retval;
+
+ if ((retval = expression(expP)) == SEG_PASS1 || retval == SEG_ABSENT || retval == SEG_BIG)
+ {
+ as_bad("Expected address expression: absolute 0 assumed");
+ retval = expP->X_seg = SEG_ABSOLUTE;
+ expP->X_add_number = 0;
+ expP->X_add_symbol = expP->X_subtract_symbol = 0;
+ }
+ return (retval); /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */
+}
+
+static segT get_known_segmented_expression(expP)
+register expressionS *expP;
+{
+ register segT retval;
+ register char * name1;
+ register char * name2;
+
+ if ((retval = get_segmented_expression (expP)) == SEG_UNKNOWN)
+ {
+ name1 = expP->X_add_symbol ? S_GET_NAME(expP->X_add_symbol) : "";
+ name2 = expP->X_subtract_symbol ?
+ S_GET_NAME(expP->X_subtract_symbol) :
+ "";
+ if (name1 && name2)
+ {
+ as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.",
+ name1, name2);
+ }
+ else
+ {
+ as_warn("Symbol \"%s\" undefined: absolute 0 assumed.",
+ name1 ? name1 : name2);
+ }
+ retval = expP->X_seg = SEG_ABSOLUTE;
+ expP->X_add_number = 0;
+ expP->X_add_symbol = expP->X_subtract_symbol = NULL;
+ }
+#ifndef MANY_SEGMENTS
+ know(retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE);
+#endif
+ return (retval);
+
+} /* get_known_segmented_expression() */
+
+
+
+/* static */ long /* JF was static, but can't be if the MD pseudos are to use it */
+ get_absolute_expression()
+{
+ expressionS exp;
+ register segT s;
+
+ if ((s = expression(&exp)) != SEG_ABSOLUTE) {
+ if (s != SEG_ABSENT) {
+ as_bad("Bad Absolute Expression, absolute 0 assumed.");
+ }
+ exp.X_add_number = 0;
+ }
+ return(exp.X_add_number);
+} /* get_absolute_expression() */
+
+char /* return terminator */
+ get_absolute_expression_and_terminator(val_pointer)
+long * val_pointer; /* return value of expression */
+{
+ *val_pointer = get_absolute_expression();
+ return (*input_line_pointer++);
+}
+
+/*
+ * demand_copy_C_string()
+ *
+ * Like demand_copy_string, but return NULL if the string contains any '\0's.
+ * Give a warning if that happens.
+ */
+char *
+ demand_copy_C_string (len_pointer)
+int *len_pointer;
+{
+ register char *s;
+
+ if ((s = demand_copy_string(len_pointer)) != 0) {
+ register int len;
+
+ for (len = *len_pointer;
+ len > 0;
+ len--) {
+ if (*s == 0) {
+ s = 0;
+ len = 1;
+ *len_pointer = 0;
+ as_bad("This string may not contain \'\\0\'");
+ }
+ }
+ }
+ return(s);
+}
+
+/*
+ * demand_copy_string()
+ *
+ * Demand string, but return a safe (=private) copy of the string.
+ * Return NULL if we can't read a string here.
+ */
+static char *demand_copy_string(lenP)
+int *lenP;
+{
+ register unsigned int c;
+ register int len;
+ char *retval;
+
+ len = 0;
+ SKIP_WHITESPACE();
+ if (*input_line_pointer == '\"') {
+ input_line_pointer++; /* Skip opening quote. */
+
+ while (is_a_char(c = next_char_of_string())) {
+ obstack_1grow(&notes, c);
+ len ++;
+ }
+ /* JF this next line is so demand_copy_C_string will return a null
+ termanated string. */
+ obstack_1grow(&notes,'\0');
+ retval=obstack_finish(&notes);
+ } else {
+ as_warn("Missing string");
+ retval = NULL;
+ ignore_rest_of_line();
+ }
+ *lenP = len;
+ return(retval);
+} /* demand_copy_string() */
+
+/*
+ * is_it_end_of_statement()
+ *
+ * In: Input_line_pointer->next character.
+ *
+ * Do: Skip input_line_pointer over all whitespace.
+ *
+ * Out: 1 if input_line_pointer->end-of-line.
+ */
+int is_it_end_of_statement() {
+ SKIP_WHITESPACE();
+ return(is_end_of_line[*input_line_pointer]);
+} /* is_it_end_of_statement() */
+
+void equals(sym_name)
+char *sym_name;
+{
+ register symbolS *symbolP; /* symbol we are working with */
+
+ input_line_pointer++;
+ if (*input_line_pointer == '=')
+ input_line_pointer++;
+
+ while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
+ input_line_pointer++;
+
+ if (sym_name[0] == '.' && sym_name[1] == '\0') {
+ /* Turn '. = mumble' into a .org mumble */
+ register segT segment;
+ expressionS exp;
+ register char *p;
+
+ segment = get_known_segmented_expression(& exp);
+ if (! need_pass_2) {
+ if (segment != now_seg && segment != SEG_ABSOLUTE)
+ as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
+ segment_name(segment),
+ segment_name(now_seg));
+ p = frag_var(rs_org, 1, 1, (relax_substateT)0, exp.X_add_symbol,
+ exp.X_add_number, (char *)0);
+ * p = 0;
+ } /* if (ok to make frag) */
+ } else {
+ symbolP=symbol_find_or_make(sym_name);
+ pseudo_set(symbolP);
+ }
+} /* equals() */
+
+/* .include -- include a file at this point. */
+
+/* ARGSUSED */
+void s_include(arg)
+int arg;
+{
+ char *newbuf;
+ char *filename;
+ int i;
+ FILE *try;
+ char *path;
+
+ filename = demand_copy_string(&i);
+ demand_empty_rest_of_line();
+ path = xmalloc(i + include_dir_maxlen + 5 /* slop */);
+ for (i = 0; i < include_dir_count; i++) {
+ strcpy(path, include_dirs[i]);
+ strcat(path, "/");
+ strcat(path, filename);
+ if (0 != (try = fopen(path, "r")))
+ {
+ fclose (try);
+ goto gotit;
+ }
+ }
+ free(path);
+ path = filename;
+ gotit:
+ /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */
+ newbuf = input_scrub_include_file (path, input_line_pointer);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+} /* s_include() */
+
+void add_include_dir(path)
+char *path;
+{
+ int i;
+
+ if (include_dir_count == 0)
+ {
+ include_dirs = (char **)xmalloc (2 * sizeof (*include_dirs));
+ include_dirs[0] = "."; /* Current dir */
+ include_dir_count = 2;
+ }
+ else
+ {
+ include_dir_count++;
+ include_dirs = (char **) realloc(include_dirs,
+ include_dir_count*sizeof (*include_dirs));
+ }
+
+ include_dirs[include_dir_count-1] = path; /* New one */
+
+ i = strlen (path);
+ if (i > include_dir_maxlen)
+ include_dir_maxlen = i;
+} /* add_include_dir() */
+
+void s_ignore(arg)
+int arg;
+{
+ while (!is_end_of_line[*input_line_pointer]) {
+ ++input_line_pointer;
+ }
+ ++input_line_pointer;
+
+ return;
+} /* s_ignore() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of read.c */
diff --git a/gnu/usr.bin/as/read.h b/gnu/usr.bin/as/read.h
new file mode 100644
index 0000000..29d3dfc
--- /dev/null
+++ b/gnu/usr.bin/as/read.h
@@ -0,0 +1,160 @@
+/* read.h - of read.c
+
+ Copyright (C) 1986, 1990, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+extern char *input_line_pointer; /* -> char we are parsing now. */
+
+#define PERMIT_WHITESPACE /* Define to make whitespace be allowed in */
+/* many syntactically unnecessary places. */
+/* Normally undefined. For compatibility */
+/* with ancient GNU cc. */
+/* #undef PERMIT_WHITESPACE */
+
+#ifdef PERMIT_WHITESPACE
+#define SKIP_WHITESPACE() {if (* input_line_pointer == ' ') ++ input_line_pointer;}
+#else
+#define SKIP_WHITESPACE() know(*input_line_pointer != ' ' )
+#endif
+
+
+#define LEX_NAME (1) /* may continue a name */
+#define LEX_BEGIN_NAME (2) /* may begin a name */
+
+#define is_name_beginner(c) ( lex_type[c] & LEX_BEGIN_NAME )
+#define is_part_of_name(c) ( lex_type[c] & LEX_NAME )
+
+#ifndef is_a_char
+#define CHAR_MASK (0xff)
+#define NOT_A_CHAR (CHAR_MASK+1)
+#define is_a_char(c) (((unsigned)(c)) <= CHAR_MASK)
+#endif /* is_a_char() */
+
+#ifdef PIC
+/* We change some of the entries in lex_type on some archs */
+extern char lex_type[];
+#else
+extern const char lex_type[];
+#endif
+extern char is_end_of_line[];
+
+/* These are initialized by the CPU specific target files (tc-*.c). */
+extern const char comment_chars[];
+extern const char line_comment_chars[];
+extern const char line_separator_chars[];
+
+#if __STDC__ == 1
+
+char *demand_copy_C_string(int *len_pointer);
+char get_absolute_expression_and_terminator(long *val_pointer);
+long get_absolute_expression(void);
+void add_include_dir(char *path);
+void big_cons(int nbytes);
+void cons(unsigned int nbytes);
+void demand_empty_rest_of_line(void);
+void equals(char *sym_name);
+void float_cons(int float_type);
+void ignore_rest_of_line(void);
+void pseudo_set(symbolS *symbolP);
+void read_a_source_file(char *name);
+void read_begin(void);
+void s_abort(void);
+void s_align_bytes(int arg);
+void s_align_ptwo(void);
+void s_app_file(int);
+void s_app_line(int);
+void s_comm(void);
+void s_data(void);
+void s_else(int arg);
+void s_end(int arg);
+void s_endif(int arg);
+void s_fill(void);
+void s_globl(void);
+void s_if(int arg);
+void s_ifdef(int arg);
+void s_ifeqs(int arg);
+void s_ignore(int arg);
+void s_include(int arg);
+void s_lcomm(int needs_align);
+void s_lsym(void);
+void s_previous(void);
+void s_org(void);
+void s_set(void);
+void s_size(void);
+void s_space(void);
+void s_text(void);
+void s_type(void);
+void s_weak(void);
+
+#else /* not __STDC__ */
+
+char *demand_copy_C_string();
+char get_absolute_expression_and_terminator();
+long get_absolute_expression();
+void add_include_dir();
+void big_cons();
+void cons();
+void demand_empty_rest_of_line();
+void equals();
+void float_cons();
+void ignore_rest_of_line();
+void pseudo_set();
+void read_a_source_file();
+void read_begin();
+void s_abort();
+void s_align_bytes();
+void s_align_ptwo();
+void s_app_file();
+void s_app_line();
+void s_comm();
+void s_data();
+void s_else();
+void s_end();
+void s_endif();
+void s_fill();
+void s_globl();
+void s_if();
+void s_ifdef();
+void s_ifeqs();
+void s_ignore();
+void s_include();
+void s_lcomm();
+void s_lsym();
+void s_previous();
+void s_org();
+void s_set();
+void s_size();
+void s_space();
+void s_text();
+void s_type();
+void s_weak();
+
+#endif /* not __STDC__ */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of read.h */
diff --git a/gnu/usr.bin/as/struc-symbol.h b/gnu/usr.bin/as/struc-symbol.h
new file mode 100644
index 0000000..412bdfb
--- /dev/null
+++ b/gnu/usr.bin/as/struc-symbol.h
@@ -0,0 +1,134 @@
+/* struct_symbol.h - Internal symbol structure
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ oYou should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+#ifndef __struc_symbol_h__
+#define __struc_symbol_h__
+
+struct symbol /* our version of an nlist node */
+{
+ obj_symbol_type sy_symbol; /* what we write in .o file (if permitted) */
+ unsigned long sy_name_offset; /* 4-origin position of sy_name in symbols */
+ /* part of object file. */
+ /* 0 for (nameless) .stabd symbols. */
+ /* Not used until write_object_file() time. */
+ long sy_number; /* 24 bit symbol number. */
+ /* Symbol numbers start at 0 and are */
+ /* unsigned. */
+ struct symbol *sy_next; /* forward chain, or NULL */
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ struct symbol *sy_previous; /* backward chain, or NULL */
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+ struct frag *sy_frag; /* NULL or -> frag this symbol attaches to. */
+ struct symbol *sy_forward; /* value is really that of this other symbol */
+ /* We will probably want to add a sy_segment here soon. */
+
+#ifdef PIC
+ /* Force symbol into symbol table, even if local */
+ int sy_forceout;
+#endif
+ /* Size of symbol as given by the .size directive */
+ void *sy_sizexp; /* (expressionS *) */
+
+ /* Auxiliary type information as given by the .type directive */
+ unsigned char sy_aux;
+#define AUX_OBJECT 1
+#define AUX_FUNC 2
+ unsigned char sy_bind;
+#define BIND_LOCAL 0 /* currently not used */
+#define BIND_GLOBAL 1 /* currently not used */
+#define BIND_WEAK 2
+};
+
+typedef struct symbol symbolS;
+
+#ifdef PIC
+symbolS *GOT_symbol; /* Pre-defined "__GLOBAL_OFFSET_TABLE" */
+int got_referenced;
+#endif
+
+typedef unsigned valueT; /* The type of n_value. Helps casting. */
+
+#ifndef WORKING_DOT_WORD
+struct broken_word {
+ struct broken_word *next_broken_word;/* One of these strucs per .word x-y */
+ fragS *frag; /* Which frag its in */
+ char *word_goes_here;/* Where in the frag it is */
+ fragS *dispfrag; /* where to add the break */
+ symbolS *add; /* symbol_x */
+ symbolS *sub; /* - symbol_y */
+ long addnum; /* + addnum */
+ int added; /* nasty thing happend yet? */
+ /* 1: added and has a long-jump */
+ /* 2: added but uses someone elses long-jump */
+ struct broken_word *use_jump; /* points to broken_word with a similar
+ long-jump */
+};
+extern struct broken_word *broken_words;
+#endif /* ndef WORKING_DOT_WORD */
+
+#define SEGMENT_TO_SYMBOL_TYPE(seg) (seg_N_TYPE[(int) (seg)])
+extern const short seg_N_TYPE[]; /* subseg.c */
+
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+#if __STDC__ == 1
+
+void symbol_clear_list_pointers(symbolS *symbolP);
+void symbol_insert(symbolS *addme, symbolS *target, symbolS **rootP, symbolS **lastP);
+void symbol_remove(symbolS *symbolP, symbolS **rootP, symbolS **lastP);
+void verify_symbol_chain(symbolS *rootP, symbolS *lastP);
+
+#else /* not __STDC__ */
+
+void symbol_clear_list_pointers();
+void symbol_insert();
+void symbol_remove();
+void verify_symbol_chain();
+
+#endif /* not __STDC__ */
+
+#define symbol_previous(s) ((s)->sy_previous)
+
+#else /* SYMBOLS_NEED_BACKPOINTERS */
+
+#define symbol_clear_list_pointers(clearme) {clearme->sy_next = NULL;}
+
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+#if __STDC__ == 1
+void symbol_append(symbolS *addme, symbolS *target, symbolS **rootP, symbolS **lastP);
+#else /* not __STDC__ */
+void symbol_append();
+#endif /* not __STDC__ */
+
+#define symbol_next(s) ((s)->sy_next)
+
+#endif /* __struc_symbol_h__ */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of struc-symbol.h */
diff --git a/gnu/usr.bin/as/subsegs.c b/gnu/usr.bin/as/subsegs.c
new file mode 100644
index 0000000..21ef534
--- /dev/null
+++ b/gnu/usr.bin/as/subsegs.c
@@ -0,0 +1,313 @@
+/* subsegs.c - subsegments -
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * Segments & sub-segments.
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+
+#include "subsegs.h"
+#include "obstack.h"
+
+#ifdef MANY_SEGMENTS
+segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
+
+frchainS* frchain_root,
+ * frchain_now;
+
+#else
+frchainS* frchain_root,
+ * frchain_now, /* Commented in "subsegs.h". */
+ * data0_frchainP;
+
+#endif
+char * const /* in: segT out: char* */
+ seg_name[] = {
+ "absolute",
+#ifdef MANY_SEGMENTS
+ "e0","e1","e2","e3","e4","e5","e6","e7","e8","e9",
+#else
+ "text",
+ "data",
+ "bss",
+#endif
+ "unknown",
+ "absent",
+ "pass1",
+ "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
+ "bignum/flonum",
+ "difference",
+ "debug",
+ "transfert vector preload",
+ "transfert vector postload",
+ "register",
+ "",
+ }; /* Used by error reporters, dumpers etc. */
+
+
+void
+ subsegs_begin()
+{
+ /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
+#ifdef MANY_SEGMENTS
+#else
+ know(SEG_ABSOLUTE == 0);
+ know(SEG_TEXT == 1);
+ know(SEG_DATA == 2);
+ know(SEG_BSS == 3);
+ know(SEG_UNKNOWN == 4);
+ know(SEG_ABSENT == 5);
+ know(SEG_PASS1 == 6);
+ know(SEG_GOOF == 7);
+ know(SEG_BIG == 8);
+ know(SEG_DIFFERENCE == 9);
+ know(SEG_DEBUG == 10);
+ know(SEG_NTV == 11);
+ know(SEG_PTV == 12);
+ know(SEG_REGISTER == 13);
+ know(SEG_MAXIMUM_ORDINAL == SEG_REGISTER );
+ /* know(segment_name(SEG_MAXIMUM_ORDINAL + 1)[0] == 0);*/
+#endif
+
+ obstack_begin(&frags, 5000);
+ frchain_root = NULL;
+ frchain_now = NULL; /* Warn new_subseg() that we are booting. */
+ /* Fake up 1st frag. */
+ /* It won't be used=> is ok if obstack... */
+ /* pads the end of it for alignment. */
+ frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
+ memset(frag_now, SIZEOF_STRUCT_FRAG, 0);
+ /* This 1st frag will not be in any frchain. */
+ /* We simply give subseg_new somewhere to scribble. */
+ now_subseg = 42; /* Lie for 1st call to subseg_new. */
+#ifdef MANY_SEGMENTS
+ {
+ int i;
+ for (i = SEG_E0; i < SEG_UNKNOWN; i++) {
+ subseg_new(i, 0);
+ segment_info[i].frchainP = frchain_now;
+ }
+ }
+#else
+ subseg_new(SEG_DATA, 0); /* .data 0 */
+ data0_frchainP = frchain_now;
+#endif
+
+}
+
+/*
+ * subseg_change()
+ *
+ * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
+ * subsegment. If we are already in the correct subsegment, change nothing.
+ * This is used eg as a worker for subseg_new [which does make a new frag_now]
+ * and for changing segments after we have read the source. We construct eg
+ * fixSs even after the source file is read, so we do have to keep the
+ * segment context correct.
+ */
+void
+ subseg_change (seg, subseg)
+register segT seg;
+register int subseg;
+{
+ now_seg = seg;
+ now_subseg = subseg;
+ know(SEG_NORMAL(seg));
+#ifdef MANY_SEGMENTS
+ seg_fix_rootP = &segment_info[seg].fix_root;
+ seg_fix_tailP = &segment_info[seg].fix_tail;
+#else
+ switch (seg) {
+ case SEG_DATA:
+ seg_fix_rootP = &data_fix_root;
+ seg_fix_tailP = &data_fix_tail;
+ break;
+ case SEG_TEXT:
+ seg_fix_rootP = &text_fix_root;
+ seg_fix_tailP = &text_fix_tail;
+ break;
+ case SEG_BSS:
+ seg_fix_rootP = &bss_fix_root;
+ seg_fix_tailP = &bss_fix_tail;
+ break;
+ }
+#endif
+}
+
+/*
+ * subseg_new()
+ *
+ * If you attempt to change to the current subsegment, nothing happens.
+ *
+ * In: segT, subsegT code for new subsegment.
+ * frag_now -> incomplete frag for current subsegment.
+ * If frag_now == NULL, then there is no old, incomplete frag, so
+ * the old frag is not closed off.
+ *
+ * Out: now_subseg, now_seg updated.
+ * Frchain_now points to the (possibly new) struct frchain for this
+ * sub-segment.
+ * Frchain_root updated if needed.
+ */
+
+void
+ subseg_new (seg, subseg) /* begin assembly for a new sub-segment */
+register segT seg; /* SEG_DATA or SEG_TEXT */
+register subsegT subseg;
+{
+ long tmp; /* JF for obstack alignment hacking */
+ know(SEG_NORMAL(seg));
+ if (seg != now_seg || subseg != now_subseg)
+ { /* we just changed sub-segments */
+ register frchainS * frcP; /* crawl frchain chain */
+ register frchainS** lastPP; /* address of last pointer */
+ frchainS *newP; /* address of new frchain */
+ register fragS *former_last_fragP;
+ register fragS *new_fragP;
+
+ if (frag_now) /* If not bootstrapping. */
+ {
+ frag_now->fr_fix = obstack_next_free(& frags) - frag_now->fr_literal;
+ frag_wane(frag_now); /* Close off any frag in old subseg. */
+ }
+ /*
+ * It would be nice to keep an obstack for each subsegment, if we swap
+ * subsegments a lot. Hence we would have much fewer frag_wanes().
+ */
+ {
+
+ obstack_finish( &frags);
+ /*
+ * If we don't do the above, the next object we put on obstack frags
+ * will appear to start at the fr_literal of the current frag.
+ * Also, above ensures that the next object will begin on a
+ * address that is aligned correctly for the engine that runs
+ * this program.
+ */
+ }
+ subseg_change (seg, (int)subseg);
+ /*
+ * Attempt to find or make a frchain for that sub seg.
+ * Crawl along chain of frchainSs, begins @ frchain_root.
+ * If we need to make a frchainS, link it into correct
+ * position of chain rooted in frchain_root.
+ */
+ for (frcP = * (lastPP = & frchain_root);
+ frcP
+ && (int)(frcP->frch_seg) <= (int)seg;
+ frcP = * ( lastPP = & frcP->frch_next)
+ )
+ {
+ if ( (int)(frcP->frch_seg) == (int)seg
+ && frcP->frch_subseg >= subseg)
+ {
+ break;
+ }
+ }
+ /*
+ * frcP: Address of the 1st frchainS in correct segment with
+ * frch_subseg >= subseg.
+ * We want to either use this frchainS, or we want
+ * to insert a new frchainS just before it.
+ *
+ * If frcP == NULL, then we are at the end of the chain
+ * of frchainS-s. A NULL frcP means we fell off the end
+ * of the chain looking for a
+ * frch_subseg >= subseg, so we
+ * must make a new frchainS.
+ *
+ * If we ever maintain a pointer to
+ * the last frchainS in the chain, we change that pointer
+ * ONLY when frcP == NULL.
+ *
+ * lastPP: Address of the pointer with value frcP;
+ * Never NULL.
+ * May point to frchain_root.
+ *
+ */
+ if ( ! frcP
+ || ( (int)(frcP->frch_seg) > (int)seg
+ || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
+ {
+ /*
+ * This should be the only code that creates a frchainS.
+ */
+ newP=(frchainS *)obstack_alloc(&frags,sizeof(frchainS));
+ memset(newP, sizeof(frchainS), 0);
+ /* This begines on a good boundary */
+ /* because a obstack_done() preceeded it. */
+ /* It implies an obstack_done(), so we */
+ /* expect the next object allocated to */
+ /* begin on a correct boundary. */
+ *lastPP = newP;
+ newP->frch_next = frcP; /* perhaps NULL */
+ (frcP = newP)->frch_subseg = subseg;
+ newP->frch_seg = seg;
+ newP->frch_last = NULL;
+ }
+ /*
+ * Here with frcP->ing to the frchainS for subseg.
+ */
+ frchain_now = frcP;
+ /*
+ * Make a fresh frag for the subsegment.
+ */
+ /* We expect this to happen on a correct */
+ /* boundary since it was proceeded by a */
+ /* obstack_done(). */
+ tmp=obstack_alignment_mask(&frags); /* JF disable alignment */
+ obstack_alignment_mask(&frags)=0;
+ frag_now=(fragS *)obstack_alloc(&frags,SIZEOF_STRUCT_FRAG);
+ obstack_alignment_mask(&frags)=tmp;
+ /* know(frags.obstack_c_next_free == frag_now->fr_literal); */
+ /* But we want any more chars to come */
+ /* immediately after the structure we just made. */
+ new_fragP = frag_now;
+ new_fragP->fr_next = NULL;
+ /*
+ * Append new frag to current frchain.
+ */
+ former_last_fragP = frcP->frch_last;
+ if (former_last_fragP)
+ {
+ know( former_last_fragP->fr_next == NULL );
+ know( frchain_now->frch_root );
+ former_last_fragP->fr_next = new_fragP;
+ }
+ else
+ {
+ frcP->frch_root = new_fragP;
+ }
+ frcP->frch_last = new_fragP;
+ } /* if (changing subsegments) */
+} /* subseg_new() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of subsegs.c */
diff --git a/gnu/usr.bin/as/subsegs.h b/gnu/usr.bin/as/subsegs.h
new file mode 100644
index 0000000..0b28804
--- /dev/null
+++ b/gnu/usr.bin/as/subsegs.h
@@ -0,0 +1,93 @@
+/* subsegs.h -> subsegs.c
+
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+/*
+ * For every sub-segment the user mentions in the ASsembler program,
+ * we make one struct frchain. Each sub-segment has exactly one struct frchain
+ * and vice versa.
+ *
+ * Struct frchain's are forward chained (in ascending order of sub-segment
+ * code number). The chain runs through frch_next of each subsegment.
+ * This makes it hard to find a subsegment's frags
+ * if programmer uses a lot of them. Most programs only use text0 and
+ * data0, so they don't suffer. At least this way:
+ * (1) There are no "arbitrary" restrictions on how many subsegments
+ * can be programmed;
+ * (2) Subsegments' frchain-s are (later) chained together in the order in
+ * which they are emitted for object file viz text then data.
+ *
+ * From each struct frchain dangles a chain of struct frags. The frags
+ * represent code fragments, for that sub-segment, forward chained.
+ */
+
+struct frchain /* control building of a frag chain */
+{ /* FRCH = FRagment CHain control */
+ struct frag * frch_root; /* 1st struct frag in chain, or NULL */
+ struct frag * frch_last; /* last struct frag in chain, or NULL */
+ struct frchain * frch_next; /* next in chain of struct frchain-s */
+ segT frch_seg; /* SEG_TEXT or SEG_DATA. */
+ subsegT frch_subseg; /* subsegment number of this chain */
+};
+
+typedef struct frchain frchainS;
+
+extern frchainS * frchain_root; /* NULL means no frchains yet. */
+/* all subsegments' chains hang off here */
+
+extern frchainS * frchain_now;
+/* Frchain we are assembling into now */
+/* That is, the current segment's frag */
+/* chain, even if it contains no (complete) */
+/* frags. */
+
+
+#ifdef MANY_SEGMENTS
+typedef struct
+{
+ frchainS *frchainP;
+ int hadone;
+ int user_stuff;
+ /* struct frag *frag_root;*/
+ /* struct frag *last_frag;*/
+ fixS *fix_root;
+ fixS *fix_tail;
+ struct internal_scnhdr scnhdr;
+ symbolS *dot;
+
+ struct lineno_list *lineno_list_head;
+ struct lineno_list *lineno_list_tail;
+
+} segment_info_type;
+segment_info_type segment_info[];
+#else
+extern frchainS * data0_frchainP;
+extern frchainS * bss0_frchainP;
+/* Sentinel for frchain crawling. */
+/* Points to the 1st data-segment frchain. */
+/* (Which is pointed to by the last text- */
+/* segment frchain.) */
+
+#endif
+
+/* end of subsegs.h */
diff --git a/gnu/usr.bin/as/symbols.c b/gnu/usr.bin/as/symbols.c
new file mode 100644
index 0000000..2473af4
--- /dev/null
+++ b/gnu/usr.bin/as/symbols.c
@@ -0,0 +1,654 @@
+/* symbols.c -symbol table-
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+
+#include "obstack.h" /* For "symbols.h" */
+#include "subsegs.h"
+
+#ifndef WORKING_DOT_WORD
+extern int new_broken_words;
+#endif
+
+static
+ struct hash_control *
+ sy_hash; /* symbol-name => struct symbol pointer */
+
+/* Below are commented in "symbols.h". */
+unsigned int local_bss_counter;
+symbolS * symbol_rootP;
+symbolS * symbol_lastP;
+symbolS abs_symbol;
+
+symbolS* dot_text_symbol;
+symbolS* dot_data_symbol;
+symbolS* dot_bss_symbol;
+
+struct obstack notes;
+
+/*
+ * Un*x idea of local labels. They are made by "n:" where n
+ * is any decimal digit. Refer to them with
+ * "nb" for previous (backward) n:
+ * or "nf" for next (forward) n:.
+ *
+ * Like Un*x AS, we have one set of local label counters for entire assembly,
+ * not one set per (sub)segment like in most assemblers. This implies that
+ * one can refer to a label in another segment, and indeed some crufty
+ * compilers have done just that.
+ *
+ * I document the symbol names here to save duplicating words elsewhere.
+ * The mth occurence of label n: is turned into the symbol "Ln^Am" where
+ * n is a digit and m is a decimal number. "L" makes it a label discarded
+ * unless debugging and "^A"('\1') ensures no ordinary symbol SHOULD get the
+ * same name as a local label symbol. The first "4:" is "L4^A1" - the m
+ * numbers begin at 1.
+ */
+
+typedef short unsigned int
+ local_label_countT;
+
+static local_label_countT
+ local_label_counter[10];
+
+static /* Returned to caller, then copied. */
+ char symbol_name_build[12]; /* used for created names ("4f") */
+
+#ifdef LOCAL_LABELS_DOLLAR
+int local_label_defined[10];
+#endif
+
+
+void
+ symbol_begin()
+{
+ symbol_lastP = NULL;
+ symbol_rootP = NULL; /* In case we have 0 symbols (!!) */
+ sy_hash = hash_new();
+ memset((char *)(& abs_symbol), '\0', sizeof(abs_symbol));
+ S_SET_SEGMENT(&abs_symbol, SEG_ABSOLUTE); /* Can't initialise a union. Sigh. */
+ memset((char *)(local_label_counter), '\0', sizeof(local_label_counter) );
+ local_bss_counter = 0;
+}
+
+/*
+ * local_label_name()
+ *
+ * Caller must copy returned name: we re-use the area for the next name.
+ */
+
+char * /* Return local label name. */
+ local_label_name(n, augend)
+register int n; /* we just saw "n:", "nf" or "nb" : n a digit */
+register int augend; /* 0 for nb, 1 for n:, nf */
+{
+ register char * p;
+ register char * q;
+ char symbol_name_temporary[10]; /* build up a number, BACKWARDS */
+
+ know( n >= 0 );
+ know( augend == 0 || augend == 1 );
+ p = symbol_name_build;
+ * p ++ = 1; /* ^A */
+ * p ++ = 'L';
+ * p ++ = n + '0'; /* Make into ASCII */
+ n = local_label_counter[ n ] + augend;
+ /* version number of this local label */
+ /*
+ * Next code just does sprintf( {}, "%d", n);
+ * It is more elegant to do the next part recursively, but a procedure
+ * call for each digit emitted is considered too costly.
+ */
+ q = symbol_name_temporary;
+ for (*q++=0; n; q++) /* emits NOTHING if n starts as 0 */
+ {
+ know(n>0); /* We expect n > 0 always */
+ *q = n % 10 + '0';
+ n /= 10;
+ }
+ while (( * p ++ = * -- q ) != '\0') ;;
+
+ /* The label, as a '\0' ended string, starts at symbol_name_build. */
+ return(symbol_name_build);
+} /* local_label_name() */
+
+
+void local_colon (n)
+int n; /* just saw "n:" */
+{
+ local_label_counter[n] ++;
+#ifdef LOCAL_LABELS_DOLLAR
+ local_label_defined[n]=1;
+#endif
+ colon (local_label_name (n, 0));
+}
+
+/*
+ * symbol_new()
+ *
+ * Return a pointer to a new symbol.
+ * Die if we can't make a new symbol.
+ * Fill in the symbol's values.
+ * Add symbol to end of symbol chain.
+ *
+ *
+ * Please always call this to create a new symbol.
+ *
+ * Changes since 1985: Symbol names may not contain '\0'. Sigh.
+ * 2nd argument is now a SEG rather than a TYPE. The mapping between
+ * segments and types is mostly encapsulated herein (actually, we inherit it
+ * from macros in struc-symbol.h).
+ */
+
+symbolS *symbol_new(name, segment, value, frag)
+char *name; /* It is copied, the caller can destroy/modify */
+segT segment; /* Segment identifier (SEG_<something>) */
+long value; /* Symbol value */
+fragS *frag; /* Associated fragment */
+{
+ unsigned int name_length;
+ char *preserved_copy_of_name;
+ symbolS *symbolP;
+
+ name_length = strlen(name) + 1; /* +1 for \0 */
+ obstack_grow(&notes, name, name_length);
+ preserved_copy_of_name = obstack_finish(&notes);
+ symbolP = (symbolS *) obstack_alloc(&notes, sizeof(symbolS));
+
+ /* symbol must be born in some fixed state. This seems as good as any. */
+ memset(symbolP, 0, sizeof(symbolS));
+
+#ifdef STRIP_UNDERSCORE
+ S_SET_NAME(symbolP, (*preserved_copy_of_name == '_'
+ ? preserved_copy_of_name + 1
+ : preserved_copy_of_name));
+#else /* STRIP_UNDERSCORE */
+ S_SET_NAME(symbolP, preserved_copy_of_name);
+#endif /* STRIP_UNDERSCORE */
+
+ S_SET_SEGMENT(symbolP, segment);
+ S_SET_VALUE(symbolP, value);
+ /* symbol_clear_list_pointers(symbolP); uneeded if symbol is born zeroed. */
+
+ symbolP->sy_frag = frag;
+ /* krm: uneeded if symbol is born zeroed.
+ symbolP->sy_forward = NULL; */ /* JF */
+ symbolP->sy_number = ~0;
+ symbolP->sy_name_offset = ~0;
+
+ /*
+ * Link to end of symbol chain.
+ */
+ symbol_append(symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
+
+ obj_symbol_new_hook(symbolP);
+
+#ifdef DEBUG
+ /* verify_symbol_chain(symbol_rootP, symbol_lastP); */
+#endif /* DEBUG */
+
+ return(symbolP);
+} /* symbol_new() */
+
+
+/*
+ * colon()
+ *
+ * We have just seen "<name>:".
+ * Creates a struct symbol unless it already exists.
+ *
+ * Gripes if we are redefining a symbol incompatibly (and ignores it).
+ *
+ */
+void colon(sym_name) /* just seen "x:" - rattle symbols & frags */
+register char * sym_name; /* symbol name, as a cannonical string */
+/* We copy this string: OK to alter later. */
+{
+ register symbolS * symbolP; /* symbol we are working with */
+
+#ifdef LOCAL_LABELS_DOLLAR
+ /* Sun local labels go out of scope whenever a non-local symbol is defined. */
+
+ if (*sym_name != 'L')
+ memset((void *) local_label_defined, '\0', sizeof(local_label_defined));
+#endif
+
+#ifndef WORKING_DOT_WORD
+ if (new_broken_words) {
+ struct broken_word *a;
+ int possible_bytes;
+ fragS *frag_tmp;
+ char *frag_opcode;
+
+ extern const md_short_jump_size;
+ extern const md_long_jump_size;
+ possible_bytes=md_short_jump_size + new_broken_words * md_long_jump_size;
+
+ frag_tmp=frag_now;
+ frag_opcode=frag_var(rs_broken_word,
+ possible_bytes,
+ possible_bytes,
+ (relax_substateT) 0,
+ (symbolS *) broken_words,
+ 0L,
+ NULL);
+
+ /* We want to store the pointer to where to insert the jump table in the
+ fr_opcode of the rs_broken_word frag. This requires a little hackery */
+ while (frag_tmp && (frag_tmp->fr_type != rs_broken_word || frag_tmp->fr_opcode))
+ frag_tmp=frag_tmp->fr_next;
+ know(frag_tmp);
+ frag_tmp->fr_opcode=frag_opcode;
+ new_broken_words = 0;
+
+ for (a=broken_words;a && a->dispfrag == 0;a=a->next_broken_word)
+ a->dispfrag=frag_tmp;
+ }
+#endif
+ if ((symbolP = symbol_find(sym_name)) != 0) {
+#ifdef OBJ_VMS
+ /*
+ * If the new symbol is .comm AND it has a size of zero,
+ * we ignore it (i.e. the old symbol overrides it)
+ */
+ if ((SEGMENT_TO_SYMBOL_TYPE((int) now_seg) == (N_UNDF | N_EXT)) &&
+ ((obstack_next_free(& frags) - frag_now->fr_literal) == 0))
+ return;
+ /*
+ * If the old symbol is .comm and it has a size of zero,
+ * we override it with the new symbol value.
+ */
+ if (S_IS_EXTERNAL(symbolP) && S_IS_DEFINED(symbolP)
+ && (S_GET_VALUE(symbolP) == 0)) {
+ symbolP->sy_frag = frag_now;
+ S_GET_OTHER(symbolP) = const_flag;
+ S_SET_VALUE(symbolP, obstack_next_free(& frags) - frag_now->fr_literal);
+ symbolP->sy_symbol.n_type |=
+ SEGMENT_TO_SYMBOL_TYPE((int) now_seg); /* keep N_EXT bit */
+ return;
+ }
+#endif /* OBJ_VMS */
+ /*
+ * Now check for undefined symbols
+ */
+ if (!S_IS_DEFINED(symbolP)) {
+ if (S_GET_VALUE(symbolP) == 0) {
+ symbolP->sy_frag = frag_now;
+#ifdef OBJ_VMS
+ S_GET_OTHER(symbolP) = const_flag;
+#endif
+ S_SET_VALUE(symbolP, obstack_next_free(&frags) - frag_now->fr_literal);
+ S_SET_SEGMENT(symbolP, now_seg);
+#ifdef N_UNDF
+ know(N_UNDF == 0);
+#endif /* if we have one, it better be zero. */
+
+ } else {
+ /*
+ * There are still several cases to check:
+ * A .comm/.lcomm symbol being redefined as
+ * initialized data is OK
+ * A .comm/.lcomm symbol being redefined with
+ * a larger size is also OK
+ *
+ * This only used to be allowed on VMS gas, but Sun cc
+ * on the sparc also depends on it.
+ */
+ /* char New_Type = SEGMENT_TO_SYMBOL_TYPE((int) now_seg); */
+
+ if (((!S_IS_DEBUG(symbolP) && !S_IS_DEFINED(symbolP) && S_IS_EXTERNAL(symbolP))
+ || (S_GET_SEGMENT(symbolP) == SEG_BSS))
+ && ((now_seg == SEG_DATA)
+ || (now_seg == S_GET_SEGMENT(symbolP)))) {
+ /*
+ * Select which of the 2 cases this is
+ */
+ if (now_seg != SEG_DATA) {
+ /*
+ * New .comm for prev .comm symbol.
+ * If the new size is larger we just
+ * change its value. If the new size
+ * is smaller, we ignore this symbol
+ */
+ if (S_GET_VALUE(symbolP)
+ < ((unsigned) (obstack_next_free(& frags) - frag_now->fr_literal))) {
+ S_SET_VALUE(symbolP,
+ obstack_next_free(& frags) -
+ frag_now->fr_literal);
+ }
+ } else {
+ /*
+ * It is a .comm/.lcomm being converted
+ * to initialized data.
+ */
+ symbolP->sy_frag = frag_now;
+#ifdef OBJ_VMS
+ S_GET_OTHER(symbolP) = const_flag;
+#endif /* OBJ_VMS */
+ S_SET_VALUE(symbolP, obstack_next_free(& frags) - frag_now->fr_literal);
+ S_SET_SEGMENT(symbolP, now_seg); /* keep N_EXT bit */
+ }
+ } else {
+#ifdef OBJ_COFF
+ as_fatal("Symbol \"%s\" is already defined as \"%s\"/%d.",
+ sym_name,
+ segment_name(S_GET_SEGMENT(symbolP)),
+ S_GET_VALUE(symbolP));
+#else /* OBJ_COFF */
+ as_fatal("Symbol \"%s\" is already defined as \"%s\"/%d.%d.%d.",
+ sym_name,
+ segment_name(S_GET_SEGMENT(symbolP)),
+ S_GET_OTHER(symbolP), S_GET_DESC(symbolP),
+ S_GET_VALUE(symbolP));
+#endif /* OBJ_COFF */
+ }
+ } /* if the undefined symbol has no value */
+ } else
+ {
+ /* Don't blow up if the definition is the same */
+ if (!(frag_now == symbolP->sy_frag
+ && S_GET_VALUE(symbolP) == obstack_next_free(&frags) - frag_now->fr_literal
+ && S_GET_SEGMENT(symbolP) == now_seg) )
+ as_fatal("Symbol %s already defined.", sym_name);
+ } /* if this symbol is not yet defined */
+
+ } else {
+ symbolP = symbol_new(sym_name,
+ now_seg,
+ (valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
+ frag_now);
+#ifdef OBJ_VMS
+ S_SET_OTHER(symbolP, const_flag);
+#endif /* OBJ_VMS */
+
+ symbol_table_insert(symbolP);
+ } /* if we have seen this symbol before */
+
+ return;
+} /* colon() */
+
+
+/*
+ * symbol_table_insert()
+ *
+ * Die if we can't insert the symbol.
+ *
+ */
+
+void symbol_table_insert(symbolP)
+symbolS *symbolP;
+{
+ register char *error_string;
+
+ know(symbolP);
+ know(S_GET_NAME(symbolP));
+
+ if (*(error_string = hash_jam(sy_hash, S_GET_NAME(symbolP), (char *)symbolP))) {
+ as_fatal("Inserting \"%s\" into symbol table failed: %s",
+ S_GET_NAME(symbolP), error_string);
+ } /* on error */
+} /* symbol_table_insert() */
+
+/*
+ * symbol_find_or_make()
+ *
+ * If a symbol name does not exist, create it as undefined, and insert
+ * it into the symbol table. Return a pointer to it.
+ */
+symbolS *symbol_find_or_make(name)
+char *name;
+{
+ register symbolS *symbolP;
+
+ symbolP = symbol_find(name);
+
+ if (symbolP == NULL) {
+ symbolP = symbol_make(name);
+
+ symbol_table_insert(symbolP);
+ } /* if symbol wasn't found */
+
+ return(symbolP);
+} /* symbol_find_or_make() */
+
+symbolS *symbol_make(name)
+char *name;
+{
+ symbolS *symbolP;
+
+ /* Let the machine description default it, e.g. for register names. */
+ symbolP = md_undefined_symbol(name);
+
+ if (!symbolP) {
+ symbolP = symbol_new(name,
+ SEG_UNKNOWN,
+ 0,
+ &zero_address_frag);
+ } /* if md didn't build us a symbol */
+
+ return(symbolP);
+} /* symbol_make() */
+
+/*
+ * symbol_find()
+ *
+ * Implement symbol table lookup.
+ * In: A symbol's name as a string: '\0' can't be part of a symbol name.
+ * Out: NULL if the name was not in the symbol table, else the address
+ * of a struct symbol associated with that name.
+ */
+
+symbolS *symbol_find(name)
+char *name;
+{
+#ifdef STRIP_UNDERSCORE
+ return(symbol_find_base(name, 1));
+#else /* STRIP_UNDERSCORE */
+ return(symbol_find_base(name, 0));
+#endif /* STRIP_UNDERSCORE */
+} /* symbol_find() */
+
+symbolS *symbol_find_base(name, strip_underscore)
+char *name;
+int strip_underscore;
+{
+ if (strip_underscore && *name == '_') name++;
+ return ( (symbolS *) hash_find( sy_hash, name ));
+}
+
+/*
+ * Once upon a time, symbols were kept in a singly linked list. At
+ * least coff needs to be able to rearrange them from time to time, for
+ * which a doubly linked list is much more convenient. Loic did these
+ * as macros which seemed dangerous to me so they're now functions.
+ * xoxorich.
+ */
+
+/* Link symbol ADDME after symbol TARGET in the chain. */
+void symbol_append(addme, target, rootPP, lastPP)
+symbolS *addme;
+symbolS *target;
+symbolS **rootPP;
+symbolS **lastPP;
+{
+ if (target == NULL) {
+ know(*rootPP == NULL);
+ know(*lastPP == NULL);
+ *rootPP = addme;
+ *lastPP = addme;
+ return;
+ } /* if the list is empty */
+
+ if (target->sy_next != NULL) {
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ target->sy_next->sy_previous = addme;
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+ } else {
+ know(*lastPP == target);
+ *lastPP = addme;
+ } /* if we have a next */
+
+ addme->sy_next = target->sy_next;
+ target->sy_next = addme;
+
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ addme->sy_previous = target;
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+#ifdef DEBUG
+ /* verify_symbol_chain(*rootPP, *lastPP); */
+#endif /* DEBUG */
+
+ return;
+} /* symbol_append() */
+
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+/* Remove SYMBOLP from the list. */
+void symbol_remove(symbolP, rootPP, lastPP)
+symbolS *symbolP;
+symbolS **rootPP;
+symbolS **lastPP;
+{
+ if (symbolP == *rootPP) {
+ *rootPP = symbolP->sy_next;
+ } /* if it was the root */
+
+ if (symbolP == *lastPP) {
+ *lastPP = symbolP->sy_previous;
+ } /* if it was the tail */
+
+ if (symbolP->sy_next != NULL) {
+ symbolP->sy_next->sy_previous = symbolP->sy_previous;
+ } /* if not last */
+
+ if (symbolP->sy_previous != NULL) {
+ symbolP->sy_previous->sy_next = symbolP->sy_next;
+ } /* if not first */
+
+#ifdef DEBUG
+ verify_symbol_chain(*rootPP, *lastPP);
+#endif /* DEBUG */
+
+ return;
+} /* symbol_remove() */
+
+/* Set the chain pointers of SYMBOL to null. */
+void symbol_clear_list_pointers(symbolP)
+symbolS *symbolP;
+{
+ symbolP->sy_next = NULL;
+ symbolP->sy_previous = NULL;
+} /* symbol_clear_list_pointers() */
+
+/* Link symbol ADDME before symbol TARGET in the chain. */
+void symbol_insert(addme, target, rootPP, lastPP)
+symbolS *addme;
+symbolS *target;
+symbolS **rootPP;
+symbolS **lastPP;
+{
+ if (target->sy_previous != NULL) {
+ target->sy_previous->sy_next = addme;
+ } else {
+ know(*rootPP == target);
+ *rootPP = addme;
+ } /* if not first */
+
+ addme->sy_previous = target->sy_previous;
+ target->sy_previous = addme;
+ addme->sy_next = target;
+
+#ifdef DEBUG
+ verify_symbol_chain(*rootPP, *lastPP);
+#endif /* DEBUG */
+
+ return;
+} /* symbol_insert() */
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+
+void verify_symbol_chain(rootP, lastP)
+symbolS *rootP;
+symbolS *lastP;
+{
+ symbolS *symbolP = rootP;
+
+ if (symbolP == NULL) {
+ return;
+ } /* empty chain */
+
+ for ( ; symbol_next(symbolP) != NULL; symbolP = symbol_next(symbolP)) {
+#ifdef SYMBOLS_NEED_BACKPOINTERS
+ /*$if (symbolP->sy_previous) {
+ know(symbolP->sy_previous->sy_next == symbolP);
+ } else {
+ know(symbolP == rootP);
+ }$*/ /* both directions */
+ know(symbolP->sy_next->sy_previous == symbolP);
+#else /* SYMBOLS_NEED_BACKPOINTERS */
+ ;
+#endif /* SYMBOLS_NEED_BACKPOINTERS */
+ } /* verify pointers */
+
+ know(lastP == symbolP);
+
+ return;
+} /* verify_symbol_chain() */
+
+
+/*
+ * decode name that may have been generated by local_label_name() above. If
+ * the name wasn't generated by local_label_name(), then return it unaltered.
+ * This is used for error messages.
+ */
+
+char *decode_local_label_name(s)
+char *s;
+{
+ char *symbol_decode;
+ int label_number;
+ /* int label_version; */
+ char *message_format = "\"%d\" (instance number %s of a local label)";
+
+ if (s[0] != 'L'
+ || s[2] != 1) {
+ return(s);
+ } /* not a local_label_name() generated name. */
+
+ label_number = s[1] - '0';
+
+ (void) sprintf(symbol_decode = obstack_alloc(&notes, strlen(s + 3) + strlen(message_format) + 10),
+ message_format, label_number, s + 3);
+
+ return(symbol_decode);
+} /* decode_local_label_name() */
+
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of symbols.c */
diff --git a/gnu/usr.bin/as/symbols.h b/gnu/usr.bin/as/symbols.h
new file mode 100644
index 0000000..4791644
--- /dev/null
+++ b/gnu/usr.bin/as/symbols.h
@@ -0,0 +1,82 @@
+/* symbols.h -
+
+ Copyright (C) 1987, 1990, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+extern struct obstack notes; /* eg FixS live here. */
+
+extern struct obstack cond_obstack; /* this is where we track .ifdef/.endif
+ (if we do that at all). */
+
+extern unsigned int local_bss_counter; /* Zeroed before a pass. */
+/* Only used by .lcomm directive. */
+
+extern symbolS *symbol_rootP; /* all the symbol nodes */
+extern symbolS *symbol_lastP; /* last struct symbol we made, or NULL */
+
+extern symbolS abs_symbol;
+
+extern symbolS *dot_text_symbol;
+extern symbolS *dot_data_symbol;
+extern symbolS *dot_bss_symbol;
+
+#if __STDC__ == 1
+
+char *decode_local_label_name(char *s);
+char *local_label_name(int n, int augend);
+symbolS *symbol_find(char *name);
+symbolS *symbol_find_base(char *name, int strip_underscore);
+symbolS *symbol_find_or_make(char *name);
+symbolS *symbol_make(char *name);
+symbolS *symbol_new(char *name, segT segment, long value, fragS *frag);
+void colon(char *sym_name);
+void local_colon(int n);
+void symbol_begin(void);
+void symbol_table_insert(symbolS *symbolP);
+void verify_symbol_chain(symbolS *rootP, symbolS *lastP);
+
+#else /* not __STDC__ */
+
+char *decode_local_label_name();
+char *local_label_name();
+symbolS *symbol_find();
+symbolS *symbol_find_base();
+symbolS *symbol_find_or_make();
+symbolS *symbol_make();
+symbolS *symbol_new();
+void colon();
+void local_colon();
+void symbol_begin();
+void symbol_table_insert();
+void verify_symbol_chain();
+
+#endif /* not __STDC__ */
+
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of symbols.h */
diff --git a/gnu/usr.bin/as/tc.h b/gnu/usr.bin/as/tc.h
new file mode 100644
index 0000000..e5b3938
--- /dev/null
+++ b/gnu/usr.bin/as/tc.h
@@ -0,0 +1,112 @@
+/* tc.h - target cpu dependent
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * $FreeBSD$
+ */
+
+
+/* In theory (mine, at least!) the machine dependent part of the assembler
+ should only have to include one file. This one. -- JF */
+
+extern const pseudo_typeS md_pseudo_table[];
+
+/* JF moved this here from as.h under the theory that nobody except MACHINE.c
+ and write.c care about it anyway. */
+
+typedef struct
+{
+ long rlx_forward; /* Forward reach. Signed number. > 0. */
+ long rlx_backward; /* Backward reach. Signed number. < 0. */
+ unsigned char rlx_length; /* Bytes length of this address. */
+ relax_substateT rlx_more; /* Next longer relax-state. */
+ /* 0 means there is no 'next' relax-state. */
+}
+relax_typeS;
+
+extern const relax_typeS md_relax_table[]; /* Define it in MACHINE.c */
+
+extern const int md_reloc_size; /* Size of a relocation record */
+
+extern void (*md_emit_relocations)();
+
+#if __STDC__ == 1
+
+char *md_atof(int what_statement_type, char *literalP, int *sizeP);
+int md_estimate_size_before_relax(fragS *fragP, segT segment);
+int md_parse_option(char **argP, int *cntP, char ***vecP);
+long md_pcrel_from(fixS *fixP);
+long md_section_align(segT seg, long align);
+short tc_coff_fix2rtype(fixS *fixP);
+symbolS *md_undefined_symbol(char *name);
+void md_apply_fix(fixS *fixP, long val);
+void md_assemble(char *str);
+void md_begin(void);
+void md_convert_frag(object_headers *headers, fragS *fragP);
+void md_create_long_jump(char *ptr, long from_addr, long to_addr, fragS *frag, symbolS *to_symbol);
+void md_create_short_jump(char *ptr, long from_addr, long to_addr, fragS *frag, symbolS *to_symbol);
+void md_end(void);
+void md_number_to_chars(char *buf, long val, int n);
+void md_operand(expressionS *expressionP);
+
+#ifndef tc_crawl_symbol_chain
+void tc_crawl_symbol_chain(object_headers *headers);
+#endif /* tc_crawl_symbol_chain */
+
+#ifndef tc_headers_hook
+void tc_headers_hook(object_headers *headers);
+#endif /* tc_headers_hook */
+
+#else
+
+char *md_atof();
+int md_estimate_size_before_relax();
+int md_parse_option();
+long md_pcrel_from();
+long md_section_align();
+short tc_coff_fix2rtype();
+symbolS *md_undefined_symbol();
+void md_apply_fix();
+void md_assemble();
+void md_begin();
+void md_convert_frag();
+void md_create_long_jump();
+void md_create_short_jump();
+void md_end();
+void md_number_to_chars();
+void md_operand();
+
+#ifndef tc_headers_hook
+void tc_headers_hook();
+#endif /* tc_headers_hook */
+
+#ifndef tc_crawl_symbol_chain
+void tc_crawl_symbol_chain();
+#endif /* tc_crawl_symbol_chain */
+
+#endif /* __STDC_ */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of tc.h */
diff --git a/gnu/usr.bin/as/testscripts/doboth b/gnu/usr.bin/as/testscripts/doboth
new file mode 100755
index 0000000..6762b81
--- /dev/null
+++ b/gnu/usr.bin/as/testscripts/doboth
@@ -0,0 +1,20 @@
+#!/bin/sh
+# $FreeBSD$
+
+x=$1 ; shift
+y=$1 ; shift
+
+rm tmp.0 > /dev/null 2>&1
+ln -s $x tmp.0
+$* tmp.0 > tmp.1
+
+rm tmp.0
+ln -s $y tmp.0
+$* tmp.0 > tmp.2
+
+rm tmp.0
+
+diff -c tmp.1 tmp.2
+exit
+
+#eof
diff --git a/gnu/usr.bin/as/testscripts/doobjcmp b/gnu/usr.bin/as/testscripts/doobjcmp
new file mode 100755
index 0000000..6297ea4
--- /dev/null
+++ b/gnu/usr.bin/as/testscripts/doobjcmp
@@ -0,0 +1,89 @@
+#!/bin/sh
+# $FreeBSD$
+# compare two object files, in depth.
+
+x=$1
+y=$2
+BOTH="$1 $2"
+
+
+# if they cmp, we're fine.
+if (cmp $BOTH > /dev/null)
+then
+ exit 0
+fi
+
+# otherwise, we must look closer.
+if (doboth $BOTH size)
+then
+ echo Sizes ok.
+else
+ echo Sizes differ:
+ size $BOTH
+# exit 1
+fi
+
+if (doboth $BOTH objdump +header)
+then
+ echo Headers ok.
+else
+ echo Header differences.
+# exit 1
+fi
+
+if (doboth $BOTH objdump +text > /dev/null)
+then
+ echo Text ok.
+else
+ echo Text differences.
+# doboth $BOTH objdump +text
+# exit 1
+fi
+
+if (doboth $BOTH objdump +data > /dev/null)
+then
+ echo Data ok.
+else
+ echo Data differences.
+# doboth $BOTH objdump +data
+# exit 1
+fi
+
+if (doboth $BOTH objdump +symbols > /dev/null)
+then
+ echo Symbols ok.
+else
+ echo -n Symbol differences...
+
+ if (doboth $BOTH dounsortsymbols)
+ then
+ echo but symbols are simply ordered differently.
+# echo Now what to do about relocs'?'
+# exit 1
+ else
+ echo and symbols differ in content.
+ exit 1
+ fi
+fi
+
+# of course, if there were symbol diffs, then the reloc symbol indexes
+# will be off.
+
+if (doboth $BOTH objdump -r > /dev/null)
+then
+ echo Reloc ok.
+else
+ echo -n Reloc differences...
+
+ if (doboth $BOTH dounsortreloc)
+ then
+ echo but relocs are simply ordered differently.
+ else
+ echo and relocs differ in content.
+ exit 1
+ fi
+fi
+
+exit
+
+# eof
diff --git a/gnu/usr.bin/as/testscripts/dostriptest b/gnu/usr.bin/as/testscripts/dostriptest
new file mode 100755
index 0000000..9cf5475
--- /dev/null
+++ b/gnu/usr.bin/as/testscripts/dostriptest
@@ -0,0 +1,15 @@
+#!/bin/sh
+# $FreeBSD$
+
+x=striptest.xx.$$
+y=striptest.yy.$$
+
+cp $1 $x
+strip $x
+cp $2 $y
+strip $y
+
+doobjcmp $x $y
+exit
+
+#eof
diff --git a/gnu/usr.bin/as/testscripts/dotest b/gnu/usr.bin/as/testscripts/dotest
new file mode 100755
index 0000000..677e864
--- /dev/null
+++ b/gnu/usr.bin/as/testscripts/dotest
@@ -0,0 +1,44 @@
+#!/bin/sh
+# ad hoc debug tool
+# $FreeBSD$
+
+x=$1
+y=$2
+
+xout=`basename $x`.xxx.$$
+yout=`basename $x`.yyy.$$
+
+mkdir $xout
+mkdir $yout
+
+for i in *.s
+do
+ echo Testing $i...
+ object=`basename $i .s`.o
+ $x $i -o $xout/$object
+ $y $i -o $yout/$object
+
+# if they cmp, we're ok. Otherwise we have to look closer.
+
+ if (cmp $xout/$object $yout/$object)
+ then
+ echo $i is ok.
+ else
+ if (doobjcmp $xout/$object $yout/$object)
+ then
+ echo Not the same but objcmp ok.
+ else
+ exit 1
+ fi
+ fi
+
+ echo
+done
+
+rm -rf $xout $yout
+
+exit 0
+
+# EOF
+
+
diff --git a/gnu/usr.bin/as/testscripts/dounsortreloc b/gnu/usr.bin/as/testscripts/dounsortreloc
new file mode 100755
index 0000000..667ee5d
--- /dev/null
+++ b/gnu/usr.bin/as/testscripts/dounsortreloc
@@ -0,0 +1,9 @@
+#!/bin/sh
+# $FreeBSD$
+# objdump the reloc table, but strip off the headings and reloc
+# numbers and sort the result. Intended for use in comparing reloc
+# tables that may not be in the same order.
+
+objdump +reloc +omit-relocation-numbers +omit-symbol-numbers $1 \
+ | sort
+#eof
diff --git a/gnu/usr.bin/as/testscripts/dounsortsymbols b/gnu/usr.bin/as/testscripts/dounsortsymbols
new file mode 100755
index 0000000..b9b3523
--- /dev/null
+++ b/gnu/usr.bin/as/testscripts/dounsortsymbols
@@ -0,0 +1,9 @@
+#!/bin/sh
+# $FreeBSD$
+# objdump the symbol table, but strip off the headings and symbol
+# numbers and sort the result. Intended for use in comparing symbol
+# tables that may not be in the same order.
+
+objdump +symbols +omit-symbol-numbers $1 \
+ | sort
+#eof
diff --git a/gnu/usr.bin/as/version.c b/gnu/usr.bin/as/version.c
new file mode 100644
index 0000000..95e747e
--- /dev/null
+++ b/gnu/usr.bin/as/version.c
@@ -0,0 +1,30 @@
+#if (__STDC__ == 1) || defined(const)
+const
+#endif
+
+/* DO NOT PUT COMMENTS ABOUT CHANGES IN THIS FILE.
+
+ This file exists only to define `version_string'.
+
+ Log changes in ChangeLog. The easiest way to do this is with
+ the Emacs command `add-change-log-entry'. If you don't use Emacs,
+ add entries of the form:
+
+ Thu Jan 1 00:00:00 1970 Dennis Ritchie (dmr at alice)
+
+ universe.c (temporal_reality): Began Time.
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+char version_string[] = "GNU assembler version 1.92.3,\n$FreeBSD$\n";
+
+#ifdef HO_VMS
+dummy3()
+{
+}
+#endif
+
+/* end of version.c */
diff --git a/gnu/usr.bin/as/write.c b/gnu/usr.bin/as/write.c
new file mode 100644
index 0000000..835383e
--- /dev/null
+++ b/gnu/usr.bin/as/write.c
@@ -0,0 +1,1224 @@
+/* write.c - emit .o file
+
+ Copyright (C) 1986, 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This thing should be set up to do byteordering correctly. But... */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "as.h"
+#include "subsegs.h"
+#include "obstack.h"
+#include "output-file.h"
+
+/* The NOP_OPCODE is for the alignment fill value.
+ * fill it a nop instruction so that the disassembler does not choke
+ * on it
+ */
+#ifndef NOP_OPCODE
+#define NOP_OPCODE 0x00
+#endif
+
+#ifndef MANY_SEGMENTS
+static struct frag *text_frag_root;
+static struct frag *data_frag_root;
+
+static struct frag *text_last_frag; /* Last frag in segment. */
+static struct frag *data_last_frag; /* Last frag in segment. */
+#endif
+
+#ifndef WORKING_DOT_WORD
+extern const int md_short_jump_size;
+extern const int md_long_jump_size;
+#endif
+
+static object_headers headers;
+
+long string_byte_count;
+
+static char *the_object_file;
+
+char *next_object_file_charP; /* Tracks object file bytes. */
+
+/* static long length; JF unused */ /* String length, including trailing '\0'. */
+
+
+#if __STDC__ == 1
+
+static int is_dnrange(struct frag *f1, struct frag *f2);
+static long fixup_segment(fixS *fixP, segT this_segment_type);
+static relax_addressT relax_align(relax_addressT address, long alignment);
+void relax_segment(struct frag *segment_frag_root, segT segment_type);
+
+#else
+
+static int is_dnrange();
+static long fixup_segment();
+static relax_addressT relax_align();
+void relax_segment();
+
+#endif /* not __STDC__ */
+
+/*
+ * fix_new()
+ *
+ * Create a fixS in obstack 'notes'.
+ */
+#ifdef PIC
+fixS *fix_new(frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type, got_symbol)
+#else
+fixS *fix_new(frag, where, size, add_symbol, sub_symbol, offset, pcrel, r_type)
+#endif
+fragS *frag; /* Which frag? */
+int where; /* Where in that frag? */
+short int size; /* 1, 2, or 4 usually. */
+symbolS *add_symbol; /* X_add_symbol. */
+symbolS *sub_symbol; /* X_subtract_symbol. */
+#ifdef PIC
+symbolS *got_symbol; /* X_got. */
+#endif
+long offset; /* X_add_number. */
+int pcrel; /* TRUE if PC-relative relocation. */
+enum reloc_type r_type; /* Relocation type */
+{
+ fixS *fixP;
+
+ fixP = (fixS *) obstack_alloc(&notes, sizeof(fixS));
+
+ fixP->fx_frag = frag;
+ fixP->fx_where = where;
+ fixP->fx_size = size;
+ fixP->fx_addsy = add_symbol;
+ fixP->fx_subsy = sub_symbol;
+#ifdef PIC
+ fixP->fx_gotsy = got_symbol;
+ if (got_symbol)
+ pcrel = 1;
+#endif
+ fixP->fx_offset = offset;
+ fixP->fx_pcrel = pcrel;
+ fixP->fx_r_type = r_type;
+
+ /* JF these 'cuz of the NS32K stuff */
+ fixP->fx_im_disp = 0;
+ fixP->fx_pcrel_adjust = 0;
+ fixP->fx_bsr = 0;
+ fixP->fx_bit_fixP = 0;
+
+ /* usually, we want relocs sorted numerically, but while
+ comparing to older versions of gas that have relocs
+ reverse sorted, it is convenient to have this compile
+ time option. xoxorich. */
+
+#ifdef REVERSE_SORT_RELOCS
+
+ fixP->fx_next = *seg_fix_rootP;
+ *seg_fix_rootP = fixP;
+
+#else /* REVERSE_SORT_RELOCS */
+
+ fixP->fx_next = NULL;
+
+ if (*seg_fix_tailP)
+ (*seg_fix_tailP)->fx_next = fixP;
+ else
+ *seg_fix_rootP = fixP;
+ *seg_fix_tailP = fixP;
+
+#endif /* REVERSE_SORT_RELOCS */
+
+ fixP->fx_callj = 0;
+ return(fixP);
+} /* fix_new() */
+
+#ifndef BFD
+void write_object_file()
+{
+ register struct frchain * frchainP; /* Track along all frchains. */
+ register fragS * fragP; /* Track along all frags. */
+ register struct frchain * next_frchainP;
+ register fragS * * prev_fragPP;
+ /* register char * name; */
+ /* symbolS *symbolP; */
+ /* register symbolS ** symbolPP; */
+ /* register fixS * fixP; JF unused */
+ unsigned int data_siz;
+
+ long object_file_size;
+
+#ifdef OBJ_VMS
+ /*
+ * Under VMS we try to be compatible with VAX-11 "C". Thus, we
+ * call a routine to check for the definition of the procedure
+ * "_main", and if so -- fix it up so that it can be program
+ * entry point.
+ */
+ VMS_Check_For_Main();
+#endif /* OBJ_VMS */
+ /*
+ * After every sub-segment, we fake an ".align ...". This conforms to BSD4.2
+ * brane-damage. We then fake ".fill 0" because that is the kind of frag
+ * that requires least thought. ".align" frags like to have a following
+ * frag since that makes calculating their intended length trivial.
+ */
+#ifndef SUB_SEGMENT_ALIGN
+#define SUB_SEGMENT_ALIGN (2)
+#endif
+ for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next) {
+#ifdef OBJ_VMS
+ /*
+ * Under VAX/VMS, the linker (and PSECT specifications)
+ * take care of correctly aligning the segments.
+ * Doing the alignment here (on initialized data) can
+ * mess up the calculation of global data PSECT sizes.
+ */
+#undef SUB_SEGMENT_ALIGN
+#define SUB_SEGMENT_ALIGN ((frchainP->frch_seg != SEG_DATA) ? 2 : 0)
+#endif /* OBJ_VMS */
+ subseg_new (frchainP->frch_seg, frchainP->frch_subseg);
+ frag_align (SUB_SEGMENT_ALIGN, NOP_OPCODE);
+ /* frag_align will have left a new frag. */
+ /* Use this last frag for an empty ".fill". */
+ /*
+ * For this segment ...
+ * Create a last frag. Do not leave a "being filled in frag".
+ */
+ frag_wane (frag_now);
+ frag_now->fr_fix = 0;
+ know( frag_now->fr_next == NULL );
+ /* know(frags.obstack_c_base == frags.obstack_c_next_free); */
+ /* Above shows we haven't left a half-completed object on obstack. */
+ } /* walk the frag chain */
+
+ /*
+ * From now on, we don't care about sub-segments.
+ * Build one frag chain for each segment. Linked thru fr_next.
+ * We know that there is at least 1 text frchain & at least 1 data frchain.
+ */
+ prev_fragPP = &text_frag_root;
+ for (frchainP = frchain_root; frchainP; frchainP = next_frchainP) {
+ know( frchainP->frch_root );
+ *prev_fragPP = frchainP->frch_root;
+ prev_fragPP = & frchainP->frch_last->fr_next;
+
+ if (((next_frchainP = frchainP->frch_next) == NULL)
+ || next_frchainP == data0_frchainP) {
+ prev_fragPP = &data_frag_root;
+ if (next_frchainP) {
+ text_last_frag = frchainP->frch_last;
+ } else {
+ data_last_frag = frchainP->frch_last;
+ }
+ }
+ } /* walk the frag chain */
+
+ /*
+ * We have two segments. If user gave -R flag, then we must put the
+ * data frags into the text segment. Do this before relaxing so
+ * we know to take advantage of -R and make shorter addresses.
+ */
+ if (flagseen[ 'R' ]) {
+ fixS *tmp;
+
+ text_last_frag->fr_next = data_frag_root;
+ text_last_frag = data_last_frag;
+ data_last_frag = NULL;
+ data_frag_root = NULL;
+ if (text_fix_root) {
+ for (tmp = text_fix_root; tmp->fx_next; tmp = tmp->fx_next) ;;
+ tmp->fx_next = data_fix_root;
+ } else
+ text_fix_root = data_fix_root;
+ data_fix_root = NULL;
+ }
+
+ relax_segment(text_frag_root, SEG_TEXT);
+ relax_segment(data_frag_root, SEG_DATA);
+ /*
+ * Now the addresses of frags are correct within the segment.
+ */
+
+ know(text_last_frag->fr_type == rs_fill && text_last_frag->fr_offset == 0);
+ H_SET_TEXT_SIZE(&headers, text_last_frag->fr_address);
+ text_last_frag->fr_address = H_GET_TEXT_SIZE(&headers);
+
+ /*
+ * Join the 2 segments into 1 huge segment.
+ * To do this, re-compute every rn_address in the SEG_DATA frags.
+ * Then join the data frags after the text frags.
+ *
+ * Determine a_data [length of data segment].
+ */
+ if (data_frag_root) {
+ register relax_addressT slide;
+
+ know((text_last_frag->fr_type == rs_fill) && (text_last_frag->fr_offset == 0));
+
+ H_SET_DATA_SIZE(&headers, data_last_frag->fr_address);
+ data_last_frag->fr_address = H_GET_DATA_SIZE(&headers);
+ slide = H_GET_TEXT_SIZE(&headers); /* & in file of the data segment. */
+
+ for (fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
+ fragP->fr_address += slide;
+ } /* for each data frag */
+
+ know(text_last_frag != 0);
+ text_last_frag->fr_next = data_frag_root;
+ } else {
+ H_SET_DATA_SIZE(&headers,0);
+ data_siz = 0;
+ }
+
+ bss_address_frag.fr_address = (H_GET_TEXT_SIZE(&headers) +
+ H_GET_DATA_SIZE(&headers));
+
+ H_SET_BSS_SIZE(&headers,local_bss_counter);
+
+ /*
+ *
+ * Crawl the symbol chain.
+ *
+ * For each symbol whose value depends on a frag, take the address of
+ * that frag and subsume it into the value of the symbol.
+ * After this, there is just one way to lookup a symbol value.
+ * Values are left in their final state for object file emission.
+ * We adjust the values of 'L' local symbols, even if we do
+ * not intend to emit them to the object file, because their values
+ * are needed for fix-ups.
+ *
+ * Unless we saw a -L flag, remove all symbols that begin with 'L'
+ * from the symbol chain. (They are still pointed to by the fixes.)
+ *
+ * Count the remaining symbols.
+ * Assign a symbol number to each symbol.
+ * Count the number of string-table chars we will emit.
+ * Put this info into the headers as appropriate.
+ *
+ */
+ know(zero_address_frag.fr_address == 0);
+ string_byte_count = sizeof(string_byte_count);
+
+ obj_crawl_symbol_chain(&headers);
+
+ if (string_byte_count == sizeof(string_byte_count)) {
+ string_byte_count = 0;
+ } /* if no strings, then no count. */
+
+ H_SET_STRING_SIZE(&headers, string_byte_count);
+
+ /*
+ * Addresses of frags now reflect addresses we use in the object file.
+ * Symbol values are correct.
+ * Scan the frags, converting any ".org"s and ".align"s to ".fill"s.
+ * Also converting any machine-dependent frags using md_convert_frag();
+ */
+ subseg_change(SEG_TEXT, 0);
+
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
+ switch (fragP->fr_type) {
+ case rs_align:
+ case rs_org:
+ fragP->fr_type = rs_fill;
+ know(fragP->fr_var == 1);
+ know(fragP->fr_next != NULL);
+
+ fragP->fr_offset = (fragP->fr_next->fr_address
+ - fragP->fr_address
+ - fragP->fr_fix);
+ break;
+
+ case rs_fill:
+ break;
+
+ case rs_machine_dependent:
+ md_convert_frag(&headers, fragP);
+
+ know((fragP->fr_next == NULL) || ((fragP->fr_next->fr_address - fragP->fr_address) == fragP->fr_fix));
+
+ /*
+ * After md_convert_frag, we make the frag into a ".space 0".
+ * Md_convert_frag() should set up any fixSs and constants
+ * required.
+ */
+ frag_wane(fragP);
+ break;
+
+#ifndef WORKING_DOT_WORD
+ case rs_broken_word: {
+ struct broken_word *lie;
+
+ if (fragP->fr_subtype) {
+ fragP->fr_fix+=md_short_jump_size;
+ for (lie=(struct broken_word *)(fragP->fr_symbol);lie && lie->dispfrag == fragP;lie=lie->next_broken_word)
+ if (lie->added == 1)
+ fragP->fr_fix+=md_long_jump_size;
+ }
+ frag_wane(fragP);
+ }
+ break;
+#endif
+
+ default:
+ BAD_CASE( fragP->fr_type );
+ break;
+ } /* switch (fr_type) */
+
+ know((fragP->fr_next == NULL)
+ || ((fragP->fr_next->fr_address - fragP->fr_address)
+ == (fragP->fr_fix + (fragP->fr_offset * fragP->fr_var))));
+ } /* for each frag. */
+
+#ifndef WORKING_DOT_WORD
+ {
+ struct broken_word *lie;
+ struct broken_word **prevP;
+
+ prevP = &broken_words;
+ for (lie = broken_words; lie; lie = lie->next_broken_word)
+ if (!lie->added) {
+#ifdef TC_NS32K
+ fix_new_ns32k(lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2,
+ lie->add,
+ lie->sub,
+ lie->addnum,
+ 0, 0, 2, 0, 0, NO_RELOC);
+#else /* TC_NS32K */
+#ifdef PIC
+ fix_new(lie->frag, lie->word_goes_here - lie->frag->fr_literal,
+ 2, lie->add,
+ lie->sub, lie->addnum,
+ 0, NO_RELOC, (symbolS *)0);
+#else
+ fix_new(lie->frag, lie->word_goes_here - lie->frag->fr_literal,
+ 2, lie->add,
+ lie->sub, lie->addnum,
+ 0, NO_RELOC);
+#endif
+#endif /* TC_NS32K */
+ /* md_number_to_chars(lie->word_goes_here,
+ S_GET_VALUE(lie->add)
+ + lie->addnum
+ - S_GET_VALUE(lie->sub),
+ 2); */
+ *prevP = lie->next_broken_word;
+ } else
+ prevP = &(lie->next_broken_word);
+
+ for (lie = broken_words; lie;) {
+ struct broken_word *untruth;
+ char *table_ptr;
+ long table_addr;
+ long from_addr,
+ to_addr;
+ int n,
+ m;
+
+ fragP = lie->dispfrag;
+
+ /* Find out how many broken_words go here */
+ n=0;
+ for (untruth = lie; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)
+ if (untruth->added == 1)
+ n++;
+
+ table_ptr = lie->dispfrag->fr_opcode;
+ table_addr = lie->dispfrag->fr_address + (table_ptr - lie->dispfrag->fr_literal);
+ /* Create the jump around the long jumps */
+ /* This is a short jump from table_ptr+0 to table_ptr+n*long_jump_size */
+ from_addr = table_addr;
+ to_addr = table_addr + md_short_jump_size + n * md_long_jump_size;
+ md_create_short_jump(table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
+ table_ptr += md_short_jump_size;
+ table_addr += md_short_jump_size;
+
+ for (m = 0; lie && lie->dispfrag == fragP; m++, lie = lie->next_broken_word) {
+ if (lie->added == 2)
+ continue;
+ /* Patch the jump table */
+ /* This is the offset from ??? to table_ptr+0 */
+ to_addr = table_addr
+ - S_GET_VALUE(lie->sub);
+ md_number_to_chars(lie->word_goes_here, to_addr, 2);
+ for (untruth = lie->next_broken_word;
+ untruth && untruth->dispfrag == fragP;
+ untruth = untruth->next_broken_word) {
+ if (untruth->use_jump == lie)
+ md_number_to_chars(untruth->word_goes_here, to_addr, 2);
+ }
+
+ /* Install the long jump */
+ /* this is a long jump from table_ptr+0 to the final target */
+ from_addr = table_addr;
+ to_addr = S_GET_VALUE(lie->add) + lie->addnum;
+ md_create_long_jump(table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
+ table_ptr += md_long_jump_size;
+ table_addr += md_long_jump_size;
+ }
+ }
+ }
+#endif /* not WORKING_DOT_WORD */
+
+#ifndef OBJ_VMS
+ { /* not vms */
+ /*
+ * Scan every FixS performing fixups. We had to wait until now to do
+ * this because md_convert_frag() may have made some fixSs.
+ */
+
+ H_SET_RELOCATION_SIZE(&headers,
+ md_reloc_size * fixup_segment(text_fix_root, SEG_TEXT),
+ md_reloc_size * fixup_segment(data_fix_root, SEG_DATA));
+
+
+ obj_pre_write_hook(&headers);
+
+ if ((had_warnings() && flagseen['Z'])
+ || had_errors() > 0) {
+ if (flagseen['Z']) {
+ as_warn("%d error%s, %d warning%s, generating bad object file.\n",
+ had_errors(), had_errors() == 1 ? "" : "s",
+ had_warnings(), had_warnings() == 1 ? "" : "s");
+ } else {
+ as_fatal("%d error%s, %d warning%s, no object file generated.\n",
+ had_errors(), had_errors() == 1 ? "" : "s",
+ had_warnings(), had_warnings() == 1 ? "" : "s");
+ } /* on want output */
+ } /* on error condition */
+
+ object_file_size = H_GET_FILE_SIZE(&headers);
+ next_object_file_charP = the_object_file = xmalloc(object_file_size);
+
+ output_file_create(out_file_name);
+
+ obj_header_append(&next_object_file_charP, &headers);
+
+ know((next_object_file_charP - the_object_file) == H_GET_HEADER_SIZE(&headers));
+
+ /*
+ * Emit code.
+ */
+ for (fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
+ register long count;
+ register char *fill_literal;
+ register long fill_size;
+
+ know(fragP->fr_type == rs_fill);
+ append(&next_object_file_charP, fragP->fr_literal, (unsigned long) fragP->fr_fix);
+ fill_literal = fragP->fr_literal + fragP->fr_fix;
+ fill_size = fragP->fr_var;
+ know(fragP->fr_offset >= 0);
+
+ for (count = fragP->fr_offset; count; count--) {
+ append(&next_object_file_charP, fill_literal, (unsigned long) fill_size);
+ } /* for each */
+
+ } /* for each code frag. */
+
+ know((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE(&headers) + H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers)));
+
+ /*
+ * Emit relocations.
+ */
+ obj_emit_relocations(&next_object_file_charP, text_fix_root, (relax_addressT)0);
+ know((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE(&headers) + H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers) + H_GET_TEXT_RELOCATION_SIZE(&headers)));
+#ifdef TC_I960
+ /* Make addresses in data relocation directives relative to beginning of
+ * first data fragment, not end of last text fragment: alignment of the
+ * start of the data segment may place a gap between the segments.
+ */
+ obj_emit_relocations(&next_object_file_charP, data_fix_root, data0_frchainP->frch_root->fr_address);
+#else /* TC_I960 */
+ obj_emit_relocations(&next_object_file_charP, data_fix_root, text_last_frag->fr_address);
+#endif /* TC_I960 */
+
+ know((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE(&headers) + H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers) + H_GET_TEXT_RELOCATION_SIZE(&headers) + H_GET_DATA_RELOCATION_SIZE(&headers)));
+
+ /*
+ * Emit line number entries.
+ */
+ OBJ_EMIT_LINENO(&next_object_file_charP, lineno_rootP, the_object_file);
+ know((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE(&headers) + H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers) + H_GET_TEXT_RELOCATION_SIZE(&headers) + H_GET_DATA_RELOCATION_SIZE(&headers) + H_GET_LINENO_SIZE(&headers)));
+
+ /*
+ * Emit symbols.
+ */
+ obj_emit_symbols(&next_object_file_charP, symbol_rootP);
+ know((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE(&headers) + H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers) + H_GET_TEXT_RELOCATION_SIZE(&headers) + H_GET_DATA_RELOCATION_SIZE(&headers) + H_GET_LINENO_SIZE(&headers) + H_GET_SYMBOL_TABLE_SIZE(&headers)));
+
+ /*
+ * Emit strings.
+ */
+
+ if (string_byte_count > 0) {
+ obj_emit_strings(&next_object_file_charP);
+ } /* only if we have a string table */
+
+ /* know((next_object_file_charP - the_object_file) == (H_GET_HEADER_SIZE(&headers) + H_GET_TEXT_SIZE(&headers) + H_GET_DATA_SIZE(&headers) + H_GET_TEXT_RELOCATION_SIZE(&headers) + H_GET_DATA_RELOCATION_SIZE(&headers) + H_GET_LINENO_SIZE(&headers) + H_GET_SYMBOL_TABLE_SIZE(&headers) + H_GET_STRING_SIZE(&headers)));
+ */
+ /* know(next_object_file_charP == the_object_file + object_file_size);*/
+
+#ifdef BFD_HEADERS
+ bfd_seek(stdoutput, 0, 0);
+ bfd_write(the_object_file, 1, object_file_size, stdoutput);
+#else
+
+ /* Write the data to the file */
+ output_file_append(the_object_file, object_file_size, out_file_name);
+#endif
+
+ output_file_close(out_file_name);
+ } /* non vms output */
+#else /* OBJ_VMS */
+ /*
+ * Now do the VMS-dependent part of writing the object file
+ */
+ VMS_write_object_file(H_GET_TEXT_SIZE(&headers), H_GET_DATA_SIZE(&headers),
+ text_frag_root, data_frag_root);
+#endif /* OBJ_VMS */
+} /* write_object_file() */
+#else
+#endif
+
+/*
+ * relax_segment()
+ *
+ * Now we have a segment, not a crowd of sub-segments, we can make fr_address
+ * values.
+ *
+ * Relax the frags.
+ *
+ * After this, all frags in this segment have addresses that are correct
+ * within the segment. Since segments live in different file addresses,
+ * these frag addresses may not be the same as final object-file addresses.
+ */
+
+
+
+void relax_segment(segment_frag_root, segment)
+struct frag * segment_frag_root;
+segT segment; /* SEG_DATA or SEG_TEXT */
+{
+ register struct frag * fragP;
+ register relax_addressT address;
+ /* register relax_addressT old_address; JF unused */
+ /* register relax_addressT new_address; JF unused */
+#ifndef MANY_SEGMENTS
+ know(segment == SEG_DATA || segment == SEG_TEXT);
+#endif
+ /* In case md_estimate_size_before_relax() wants to make fixSs. */
+ subseg_change(segment, 0);
+
+ /*
+ * For each frag in segment: count and store (a 1st guess of) fr_address.
+ */
+ address = 0;
+ for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
+ fragP->fr_address = address;
+ address += fragP->fr_fix;
+
+ switch (fragP->fr_type) {
+ case rs_fill:
+ address += fragP->fr_offset * fragP->fr_var ;
+ break;
+
+ case rs_align:
+ address += relax_align(address, fragP->fr_offset);
+ break;
+
+ case rs_org:
+ /*
+ * Assume .org is nugatory. It will grow with 1st relax.
+ */
+ break;
+
+ case rs_machine_dependent:
+ address += md_estimate_size_before_relax(fragP, segment);
+ break;
+
+#ifndef WORKING_DOT_WORD
+ /* Broken words don't concern us yet */
+ case rs_broken_word:
+ break;
+#endif
+
+ default:
+ BAD_CASE(fragP->fr_type);
+ break;
+ } /* switch (fr_type) */
+ } /* for each frag in the segment */
+
+ /*
+ * Do relax().
+ */
+ {
+ register long stretch; /* May be any size, 0 or negative. */
+ /* Cumulative number of addresses we have */
+ /* relaxed this pass. */
+ /* We may have relaxed more than one address. */
+ register long stretched; /* Have we stretched on this pass? */
+ /* This is 'cuz stretch may be zero, when,
+ in fact some piece of code grew, and
+ another shrank. If a branch instruction
+ doesn't fit anymore, we could be scrod */
+
+ do {
+ stretch = stretched = 0;
+ for (fragP = segment_frag_root; fragP; fragP = fragP->fr_next) {
+ register long growth = 0;
+ register unsigned long was_address;
+ register long offset;
+ register symbolS *symbolP;
+ register long target;
+ register long after;
+ register long aim;
+
+ was_address = fragP->fr_address;
+ address = fragP->fr_address += stretch;
+ symbolP = fragP->fr_symbol;
+ offset = fragP->fr_offset;
+
+ switch (fragP->fr_type) {
+ case rs_fill: /* .fill never relaxes. */
+ growth = 0;
+ break;
+
+#ifndef WORKING_DOT_WORD
+ /* JF: This is RMS's idea. I do *NOT* want to be blamed
+ for it I do not want to write it. I do not want to have
+ anything to do with it. This is not the proper way to
+ implement this misfeature. */
+ case rs_broken_word: {
+ struct broken_word *lie;
+ struct broken_word *untruth;
+
+ /* Yes this is ugly (storing the broken_word pointer
+ in the symbol slot). Still, this whole chunk of
+ code is ugly, and I don't feel like doing anything
+ about it. Think of it as stubbornness in action */
+ growth=0;
+ for (lie=(struct broken_word *)(fragP->fr_symbol);
+ lie && lie->dispfrag == fragP;
+ lie=lie->next_broken_word) {
+
+ if (lie->added)
+ continue;
+
+ offset = lie->add->sy_frag->fr_address+ S_GET_VALUE(lie->add) + lie->addnum -
+ (lie->sub->sy_frag->fr_address+ S_GET_VALUE(lie->sub));
+ if (offset <= -32768 || offset >= 32767) {
+#if 0
+ if (flagseen['K'])
+ as_warn(".word %s-%s+%ld didn't fit",
+ S_GET_NAME(lie->add),
+ S_GET_NAME(lie->sub),
+ lie->addnum);
+#endif
+ lie->added=1;
+ if (fragP->fr_subtype == 0) {
+ fragP->fr_subtype++;
+ growth+=md_short_jump_size;
+ }
+ for (untruth=lie->next_broken_word;untruth && untruth->dispfrag == lie->dispfrag;untruth=untruth->next_broken_word)
+ if ((untruth->add->sy_frag == lie->add->sy_frag)
+ && S_GET_VALUE(untruth->add) == S_GET_VALUE(lie->add)) {
+ untruth->added=2;
+ untruth->use_jump=lie;
+ }
+ growth += md_long_jump_size;
+ }
+ }
+
+ break;
+ } /* case rs_broken_word */
+#endif
+ case rs_align:
+ growth = relax_align((relax_addressT) (address + fragP->fr_fix), offset)
+ - relax_align((relax_addressT) (was_address + fragP->fr_fix), offset);
+ break;
+
+ case rs_org:
+ target = offset;
+
+ if (symbolP) {
+#ifdef MANY_SEGMENTS
+#else
+ know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT(symbolP) == SEG_DATA) || (S_GET_SEGMENT(symbolP) == SEG_TEXT));
+ know(symbolP->sy_frag);
+ know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || (symbolP->sy_frag == &zero_address_frag));
+#endif
+ target += S_GET_VALUE(symbolP)
+ + symbolP->sy_frag->fr_address;
+ } /* if we have a symbol */
+
+ know(fragP->fr_next);
+ after = fragP->fr_next->fr_address;
+ growth = ((target - after ) > 0) ? (target - after) : 0;
+ /* Growth may be -ve, but variable part */
+ /* of frag cannot have < 0 chars. */
+ /* That is, we can't .org backwards. */
+
+ growth -= stretch; /* This is an absolute growth factor */
+ break;
+
+ case rs_machine_dependent: {
+ register const relax_typeS * this_type;
+ register const relax_typeS * start_type;
+ register relax_substateT next_state;
+ register relax_substateT this_state;
+
+ start_type = this_type = md_relax_table + (this_state = fragP->fr_subtype);
+ target = offset;
+
+ if (symbolP) {
+#ifndef MANY_SEGMENTS
+ know((S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || (S_GET_SEGMENT(symbolP) == SEG_DATA) || (S_GET_SEGMENT(symbolP) == SEG_TEXT));
+#endif
+ know(symbolP->sy_frag);
+ know(!(S_GET_SEGMENT(symbolP) == SEG_ABSOLUTE) || symbolP->sy_frag == &zero_address_frag );
+ target +=
+ S_GET_VALUE(symbolP)
+ + symbolP->sy_frag->fr_address;
+
+ /* If frag has yet to be reached on this pass,
+ assume it will move by STRETCH just as we did.
+ If this is not so, it will be because some frag
+ between grows, and that will force another pass. */
+
+ /* JF was just address */
+ /* JF also added is_dnrange hack */
+ /* There's gotta be a better/faster/etc way
+ to do this... */
+ /* gnu@cygnus.com: I changed this from > to >=
+ because I ran into a zero-length frag (fr_fix=0)
+ which was created when the obstack needed a new
+ chunk JUST AFTER the opcode of a branch. Since
+ fr_fix is zero, fr_address of this frag is the same
+ as fr_address of the next frag. This
+ zero-length frag was variable and jumped to .+2
+ (in the next frag), but since the > comparison
+ below failed (the two were =, not >), "stretch"
+ was not added to the target. Stretch was 178, so
+ the offset appeared to be .-176 instead, which did
+ not fit into a byte branch, so the assembler
+ relaxed the branch to a word. This didn't compare
+ with what happened when the same source file was
+ assembled on other machines, which is how I found it.
+ You might want to think about what other places have
+ trouble with zero length frags... */
+
+ if (symbolP->sy_frag->fr_address >= was_address
+ && is_dnrange(fragP,symbolP->sy_frag)) {
+ target += stretch;
+ } /* */
+
+ } /* if there's a symbol attached */
+
+ aim = target - address - fragP->fr_fix;
+ /* The displacement is affected by the instruction size
+ * for the 32k architecture. I think we ought to be able
+ * to add fragP->fr_pcrel_adjust in all cases (it should be
+ * zero if not used), but just in case it breaks something
+ * else we'll put this inside #ifdef NS32K ... #endif
+ */
+#ifdef TC_NS32K
+ aim += fragP->fr_pcrel_adjust;
+#endif /* TC_NS32K */
+
+ if (aim < 0) {
+ /* Look backwards. */
+ for (next_state = this_type->rlx_more; next_state; ) {
+ if (aim >= this_type->rlx_backward) {
+ next_state = 0;
+ } else { /* Grow to next state. */
+ this_type = md_relax_table + (this_state = next_state);
+ next_state = this_type->rlx_more;
+ }
+ }
+ } else {
+#ifdef DONTDEF
+ /* JF these next few lines of code are for the mc68020 which can't handle short
+ offsets of zero in branch instructions. What a kludge! */
+ if (aim == 0 && this_state == (1<<2+0)) { /* FOO hard encoded from m.c */
+ aim=this_type->rlx_forward+1; /* Force relaxation into word mode */
+ }
+#endif
+#ifdef M68K_AIM_KLUDGE
+ M68K_AIM_KLUDGE(aim, this_state, this_type);
+#endif
+ /* JF end of 68020 code */
+ /* Look forwards. */
+ for (next_state = this_type->rlx_more; next_state; ) {
+ if (aim <= this_type->rlx_forward) {
+ next_state = 0;
+ } else { /* Grow to next state. */
+ this_type = md_relax_table + (this_state = next_state);
+ next_state = this_type->rlx_more;
+ }
+ }
+ }
+
+ if ((growth = this_type->rlx_length - start_type->rlx_length) != 0)
+ fragP->fr_subtype = this_state;
+
+ break;
+ } /* case rs_machine_dependent */
+
+ default:
+ BAD_CASE( fragP->fr_type );
+ break;
+ }
+ if (growth) {
+ stretch += growth;
+ stretched++;
+ }
+ } /* For each frag in the segment. */
+ } while (stretched); /* Until nothing further to relax. */
+ } /* do_relax */
+
+ /*
+ * We now have valid fr_address'es for each frag.
+ */
+
+ /*
+ * All fr_address's are correct, relative to their own segment.
+ * We have made all the fixS we will ever make.
+ */
+} /* relax_segment() */
+
+/*
+ * Relax_align. Advance location counter to next address that has 'alignment'
+ * lowest order bits all 0s.
+ */
+
+/* How many addresses does the .align take? */
+static relax_addressT relax_align(address, alignment)
+register relax_addressT address; /* Address now. */
+register long alignment; /* Alignment (binary). */
+{
+ relax_addressT mask;
+ relax_addressT new_address;
+
+ mask = ~ ( (~0) << alignment );
+ new_address = (address + mask) & (~ mask);
+ return (new_address - address);
+} /* relax_align() */
+
+/* fixup_segment()
+
+ Go through all the fixS's in a segment and see which ones can be
+ handled now. (These consist of fixS where we have since discovered
+ the value of a symbol, or the address of the frag involved.)
+ For each one, call md_apply_fix to put the fix into the frag data.
+
+ Result is a count of how many relocation structs will be needed to
+ handle the remaining fixS's that we couldn't completely handle here.
+ These will be output later by emit_relocations(). */
+
+static long fixup_segment(fixP, this_segment_type)
+register fixS *fixP;
+segT this_segment_type; /* N_TYPE bits for segment. */
+{
+ register long seg_reloc_count;
+ register symbolS *add_symbolP;
+ register symbolS *sub_symbolP;
+ register long add_number;
+ register int size;
+ register char *place;
+ register long where;
+ register char pcrel;
+ register fragS *fragP;
+ register segT add_symbol_segment = SEG_ABSOLUTE;
+
+ /* FIXME: remove this line */ /* fixS *orig = fixP; */
+ seg_reloc_count = 0;
+
+ for ( ; fixP; fixP = fixP->fx_next) {
+ fragP = fixP->fx_frag;
+ know(fragP);
+ where = fixP->fx_where;
+ place = fragP->fr_literal + where;
+ size = fixP->fx_size;
+ add_symbolP = fixP->fx_addsy;
+#ifdef TC_I960
+ if (fixP->fx_callj && TC_S_IS_CALLNAME(add_symbolP)) {
+ /* Relocation should be done via the
+ associated 'bal' entry point
+ symbol. */
+
+ if (!TC_S_IS_BALNAME(tc_get_bal_of_call(add_symbolP))) {
+ as_bad("No 'bal' entry point for leafproc %s",
+ S_GET_NAME(add_symbolP));
+ continue;
+ }
+ fixP->fx_addsy = add_symbolP = tc_get_bal_of_call(add_symbolP);
+ } /* callj relocation */
+#endif
+ sub_symbolP = fixP->fx_subsy;
+ add_number = fixP->fx_offset;
+ pcrel = fixP->fx_pcrel;
+
+ if (add_symbolP) {
+ add_symbol_segment = S_GET_SEGMENT(add_symbolP);
+ } /* if there is an addend */
+
+ if (sub_symbolP) {
+ if (!add_symbolP) {
+ /* Its just -sym */
+ if (S_GET_SEGMENT(sub_symbolP) != SEG_ABSOLUTE) {
+ as_bad("Negative of non-absolute symbol %s", S_GET_NAME(sub_symbolP));
+ } /* not absolute */
+
+ add_number -= S_GET_VALUE(sub_symbolP);
+
+ /* if sub_symbol is in the same segment that add_symbol
+ and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
+ } else if ((S_GET_SEGMENT(sub_symbolP) == add_symbol_segment)
+ && (SEG_NORMAL(add_symbol_segment)
+ || (add_symbol_segment == SEG_ABSOLUTE))) {
+ /* Difference of 2 symbols from same segment. */
+ /* Can't make difference of 2 undefineds: 'value' means */
+ /* something different for N_UNDF. */
+#ifdef TC_I960
+ /* Makes no sense to use the difference of 2 arbitrary symbols
+ * as the target of a call instruction.
+ */
+ if (fixP->fx_callj) {
+ as_bad("callj to difference of 2 symbols");
+ }
+#endif /* TC_I960 */
+#ifdef PIC
+ if (picmode &&
+ S_IS_EXTERNAL(add_symbolP)) {
+ as_bad("Can't reduce difference of external symbols in PIC code");
+ }
+#endif
+ add_number += S_GET_VALUE(add_symbolP) -
+ S_GET_VALUE(sub_symbolP);
+
+ add_symbolP = NULL;
+ fixP->fx_addsy = NULL;
+ } else {
+ /* Different segments in subtraction. */
+ know(!(S_IS_EXTERNAL(sub_symbolP) && (S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)));
+
+ if ((S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)) {
+ add_number -= S_GET_VALUE(sub_symbolP);
+ } else {
+ as_bad("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
+ segment_name(S_GET_SEGMENT(sub_symbolP)),
+ S_GET_NAME(sub_symbolP), fragP->fr_address + where);
+ } /* if absolute */
+ }
+ } /* if sub_symbolP */
+
+#ifdef PIC
+ /*
+ * Bring _GLOBAL_OFFSET_TABLE_ forward, now we've had the
+ * chance to collapse any accompanying symbols into a number.
+ * This is the sequel of the hack in expr.c to parse operands
+ * of the form `_GLOBAL_OFFSET_TABLE_+(L1-L2)'. Note that
+ * _GLOBAL_OFFSET_TABLE_ can only be an "add symbol".
+ */
+ if (add_symbolP == NULL && fixP->fx_gotsy != NULL) {
+ add_symbolP = fixP->fx_addsy = fixP->fx_gotsy;
+ add_symbol_segment = S_GET_SEGMENT(add_symbolP);
+ }
+#endif
+
+ if (add_symbolP) {
+ if (add_symbol_segment == this_segment_type && pcrel) {
+ /*
+ * This fixup was made when the symbol's segment was
+ * SEG_UNKNOWN, but it is now in the local segment.
+ * So we know how to do the address without relocation.
+ */
+#ifdef TC_I960
+ /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
+ * in which cases it modifies *fixP as appropriate. In the case
+ * of a 'calls', no further work is required, and *fixP has been
+ * set up to make the rest of the code below a no-op.
+ */
+ reloc_callj(fixP);
+#endif /* TC_I960 */
+
+ add_number += S_GET_VALUE(add_symbolP);
+ add_number -= md_pcrel_from(fixP);
+ pcrel = 0; /* Lie. Don't want further pcrel processing. */
+ fixP->fx_addsy = NULL; /* No relocations please. */
+ } else {
+ switch (add_symbol_segment) {
+ case SEG_ABSOLUTE:
+#ifdef TC_I960
+ reloc_callj(fixP); /* See comment about reloc_callj() above*/
+#endif /* TC_I960 */
+ add_number += S_GET_VALUE(add_symbolP);
+ fixP->fx_addsy = NULL;
+ add_symbolP = NULL;
+ break;
+ default:
+ seg_reloc_count ++;
+#ifdef PIC
+ /*
+ * Do not fixup refs to global data
+ * even if defined here.
+ */
+ if (!picmode ||
+#ifdef TC_NS32K
+ fixP->fx_pcrel ||
+#endif
+ (fixP->fx_r_type != RELOC_GLOB_DAT &&
+#ifdef TC_I386
+/* XXX - This must be rationalized */
+ fixP->fx_r_type != RELOC_GOT &&
+ fixP->fx_r_type != RELOC_GOTOFF &&
+#endif
+ (fixP->fx_r_type != RELOC_32 ||
+ !S_IS_EXTERNAL(add_symbolP))))
+#endif
+ add_number += S_GET_VALUE(add_symbolP);
+ break;
+
+ case SEG_UNKNOWN:
+#ifdef TC_I960
+ if ((int)fixP->fx_bit_fixP == 13) {
+ /* This is a COBR instruction. They have only a
+ * 13-bit displacement and are only to be used
+ * for local branches: flag as error, don't generate
+ * relocation.
+ */
+ as_bad("can't use COBR format with external label");
+ fixP->fx_addsy = NULL; /* No relocations please. */
+ continue;
+ } /* COBR */
+#endif /* TC_I960 */
+
+#ifdef OBJ_COFF
+#ifdef TE_I386AIX
+ if (S_IS_COMMON(add_symbolP))
+ add_number += S_GET_VALUE(add_symbolP);
+#endif /* TE_I386AIX */
+#endif /* OBJ_COFF */
+ ++seg_reloc_count;
+
+ break;
+
+
+ } /* switch on symbol seg */
+ } /* if not in local seg */
+ } /* if there was a + symbol */
+
+ if (pcrel) {
+ add_number -= md_pcrel_from(fixP);
+ if (add_symbolP == 0) {
+ fixP->fx_addsy = & abs_symbol;
+ ++seg_reloc_count;
+ } /* if there's an add_symbol */
+ } /* if pcrel */
+
+ if (!fixP->fx_bit_fixP) {
+ if ((size == 1 &&
+ (add_number& ~0xFF) && (add_number & ~0xFF != (-1 & ~0xFF))) ||
+ (size == 2 &&
+ (add_number& ~0xFFFF) && (add_number & ~0xFFFF != (-1 & ~0xFFFF)))) {
+ as_bad("Value of %d too large for field of %d bytes at 0x%x",
+ add_number, size, fragP->fr_address + where);
+ } /* generic error checking */
+ } /* not a bit fix */
+
+ md_apply_fix(fixP, add_number);
+ } /* For each fixS in this segment. */
+
+#ifdef OBJ_COFF
+#ifdef TC_I960
+ {
+ fixS *topP = fixP;
+
+ /* two relocs per callj under coff. */
+ for (fixP = topP; fixP; fixP = fixP->fx_next) {
+ if (fixP->fx_callj && fixP->fx_addsy != 0) {
+ ++seg_reloc_count;
+ } /* if callj and not already fixed. */
+ } /* for each fix */
+ }
+#endif /* TC_I960 */
+
+#endif /* OBJ_COFF */
+ return(seg_reloc_count);
+} /* fixup_segment() */
+
+
+static int is_dnrange(f1,f2)
+struct frag *f1;
+struct frag *f2;
+{
+ while (f1) {
+ if (f1->fr_next == f2)
+ return 1;
+ f1=f1->fr_next;
+ }
+ return 0;
+} /* is_dnrange() */
+
+/* Append a string onto another string, bumping the pointer along. */
+void
+ append (charPP, fromP, length)
+char **charPP;
+char *fromP;
+unsigned long length;
+{
+ if (length) { /* Don't trust memcpy() of 0 chars. */
+ memcpy(*charPP, fromP, (int) length);
+ *charPP += length;
+ }
+}
+
+int section_alignment[SEG_MAXIMUM_ORDINAL];
+
+/*
+ * This routine records the largest alignment seen for each segment.
+ * If the beginning of the segment is aligned on the worst-case
+ * boundary, all of the other alignments within it will work. At
+ * least one object format really uses this info.
+ */
+void record_alignment(seg, align)
+segT seg; /* Segment to which alignment pertains */
+int align; /* Alignment, as a power of 2
+ * (e.g., 1 => 2-byte boundary, 2 => 4-byte boundary, etc.)
+ */
+{
+
+ if ( align > section_alignment[(int) seg] ){
+ section_alignment[(int) seg] = align;
+ } /* if highest yet */
+
+ return;
+} /* record_alignment() */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of write.c */
diff --git a/gnu/usr.bin/as/write.h b/gnu/usr.bin/as/write.h
new file mode 100644
index 0000000..8b51880
--- /dev/null
+++ b/gnu/usr.bin/as/write.h
@@ -0,0 +1,120 @@
+/* write.h
+
+ Copyright (C) 1987, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/*
+ * write.h,v 1.3 1993/10/02 20:58:02 pk Exp
+ */
+
+
+#ifndef TC_I960
+#ifdef hpux
+#define EXEC_MACHINE_TYPE HP9000S200_ID
+#endif
+#endif /* TC_I960 */
+
+#ifndef LOCAL_LABEL
+#ifdef DOT_LABEL_PREFIX
+#define LOCAL_LABEL(name) (name[0] == '.' \
+ && (name[1] == 'L' || name[1] == '.'))
+#else /* not defined DOT_LABEL_PREFIX */
+#define LOCAL_LABEL(name) (name[0] == 'L')
+#endif /* not defined DOT_LABEL_PREFIX */
+#endif /* LOCAL_LABEL */
+
+#define S_LOCAL_NAME(s) (LOCAL_LABEL(S_GET_NAME(s)))
+
+#include "bit_fix.h"
+
+/*
+ * FixSs may be built up in any order.
+ */
+
+struct fix {
+ fragS *fx_frag; /* Which frag? */
+ long fx_where; /* Where is the 1st byte to fix up? */
+ symbolS *fx_addsy; /* NULL or Symbol whose value we add in. */
+ symbolS *fx_subsy; /* NULL or Symbol whose value we subtract. */
+#ifdef PIC
+ symbolS *fx_gotsy; /* NULL or __GLOBAL_OFFSET_TABLE_ . */
+#endif
+ long fx_offset; /* Absolute number we add in. */
+ struct fix *fx_next; /* NULL or -> next fixS. */
+ short int fx_size; /* How many bytes are involved? */
+ char fx_pcrel; /* TRUE: pc-relative. */
+ char fx_pcrel_adjust; /* pc-relative offset adjust */
+ char fx_im_disp; /* TRUE: value is a displacement */
+ bit_fixS *fx_bit_fixP; /* IF NULL no bitfix's to do */
+ char fx_bsr; /* sequent-hack */
+ enum reloc_type fx_r_type; /* Sparc hacks */
+ char fx_callj; /* TRUE if target is a 'callj' (used by i960) */
+ long fx_addnumber;
+};
+
+typedef struct fix fixS;
+
+COMMON char *next_object_file_charP;
+
+#ifndef MANY_SEGMENTS
+COMMON fixS *text_fix_root, *text_fix_tail; /* Chains fixSs. */
+COMMON fixS *data_fix_root, *data_fix_tail; /* Chains fixSs. */
+COMMON fixS *bss_fix_root, *bss_fix_tail; /* Chains fixSs. */
+#endif
+COMMON fixS **seg_fix_rootP, **seg_fix_tailP; /* -> one of above. */
+extern long string_byte_count;
+extern int section_alignment[];
+
+#if __STDC__ == 1
+
+bit_fixS *bit_fix_new(int size, int offset, long base_type, long base_adj, long min, long max, long add);
+void append(char **charPP, char *fromP, unsigned long length);
+void record_alignment(segT seg, int align);
+void write_object_file(void);
+
+fixS *fix_new(fragS *frag,
+ int where,
+ int size,
+ symbolS *add_symbol,
+ symbolS *sub_symbol,
+ long offset,
+ int pcrel,
+ enum reloc_type r_type
+#ifdef PIC
+ ,symbolS *got_symbol);
+#else
+ );
+#endif
+
+#else /* not __STDC__ */
+
+bit_fixS *bit_fix_new();
+fixS *fix_new();
+void append();
+void record_alignment();
+void write_object_file();
+
+#endif /* not __STDC__ */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of write.h */
diff --git a/gnu/usr.bin/as/xmalloc.c b/gnu/usr.bin/as/xmalloc.c
new file mode 100644
index 0000000..6c97b06
--- /dev/null
+++ b/gnu/usr.bin/as/xmalloc.c
@@ -0,0 +1,75 @@
+/* xmalloc.c - get memory or bust
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ NAME
+ xmalloc() - get memory or bust
+ INDEX
+ xmalloc() uses malloc()
+
+ SYNOPSIS
+ char * my_memory;
+
+ my_memory = xmalloc(42); / * my_memory gets address of 42 chars * /
+
+ DESCRIPTION
+
+ Use xmalloc() as an "error-free" malloc(). It does almost the same job.
+ When it cannot honour your request for memory it BOMBS your program
+ with a "virtual memory exceeded" message. Malloc() returns NULL and
+ does not bomb your program.
+
+ SEE ALSO
+ malloc()
+
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <stdio.h>
+
+#if __STDC__ == 1
+#include <stdlib.h>
+#else
+#ifdef USG
+#include <malloc.h>
+#else
+char * malloc();
+#endif /* USG */
+#endif /* not __STDC__ */
+
+#define error as_fatal
+
+char * xmalloc(n)
+long n;
+{
+ char * retval;
+ void error();
+
+ if ((retval = malloc ((unsigned)n)) == NULL)
+ {
+ error("virtual memory exceeded");
+ }
+ return (retval);
+}
+
+/* end of xmalloc.c */
diff --git a/gnu/usr.bin/as/xrealloc.c b/gnu/usr.bin/as/xrealloc.c
new file mode 100644
index 0000000..72189d5
--- /dev/null
+++ b/gnu/usr.bin/as/xrealloc.c
@@ -0,0 +1,74 @@
+/* xrealloc.c - new memory or bust
+
+ Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GAS; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/*
+
+ NAME
+ xrealloc () - get more memory or bust
+ INDEX
+ xrealloc () uses realloc ()
+ SYNOPSIS
+ char *my_memory;
+
+ my_memory = xrealloc (my_memory, 42);
+ / * my_memory gets (perhaps new) address of 42 chars * /
+
+ DESCRIPTION
+
+ Use xrealloc () as an "error-free" realloc ().It does almost the same
+ job. When it cannot honour your request for memory it BOMBS your
+ program with a "virtual memory exceeded" message. Realloc() returns
+ NULL and does not bomb your program.
+
+ SEE ALSO
+ realloc ()
+ */
+
+#ifndef lint
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+
+#if __STDC__ == 1
+#include <stdlib.h>
+#else
+#ifdef USG
+#include <malloc.h>
+#else
+char *realloc ();
+#endif /* USG */
+#endif /* not __STDC__ */
+
+#define error as_fatal
+
+char *
+ xrealloc (ptr, n)
+register char *ptr;
+long n;
+{
+ void error();
+
+ if ((ptr = realloc (ptr, (unsigned)n)) == 0)
+ error ("virtual memory exceeded");
+ return (ptr);
+}
+
+/* end of xrealloc.c */
diff --git a/gnu/usr.bin/bc/Makefile b/gnu/usr.bin/bc/Makefile
new file mode 100644
index 0000000..fcf0fd0
--- /dev/null
+++ b/gnu/usr.bin/bc/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+BCDIR= ${.CURDIR}/../../../contrib/bc
+.PATH: ${BCDIR}/bc ${BCDIR}/lib ${BCDIR}/doc ${BCDIR}/Examples
+
+PROG= bc
+SRCS= bc.y execute.c global.c load.c main.c scan.l storage.c util.c \
+ number.c getopt.c getopt1.c
+CFLAGS+=-I. -I${.CURDIR} -I${BCDIR}/h -I${BCDIR}/bc
+CFLAGS+=-DHAVE_CONFIG_H
+DPADD= ${LIBREADLINE} ${LIBTERMCAP}
+LDADD= -lreadline -ltermcap
+
+FILES= ckbook.b pi.b primes.b twins.b
+FILESDIR= ${SHAREDIR}/examples/bc
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/bc/config.h b/gnu/usr.bin/bc/config.h
new file mode 100644
index 0000000..b9e3520
--- /dev/null
+++ b/gnu/usr.bin/bc/config.h
@@ -0,0 +1,84 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* VERSION number for DC target*/
+#define DC_VERSION "1.3"
+
+/* COPYRIGHT notice for DC target */
+#define DC_COPYRIGHT "Copyright 1994, 1997, 1998, 2000 Free Software Foundation, Inc."
+
+/* COPYRIGHT notice for BC target */
+#define BC_COPYRIGHT "Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc."
+
+/* Define to use the readline library. */
+#define READLINE 1
+
+/* Define to use the BSD libedit library. */
+/* #define LIBEDIT 1 */
+
+/* Define to `size_t' if <sys/types.h> and <stddef.h> don't define. */
+/* #undef ptrdiff_t */
+
+/* Define if you have the isgraph function. */
+#define HAVE_ISGRAPH 1
+
+/* Define if you have the setvbuf function. */
+#define HAVE_SETVBUF 1
+
+/* Define if you have the <lib.h> header file. */
+/* #undef HAVE_LIB_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "bc"
+
+/* Version number of package */
+#define VERSION "1.06"
+
diff --git a/gnu/usr.bin/binutils/Makefile b/gnu/usr.bin/binutils/Makefile
new file mode 100644
index 0000000..cba9b7f
--- /dev/null
+++ b/gnu/usr.bin/binutils/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+# In my absence, bde and jdp have pre-approval for any commit they feel
+# necessary.
+MAINTAINER= obrien@FreeBSD.org
+
+SUBDIR= libiberty libbfd libopcodes libbinutils \
+ addr2line ar as gasp ld nm objcopy objdump ranlib readelf \
+ size strings strip doc
+
+NO_GDB=yes
+TARGET_ARCH?= ${MACHINE_ARCH}
+.if (${TARGET_ARCH} == "alpha" || ${TARGET_ARCH} == "i386") \
+ && !defined(NO_GDB)
+SUBDIR+= gdb gdbserver gdbreplay
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/binutils/Makefile.inc b/gnu/usr.bin/binutils/Makefile.inc
new file mode 100644
index 0000000..a988a12
--- /dev/null
+++ b/gnu/usr.bin/binutils/Makefile.inc
@@ -0,0 +1,6 @@
+#
+# $FreeBSD$
+#
+
+BINDIR?= /usr/libexec/elf
+WARNS?= 3
diff --git a/gnu/usr.bin/binutils/Makefile.inc0 b/gnu/usr.bin/binutils/Makefile.inc0
new file mode 100644
index 0000000..f9de70b
--- /dev/null
+++ b/gnu/usr.bin/binutils/Makefile.inc0
@@ -0,0 +1,49 @@
+# $FreeBSD$
+#
+# This is included explicitly at the top of each sub-Makefile. We can't
+# use the normal "Makefile.inc" mechanism, because we need some of these
+# definitions before the sub-Makefile is processed.
+
+VERSION= "2.12.0 [FreeBSD] 2002-04-10"
+VERSION_DATE= 20020410
+
+TARGET_ARCH?= ${MACHINE_ARCH}
+BINUTIL_ARCH= ${TARGET_ARCH}
+
+# RELTOP is the relative path to this point in the source or object
+# tree, from any subdirectory of same. It gets extra "../" prefixes
+# added to it as we descend into subdirectories.
+RELTOP:= ..
+
+RELSRC= ${RELTOP}/../../../contrib/binutils
+SRCDIR= ${.CURDIR}/${RELSRC}
+
+.if (${TARGET_ARCH} == "alpha")
+WARNS= 2
+.endif
+CFLAGS+= -D_GNU_SOURCE
+CFLAGS+= -I.
+.if exists(${.CURDIR}/${BINUTIL_ARCH})
+CFLAGS+= -I${.CURDIR}/${BINUTIL_ARCH}
+.endif
+CFLAGS+= -I${.CURDIR}
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbfd/${BINUTIL_ARCH}
+CFLAGS+= -I${SRCDIR}/include
+
+.if exists(${.CURDIR}/${BINUTIL_ARCH})
+.PATH: ${.CURDIR}/${BINUTIL_ARCH}
+.endif
+
+ARCHS= ${BINUTIL_ARCH}
+
+.for _arch in ${CROSS_ARCH}
+.if (${ARCHS:R:M${_arch:R}} == "")
+ARCHS+= $(_arch)
+.endif
+.endfor
+
+.for _arch in ${ARCHS}
+.if exists(${.CURDIR}/Makefile.${_arch})
+.include "${.CURDIR}/Makefile.${_arch}"
+.endif
+.endfor
diff --git a/gnu/usr.bin/binutils/addr2line/Makefile b/gnu/usr.bin/binutils/addr2line/Makefile
new file mode 100644
index 0000000..6988857
--- /dev/null
+++ b/gnu/usr.bin/binutils/addr2line/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= addr2line
+SRCS= addr2line.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/ar/Makefile b/gnu/usr.bin/binutils/ar/Makefile
new file mode 100644
index 0000000..d1e6493
--- /dev/null
+++ b/gnu/usr.bin/binutils/ar/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= ar
+SRCS= ar.c not-ranlib.c
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+CFLAGS+= -I${SRCDIR}/bfd
+NOSHARED?= yes
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/as/Makefile b/gnu/usr.bin/binutils/as/Makefile
new file mode 100644
index 0000000..ec92738
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/Makefile
@@ -0,0 +1,34 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc0"
+
+GASES= ${BINUTIL_ARCH}
+FORMATS=freebsd
+
+# Only build the cross tools when not cross-compiling.
+.if ${TARGET_ARCH} == ${MACHINE_ARCH}
+.if defined(CROSS_ARCH)
+.for _g in ${CROSS_ARCH}
+.if (${GASES:R:M${_g:R}} == "")
+GASES+= $(_g)
+.endif
+.endfor
+.endif
+.if defined(CROSS_FORMATS)
+.for _f in ${CROSS_FORMATS}
+.if (${FORMATS:R:M${_f:R}} == "")
+FORMATS+= $(_f)
+.endif
+.endfor
+.endif
+.endif
+
+.for _g in ${GASES}
+.for _f in ${FORMATS}
+.if exists(${.CURDIR}/${_g}-${_f})
+SUBDIR+= ${_g}-${_f}
+.endif
+.endfor
+.endfor
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/binutils/as/Makefile.inc b/gnu/usr.bin/binutils/as/Makefile.inc
new file mode 100644
index 0000000..835b5e3
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/Makefile.inc
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+# BINDIR
+.include "${.CURDIR}/../../Makefile.inc"
diff --git a/gnu/usr.bin/binutils/as/Makefile.inc0 b/gnu/usr.bin/binutils/as/Makefile.inc0
new file mode 100644
index 0000000..9296264
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/Makefile.inc0
@@ -0,0 +1,42 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../../Makefile.inc0"
+
+RELTOP:= ../${RELTOP}
+.PATH: ${SRCDIR}/gas ${SRCDIR}/gas/config
+
+PROG= as
+MAN= doc/as.1
+SRCS+= app.c as.c atof-generic.c atof-ieee.c bignum-copy.c \
+ cond.c dwarf2dbg.c ecoff.c expr.c flonum-copy.c flonum-konst.c \
+ flonum-mult.c frags.c hash.c input-file.c \
+ input-scrub.c listing.c literal.c macro.c messages.c \
+ output-file.c read.c sb.c stabs.c \
+ subsegs.c symbols.c write.c depend.c ehopt.c
+# DEO: why not used?
+#SRCS+= itbl-ops.c
+.if (${TARGET_ARCH} == "alpha")
+WARNS= 0
+.else
+WARNS= 2
+.endif
+CFLAGS+= -I${SRCDIR}/gas -I${SRCDIR}/gas/config -I${SRCDIR} -I${.CURDIR}/..
+CFLAGS+= -DVERSION=\"${VERSION:C/[ ]?${VERSION_DATE}[ ]?//g}\"
+CFLAGS+= -DBFD_VERSION_STRING=\"${VERSION}\"
+NOSHARED?= yes
+DPADD= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+DPADD+= ${RELTOP}/libopcodes/libopcodes.a
+LDADD= ${DPADD}
+
+# If set, BINUTILSDISTDIR is the path to a directory containing the full GNU
+# binutils release. FreeBSD only distributes the bits that are required to
+# build native architectures. BINUTILSDISTDIR is needed to build cross tools.
+.if defined(BINUTILSDISTDIR) && exists(${BINUTILSDISTDIR})
+.PATH: ${BINUTILSDISTDIR}/gas ${BINUTILSDISTDIR}/gas/config
+CFLAGS+= -I${BINUTILSDISTDIR}/gas
+CFLAGS+= -I${BINUTILSDISTDIR}/gas/config
+CFLAGS+= -I${BINUTILSDISTDIR}/bfd
+CFLAGS+= -I${BINUTILSDISTDIR}/include
+CFLAGS+= -I${BINUTILSDISTDIR}
+.endif
diff --git a/gnu/usr.bin/binutils/as/alpha-freebsd/Makefile b/gnu/usr.bin/binutils/as/alpha-freebsd/Makefile
new file mode 100644
index 0000000..c275d30
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/alpha-freebsd/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc0"
+
+.if ${TARGET_ARCH} != "alpha"
+NOMAN= true
+BINDIR= /usr/libexec/cross/alpha-freebsd
+.endif
+SRCS+= obj-elf.c tc-alpha.c
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/as/alpha-freebsd/config.h b/gnu/usr.bin/binutils/as/alpha-freebsd/config.h
new file mode 100644
index 0000000..fcbdec0
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/alpha-freebsd/config.h
@@ -0,0 +1,279 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the remove function. */
+/* #undef HAVE_REMOVE */
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the unlink function. */
+#define HAVE_UNLINK 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Define if you have the <varargs.h> header file. */
+#define HAVE_VARARGS_H 1
+
+/* Name of package */
+#define PACKAGE "gas"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if defaulting to ELF on SCO 5. */
+/* #undef SCO_ELF */
+
+/* Using strict COFF? */
+/* #undef STRICTCOFF */
+
+/* Define if default target is PowerPC Solaris. */
+/* #undef TARGET_SOLARIS_COMMENT */
+
+/* Define as 1 if big endian. */
+/* #undef TARGET_BYTES_BIG_ENDIAN */
+
+/* Use ELF stabs for MIPS, not ECOFF stabs */
+/* #undef MIPS_STABS_ELF */
+
+/* Default architecture. */
+/* #undef DEFAULT_ARCH */
+
+/* Using cgen code? */
+/* #undef USING_CGEN */
+
+/* Using i386 COFF? */
+/* #undef I386COFF */
+
+/* Using m68k COFF? */
+/* #undef M68KCOFF */
+
+/* Using m88k COFF? */
+/* #undef M88KCOFF */
+
+/* a.out support? */
+/* #undef OBJ_MAYBE_AOUT */
+
+/* b.out support? */
+/* #undef OBJ_MAYBE_BOUT */
+
+/* COFF support? */
+/* #undef OBJ_MAYBE_COFF */
+
+/* ECOFF support? */
+/* #undef OBJ_MAYBE_ECOFF */
+
+/* ELF support? */
+/* #undef OBJ_MAYBE_ELF */
+
+/* generic support? */
+/* #undef OBJ_MAYBE_GENERIC */
+
+/* HP300 support? */
+/* #undef OBJ_MAYBE_HP300 */
+
+/* IEEE support? */
+/* #undef OBJ_MAYBE_IEEE */
+
+/* SOM support? */
+/* #undef OBJ_MAYBE_SOM */
+
+/* VMS support? */
+/* #undef OBJ_MAYBE_VMS */
+
+/* Use emulation support? */
+/* #undef USE_EMULATIONS */
+
+/* Supported emulations. */
+#define EMULATIONS
+
+/* Default emulation. */
+#define DEFAULT_EMULATION ""
+
+/* old COFF support? */
+/* #undef MANY_SEGMENTS */
+
+/* Use BFD interface? */
+#define BFD_ASSEMBLER 1
+
+/* Target alias. */
+#define TARGET_ALIAS "alpha-obrien-freebsd5.0"
+
+/* Canonical target. */
+#define TARGET_CANONICAL "alpha-obrien-freebsd5.0"
+
+/* Target CPU. */
+#define TARGET_CPU "alpha"
+
+/* Target vendor. */
+#define TARGET_VENDOR "obrien"
+
+/* Target OS. */
+#define TARGET_OS "freebsd5.0"
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Compiling cross-assembler? */
+/* #undef CROSS_COMPILE */
+
+/* assert broken? */
+/* #undef BROKEN_ASSERT */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if malloc is not declared in system header files. */
+/* #undef NEED_DECLARATION_MALLOC */
+
+/* Define if free is not declared in system header files. */
+/* #undef NEED_DECLARATION_FREE */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Define if errno is not declared in system header files. */
+/* #undef NEED_DECLARATION_ERRNO */
+
diff --git a/gnu/usr.bin/binutils/as/alpha-freebsd/targ-cpu.h b/gnu/usr.bin/binutils/as/alpha-freebsd/targ-cpu.h
new file mode 100644
index 0000000..2738848
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/alpha-freebsd/targ-cpu.h
@@ -0,0 +1 @@
+#include "tc-alpha.h"
diff --git a/gnu/usr.bin/binutils/as/i386-freebsd/Makefile b/gnu/usr.bin/binutils/as/i386-freebsd/Makefile
new file mode 100644
index 0000000..1cfcb0c
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/i386-freebsd/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc0"
+
+NOMAN= true
+.if ${TARGET_ARCH} != "i386"
+BINDIR= /usr/libexec/cross/i386-freebsd
+.endif
+SRCS+= obj-elf.c tc-i386.c
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/as/i386-freebsd/config.h b/gnu/usr.bin/binutils/as/i386-freebsd/config.h
new file mode 100644
index 0000000..842af61
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/i386-freebsd/config.h
@@ -0,0 +1,279 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the remove function. */
+/* #undef HAVE_REMOVE */
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the unlink function. */
+#define HAVE_UNLINK 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Define if you have the <varargs.h> header file. */
+#define HAVE_VARARGS_H 1
+
+/* Name of package */
+#define PACKAGE "gas"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if defaulting to ELF on SCO 5. */
+/* #undef SCO_ELF */
+
+/* Using strict COFF? */
+/* #undef STRICTCOFF */
+
+/* Define if default target is PowerPC Solaris. */
+/* #undef TARGET_SOLARIS_COMMENT */
+
+/* Define as 1 if big endian. */
+/* #undef TARGET_BYTES_BIG_ENDIAN */
+
+/* Use ELF stabs for MIPS, not ECOFF stabs */
+/* #undef MIPS_STABS_ELF */
+
+/* Default architecture. */
+/* #define DEFAULT_ARCH "i386" */
+
+/* Using cgen code? */
+/* #undef USING_CGEN */
+
+/* Using i386 COFF? */
+/* #undef I386COFF */
+
+/* Using m68k COFF? */
+/* #undef M68KCOFF */
+
+/* Using m88k COFF? */
+/* #undef M88KCOFF */
+
+/* a.out support? */
+/* #undef OBJ_MAYBE_AOUT */
+
+/* b.out support? */
+/* #undef OBJ_MAYBE_BOUT */
+
+/* COFF support? */
+/* #undef OBJ_MAYBE_COFF */
+
+/* ECOFF support? */
+/* #undef OBJ_MAYBE_ECOFF */
+
+/* ELF support? */
+/* #undef OBJ_MAYBE_ELF */
+
+/* generic support? */
+/* #undef OBJ_MAYBE_GENERIC */
+
+/* HP300 support? */
+/* #undef OBJ_MAYBE_HP300 */
+
+/* IEEE support? */
+/* #undef OBJ_MAYBE_IEEE */
+
+/* SOM support? */
+/* #undef OBJ_MAYBE_SOM */
+
+/* VMS support? */
+/* #undef OBJ_MAYBE_VMS */
+
+/* Use emulation support? */
+/* #undef USE_EMULATIONS */
+
+/* Supported emulations. */
+#define EMULATIONS &i386elf,
+
+/* Default emulation. */
+#define DEFAULT_EMULATION "i386elf"
+
+/* old COFF support? */
+/* #undef MANY_SEGMENTS */
+
+/* Use BFD interface? */
+#define BFD_ASSEMBLER 1
+
+/* Target alias. */
+#define TARGET_ALIAS "i386-obrien-freebsd5.0"
+
+/* Canonical target. */
+#define TARGET_CANONICAL "i386-obrien-freebsd5.0"
+
+/* Target CPU. */
+#define TARGET_CPU "i386"
+
+/* Target vendor. */
+#define TARGET_VENDOR "obrien"
+
+/* Target OS. */
+#define TARGET_OS "freebsd5.0"
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Compiling cross-assembler? */
+/* #undef CROSS_COMPILE */
+
+/* assert broken? */
+/* #undef BROKEN_ASSERT */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if malloc is not declared in system header files. */
+/* #undef NEED_DECLARATION_MALLOC */
+
+/* Define if free is not declared in system header files. */
+/* #undef NEED_DECLARATION_FREE */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Define if errno is not declared in system header files. */
+/* #undef NEED_DECLARATION_ERRNO */
+
diff --git a/gnu/usr.bin/binutils/as/i386-freebsd/targ-cpu.h b/gnu/usr.bin/binutils/as/i386-freebsd/targ-cpu.h
new file mode 100644
index 0000000..f4be0e5
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/i386-freebsd/targ-cpu.h
@@ -0,0 +1 @@
+#include "tc-i386.h"
diff --git a/gnu/usr.bin/binutils/as/ia64-freebsd/Makefile b/gnu/usr.bin/binutils/as/ia64-freebsd/Makefile
new file mode 100644
index 0000000..59e147c
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/ia64-freebsd/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc0"
+
+.if ${TARGET_ARCH} != "ia64"
+NOMAN= true
+BINDIR= /usr/libexec/cross/ia64-freebsd
+.endif
+SRCS+= obj-elf.c tc-ia64.c
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/as/ia64-freebsd/config.h b/gnu/usr.bin/binutils/as/ia64-freebsd/config.h
new file mode 100644
index 0000000..078e8f8
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/ia64-freebsd/config.h
@@ -0,0 +1,279 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the remove function. */
+/* #undef HAVE_REMOVE */
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the unlink function. */
+#define HAVE_UNLINK 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Define if you have the <varargs.h> header file. */
+#define HAVE_VARARGS_H 1
+
+/* Name of package */
+#define PACKAGE "gas"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if defaulting to ELF on SCO 5. */
+/* #undef SCO_ELF */
+
+/* Using strict COFF? */
+/* #undef STRICTCOFF */
+
+/* Define if default target is PowerPC Solaris. */
+/* #undef TARGET_SOLARIS_COMMENT */
+
+/* Define as 1 if big endian. */
+/* #undef TARGET_BYTES_BIG_ENDIAN */
+
+/* Use ELF stabs for MIPS, not ECOFF stabs */
+/* #undef MIPS_STABS_ELF */
+
+/* Default architecture. */
+/* #undef DEFAULT_ARCH */
+
+/* Using cgen code? */
+/* #undef USING_CGEN */
+
+/* Using i386 COFF? */
+/* #undef I386COFF */
+
+/* Using m68k COFF? */
+/* #undef M68KCOFF */
+
+/* Using m88k COFF? */
+/* #undef M88KCOFF */
+
+/* a.out support? */
+/* #undef OBJ_MAYBE_AOUT */
+
+/* b.out support? */
+/* #undef OBJ_MAYBE_BOUT */
+
+/* COFF support? */
+/* #undef OBJ_MAYBE_COFF */
+
+/* ECOFF support? */
+/* #undef OBJ_MAYBE_ECOFF */
+
+/* ELF support? */
+/* #undef OBJ_MAYBE_ELF */
+
+/* generic support? */
+/* #undef OBJ_MAYBE_GENERIC */
+
+/* HP300 support? */
+/* #undef OBJ_MAYBE_HP300 */
+
+/* IEEE support? */
+/* #undef OBJ_MAYBE_IEEE */
+
+/* SOM support? */
+/* #undef OBJ_MAYBE_SOM */
+
+/* VMS support? */
+/* #undef OBJ_MAYBE_VMS */
+
+/* Use emulation support? */
+/* #undef USE_EMULATIONS */
+
+/* Supported emulations. */
+#define EMULATIONS
+
+/* Default emulation. */
+#define DEFAULT_EMULATION ""
+
+/* old COFF support? */
+/* #undef MANY_SEGMENTS */
+
+/* Use BFD interface? */
+#define BFD_ASSEMBLER 1
+
+/* Target alias. */
+#define TARGET_ALIAS "ia64-obrien-freebsd5.0"
+
+/* Canonical target. */
+#define TARGET_CANONICAL "ia64-obrien-freebsd5.0"
+
+/* Target CPU. */
+#define TARGET_CPU "ia64"
+
+/* Target vendor. */
+#define TARGET_VENDOR "obrien"
+
+/* Target OS. */
+#define TARGET_OS "freebsd5.0"
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Compiling cross-assembler? */
+/* #undef CROSS_COMPILE */
+
+/* assert broken? */
+/* #undef BROKEN_ASSERT */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if malloc is not declared in system header files. */
+/* #undef NEED_DECLARATION_MALLOC */
+
+/* Define if free is not declared in system header files. */
+/* #undef NEED_DECLARATION_FREE */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Define if errno is not declared in system header files. */
+/* #undef NEED_DECLARATION_ERRNO */
+
diff --git a/gnu/usr.bin/binutils/as/ia64-freebsd/targ-cpu.h b/gnu/usr.bin/binutils/as/ia64-freebsd/targ-cpu.h
new file mode 100644
index 0000000..a0a6360
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/ia64-freebsd/targ-cpu.h
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+
+#include "tc-ia64.h"
diff --git a/gnu/usr.bin/binutils/as/obj-format.h b/gnu/usr.bin/binutils/as/obj-format.h
new file mode 100644
index 0000000..02a3030
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/obj-format.h
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+
+#include "obj-elf.h"
diff --git a/gnu/usr.bin/binutils/as/powerpc-freebsd/Makefile b/gnu/usr.bin/binutils/as/powerpc-freebsd/Makefile
new file mode 100644
index 0000000..98ef3dd
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/powerpc-freebsd/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc0"
+
+.if ${TARGET_ARCH} != "powerpc"
+NOMAN= true
+BINDIR= /usr/libexec/cross/powerpc-freebsd
+# If we aren't doing cross-assembling, some operations can be optimized, since
+# byte orders and value sizes don't need to be adjusted.
+CFLAGS+= -DCROSS_COMPILE=1
+.endif
+SRCS+= obj-elf.c tc-ppc.c
+
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/as/powerpc-freebsd/config.h b/gnu/usr.bin/binutils/as/powerpc-freebsd/config.h
new file mode 100644
index 0000000..6333f48
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/powerpc-freebsd/config.h
@@ -0,0 +1,279 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the remove function. */
+/* #undef HAVE_REMOVE */
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the unlink function. */
+#define HAVE_UNLINK 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Define if you have the <varargs.h> header file. */
+#define HAVE_VARARGS_H 1
+
+/* Name of package */
+#define PACKAGE "gas"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if defaulting to ELF on SCO 5. */
+/* #undef SCO_ELF */
+
+/* Using strict COFF? */
+/* #undef STRICTCOFF */
+
+/* Define if default target is PowerPC Solaris. */
+/* #undef TARGET_SOLARIS_COMMENT */
+
+/* Define as 1 if big endian. */
+/* #undef TARGET_BYTES_BIG_ENDIAN */
+
+/* Use ELF stabs for MIPS, not ECOFF stabs */
+/* #undef MIPS_STABS_ELF */
+
+/* Default architecture. */
+/* #undef DEFAULT_ARCH */
+
+/* Using cgen code? */
+/* #undef USING_CGEN */
+
+/* Using i386 COFF? */
+/* #undef I386COFF */
+
+/* Using m68k COFF? */
+/* #undef M68KCOFF */
+
+/* Using m88k COFF? */
+/* #undef M88KCOFF */
+
+/* a.out support? */
+/* #undef OBJ_MAYBE_AOUT */
+
+/* b.out support? */
+/* #undef OBJ_MAYBE_BOUT */
+
+/* COFF support? */
+/* #undef OBJ_MAYBE_COFF */
+
+/* ECOFF support? */
+/* #undef OBJ_MAYBE_ECOFF */
+
+/* ELF support? */
+/* #undef OBJ_MAYBE_ELF */
+
+/* generic support? */
+/* #undef OBJ_MAYBE_GENERIC */
+
+/* HP300 support? */
+/* #undef OBJ_MAYBE_HP300 */
+
+/* IEEE support? */
+/* #undef OBJ_MAYBE_IEEE */
+
+/* SOM support? */
+/* #undef OBJ_MAYBE_SOM */
+
+/* VMS support? */
+/* #undef OBJ_MAYBE_VMS */
+
+/* Use emulation support? */
+/* #undef USE_EMULATIONS */
+
+/* Supported emulations. */
+#define EMULATIONS
+
+/* Default emulation. */
+#define DEFAULT_EMULATION ""
+
+/* old COFF support? */
+/* #undef MANY_SEGMENTS */
+
+/* Use BFD interface? */
+#define BFD_ASSEMBLER 1
+
+/* Target alias. */
+#define TARGET_ALIAS "powerpc-obrien-freebsd5.0"
+
+/* Canonical target. */
+#define TARGET_CANONICAL "powerpc-obrien-freebsd5.0"
+
+/* Target CPU. */
+#define TARGET_CPU "powerpc"
+
+/* Target vendor. */
+#define TARGET_VENDOR "obrien"
+
+/* Target OS. */
+#define TARGET_OS "freebsd5.0"
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Compiling cross-assembler? */
+/* #undef CROSS_COMPILE */
+
+/* assert broken? */
+/* #undef BROKEN_ASSERT */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if malloc is not declared in system header files. */
+/* #undef NEED_DECLARATION_MALLOC */
+
+/* Define if free is not declared in system header files. */
+/* #undef NEED_DECLARATION_FREE */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Define if errno is not declared in system header files. */
+/* #undef NEED_DECLARATION_ERRNO */
+
diff --git a/gnu/usr.bin/binutils/as/powerpc-freebsd/itbl-cpu.h b/gnu/usr.bin/binutils/as/powerpc-freebsd/itbl-cpu.h
new file mode 100644
index 0000000..b55da9a
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/powerpc-freebsd/itbl-cpu.h
@@ -0,0 +1,6 @@
+/* $FreeBSD$ */
+
+/* Values for processors will be from 0 to NUMBER_OF_PROCESSORS-1 */
+#define NUMBER_OF_PROCESSORS 1
+
+#include "itbl-ppc.h"
diff --git a/gnu/usr.bin/binutils/as/powerpc-freebsd/targ-cpu.h b/gnu/usr.bin/binutils/as/powerpc-freebsd/targ-cpu.h
new file mode 100644
index 0000000..891bd6c
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/powerpc-freebsd/targ-cpu.h
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+
+#include "tc-ppc.h"
diff --git a/gnu/usr.bin/binutils/as/sparc64-freebsd/Makefile b/gnu/usr.bin/binutils/as/sparc64-freebsd/Makefile
new file mode 100644
index 0000000..258808b
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/sparc64-freebsd/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc0"
+
+.if ${TARGET_ARCH} != "sparc64"
+NOMAN= true
+BINDIR= /usr/libexec/cross/sparc64-freebsd
+# If we aren't doing cross-assembling, some operations can be optimized, since
+# byte orders and value sizes don't need to be adjusted.
+CFLAGS+= -DCROSS_COMPILE=1
+.endif
+SRCS+= obj-elf.c tc-sparc.c
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/as/sparc64-freebsd/config.h b/gnu/usr.bin/binutils/as/sparc64-freebsd/config.h
new file mode 100644
index 0000000..e32566b
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/sparc64-freebsd/config.h
@@ -0,0 +1,279 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the remove function. */
+/* #undef HAVE_REMOVE */
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the unlink function. */
+#define HAVE_UNLINK 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Define if you have the <varargs.h> header file. */
+#define HAVE_VARARGS_H 1
+
+/* Name of package */
+#define PACKAGE "gas"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if defaulting to ELF on SCO 5. */
+/* #undef SCO_ELF */
+
+/* Using strict COFF? */
+/* #undef STRICTCOFF */
+
+/* Define if default target is PowerPC Solaris. */
+/* #undef TARGET_SOLARIS_COMMENT */
+
+/* Define as 1 if big endian. */
+/* #undef TARGET_BYTES_BIG_ENDIAN */
+
+/* Use ELF stabs for MIPS, not ECOFF stabs */
+/* #undef MIPS_STABS_ELF */
+
+/* Default architecture. */
+#define DEFAULT_ARCH "v9-64"
+
+/* Using cgen code? */
+/* #undef USING_CGEN */
+
+/* Using i386 COFF? */
+/* #undef I386COFF */
+
+/* Using m68k COFF? */
+/* #undef M68KCOFF */
+
+/* Using m88k COFF? */
+/* #undef M88KCOFF */
+
+/* a.out support? */
+/* #undef OBJ_MAYBE_AOUT */
+
+/* b.out support? */
+/* #undef OBJ_MAYBE_BOUT */
+
+/* COFF support? */
+/* #undef OBJ_MAYBE_COFF */
+
+/* ECOFF support? */
+/* #undef OBJ_MAYBE_ECOFF */
+
+/* ELF support? */
+/* #undef OBJ_MAYBE_ELF */
+
+/* generic support? */
+/* #undef OBJ_MAYBE_GENERIC */
+
+/* HP300 support? */
+/* #undef OBJ_MAYBE_HP300 */
+
+/* IEEE support? */
+/* #undef OBJ_MAYBE_IEEE */
+
+/* SOM support? */
+/* #undef OBJ_MAYBE_SOM */
+
+/* VMS support? */
+/* #undef OBJ_MAYBE_VMS */
+
+/* Use emulation support? */
+/* #undef USE_EMULATIONS */
+
+/* Supported emulations. */
+#define EMULATIONS
+
+/* Default emulation. */
+#define DEFAULT_EMULATION ""
+
+/* old COFF support? */
+/* #undef MANY_SEGMENTS */
+
+/* Use BFD interface? */
+#define BFD_ASSEMBLER 1
+
+/* Target alias. */
+#define TARGET_ALIAS "sparc64-obrien-freebsd5.0"
+
+/* Canonical target. */
+#define TARGET_CANONICAL "sparc64-obrien-freebsd5.0"
+
+/* Target CPU. */
+#define TARGET_CPU "sparc64"
+
+/* Target vendor. */
+#define TARGET_VENDOR "obrien"
+
+/* Target OS. */
+#define TARGET_OS "freebsd5.0"
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Compiling cross-assembler? */
+/* #undef CROSS_COMPILE */
+
+/* assert broken? */
+/* #undef BROKEN_ASSERT */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if malloc is not declared in system header files. */
+/* #undef NEED_DECLARATION_MALLOC */
+
+/* Define if free is not declared in system header files. */
+/* #undef NEED_DECLARATION_FREE */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Define if errno is not declared in system header files. */
+/* #undef NEED_DECLARATION_ERRNO */
+
diff --git a/gnu/usr.bin/binutils/as/sparc64-freebsd/targ-cpu.h b/gnu/usr.bin/binutils/as/sparc64-freebsd/targ-cpu.h
new file mode 100644
index 0000000..46e4313
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/sparc64-freebsd/targ-cpu.h
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+
+#include "tc-sparc.h"
diff --git a/gnu/usr.bin/binutils/as/targ-env.h b/gnu/usr.bin/binutils/as/targ-env.h
new file mode 100644
index 0000000..8e14d63
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/targ-env.h
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+
+#include "te-freebsd.h"
diff --git a/gnu/usr.bin/binutils/as/x86-64-freebsd/Makefile b/gnu/usr.bin/binutils/as/x86-64-freebsd/Makefile
new file mode 100644
index 0000000..c5d1846
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/x86-64-freebsd/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc0"
+
+NOMAN= true
+SRCS+= obj-elf.c tc-i386.c
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/as/x86-64-freebsd/config.h b/gnu/usr.bin/binutils/as/x86-64-freebsd/config.h
new file mode 100644
index 0000000..2eebc16
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/x86-64-freebsd/config.h
@@ -0,0 +1,282 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the remove function. */
+/* #undef HAVE_REMOVE */
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the unlink function. */
+#define HAVE_UNLINK 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Define if you have the <varargs.h> header file. */
+#define HAVE_VARARGS_H 1
+
+/* Name of package */
+#define PACKAGE "gas"
+
+/* Version number of package */
+/* #define VERSION "2.12.1" */
+
+/* Define if defaulting to ELF on SCO 5. */
+/* #undef SCO_ELF */
+
+/* Using strict COFF? */
+/* #undef STRICTCOFF */
+
+/* Define if default target is PowerPC Solaris. */
+/* #undef TARGET_SOLARIS_COMMENT */
+
+/* Define as 1 if big endian. */
+/* #undef TARGET_BYTES_BIG_ENDIAN */
+
+/* Use ELF stabs for MIPS, not ECOFF stabs */
+/* #undef MIPS_STABS_ELF */
+
+/* Default architecture. */
+#define DEFAULT_ARCH "x86_64"
+
+/* Using cgen code? */
+/* #undef USING_CGEN */
+
+/* Using i386 COFF? */
+/* #undef I386COFF */
+
+/* Using m68k COFF? */
+/* #undef M68KCOFF */
+
+/* Using m88k COFF? */
+/* #undef M88KCOFF */
+
+/* a.out support? */
+/* #undef OBJ_MAYBE_AOUT */
+
+/* b.out support? */
+/* #undef OBJ_MAYBE_BOUT */
+
+/* COFF support? */
+/* #undef OBJ_MAYBE_COFF */
+
+/* ECOFF support? */
+/* #undef OBJ_MAYBE_ECOFF */
+
+/* ELF support? */
+/* #undef OBJ_MAYBE_ELF */
+
+/* generic support? */
+/* #undef OBJ_MAYBE_GENERIC */
+
+/* HP300 support? */
+/* #undef OBJ_MAYBE_HP300 */
+
+/* IEEE support? */
+/* #undef OBJ_MAYBE_IEEE */
+
+/* SOM support? */
+/* #undef OBJ_MAYBE_SOM */
+
+/* VMS support? */
+/* #undef OBJ_MAYBE_VMS */
+
+/* Use emulation support? */
+/* #undef USE_EMULATIONS */
+
+/* Supported emulations. */
+#define EMULATIONS &i386elf,
+
+/* Default emulation. */
+#define DEFAULT_EMULATION "i386elf"
+
+/* old COFF support? */
+/* #undef MANY_SEGMENTS */
+
+/* Use BFD interface? */
+#define BFD_ASSEMBLER 1
+
+/* Target alias. */
+#define TARGET_ALIAS "x86_64-obrien-freebsd5"
+
+/* Canonical target. */
+#define TARGET_CANONICAL "x86_64-obrien-freebsd5"
+
+/* Target CPU. */
+#define TARGET_CPU "x86_64"
+
+/* Target vendor. */
+#define TARGET_VENDOR "obrien"
+
+/* Target OS. */
+#define TARGET_OS "freebsd5"
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Compiling cross-assembler? */
+/* #undef CROSS_COMPILE */
+
+/* assert broken? */
+/* #undef BROKEN_ASSERT */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if malloc is not declared in system header files. */
+/* #undef NEED_DECLARATION_MALLOC */
+
+/* Define if free is not declared in system header files. */
+/* #undef NEED_DECLARATION_FREE */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Define if errno is not declared in system header files. */
+/* #undef NEED_DECLARATION_ERRNO */
+
diff --git a/gnu/usr.bin/binutils/as/x86-64-freebsd/itbl-cpu.h b/gnu/usr.bin/binutils/as/x86-64-freebsd/itbl-cpu.h
new file mode 100644
index 0000000..a0fe73b
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/x86-64-freebsd/itbl-cpu.h
@@ -0,0 +1,3 @@
+/* $FreeBSD$ */
+
+#include "itbl-i386.h"
diff --git a/gnu/usr.bin/binutils/as/x86-64-freebsd/targ-cpu.h b/gnu/usr.bin/binutils/as/x86-64-freebsd/targ-cpu.h
new file mode 100644
index 0000000..34219a5
--- /dev/null
+++ b/gnu/usr.bin/binutils/as/x86-64-freebsd/targ-cpu.h
@@ -0,0 +1,3 @@
+/* $FreeBSD$*/
+
+#include "tc-i386.h"
diff --git a/gnu/usr.bin/binutils/doc/Makefile b/gnu/usr.bin/binutils/doc/Makefile
new file mode 100644
index 0000000..a03a46c
--- /dev/null
+++ b/gnu/usr.bin/binutils/doc/Makefile
@@ -0,0 +1,47 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+GDBDIR= ${.CURDIR}/../../../../contrib/gdb
+CONTRIBDIR= ${.CURDIR}/../../../../contrib
+
+.PATH: ${SRCDIR}/gas/doc ${SRCDIR}/ld ${SRCDIR}/bfd/doc ${GDBDIR}/gdb/doc
+
+INFO = as ld annotate gasp gdbint stabs binutils
+INFOSECTION= "Programming & development tools."
+INFOENTRY_as= "* As: (as). The GNU assembler."
+INFOENTRY_gasp= "* Gasp: (gasp). The GNU Assembler Macro Preprocessor."
+INFOENTRY_ld= "* Ld: (ld). The GNU linker."
+INFOENTRY_annotate= "* GDB annotation: (annotate). Annotations for the GNU Debugger (GDB)."
+INFOENTRY_binutils= "* Binutils: (binutils). The GNU Binary Utilities."
+
+MAKEINFOFLAGS+= --no-validate
+MAKEINFOFLAGS+= -I ${SRCDIR}/gas/doc -I ${SRCDIR}/ld -I ${SRCDIR}/bfd/doc
+MAKEINFOFLAGS+= -I ${SRCDIR}/binutils
+MAKEINFOFLAGS+= -I ${GDBDIR}/gdb/doc
+MAKEINFOFLAGS+= -I ${CONTRIBDIR}/libreadline/doc
+
+CLEANFILES= gdb-cfg.texi inc-hist.texi inc-hist.texi.orig \
+ gasver.texi ldver.texi
+
+as.info: as.texinfo asconfig.texi c-i386.texi gasver.texi
+ld.info: ld.texinfo bfdsumm.texi ldver.texi
+
+gdb.info: gdb.texinfo gdb-cfg.texi GDBvn.texi remote.texi \
+ rluser.texinfo inc-hist.texi
+
+gdb-cfg.texi: all-cfg.texi
+ ln -sf ${.ALLSRC} ${.TARGET}
+
+.PATH: ${SRCDIR}/binutils
+binutils.info: binutils.texi config.texi
+
+gasver.texi ldver.texi:
+ echo "@set VERSION ${VERSION}" > ${.TARGET}
+
+.PATH: ${CONTRIBDIR}/libreadline/doc
+inc-hist.texi: hsuser.texinfo inc-hist.diff
+ cp ${.ALLSRC:M*.texinfo} ${.TARGET}
+ patch -b .orig < ${.ALLSRC:M*.diff}
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/binutils/doc/asconfig.texi b/gnu/usr.bin/binutils/doc/asconfig.texi
new file mode 100644
index 0000000..2a7b652
--- /dev/null
+++ b/gnu/usr.bin/binutils/doc/asconfig.texi
@@ -0,0 +1,70 @@
+@c Copyright 1992, 1993 Free Software Foundation, Inc.
+@c This file is part of the documentation for the GAS manual
+
+@c Configuration settings for all-inclusive version of manual
+
+@c switches:------------------------------------------------------------
+@c Properties of the manual
+@c ========================
+@c Discuss all architectures?
+@clear ALL-ARCH
+@c A generic form of manual (not tailored to specific target)?
+@clear GENERIC
+@c Include text on assembler internals?
+@set INTERNALS
+@c Many object formats supported in this config?
+@clear MULTI-OBJ
+
+@c Object formats of interest
+@c ==========================
+@clear AOUT
+@clear BOUT
+@clear COFF
+@set ELF
+@clear SOM
+
+@c CPUs of interest
+@c ================
+@clear A29K
+@clear ARC
+@clear ARM
+@clear D10V
+@clear H8/300
+@clear H8/500
+@clear SH
+@set I80386
+@clear I960
+@clear MIPS
+@clear M32R
+@clear M680X0
+@clear Z8000
+@clear SPARC
+@clear VAX
+@clear VXWORKS
+@clear HPPA
+@clear V850
+
+@c Does this version of the assembler use the difference-table kluge?
+@clear DIFF-TBL-KLUGE
+
+@c Do all machines described use IEEE floating point?
+@set IEEEFLOAT
+
+@c Is a word 32 bits, or 16?
+@set W32
+@clear W16
+
+@c Do symbols have different characters than usual?
+@clear SPECIAL-SYMS
+
+@c strings:------------------------------------------------------------
+@c Name of the assembler:
+@set AS as
+@c Name of C compiler:
+@set GCC gcc
+@c Name of linker:
+@set LD ld
+@c Text for target machine (best not used in generic case; but just in case...)
+@set TARGET i386
+@c Name of object format (NOT SET in generic version)
+@set OBJ-NAME ELF
diff --git a/gnu/usr.bin/binutils/doc/inc-hist.diff b/gnu/usr.bin/binutils/doc/inc-hist.diff
new file mode 100644
index 0000000..721db26
--- /dev/null
+++ b/gnu/usr.bin/binutils/doc/inc-hist.diff
@@ -0,0 +1,31 @@
+$FreeBSD$
+
+--- inc-hist.texi.orig Wed Apr 11 08:20:01 2001
++++ inc-hist.texi Wed Apr 11 08:21:57 2001
+@@ -26,9 +26,9 @@
+ @node Using History Interactively
+ @chapter Using History Interactively
+
+-@ifclear BashFeatures
+-@defcodeindex bt
+-@end ifclear
++@c @ifclear BashFeatures
++@c @defcodeindex bt
++@c @end ifclear
+
+ @ifset BashFeatures
+ This chapter describes how to use the @sc{gnu} History Library
+@@ -39,9 +39,10 @@
+ @end ifset
+ @ifclear BashFeatures
+ This chapter describes how to use the @sc{gnu} History Library interactively,
+-from a user's standpoint. It should be considered a user's guide. For
+-information on using the @sc{gnu} History Library in your own programs,
+-@pxref{Programming with GNU History}.
++from a user's standpoint.
++@c It should be considered a user's guide. For
++@c information on using the @sc{gnu} History Library in your own programs,
++@c @pxref{Programming with GNU History}.
+ @end ifclear
+
+ @ifset BashFeatures
diff --git a/gnu/usr.bin/binutils/gasp/Makefile b/gnu/usr.bin/binutils/gasp/Makefile
new file mode 100644
index 0000000..aad9355
--- /dev/null
+++ b/gnu/usr.bin/binutils/gasp/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/gas
+
+PROG= gasp
+SRCS+= gasp.c macro.c sb.c hash.c
+WARNS= 2
+CFLAGS+= -DBFD_ASSEMBLER
+CFLAGS+= -I${SRCDIR} -I${SRCDIR}/gas -I${SRCDIR}/gas/config
+CFLAGS+= -I${.CURDIR}/../as/${TARGET_ARCH}-freebsd -I${.CURDIR}/../as
+DPADD= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/gasp/gasp.1 b/gnu/usr.bin/binutils/gasp/gasp.1
new file mode 100644
index 0000000..39428f1
--- /dev/null
+++ b/gnu/usr.bin/binutils/gasp/gasp.1
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1999
+.\" The Regents of the University of California. All rights reserved.
+.\" and David E. O'Brien
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 29, 1999
+.Dt GASP 1
+.Os
+.Sh NAME
+.Nm gasp
+.Nd the GNU Assembler Macro Preprocessor
+.Sh SYNOPSIS
+.Nm
+.Op Fl adhMpsuv
+.Op Fl c Ar char
+.Op Fl o Ar outfile
+.Op Fl D Ns Ar name=value
+.Op Fl I Ns Ar path
+.Op infile
+.Sh DESCRIPTION
+.Nm
+is the GNU Assembler Macro Preprocessor.
+The argument
+.Ar infile
+is processed and the resulting text is sent to the standard output.
+.Pp
+The options are as follows:
+.Bl -tag -width "-Dname=value"
+.It Fl a
+Enter enter alternate macro mode.
+Also specifiable as
+.Op Fl \-alternate
+.It Fl c Ar char
+Change the comment character from `!'
+Also specifiable as
+.Op Fl \-commentchar\ char
+.It Fl d
+Print limited debugging information.
+Also specifiable as
+.Op Fl \-debug
+.It Fl h
+Print the help message.
+Also specifiable as
+.Op Fl \-help
+.It Fl M
+Enter MRI compatibility mode
+Also specifiable as
+.Op Fl \-mri
+.It Fl o Ar outfile
+Specify the output file.
+Also specifiable as
+.Op Fl \-output\ outfile
+.It Fl p
+Print line numbers.
+Also specifiable as
+.Op Fl \-print
+.It Fl s
+Copy source through as comments.
+Also specifiable as
+.Op Fl \-copysource
+.It Fl u
+Allow unreasonable nesting.
+Also specifiable as
+.Op Fl \-unreasonable
+.It Fl v
+Print the program version and exit.
+Also specifiable as
+.Op Fl \-version
+.It Fl D Ns Ar name=value
+Define the preprocessor symbol
+.Ar name
+to have the value specified by "value".
+.It Fl I Ns Ar path
+Add
+.Ar path
+to the include path list.
+.El
+.Sh SEE ALSO
+.Xr cpp 1 ,
+.Xr m4 1
+.Rs
+.%T The gasp GNU hypertext system info pages
+.Re
+.Sh HISTORY
+The
+.Nm
+command is part of the GNU Binutils package.
+.Sh AUTHORS
+This man page was written by
+.An David E. O'Brien .
diff --git a/gnu/usr.bin/binutils/gdb/Makefile b/gnu/usr.bin/binutils/gdb/Makefile
new file mode 100644
index 0000000..291a0a18
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/Makefile
@@ -0,0 +1,112 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils
+
+NOSHARED?=yes
+PROG= gdb
+XSRCS= annotate.c 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 copying.c core-regset.c \
+ corefile.c corelow.c cp-valprint.c dcache.c dbxread.c \
+ demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \
+ exec.c expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
+ findvar%UAfix.c fork-child.c freebsd-uthread.c gdbarch.c gdbtypes.c \
+ infcmd.c inflow.c infptrace.c infrun.c inftarg.c language.c \
+ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c nlmread.c \
+ m2-lang.c m2-exp.y m2-typeprint.c m2-valprint.c main.c maint.c \
+ mdebugread.c mem-break.c minsyms.c objfiles.c parse.c \
+ printcmd.c remote.c remote-utils.c scm-exp.c scm-lang.c \
+ scm-valprint.c solib.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 \
+ version.c serial.c ser-unix.c ser-tcp.c
+SRCS= init.c ${XSRCS}
+SRCS+= wait.h
+
+.if exists(${.CURDIR}/Makefile.${TARGET_ARCH})
+.include "${.CURDIR}/Makefile.${TARGET_ARCH}"
+.endif
+
+WARNS= 0
+.if ${TARGET_ARCH} != ${MACHINE_ARCH}
+CFLAGS+= -DCROSS_COMPILE=1
+.endif
+CFLAGS+= -I${.CURDIR}/${TARGET_ARCH}
+CFLAGS+= -I${SRCDIR}/binutils
+CFLAGS+= -I${SRCDIR}/bfd
+CFLAGS+= -I${GDBDIR}/gdb
+CFLAGS+= -I${GDBDIR}/gdb/config
+DPADD= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libopcodes/libopcodes.a
+DPADD+= ${LIBGNUREGEX}
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+DPADD+= ${LIBREADLINE}
+DPADD+= ${LIBTERMCAP}
+LDADD+= ${RELTOP}/libbfd/libbfd.a
+LDADD+= ${RELTOP}/libopcodes/libopcodes.a
+LDADD+= -lgnuregex
+LDADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD+= -lreadline
+LDADD+= -ltermcap
+
+GDBDIR= ${.CURDIR}/../../../../contrib/gdb
+.PATH: ${GDBDIR}/gdb
+.PATH: ${SRCDIR}/opcodes
+
+CFLAGS+= -DFREEBSD_ELF
+
+CFLAGS+= -I$(.CURDIR) -I${DESTDIR}/usr/include/readline
+YFLAGS=
+
+CLEANFILES= init.c init.c-tmp wait.h
+CLEANFILES+= findvar%UAfix.c
+
+# 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: ${XSRCS}
+ @${ECHO} Making ${.TARGET}
+ @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 'void initialize_all_files () {' >>init.c-tmp
+ @for i in ${.ALLSRC} ; do \
+ filename=`echo $$i | sed \
+ -e '/^Onindy.c/d' \
+ -e '/^nindy.c/d' \
+ -e '/ttyflush.c/d' \
+ -e '/xdr_ld.c/d' \
+ -e '/xdr_ptrace.c/d' \
+ -e '/xdr_rdb.c/d' \
+ -e '/udr.c/d' \
+ -e '/udip2soc.c/d' \
+ -e '/udi2go32.c/d' \
+ -e '/version.c/d' \
+ -e '/^[a-z0-9A-Z_]*_[SU].c/d' \
+ -e '/[a-z0-9A-Z_]*-exp.tab.c/d'` ; \
+ case $$filename in \
+ "") ;; \
+ *) sed <$$filename >>init.c-tmp -n \
+ -e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (); \1 ();}/p' ; ;; \
+ esac ; \
+ done
+ @echo '}' >>init.c-tmp
+ @mv init.c-tmp ${.TARGET}
+
+.PRECIOUS: init.c
+
+wait.h:
+ ln -sf ${.CURDIR}/../../../../sys/sys/wait.h ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/gdb/Makefile.alpha b/gnu/usr.bin/binutils/gdb/Makefile.alpha
new file mode 100644
index 0000000..73f77af
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/Makefile.alpha
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/alpha
+
+.if ${TARGET_ARCH} == ${MACHINE_ARCH}
+XSRCS+= freebsd-nat.c
+.else
+XSRCS+= freebsd-nat-stubs.c
+.endif
+XSRCS+= alpha-tdep.c kvm-fbsd.c
+LDADD+= -lkvm
+
+findvar%UAfix.c: findvar.c
+ sed -e \
+ 's,char registers[REGISTER_BYTES + /* SLOP */ 256];,char registers[REGISTER_BYTES + /* SLOP */ 256] __attribute__ ((aligned (8)));,g' \
+ ${.ALLSRC} >${.TARGET}
diff --git a/gnu/usr.bin/binutils/gdb/Makefile.i386 b/gnu/usr.bin/binutils/gdb/Makefile.i386
new file mode 100644
index 0000000..d78cf9b
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/Makefile.i386
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/i386
+
+XSRCS+= freebsd-nat.c i386-tdep.c i387-tdep.c kvm-fbsd.c
+
+CFLAGS+= -Dprint_insn_i386=print_insn_i386_att
+
+findvar%UAfix.c: findvar.c
+ ln -sf ${.ALLSRC} ${.TARGET}
diff --git a/gnu/usr.bin/binutils/gdb/alpha/freebsd-nat-stubs.c b/gnu/usr.bin/binutils/gdb/alpha/freebsd-nat-stubs.c
new file mode 100644
index 0000000..08183d8
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/alpha/freebsd-nat-stubs.c
@@ -0,0 +1,55 @@
+/* $FreeBSD$ */
+
+#include "defs.h"
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 8
+
+#define JB_PC 2
+
+int kernel_debugging = 0;
+
+fetch_kcore_registers (pcbp)
+ struct pcb *pcbp;
+{
+ return;
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ return;
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ return;
+}
+
+/* From gdb/alpha-nat.c. */
+
+/* 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;
+}
diff --git a/gnu/usr.bin/binutils/gdb/alpha/freebsd-nat.c b/gnu/usr.bin/binutils/gdb/alpha/freebsd-nat.c
new file mode 100644
index 0000000..515d244
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/alpha/freebsd-nat.c
@@ -0,0 +1,174 @@
+/* $FreeBSD$ */
+/* Native-dependent code for BSD Unix running on alphas'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"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <string.h>
+#include "gdbcore.h"
+#include "value.h"
+#include "inferior.h"
+
+#if defined(HAVE_GREGSET_T)
+#include <sys/procfs.h>
+#endif
+
+int kernel_debugging = 0;
+
+/* 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;
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+
+ for (r = 0; r < 31; r++)
+ memcpy (&registers[REGISTER_BYTE (r)],
+ &regs.r_regs[r], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&registers[REGISTER_BYTE (r + FP0_REGNUM)],
+ &fpregs.fpr_regs[r], sizeof(u_int64_t));
+ memcpy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &regs.r_regs[31], sizeof(u_int64_t));
+
+ memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, sizeof(u_int64_t));
+ memset (&registers[REGISTER_BYTE (FP_REGNUM)], 0, sizeof(u_int64_t));
+
+ registers_fetched ();
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ for (r = 0; r < 31; r++)
+ memcpy (&regs.r_regs[r],
+ &registers[REGISTER_BYTE (r)], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&fpregs.fpr_regs[r],
+ &registers[REGISTER_BYTE (r + FP0_REGNUM)], sizeof(u_int64_t));
+ memcpy (&regs.r_regs[31],
+ &registers[REGISTER_BYTE (PC_REGNUM)], sizeof(u_int64_t));
+
+ ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+}
+
+#ifdef HAVE_GREGSET_T
+void
+supply_gregset (gp)
+ gregset_t *gp;
+{
+ int regno = 0;
+
+ /* These must be ordered the same as REGISTER_NAMES in
+ config/alpha/tm-alpha.h. */
+ for (regno = 0; regno < 31; regno++)
+ supply_register (regno, (char *)&gp->r_regs[regno]);
+ supply_register (PC_REGNUM, (char *)&gp->r_regs[regno]);
+}
+#endif /* HAVE_GREGSET_T */
+
+#ifdef HAVE_FPREGSET_T
+void
+supply_fpregset (fp)
+ fpregset_t *fp;
+{
+ int regno = 0;
+
+ for (regno = 0; regno < 32; regno++)
+ supply_register (regno + 32, (char *)&fp->fpr_regs[regno]);
+}
+#endif /* HAVE_FPREGSET_T */
+
+/*
+ * Get registers from a kernel crash dump or live kernel.
+ * Called by kvm-fbsd.c:get_kcore_registers().
+ */
+fetch_kcore_registers (pcbp)
+ struct pcb *pcbp;
+{
+
+ /* First clear out any garbage. */
+ memset(registers, '\0', REGISTER_BYTES);
+
+ /* SP */
+ *(long *) &registers[REGISTER_BYTE (SP_REGNUM)] =
+ pcbp->pcb_hw.apcb_ksp;
+
+ /* S0 through S6 */
+ memcpy (&registers[REGISTER_BYTE (S0_REGNUM)],
+ &pcbp->pcb_context[0], 7 * sizeof(long));
+
+ /* PC */
+ *(long *) &registers[REGISTER_BYTE (PC_REGNUM)] =
+ pcbp->pcb_context[7];
+
+ registers_fetched ();
+}
+
diff --git a/gnu/usr.bin/binutils/gdb/alpha/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb/alpha/kvm-fbsd.c
new file mode 100644
index 0000000..23a016e
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/alpha/kvm-fbsd.c
@@ -0,0 +1,451 @@
+/* Kernel core dump functions below target vector, for GDB.
+ Copyright 1986, 1987, 1989, 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.
+*/
+
+/* $FreeBSD$ */
+
+/*
+ * This works like "remote" but, you use it like this:
+ * target kcore /dev/mem
+ * or
+ * target kcore /var/crash/host/core.0
+ *
+ * This way makes it easy to short-circut the whole bfd monster,
+ * and direct the inferior stuff to our libkvm implementation.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <paths.h>
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+
+static void
+kcore_files_info PARAMS ((struct target_ops *));
+
+static void
+kcore_close PARAMS ((int));
+
+static void
+get_kcore_registers PARAMS ((int));
+
+static int
+xfer_mem PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static int
+xfer_umem PARAMS ((CORE_ADDR, char *, int, int));
+
+static char *core_file;
+static kvm_t *core_kd;
+static struct pcb cur_pcb;
+
+static struct target_ops kcore_ops;
+int kernel_writablecore;
+
+/*
+ * Read the "thing" at kernel address 'addr' into the space pointed to
+ * by point. The length of the "thing" is determined by the type of p.
+ * Result is non-zero if transfer fails.
+ */
+#define kvread(addr, p) \
+(target_read_memory((CORE_ADDR)(addr), (char *)(p), sizeof(*(p))))
+
+
+CORE_ADDR
+ksym_lookup(name)
+ const char *name;
+{
+ struct minimal_symbol *sym;
+
+ sym = lookup_minimal_symbol(name, NULL, NULL);
+ if (sym == NULL)
+ error("kernel symbol `%s' not found.", name);
+
+ return SYMBOL_VALUE_ADDRESS(sym);
+}
+
+/*
+ * Provide the address of an initial PCB to use.
+ * If this is a crash dump, try for "dumppcb".
+ * If no "dumppcb" or it's /dev/mem, use proc0.
+ * Return the core address of the PCB we found.
+ */
+static CORE_ADDR
+initial_pcb()
+{
+ struct minimal_symbol *sym;
+ CORE_ADDR addr;
+ void *val;
+
+ /* Make sure things are open... */
+ if (!core_kd || !core_file)
+ return (0);
+
+ /* If this is NOT /dev/mem try for dumppcb. */
+ if (strncmp(core_file, _PATH_DEV, sizeof _PATH_DEV - 1)) {
+ sym = lookup_minimal_symbol("dumppcb", NULL, NULL);
+ if (sym != NULL) {
+ addr = SYMBOL_VALUE_ADDRESS(sym);
+ return (addr);
+ }
+ }
+
+ /*
+ * OK, just use proc0pcb. Note that curproc might
+ * not exist, and if it does, it will point to gdb.
+ * Therefore, just use proc0 and let the user set
+ * some other context if they care about it.
+ */
+ addr = ksym_lookup("thread0");
+ if (kvread(addr, &val)) {
+ error("cannot read thread0 pointer at %x\n", addr);
+ val = 0;
+ } else {
+ /* Read the PCB address in proc structure. */
+ addr = (CORE_ADDR)val + offsetof(struct thread, td_pcb);
+ if (kvread(addr, &val)) {
+ error("cannot read thread0->td_pcb pointer at %x\n", addr);
+ val = 0;
+ }
+ }
+
+ return ((CORE_ADDR)val);
+}
+
+/*
+ * Set the current context to that of the PCB struct
+ * at the system address passed.
+ */
+static int
+set_context(addr)
+ CORE_ADDR addr;
+{
+
+ if (kvread(addr, &cur_pcb))
+ error("cannot read pcb at %#x", addr);
+
+ /* Fetch all registers from core file */
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ return (0);
+}
+
+/* Discard all vestiges of any previous core file and mark data and stack
+ spaces as empty. */
+
+/* ARGSUSED */
+static void
+kcore_close (quitting)
+ int quitting;
+{
+
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ if (core_kd) {
+ kvm_close(core_kd);
+ free(core_file);
+ core_file = NULL;
+ core_kd = NULL;
+ }
+}
+
+/* This routine opens and sets up the core file bfd. */
+
+static void
+kcore_open (filename, from_tty)
+ char *filename; /* the core file */
+ int from_tty;
+{
+ kvm_t *kd;
+ const char *p;
+ struct cleanup *old_chain;
+ char buf[256], *cp;
+ int ontop;
+ CORE_ADDR addr;
+
+ target_preopen (from_tty);
+
+ /* The exec file is required for symbols. */
+ if (exec_bfd == NULL)
+ error("No kernel exec file specified");
+
+ if (core_kd) {
+ error ("No core file specified."
+ " (Use `detach' to stop debugging a core file.)");
+ return;
+ }
+
+ if (!filename) {
+ error ("No core file specified.");
+ return;
+ }
+
+ filename = tilde_expand (filename);
+ if (filename[0] != '/') {
+ cp = concat (current_directory, "/", filename, NULL);
+ free (filename);
+ filename = cp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ kd = kvm_open (bfd_get_filename(exec_bfd), filename, NULL,
+ kernel_writablecore ? O_RDWR: O_RDONLY, 0);
+ if (kd == NULL) {
+ perror_with_name (filename);
+ return;
+ }
+
+ /* Looks semi-reasonable. Toss the old core file and work on the new. */
+
+ discard_cleanups (old_chain); /* Don't free filename any more */
+ core_file = filename;
+ unpush_target (&kcore_ops);
+ ontop = !push_target (&kcore_ops);
+
+ /* Note unpush_target (above) calls kcore_close. */
+ core_kd = kd;
+
+ /* print out the panic string if there is one */
+ if (kvread(ksym_lookup("panicstr"), &addr) == 0 &&
+ addr != 0 &&
+ target_read_memory(addr, buf, sizeof(buf)) == 0) {
+
+ for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
+ if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+ *cp = '?';
+ *cp = '\0';
+ if (buf[0] != '\0')
+ printf_filtered("panic: %s\n", buf);
+ }
+
+ if (!ontop) {
+ warning (
+"you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''", target_longname);
+ return;
+ }
+
+ /* Now, set up process context, and print the top of stack */
+ (void)set_context(initial_pcb());
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+kcore_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Too many arguments");
+ unpush_target (&kcore_ops);
+ reinit_frame_cache ();
+ if (from_tty)
+ printf_filtered ("No kernel 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_kcore_registers (regno)
+ int regno;
+{
+
+ /*
+ * XXX - Only read the pcb when set_context() is called.
+ * When looking at a live kernel this may be a problem,
+ * but the user can do another "proc" or "pcb" command to
+ * grab a new copy of the pcb...
+ */
+
+ /*
+ * Zero out register set then fill in the ones we know about.
+ */
+ fetch_kcore_registers (&cur_pcb);
+}
+
+static void
+kcore_files_info (t)
+ struct target_ops *t;
+{
+ printf_filtered ("\t`%s'\n", core_file);
+}
+
+/* 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;
+}
+
+static int
+xfer_kmem (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ int n;
+
+#if 0 /* XXX */
+ if (it is a user address)
+ return xfer_umem(memaddr, myaddr, len, write);
+#endif
+
+ if (core_kd == NULL)
+ return 0;
+
+ if (write)
+ n = kvm_write(core_kd, memaddr, myaddr, len);
+ else
+ n = kvm_read (core_kd, memaddr, myaddr, len) ;
+ if (n < 0) {
+ fprintf_unfiltered (gdb_stderr, "can not access 0x%x, %s\n",
+ memaddr, kvm_geterr(core_kd));
+ n = 0;
+ }
+
+ return n;
+}
+
+#if 0 /* XXX */
+static int
+xfer_umem (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write; /* ignored */
+{
+ int n;
+ struct proc proc;
+
+ if (kvread(cur_proc, &proc))
+ error("cannot read proc at %#x", cur_proc);
+ n = kvm_uread(core_kd, &proc, memaddr, myaddr, len) ;
+
+ if (n < 0)
+ return 0;
+ return n;
+}
+#endif
+
+static void
+set_proc_cmd(arg)
+ char *arg;
+{
+ CORE_ADDR addr, first_td;
+ void *val;
+
+ if (!arg)
+ error_no_arg("proc address for the new context");
+
+ if (core_kd == NULL)
+ error("no kernel core file");
+
+ addr = (CORE_ADDR)parse_and_eval_address(arg);
+
+ /* Find the first thread in the process XXXKSE */
+ addr += offsetof(struct proc, p_threads.tqh_first);
+ if (kvread(addr, &first_td))
+ error("cannot read thread ptr");
+
+ /* Read the PCB address in thread structure. */
+ addr = first_td + offsetof(struct thread, td_pcb);
+ if (kvread(addr, &val))
+ error("cannot read pcb ptr");
+
+ /* Read the PCB address in proc structure. */
+ if (set_context((CORE_ADDR)val))
+ error("invalid proc address");
+}
+
+static void
+set_pcb_cmd(arg)
+ char *arg;
+{
+ CORE_ADDR addr;
+ void *val;
+
+ if (!arg)
+ error_no_arg("pcb address for the new context");
+
+ if (core_kd == NULL)
+ error("no kernel core file");
+
+ addr = (CORE_ADDR)parse_and_eval_address(arg);
+
+ if (set_context(addr))
+ error("invalid pcb address");
+}
+
+
+
+void
+_initialize_kcorelow()
+{
+ kcore_ops.to_shortname = "kcore";
+ kcore_ops.to_longname = "Kernel core dump file";
+ kcore_ops.to_doc =
+ "Use a core file as a target. Specify the filename of the core file.";
+ kcore_ops.to_open = kcore_open;
+ kcore_ops.to_close = kcore_close;
+ kcore_ops.to_attach = find_default_attach;
+ kcore_ops.to_detach = kcore_detach;
+ kcore_ops.to_fetch_registers = get_kcore_registers;
+ kcore_ops.to_xfer_memory = xfer_kmem;
+ kcore_ops.to_files_info = kcore_files_info;
+ kcore_ops.to_create_inferior = find_default_create_inferior;
+ kcore_ops.to_stratum = kcore_stratum;
+ kcore_ops.to_has_memory = 1;
+ kcore_ops.to_has_stack = 1;
+ kcore_ops.to_has_registers = 1;
+ kcore_ops.to_magic = OPS_MAGIC;
+
+ add_target (&kcore_ops);
+ add_com ("proc", class_obscure, set_proc_cmd, "Set current process context");
+}
diff --git a/gnu/usr.bin/binutils/gdb/alpha/nm.h b/gnu/usr.bin/binutils/gdb/alpha/nm.h
new file mode 100644
index 0000000..1b63ef2
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/alpha/nm.h
@@ -0,0 +1,97 @@
+/* Native definitions for alpha running FreeBSD.
+ 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 */
+
+/* $FreeBSD$ */
+
+#include <sys/types.h>
+
+#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
+
+/* We define our own fetch/store methods */
+#define FETCH_INFERIOR_REGISTERS
+
+extern CORE_ADDR alpha_u_regs_offset();
+#define U_REGS_OFFSET alpha_u_regs_offset()
+
+#define PTRACE_ARG3_TYPE caddr_t
+
+/* ptrace transfers longs, the ptrace man page is lying. */
+
+#define PTRACE_XFER_TYPE int
+
+/* 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"
+#include "elf/common.h"
+
+#define SVR4_SHARED_LIBS
+#define TARGET_ELF64
+
+/* 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))
+
+extern int kernel_debugging;
+extern int kernel_writablecore;
+
+#define ADDITIONAL_OPTIONS \
+ {"kernel", no_argument, &kernel_debugging, 1}, \
+ {"k", no_argument, &kernel_debugging, 1}, \
+ {"wcore", no_argument, &kernel_writablecore, 1}, \
+ {"w", no_argument, &kernel_writablecore, 1},
+
+#define ADDITIONAL_OPTION_HELP \
+ "\
+ --kernel Enable kernel debugging.\n\
+ --wcore Make core file writable (only works for /dev/mem).\n\
+ This option only works while debugging a kernel !!\n\
+"
+
+#define DEFAULT_PROMPT kernel_debugging?"(kgdb) ":"(gdb) "
+
+/* misuse START_PROGRESS to test whether we're running as kgdb */
+/* START_PROGRESS is called at the top of main */
+#undef START_PROGRESS
+#define START_PROGRESS(STR,N) \
+ if (!strcmp(STR, "kgdb")) \
+ kernel_debugging = 1;
+
diff --git a/gnu/usr.bin/binutils/gdb/alpha/tm.h b/gnu/usr.bin/binutils/gdb/alpha/tm.h
new file mode 100644
index 0000000..4836b1d
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/alpha/tm.h
@@ -0,0 +1,48 @@
+/* $FreeBSD$ */
+/* Definitions to make GDB run on an Alpha box under FreeBSD. 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_FREEBSDALPHA_H
+#define TM_FREEBSDALPHA_H
+
+#include "alpha/tm-alpha.h"
+#ifndef S0_REGNUM
+#define S0_REGNUM (T7_REGNUM+1)
+#endif
+
+#ifndef VM_MIN_ADDRESS
+#define VM_MIN_ADDRESS (0)
+#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 FreeBSD and most implementations. */
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+struct objfile;
+void freebsd_uthread_new_objfile PARAMS ((struct objfile *objfile));
+#define target_new_objfile(OBJFILE) freebsd_uthread_new_objfile (OBJFILE)
+
+extern char *freebsd_uthread_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) freebsd_uthread_pid_to_str (PID)
+
+#endif /* TM_FREEBSDALPHA_H */
diff --git a/gnu/usr.bin/binutils/gdb/alpha/version.c b/gnu/usr.bin/binutils/gdb/alpha/version.c
new file mode 100644
index 0000000..e239829
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/alpha/version.c
@@ -0,0 +1,4 @@
+/* $FreeBSD$ */
+char *version = "4.18 (FreeBSD)";
+char *host_name = "alpha-unknown-freebsd";
+char *target_name = "alpha-unknown-freebsd";
diff --git a/gnu/usr.bin/binutils/gdb/alpha/xm.h b/gnu/usr.bin/binutils/gdb/alpha/xm.h
new file mode 100644
index 0000000..9d340a3
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/alpha/xm.h
@@ -0,0 +1,30 @@
+/* Host definitions for GDB running on an Alpha under FreeBSD
+ 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
+
+#include <limits.h>
diff --git a/gnu/usr.bin/binutils/gdb/config.h b/gnu/usr.bin/binutils/gdb/config.h
new file mode 100644
index 0000000..24d4fd6
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/config.h
@@ -0,0 +1,330 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* 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. */
+#define HAVE_ALLOCA 1
+
+/* 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. */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* 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). */
+#define RETSIGTYPE void
+
+/* 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. */
+#define STDC_HEADERS 1
+
+/* 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. */
+#define CC_HAS_LONG_LONG 1
+
+/* Define if the "ll" format works to print long long ints. */
+#define PRINTF_HAS_LONG_LONG 1
+
+/* Define if the "%Lg" format works to print long doubles. */
+#define PRINTF_HAS_LONG_DOUBLE 1
+
+/* Define if the "%Lg" format works to scan long doubles. */
+#define SCANF_HAS_LONG_DOUBLE 1
+
+/* 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. */
+#define HAVE_BCOPY 1
+
+/* Define if you have the btowc function. */
+/* #undef HAVE_BTOWC */
+
+/* Define if you have the bzero function. */
+#define HAVE_BZERO 1
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the isascii function. */
+#define HAVE_ISASCII 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setpgid function. */
+#define HAVE_SETPGID 1
+
+/* Define if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* 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. */
+#define HAVE_CTYPE_H 1
+
+/* Define if you have the <curses.h> header file. */
+#define HAVE_CURSES_H 1
+
+/* Define if you have the <endian.h> header file. */
+/* #undef HAVE_ENDIAN_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <link.h> header file. */
+#define HAVE_LINK_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* 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. */
+#define HAVE_SGTTY_H 1
+
+/* Define if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/debugreg.h> header file. */
+/* #undef HAVE_SYS_DEBUGREG_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/procfs.h> header file. */
+#define HAVE_SYS_PROCFS_H 1
+
+/* Define if you have the <sys/ptrace.h> header file. */
+#define HAVE_SYS_PTRACE_H 1
+
+/* 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. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have the <term.h> header file. */
+#define HAVE_TERM_H 1
+
+/* Define if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* 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). */
+#define HAVE_LIBM 1
+
+/* 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. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+#define ENABLE_NLS 1
+
+/* 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. */
+#ifndef CROSS_COMPILE
+#define HAVE_GREGSET_T 1
+#endif
+
+/* Define if <sys/procfs.h> has fpregset_t. */
+#define HAVE_FPREGSET_T 1
+
diff --git a/gnu/usr.bin/binutils/gdb/freebsd-uthread.c b/gnu/usr.bin/binutils/gdb/freebsd-uthread.c
new file mode 100644
index 0000000..9d89589
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/freebsd-uthread.c
@@ -0,0 +1,1102 @@
+/* $FreeBSD$ */
+/* Low level interface for debugging FreeBSD user 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 FreeBSD user-mode thread implementation.
+
+ FreeBSD threads are true user-mode threads, which are invoked via
+ the pthread_* 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.
+
+ Based largely on hpux-thread.c
+
+ */
+
+
+#include "defs.h"
+#include <sys/queue.h>
+#include <signal.h>
+#include <setjmp.h>
+#include "gdbthread.h"
+#include "target.h"
+#include "inferior.h"
+#include <fcntl.h>
+#include <ucontext.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_freebsd_uthread PARAMS ((void));
+
+static int main_pid = -1; /* Real process ID */
+
+/* Set to true while we are part-way through attaching */
+static int freebsd_uthread_attaching;
+
+static int freebsd_uthread_active = 0;
+static CORE_ADDR P_thread_list;
+static CORE_ADDR P_thread_run;
+
+static struct cleanup * save_inferior_pid PARAMS ((void));
+
+static void restore_inferior_pid PARAMS ((int pid));
+
+static void freebsd_uthread_resume PARAMS ((int pid, int step,
+ enum target_signal signo));
+
+static void init_freebsd_uthread_ops PARAMS ((void));
+
+static struct target_ops freebsd_uthread_ops;
+static struct target_thread_vector freebsd_uthread_vec;
+
+/*
+
+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 ((make_cleanup_func) restore_inferior_pid,
+ (void *)(intptr_t) inferior_pid);
+}
+
+static void
+restore_inferior_pid (pid)
+ int pid;
+{
+ inferior_pid = pid;
+}
+
+static int find_active_thread PARAMS ((void));
+
+struct cached_pthread {
+ u_int64_t uniqueid;
+ int state;
+ CORE_ADDR name;
+ union {
+ ucontext_t uc;
+ jmp_buf jb;
+ } ctx;
+};
+
+static int cached_thread;
+static struct cached_pthread cached_pthread;
+static CORE_ADDR cached_pthread_addr;
+
+#define THREADID_TID(id) ((id) >> 17)
+#define THREADID_PID(id) ((id) & ((1 << 17) - 1))
+
+LIST_HEAD(idmaplist, idmap);
+
+struct idmap {
+ LIST_ENTRY(idmap) link;
+ u_int64_t uniqueid;
+ int tid;
+};
+
+#define MAPHASH_SIZE 257
+#define TID_MIN 1
+#define TID_MAX 16383
+
+static int tid_to_hash[TID_MAX + 1]; /* set to map_hash index */
+static struct idmaplist map_hash[MAPHASH_SIZE];
+static int next_free_tid = TID_MIN; /* first available tid */
+static int last_free_tid = TID_MIN; /* first unavailable */
+
+static CORE_ADDR P_thread_next_offset;
+static CORE_ADDR P_thread_uniqueid_offset;
+static CORE_ADDR P_thread_state_offset;
+static CORE_ADDR P_thread_name_offset;
+static CORE_ADDR P_thread_ctx_offset;
+static CORE_ADDR P_thread_PS_RUNNING_value;
+static CORE_ADDR P_thread_PS_DEAD_value;
+
+static int next_offset;
+static int uniqueid_offset;
+static int state_offset;
+static int name_offset;
+static int ctx_offset;
+static int PS_RUNNING_value;
+static int PS_DEAD_value;
+
+#define UNIQUEID_HASH(id) (id % MAPHASH_SIZE)
+#define TID_ADD1(tid) (((tid) + 1) == TID_MAX + 1 \
+ ? TID_MIN : (tid) + 1)
+#define IS_TID_FREE(tid) (tid_to_hash[tid] == -1)
+
+static int
+get_new_tid(h)
+ int h;
+{
+ int tid = next_free_tid;
+
+ tid_to_hash[tid] = h;
+ next_free_tid = TID_ADD1(next_free_tid);
+ if (next_free_tid == last_free_tid)
+ {
+ int i;
+
+ for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i))
+ if (IS_TID_FREE(i))
+ break;
+ if (TID_ADD1(i) == last_free_tid)
+ {
+ error("too many threads");
+ return 0;
+ }
+ next_free_tid = i;
+ for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i))
+ ;
+ last_free_tid = i;
+ }
+
+ return tid;
+}
+
+static int
+find_pid(uniqueid)
+ u_int64_t uniqueid;
+{
+ int h = UNIQUEID_HASH(uniqueid);
+ struct idmap *im;
+
+ LIST_FOREACH(im, &map_hash[h], link)
+ if (im->uniqueid == uniqueid)
+ return (im->tid << 17) + main_pid;
+
+ im = xmalloc(sizeof(struct idmap));
+ im->uniqueid = uniqueid;
+ im->tid = get_new_tid(h);
+ LIST_INSERT_HEAD(&map_hash[h], im, link);
+
+ return (im->tid << 17) + main_pid;
+}
+
+static void
+free_pid(pid)
+ int pid;
+{
+ int tid = THREADID_TID(pid);
+ int h = tid_to_hash[tid];
+ struct idmap *im;
+
+ if (!tid) return;
+
+ LIST_FOREACH(im, &map_hash[h], link)
+ if (im->tid == tid)
+ break;
+
+ if (!im) return;
+
+ LIST_REMOVE(im, link);
+ tid_to_hash[tid] = -1;
+ free(im);
+}
+
+#define READ_OFFSET(field) read_memory(P_thread_##field##_offset, \
+ (char *) &field##_offset, \
+ sizeof(field##_offset))
+
+#define READ_VALUE(name) read_memory(P_thread_##name##_value, \
+ (char *) &name##_value, \
+ sizeof(name##_value))
+
+static void
+read_thread_offsets ()
+{
+ READ_OFFSET(next);
+ READ_OFFSET(uniqueid);
+ READ_OFFSET(state);
+ READ_OFFSET(name);
+ READ_OFFSET(ctx);
+
+ READ_VALUE(PS_RUNNING);
+ READ_VALUE(PS_DEAD);
+}
+
+#define READ_FIELD(ptr, T, field, result) \
+ read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result)
+
+static u_int64_t
+read_pthread_uniqueid (ptr)
+ CORE_ADDR ptr;
+{
+ u_int64_t uniqueid;
+ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
+ return uniqueid;
+}
+
+static CORE_ADDR
+read_pthread_next (ptr)
+ CORE_ADDR ptr;
+{
+ CORE_ADDR next;
+ READ_FIELD(ptr, CORE_ADDR, next, next);
+ return next;
+}
+
+static void
+read_cached_pthread (ptr, cache)
+ CORE_ADDR ptr;
+ struct cached_pthread *cache;
+{
+ READ_FIELD(ptr, u_int64_t, uniqueid, cache->uniqueid);
+ READ_FIELD(ptr, int, state, cache->state);
+ READ_FIELD(ptr, CORE_ADDR, name, cache->name);
+ READ_FIELD(ptr, ucontext_t, ctx, cache->ctx);
+}
+
+static int
+find_active_thread ()
+{
+ CORE_ADDR ptr;
+
+ if (main_pid == -1)
+ return -1;
+
+ read_memory ((CORE_ADDR)P_thread_run,
+ (char *)&ptr,
+ sizeof ptr);
+
+ return find_pid(read_pthread_uniqueid(ptr));
+}
+
+static CORE_ADDR find_pthread_addr PARAMS ((int thread));
+static struct cached_pthread * find_pthread PARAMS ((int thread));
+
+static CORE_ADDR
+find_pthread_addr (thread)
+ int thread;
+{
+ CORE_ADDR ptr;
+
+ if (thread == cached_thread)
+ return cached_pthread_addr;
+
+ read_memory ((CORE_ADDR)P_thread_list,
+ (char *)&ptr,
+ sizeof ptr);
+
+ while (ptr != 0)
+ {
+ if (find_pid(read_pthread_uniqueid(ptr)) == thread)
+ {
+ cached_thread = thread;
+ cached_pthread_addr = ptr;
+ read_cached_pthread(ptr, &cached_pthread);
+ return ptr;
+ }
+ ptr = read_pthread_next(ptr);
+ }
+
+ return NULL;
+}
+
+static struct cached_pthread *
+find_pthread (thread)
+ int thread;
+{
+ CORE_ADDR ptr;
+
+ if (thread == cached_thread)
+ return &cached_pthread;
+
+ read_memory ((CORE_ADDR)P_thread_list,
+ (char *)&ptr,
+ sizeof ptr);
+
+ while (ptr != 0)
+ {
+ if (find_pid(read_pthread_uniqueid(ptr)) == thread)
+ {
+ cached_thread = thread;
+ cached_pthread_addr = ptr;
+ read_cached_pthread(ptr, &cached_pthread);
+ return &cached_pthread;
+ }
+ ptr = read_pthread_next(ptr);
+ }
+
+#if 0
+ error ("Can't find pthread %d,%d",
+ THREADID_TID(thread), THREADID_PID(thread));
+#endif
+ 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
+freebsd_uthread_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
+freebsd_uthread_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ child_ops.to_attach (args, from_tty);
+ push_target (&freebsd_uthread_ops);
+ freebsd_uthread_attaching = 1;
+}
+
+/* After an attach, see if the target is threaded */
+
+static void
+freebsd_uthread_post_attach (pid)
+ int pid;
+{
+ if (freebsd_uthread_active)
+ {
+ read_thread_offsets ();
+
+ main_pid = pid;
+
+ bind_target_thread_vector (&freebsd_uthread_vec);
+
+ inferior_pid = find_active_thread ();
+
+ add_thread (inferior_pid);
+ }
+ else
+ {
+ unpush_target (&freebsd_uthread_ops);
+ push_target (&child_ops);
+ }
+
+ freebsd_uthread_attaching = 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 the normal ptrace (PTRACE_TRACEME). */
+
+static void
+freebsd_uthread_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
+freebsd_uthread_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
+{
+ struct cleanup *old_chain;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_resume (pid, step, signo);
+ return;
+ }
+
+ old_chain = save_inferior_pid ();
+
+ pid = inferior_pid = main_pid;
+
+ child_ops.to_resume (pid, step, signo);
+
+ cached_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
+freebsd_uthread_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int rtnval;
+ struct cleanup *old_chain;
+
+ if (freebsd_uthread_attaching)
+ {
+ return child_ops.to_wait (pid, ourstatus);
+ }
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ if (pid != -1)
+ pid = main_pid;
+
+ rtnval = child_ops.to_wait (pid, ourstatus);
+
+ if (rtnval >= 0)
+ {
+ rtnval = find_active_thread ();
+ if (!in_thread_list (rtnval))
+ add_thread (rtnval);
+ }
+
+ do_cleanups (old_chain);
+
+ return rtnval;
+}
+
+#ifdef __i386__
+
+static char sigmap[NUM_REGS] = /* map reg to sigcontext */
+{
+ 12, /* eax */
+ 11, /* ecx */
+ 10, /* edx */
+ 9, /* ebx */
+ 8, /* esp */
+ 7, /* ebp */
+ 6, /* esi */
+ 5, /* edi */
+ 15, /* eip */
+ 17, /* eflags */
+ 16, /* cs */
+ 19, /* ss */
+ 4, /* ds */
+ 3, /* es */
+ 2, /* fs */
+ 1, /* gs */
+};
+
+static char jmpmap[NUM_REGS] = /* map reg to jmp_buf */
+{
+ 6, /* eax */
+ -1, /* ecx */
+ -1, /* edx */
+ 1, /* ebx */
+ 2, /* esp */
+ 3, /* ebp */
+ 4, /* esi */
+ 5, /* edi */
+ 0, /* eip */
+ -1, /* eflags */
+ -1, /* cs */
+ -1, /* ss */
+ -1, /* ds */
+ -1, /* es */
+ -1, /* fs */
+ -1, /* gs */
+};
+
+#endif
+
+#ifdef __alpha__
+
+static char sigmap[NUM_REGS] = /* map reg to sigcontext */
+{
+ 1, 2, 3, 4, 5, 6, 7, 8, /* v0 - t6 */
+ 9, 10, 11, 12, 13, 14, 15, 16, /* t7 - fp */
+ 17, 18, 19, 20, 21, 22, 23, 24, /* a0 - t9 */
+ 25, 26, 27, 28, 29, 30, 31, 32, /* t10 - zero */
+ 38, 39, 40, 41, 42, 43, 44, 45, /* f0 - f7 */
+ 46, 47, 48, 49, 50, 51, 52, 53, /* f8 - f15 */
+ 54, 55, 56, 57, 58, 59, 60, 61, /* f16 - f23 */
+ 62, 63, 64, 65, 66, 67, 68, 69, /* f24 - f31 */
+ 33, -1 /* pc, vfp */
+};
+static char jmpmap[NUM_REGS] = {
+ 4, 5, 6, 7, 8, 9, 10, 11, /* v0 - t6 */
+ 12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */
+ 20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */
+ 28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */
+ 37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */
+ 45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */
+ 53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */
+ 61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */
+ 2, -1, /* pc, vfp */
+};
+
+#endif
+
+static void
+freebsd_uthread_fetch_registers (regno)
+ int regno;
+{
+ struct cached_pthread *thread;
+ struct cleanup *old_chain;
+ int active;
+ int first_regno, last_regno;
+ register_t *regbase;
+ char *regmap;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_fetch_registers (regno);
+ return;
+ }
+
+ thread = find_pthread (inferior_pid);
+
+ old_chain = save_inferior_pid ();
+
+ active = (inferior_pid == find_active_thread());
+
+ inferior_pid = main_pid;
+
+ if (active)
+ {
+ 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;
+ }
+
+ regbase = (register_t*) &thread->ctx.jb[0];
+ regmap = jmpmap;
+
+ for (regno = first_regno; regno <= last_regno; regno++)
+ {
+ if (regmap[regno] == -1)
+ child_ops.to_fetch_registers (regno);
+ else
+ supply_register (regno, (char*) &regbase[regmap[regno]]);
+ }
+
+ do_cleanups (old_chain);
+}
+
+static void
+freebsd_uthread_store_registers (regno)
+ int regno;
+{
+ struct cached_pthread *thread;
+ CORE_ADDR ptr;
+ struct cleanup *old_chain;
+ int first_regno, last_regno;
+ u_int32_t *regbase;
+ char *regmap;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_store_registers (regno);
+ return;
+ }
+
+ thread = find_pthread (inferior_pid);
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ if (thread->state == PS_RUNNING_value)
+ {
+ 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;
+ }
+
+ regbase = (u_int32_t*) &thread->ctx.jb[0];
+ regmap = jmpmap;
+
+ ptr = find_pthread_addr (inferior_pid);
+ for (regno = first_regno; regno <= last_regno; regno++)
+ {
+ if (regmap[regno] == -1)
+ child_ops.to_store_registers (regno);
+ else
+ {
+ u_int32_t *reg = &regbase[regmap[regno]];
+ int off;
+
+ /* Hang onto cached value */
+ memcpy(reg, registers + REGISTER_BYTE (regno),
+ REGISTER_RAW_SIZE (regno));
+
+ /* And push out to inferior */
+ off = (char *) reg - (char *) thread;
+ write_memory (ptr + off,
+ 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
+freebsd_uthread_prepare_to_store ()
+{
+ struct cleanup *old_chain;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_prepare_to_store ();
+ return;
+ }
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ child_ops.to_prepare_to_store ();
+
+ do_cleanups (old_chain);
+}
+
+static int
+freebsd_uthread_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;
+
+ if (freebsd_uthread_attaching)
+ {
+ return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
+ }
+
+ 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
+freebsd_uthread_files_info (ignore)
+ struct target_ops *ignore;
+{
+ child_ops.to_files_info (ignore);
+}
+
+static void
+freebsd_uthread_kill_inferior ()
+{
+ inferior_pid = main_pid;
+ child_ops.to_kill ();
+}
+
+static void
+freebsd_uthread_notice_signals (pid)
+ int pid;
+{
+ struct cleanup *old_chain;
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ child_ops.to_notice_signals (pid);
+
+ do_cleanups (old_chain);
+}
+
+/* Fork an inferior process, and start debugging it with /proc. */
+
+static void
+freebsd_uthread_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ child_ops.to_create_inferior (exec_file, allargs, env);
+
+ if (inferior_pid && freebsd_uthread_active)
+ {
+ read_thread_offsets ();
+
+ main_pid = inferior_pid;
+
+ push_target (&freebsd_uthread_ops);
+ bind_target_thread_vector (&freebsd_uthread_vec);
+
+ inferior_pid = find_active_thread ();
+
+ add_thread (inferior_pid);
+ }
+}
+
+/* This routine is called to find out if the inferior is using threads.
+ We check for the _thread_run and _thread_list globals. */
+
+void
+freebsd_uthread_new_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct minimal_symbol *ms;
+
+ if (!objfile)
+ {
+ freebsd_uthread_active = 0;
+ return;
+ }
+
+ ms = lookup_minimal_symbol ("_thread_run", NULL, objfile);
+
+ if (!ms)
+ return;
+
+ P_thread_run = SYMBOL_VALUE_ADDRESS (ms);
+
+ ms = lookup_minimal_symbol ("_thread_list", NULL, objfile);
+
+ if (!ms)
+ return;
+
+ P_thread_list = SYMBOL_VALUE_ADDRESS (ms);
+
+#define OFFSET_SYM(field) "_thread_" #field "_offset"
+#define LOOKUP_OFFSET(field) \
+ do { \
+ ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile); \
+ if (!ms) \
+ return; \
+ P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms); \
+ } while (0);
+
+#define VALUE_SYM(name) "_thread_" #name "_value"
+#define LOOKUP_VALUE(name) \
+ do { \
+ ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile); \
+ if (!ms) \
+ return; \
+ P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms); \
+ } while (0);
+
+ LOOKUP_OFFSET(next);
+ LOOKUP_OFFSET(uniqueid);
+ LOOKUP_OFFSET(state);
+ LOOKUP_OFFSET(name);
+ LOOKUP_OFFSET(ctx);
+
+ LOOKUP_VALUE(PS_RUNNING);
+ LOOKUP_VALUE(PS_DEAD);
+
+ freebsd_uthread_active = 1;
+}
+
+int
+freebsd_uthread_has_exited (pid, wait_status, exit_status)
+ int pid;
+ int wait_status;
+ int * exit_status;
+{
+ int t = child_ops.to_has_exited (pid, wait_status, exit_status);
+ if (t)
+ main_pid = -1;
+ return t;
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+freebsd_uthread_mourn_inferior ()
+{
+ inferior_pid = main_pid; /* don't bother to restore inferior_pid */
+ child_ops.to_mourn_inferior ();
+ unpush_target (&freebsd_uthread_ops);
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
+
+static int
+freebsd_uthread_can_run ()
+{
+ return child_suppress_run;
+}
+
+static int
+freebsd_uthread_thread_alive (pid)
+ int pid;
+{
+ struct cleanup *old_chain;
+ struct cached_pthread *thread;
+ int ret = 0;
+
+ if (freebsd_uthread_attaching)
+ return 1;
+
+ /*
+ * We can get called from child_ops.to_wait() which passes the underlying
+ * pid (without a thread number).
+ */
+ if (THREADID_TID(pid) == 0)
+ return 1;
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ if (find_pthread_addr (pid) != 0)
+ {
+ thread = find_pthread (pid);
+ ret = (thread->state != PS_DEAD_value);
+ }
+
+ do_cleanups (old_chain);
+
+ if (!ret)
+ free_pid(pid);
+
+ return ret;
+}
+
+static void
+freebsd_uthread_stop ()
+{
+ struct cleanup *old_chain;
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ child_ops.to_stop ();
+
+ do_cleanups (old_chain);
+}
+
+static int
+freebsd_uthread_find_new_threads ()
+{
+ CORE_ADDR ptr;
+ int state;
+ u_int64_t uniqueid;
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ read_memory ((CORE_ADDR)P_thread_list,
+ (char *)&ptr,
+ sizeof ptr);
+
+ while (ptr != 0)
+ {
+ READ_FIELD(ptr, int, state, state);
+ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
+ if (state != PS_DEAD_value &&
+ !in_thread_list (find_pid(uniqueid)))
+ add_thread (find_pid(uniqueid));
+ ptr = read_pthread_next(ptr);
+ }
+
+ do_cleanups (old_chain);
+
+ return 0;
+}
+
+/* MUST MATCH enum pthread_state */
+static const char *statenames[] = {
+ "RUNNING",
+ "SIGTHREAD",
+ "MUTEX_WAIT",
+ "COND_WAIT",
+ "FDLR_WAIT",
+ "FDLW_WAIT",
+ "FDR_WAIT",
+ "FDW_WAIT",
+ "POLL_WAIT",
+ "FILE_WAIT",
+ "SELECT_WAIT",
+ "SLEEP_WAIT",
+ "WAIT_WAIT",
+ "SIGSUSPEND",
+ "SIGWAIT",
+ "SPINBLOCK",
+ "JOIN",
+ "SUSPENDED",
+ "DEAD",
+ "DEADLOCK",
+};
+
+static int
+freebsd_uthread_get_thread_info (ref, selection, info)
+ gdb_threadref *ref;
+ int selection;
+ struct gdb_ext_thread_info *info;
+{
+ int pid = *ref;
+ struct cached_pthread *thread = find_pthread (pid);
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ memset(&info->threadid, 0, OPAQUETHREADBYTES);
+
+ memcpy(&info->threadid, ref, sizeof *ref);
+ info->active = thread->state == PS_RUNNING_value;
+ strcpy(info->display, statenames[thread->state]);
+ if (thread->name)
+ read_memory ((CORE_ADDR) thread->name, info->shortname, 32);
+ else
+ strcpy(info->shortname, "");
+
+ do_cleanups (old_chain);
+ return (0);
+}
+
+char *
+freebsd_uthread_pid_to_str (pid)
+ int pid;
+{
+ static char buf[30];
+
+ if (STREQ (current_target.to_shortname, "freebsd-uthreads"))
+ sprintf (buf, "process %d, thread %d\0",
+ THREADID_PID(pid), THREADID_TID(pid));
+ else
+ sprintf (buf, "process %d\0", pid);
+
+ return buf;
+}
+
+
+static void
+init_freebsd_uthread_ops ()
+{
+ freebsd_uthread_ops.to_shortname = "freebsd-uthreads";
+ freebsd_uthread_ops.to_longname = "FreeBSD uthreads";
+ freebsd_uthread_ops.to_doc = "FreeBSD user threads support.";
+ freebsd_uthread_ops.to_open = freebsd_uthread_open;
+ freebsd_uthread_ops.to_attach = freebsd_uthread_attach;
+ freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach;
+ freebsd_uthread_ops.to_detach = freebsd_uthread_detach;
+ freebsd_uthread_ops.to_resume = freebsd_uthread_resume;
+ freebsd_uthread_ops.to_wait = freebsd_uthread_wait;
+ freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers;
+ freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers;
+ freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store;
+ freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory;
+ freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info;
+ freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ freebsd_uthread_ops.to_terminal_init = terminal_init_inferior;
+ freebsd_uthread_ops.to_terminal_inferior = terminal_inferior;
+ freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ freebsd_uthread_ops.to_terminal_ours = terminal_ours;
+ freebsd_uthread_ops.to_terminal_info = child_terminal_info;
+ freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior;
+ freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior;
+ freebsd_uthread_ops.to_has_exited = freebsd_uthread_has_exited;
+ freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior;
+ freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run;
+ freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals;
+ freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive;
+ freebsd_uthread_ops.to_stop = freebsd_uthread_stop;
+ freebsd_uthread_ops.to_stratum = process_stratum;
+ freebsd_uthread_ops.to_has_all_memory = 1;
+ freebsd_uthread_ops.to_has_memory = 1;
+ freebsd_uthread_ops.to_has_stack = 1;
+ freebsd_uthread_ops.to_has_registers = 1;
+ freebsd_uthread_ops.to_has_execution = 1;
+ freebsd_uthread_ops.to_has_thread_control = 0;
+ freebsd_uthread_ops.to_magic = OPS_MAGIC;
+
+ freebsd_uthread_vec.find_new_threads = freebsd_uthread_find_new_threads;
+ freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info;
+}
+
+void
+_initialize_freebsd_uthread ()
+{
+ init_freebsd_uthread_ops ();
+ add_target (&freebsd_uthread_ops);
+
+ child_suppress_run = 1;
+}
diff --git a/gnu/usr.bin/binutils/gdb/gdb.1 b/gnu/usr.bin/binutils/gdb/gdb.1
new file mode 100644
index 0000000..b6cd3cc
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/gdb.1
@@ -0,0 +1,385 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.\" $FreeBSD$
+.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 "[\|" \-k "\|]"
+.RB "[\|" \-wcore "\|]"
+.RB "[\|" "\-b\ "\c
+.IR bps "\|]"
+.RB "[\|" "\-tty="\c
+.IR dev "\|]"
+.RB "[\|" "\-s "\c
+.I symfile\c
+\&\|]
+.RB "[\|" "\-e "\c
+.I prog\c
+\&\|]
+.RB "[\|" "\-se "\c
+.I prog\c
+\&\|]
+.RB "[\|" "\-c "\c
+.I core\c
+\&\|]
+.RB "[\|" "\-x "\c
+.I cmds\c
+\&\|]
+.RB "[\|" "\-d "\c
+.I dir\c
+\&\|]
+.RB "[\|" \c
+.I prog\c
+.RB "[\|" \c
+.IR core \||\| procID\c
+\&\|]\&\|]
+.ad b
+.SH DESCRIPTION
+The purpose of a debugger such as GDB is to allow you to see what is
+going on ``inside'' another program while it executes\(em\&or what another
+program was doing at the moment it crashed.
+
+GDB can do four main kinds of things (plus other things in support of
+these) to help you catch bugs in the act:
+
+.TP
+\ \ \ \(bu
+Start your program, specifying anything that might affect its behavior.
+
+.TP
+\ \ \ \(bu
+Make your program stop on specified conditions.
+
+.TP
+\ \ \ \(bu
+Examine what has happened, when your program has stopped.
+
+.TP
+\ \ \ \(bu
+Change things in your program, so you can experiment with correcting the
+effects of one bug and go on to learn about another.
+.PP
+
+You can use GDB to debug programs written in C, C++, and Modula-2.
+Fortran support will be added when a GNU Fortran compiler is ready.
+
+GDB is invoked with the shell command \c
+.B gdb\c
+\&. Once started, it reads
+commands from the terminal until you tell it to exit with the GDB
+command \c
+.B quit\c
+\&. You can get online help from \c
+.B gdb\c
+\& itself
+by using the command \c
+.B help\c
+\&.
+
+You can run \c
+.B gdb\c
+\& with no arguments or options; but the most
+usual way to start GDB is with one argument or two, specifying an
+executable program as the argument:
+.sp
+.br
+gdb\ program
+.br
+.sp
+
+You can also start with both an executable program and a core file specified:
+.sp
+.br
+gdb\ program\ core
+.br
+.sp
+
+You can, instead, specify a process ID as a second argument, if you want
+to debug a running process:
+.sp
+.br
+gdb\ program\ 1234
+.br
+.sp
+
+would attach GDB to process \c
+.B 1234\c
+\& (unless you also have a file
+named `\|\c
+.B 1234\c
+\&\|'; GDB does check for a core file first).
+
+Here are some of the most frequently needed GDB commands:
+.TP
+.B break \fR[\|\fIfile\fB:\fR\|]\fIfunction
+\&
+Set a breakpoint at \c
+.I function\c
+\& (in \c
+.I file\c
+\&).
+.TP
+.B run \fR[\|\fIarglist\fR\|]
+Start your program (with \c
+.I arglist\c
+\&, if specified).
+.TP
+.B bt
+Backtrace: display the program stack.
+.TP
+.BI print " expr"\c
+\&
+Display the value of an expression.
+.TP
+.B c
+Continue running your program (after stopping, e.g. at a breakpoint).
+.TP
+.B next
+Execute next program line (after stopping); step \c
+.I over\c
+\& any
+function calls in the line.
+.TP
+.B step
+Execute next program line (after stopping); step \c
+.I into\c
+\& any
+function calls in the line.
+.TP
+.B help \fR[\|\fIname\fR\|]
+Show information about GDB command \c
+.I name\c
+\&, or general information
+about using GDB.
+.TP
+.B quit
+Exit from GDB.
+.PP
+For full details on GDB, see \c
+.I
+Using GDB: A Guide to the GNU Source-Level Debugger\c
+\&, by Richard M. Stallman and Roland H. Pesch. The same text is available online
+as the \c
+.B gdb\c
+\& entry in the \c
+.B info\c
+\& program.
+.SH OPTIONS
+Any arguments other than options specify an executable
+file and core file (or process ID); that is, the first argument
+encountered with no
+associated option flag is equivalent to a `\|\c
+.B \-se\c
+\&\|' option, and the
+second, if any, is equivalent to a `\|\c
+.B \-c\c
+\&\|' option if it's the name of a file. Many options have
+both long and short forms; both are shown here. The long forms are also
+recognized if you truncate them, so long as enough of the option is
+present to be unambiguous. (If you prefer, you can flag option
+arguments with `\|\c
+.B +\c
+\&\|' rather than `\|\c
+.B \-\c
+\&\|', though we illustrate the
+more usual convention.)
+
+All the options and command line arguments you give are processed
+in sequential order. The order makes a difference when the
+`\|\c
+.B \-x\c
+\&\|' option is used.
+
+.TP
+.B \-help
+.TP
+.B \-h
+List all options, with brief explanations.
+
+.TP
+.BI "\-symbols=" "file"\c
+.TP
+.BI "\-s " "file"\c
+\&
+Read symbol table from file \c
+.I file\c
+\&.
+
+.TP
+.BI "\-exec=" "file"\c
+.TP
+.BI "\-e " "file"\c
+\&
+Use file \c
+.I file\c
+\& as the executable file to execute when
+appropriate, and for examining pure data in conjunction with a core
+dump.
+
+.TP
+.BI "\-se=" "file"\c
+\&
+Read symbol table from file \c
+.I file\c
+\& and use it as the executable
+file.
+
+.TP
+.BI "\-core=" "file"\c
+.TP
+.BI "\-c " "file"\c
+\&
+Use file \c
+.I file\c
+\& as a core dump to examine.
+
+.TP
+.BI "\-command=" "file"\c
+.TP
+.BI "\-x " "file"\c
+\&
+Execute GDB commands from file \c
+.I file\c
+\&.
+
+.TP
+.BI "\-directory=" "directory"\c
+.TP
+.BI "\-d " "directory"\c
+\&
+Add \c
+.I directory\c
+\& to the path to search for source files.
+.PP
+
+.TP
+.B \-nx
+.TP
+.B \-n
+Do not execute commands from any `\|\c
+.B .gdbinit\c
+\&\|' initialization files.
+Normally, the commands in these files are executed after all the
+command options and arguments have been processed.
+
+
+.TP
+.B \-quiet
+.TP
+.B \-q
+``Quiet''. Do not print the introductory and copyright messages. These
+messages are also suppressed in batch mode.
+
+.TP
+.B \-batch
+Run in batch mode. Exit with status \c
+.B 0\c
+\& after processing all the command
+files specified with `\|\c
+.B \-x\c
+\&\|' (and `\|\c
+.B .gdbinit\c
+\&\|', if not inhibited).
+Exit with nonzero status if an error occurs in executing the GDB
+commands in the command files.
+
+Batch mode may be useful for running GDB as a filter, for example to
+download and run a program on another computer; in order to make this
+more useful, the message
+.sp
+.br
+Program\ exited\ normally.
+.br
+.sp
+
+(which is ordinarily issued whenever a program running under GDB control
+terminates) is not issued when running in batch mode.
+
+.TP
+.BI "\-cd=" "directory"\c
+\&
+Run GDB using \c
+.I directory\c
+\& as its working directory,
+instead of the current directory.
+
+.TP
+.B \-fullname
+.TP
+.B \-f
+Emacs sets this option when it runs GDB as a subprocess. It tells GDB
+to output the full file name and line number in a standard,
+recognizable fashion each time a stack frame is displayed (which
+includes each time the program stops). This recognizable format looks
+like two `\|\c
+.B \032\c
+\&\|' characters, followed by the file name, line number
+and character position separated by colons, and a newline. The
+Emacs-to-GDB interface program uses the two `\|\c
+.B \032\c
+\&\|' characters as
+a signal to display the source code for the frame.
+
+.TP
+.B \-kernel
+.TP
+.B \-k
+Use gdb in kernel debugging mode. The prompt is set to ``(kgdb)''.
+
+.TP
+.B \-wcore
+This option may only be used in kernel debugging mode while
+debugging a ``live'' kernel and makes the corefile (/dev/mem)
+writable.
+
+.TP
+.BI "\-b " "bps"\c
+\&
+Set the line speed (baud rate or bits per second) of any serial
+interface used by GDB for remote debugging.
+
+.TP
+.BI "\-tty=" "device"\c
+\&
+Run using \c
+.I device\c
+\& for your program's standard input and output.
+.PP
+
+.SH "SEE ALSO"
+.RB "`\|" gdb "\|'"
+entry in
+.B info\c
+\&;
+.I
+Using GDB: A Guide to the GNU Source-Level Debugger\c
+, Richard M. Stallman and Roland H. Pesch, July 1991.
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c b/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c
new file mode 100644
index 0000000..a346f47
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c
@@ -0,0 +1,710 @@
+/* $FreeBSD$ */
+/* 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"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include "gdbcore.h"
+#include "value.h"
+#include "inferior.h"
+
+#if defined(HAVE_GREGSET_T) || defined(HAVE_FPREGSET_T)
+#include <sys/procfs.h>
+#endif
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'tEAX' come from <machine/reg.h> */
+static int tregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS,
+ tDS, tES, tFS, tGS,
+};
+
+static struct save87 pcb_savefpu;
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (&registers[REGISTER_BYTE (r)], ((int *)&inferior_registers) + tregmap[r], 4);
+
+ registers_fetched ();
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (((int *)&inferior_registers) + tregmap[r], &registers[REGISTER_BYTE (r)], 4);
+
+ ptrace (PT_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+}
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them.
+ Extract the floating point state out of the core file and store
+ it where `float_info' will find it.
+
+ 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 int cregno;
+ register int addr;
+ int bad_reg = -1;
+ int offset;
+ struct pcb *tmp_pcbaddr;
+
+ /*
+ * First get virtual address of user structure. Then calculate offset.
+ */
+ memcpy(&tmp_pcbaddr,
+ &((struct user *) core_reg_sect)->u_kproc.ki_pcb,
+ sizeof(tmp_pcbaddr));
+ offset = -reg_addr - (int) tmp_pcbaddr;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ cregno = tregmap[regno];
+ if (cregno == tGS)
+ addr = offsetof (struct pcb, pcb_gs);
+ else
+ addr = offset + 4 * cregno;
+ 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.", gdb_register_names[bad_reg]);
+ }
+
+ addr = offsetof (struct pcb, pcb_save);
+ memcpy (&pcb_savefpu, core_reg_sect + addr, sizeof pcb_savefpu);
+}
+
+#ifdef FLOAT_INFO
+#include "expression.h"
+#include "language.h" /* for local_hex_string */
+#include "floatformat.h"
+
+#include <sys/param.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
+
+static void
+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 */
+}
+
+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 instruction: ");
+ 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--)
+ {
+ int exp;
+ int mantissa_or;
+ int normal;
+ char *sign;
+ int st_regno;
+ unsigned short *usregs;
+ double val;
+
+ /* The physical regno `fpreg' is only relevant as an index into the
+ * tag word. Logical `%st' numbers are required for indexing ep->regs.
+ */
+ st_regno = (fpreg + 8 - top) & 7;
+
+ printf_unfiltered ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : " ");
+
+ 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[st_regno][i]);
+
+ printf_unfiltered (" ");
+
+ /*
+ * Handle weird cases better than floatformat_to_double () and
+ * printf ().
+ */
+ usregs = (unsigned short *) ep->regs[st_regno];
+ sign = usregs[4] & 0x8000 ? "-" : "";
+ exp = usregs[4] & 0x7fff;
+ normal = usregs[3] & 0x8000;
+ mantissa_or = usregs[0] | usregs[1] | usregs[2] | (usregs[3] & 0x7fff);
+ if (exp == 0)
+ {
+ if (normal)
+ printf_unfiltered ("Pseudo Denormal (0 as a double)");
+ else if (mantissa_or == 0)
+ printf_unfiltered ("%s0", sign);
+ else
+ printf_unfiltered ("Denormal (0 as a double)");
+ }
+ else if (exp == 0x7fff)
+ {
+ if (!normal)
+ printf_unfiltered ("Pseudo ");
+ if (mantissa_or == 0)
+ printf_unfiltered ("%sInf", sign);
+ else
+ printf_unfiltered ("%s NaN",
+ usregs[3] & 0x4000 ? "Quiet" : "Signaling");
+ if (!normal)
+ printf_unfiltered (" (NaN)");
+ }
+ else if (!normal)
+ printf_unfiltered ("Unnormal (NaN)");
+ else
+ {
+#if 0
+ /* Use this we stop trapping on overflow. */
+ floatformat_to_double(&floatformat_i387_ext,
+ (char *) ep->regs[st_regno], &val);
+#else
+ i387_to_double((char *) ep->regs[st_regno], (char *) &val);
+#endif
+ printf_unfiltered ("%g", val);
+ }
+ printf_unfiltered ("\n");
+ }
+}
+
+void
+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)];
+ char fpvalid;
+ unsigned int rounded_addr;
+ unsigned int rounded_size;
+ /*extern int corechan;*/
+ int skip;
+ extern int inferior_pid;
+
+ if (inferior_pid != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+ ptrace(PT_GETFPREGS, pid, &buf[0], sizeof(struct fpreg));
+ fpstatep = (struct fpstate *)&buf[0];
+ }
+ else
+ fpstatep = &pcb_savefpu;
+
+ print_387_status (fpstatep->sv_ex_sw, (struct env387 *)fpstatep);
+}
+#endif /* FLOAT_INFO */
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#ifdef SETUP_ARBITRARY_FRAME
+#include "frame.h"
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+ int argc;
+ CORE_ADDR *argv;
+{
+ if (argc != 2)
+ error ("i386 frame specifications require two arguments: sp and pc");
+
+ return create_new_frame (argv[0], argv[1]);
+}
+#endif /* SETUP_ARBITRARY_FRAME */
+
+#ifdef HAVE_GREGSET_T
+void
+supply_gregset (gp)
+ gregset_t *gp;
+{
+ int regno = 0;
+
+ /* These must be ordered the same as REGISTER_NAMES in
+ config/i386/tm-i386.h. */
+ supply_register (regno++, (char *)&gp->r_eax);
+ supply_register (regno++, (char *)&gp->r_ecx);
+ supply_register (regno++, (char *)&gp->r_edx);
+ supply_register (regno++, (char *)&gp->r_ebx);
+ supply_register (regno++, (char *)&gp->r_esp);
+ supply_register (regno++, (char *)&gp->r_ebp);
+ supply_register (regno++, (char *)&gp->r_esi);
+ supply_register (regno++, (char *)&gp->r_edi);
+ supply_register (regno++, (char *)&gp->r_eip);
+ supply_register (regno++, (char *)&gp->r_eflags);
+ supply_register (regno++, (char *)&gp->r_cs);
+ supply_register (regno++, (char *)&gp->r_ss);
+ supply_register (regno++, (char *)&gp->r_ds);
+ supply_register (regno++, (char *)&gp->r_es);
+ supply_register (regno++, (char *)&gp->r_fs);
+ supply_register (regno++, (char *)&gp->r_gs);
+}
+#endif /* HAVE_GREGSET_T */
+
+#ifdef HAVE_FPREGSET_T
+void
+supply_fpregset (fp)
+ fpregset_t *fp;
+{
+ memcpy (&pcb_savefpu, fp, sizeof pcb_savefpu);
+}
+#endif /* HAVE_FPREGSET_T */
+
+/* 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);
+}
+
+#ifdef PT_GETDBREGS
+
+/*
+ * 0: no trace output
+ * 1: trace watchpoint requests
+ * 2: trace `watchpoint hit?' tests, too
+ */
+#define WATCHPOINT_DEBUG 0
+
+#include "breakpoint.h"
+
+int
+can_watch(type, cnt, ot)
+ int type, cnt, ot;
+{
+ int rv;
+ static int cnt_watch, cnt_awatch;
+
+ switch (type)
+ {
+ case bp_hardware_watchpoint:
+ cnt_watch = cnt;
+ break;
+
+ case bp_access_watchpoint:
+ cnt_awatch = cnt;
+ break;
+
+ default:
+ rv = 0;
+ goto overandout;
+ }
+
+ rv = cnt_watch + cnt_awatch <= 4? 1: -1;
+
+ overandout:
+#if WATCHPOINT_DEBUG
+ printf_filtered("can_watch(%d, %d, %d) = %d (counts: w: %d, rw: %d)\n",
+ type, cnt, ot, rv, cnt_watch, cnt_awatch);
+#endif
+
+ return rv;
+}
+
+int
+stopped_by_watchpoint()
+{
+ struct dbreg dbr;
+ extern int inferior_pid;
+
+ if (current_target.to_shortname == 0 ||
+ ! (strcmp(current_target.to_shortname, "child") == 0 ||
+ strcmp(current_target.to_shortname, "freebsd-uthreads") == 0))
+ return 0;
+
+ if (inferior_pid != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+
+ if (ptrace(PT_GETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_GETDBREGS) failed");
+ return 0;
+ }
+#if WATCHPOINT_DEBUG > 1
+ printf_filtered("stopped_by_watchpoint(): DR6 = %#x\n", dbr.dr6);
+#endif
+ /*
+ * If a hardware watchpoint was hit, one of the lower 4 bits in
+ * DR6 is set (the actual bit indicates which of DR0...DR3 triggered
+ * the trap).
+ */
+ return dbr.dr6 & 0x0f;
+ }
+ else
+ {
+ warning("Can't set a watchpoint on a core file.");
+ return 0;
+ }
+}
+
+int
+insert_watchpoint(addr, len, type)
+ int addr, len, type;
+{
+ struct dbreg dbr;
+ extern int inferior_pid;
+
+ if (current_target.to_shortname == 0 ||
+ ! (strcmp(current_target.to_shortname, "child") == 0 ||
+ strcmp(current_target.to_shortname, "freebsd-uthreads") == 0))
+ return 0;
+
+ if (inferior_pid != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+ int i, mask;
+ unsigned int sbits;
+
+ if (ptrace(PT_GETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_GETDBREGS) failed");
+ return 0;
+ }
+
+ for (i = 0, mask = 0x03; i < 4; i++, mask <<= 2)
+ if ((dbr.dr7 & mask) == 0)
+ break;
+ if (i >= 4) {
+ warning("no more hardware watchpoints available");
+ return -1;
+ }
+
+ /* paranoia */
+ if (len > 4)
+ {
+ warning("watchpoint length %d unsupported, using lenght = 4",
+ len);
+ len = 4;
+ }
+ else if (len == 3)
+ {
+ warning("weird watchpoint length 3, using 2");
+ len = 2;
+ }
+ else if (len == 0)
+ {
+ warning("weird watchpoint length 0, using 1");
+ len = 1;
+ }
+
+ switch (len)
+ {
+ case 1: sbits = 0; break;
+ case 2: sbits = 4; break;
+ case 4: sbits = 0x0c; break;
+ }
+
+ /*
+ * The `type' value is 0 for `watch on write', 1 for `watch on
+ * read', 2 for `watch on both'. The i386 debug register
+ * breakpoint types are 0 for `execute' (not used in GDB), 1 for
+ * `write', and 4 for `read/write'. Plain `read' trapping is
+ * not supported on i386, value 3 is illegal.
+ */
+ switch (type)
+ {
+ default:
+ warning("weird watchpoint type %d, using a write watchpoint");
+ /* FALLTHROUGH */
+ case 0:
+ sbits |= 1;
+ break;
+
+ case 2:
+ sbits |= 3;
+ break;
+ }
+ sbits <<= 4 * i + 16;
+ sbits |= 1 << 2 * i;
+
+ dbr.dr7 |= sbits;
+ *(&dbr.dr0 + i) = (unsigned int)addr;
+
+#if WATCHPOINT_DEBUG
+ printf_filtered("insert_watchpoint(), inserting DR7 = %#x, DR%d = %#x\n",
+ dbr.dr7, i, addr);
+#endif
+ if (ptrace(PT_SETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_SETDBREGS) failed");
+ return 0;
+ }
+ }
+ else
+ {
+ warning("Can't set a watchpoint on a core file.");
+ return 0;
+ }
+}
+
+int
+remove_watchpoint(addr, len, type)
+ int addr, len, type;
+{
+ struct dbreg dbr;
+ extern int inferior_pid;
+
+ if (current_target.to_shortname == 0 ||
+ ! (strcmp(current_target.to_shortname, "child") == 0 ||
+ strcmp(current_target.to_shortname, "freebsd-uthreads") == 0))
+ return 0;
+
+ if (inferior_pid != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+ int i;
+ unsigned int sbits, *dbregp;
+
+ if (ptrace(PT_GETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_GETDBREGS) failed");
+ return 0;
+ }
+
+ for (i = 0, dbregp = &dbr.dr0; i < 4; i++, dbregp++)
+ if (*dbregp == (unsigned int)addr)
+ break;
+ if (i >= 4)
+ {
+ warning("watchpoint for address %#x not found", addr);
+ return -1;
+ }
+
+ *dbregp = 0;
+ sbits = 0xf << (4 * i + 16);
+ sbits |= 3 << 2 * i;
+ dbr.dr7 &= ~sbits;
+
+#if WATCHPOINT_DEBUG
+ printf_filtered("remove_watchpoint(): removing watchpoint for %#x, DR7 = %#x\n",
+ addr, dbr.dr7);
+#endif
+ if (ptrace(PT_SETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_SETDBREGS) failed");
+ return 0;
+ }
+ }
+ else
+ {
+ warning("Can't set a watchpoint on a core file.");
+ return 0;
+ }
+}
+
+#endif /* PT_GETDBREGS */
+
+CORE_ADDR
+fbsd_sigtramp_saved_pc (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR sigcontext_addr;
+ CORE_ADDR sigcode_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;
+ int sigcode_offs = (-1 * 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);
+
+#ifdef OSIGCODE_MAGIC_OFFSET
+ if (frame->next)
+ sigcode_addr = read_memory_integer (FRAME_ARGS_ADDRESS (frame->next)
+ + FRAME_ARGS_SKIP
+ + sigcode_offs,
+ ptrbytes);
+ else
+ sigcode_addr = read_memory_integer (read_register (SP_REGNUM)
+ + sigcode_offs,
+ ptrbytes);
+ target_read_memory (sigcode_addr + OSIGCODE_MAGIC_OFFSET,
+ buf, ptrbytes);
+ if (extract_unsigned_integer(buf, ptrbytes) == 0x01d516) {
+ target_read_memory (sigcontext_addr + OSIGCONTEXT_PC_OFFSET,
+ buf, ptrbytes);
+ } else
+#endif
+ /* 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 + NSIGCONTEXT_PC_OFFSET, buf, ptrbytes);
+ return extract_unsigned_integer (buf, ptrbytes);
+}
diff --git a/gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c
new file mode 100644
index 0000000..a695ab4
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c
@@ -0,0 +1,1045 @@
+/* Live and postmortem kernel debugging functions for FreeBSD.
+ 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. */
+
+/* $FreeBSD$ */
+
+#include "defs.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <sys/sysctl.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+#include <sys/stat.h>
+#include <unistd.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/tss.h>
+#include <machine/frame.h>
+#define _KERNEL
+#include <sys/pcpu.h>
+#undef _KERNEL
+
+static void kcore_files_info PARAMS ((struct target_ops *));
+
+static void kcore_close PARAMS ((int));
+
+static void get_kcore_registers PARAMS ((int));
+
+static int kcore_xfer_kmem PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static int xfer_umem PARAMS ((CORE_ADDR, char *, int, int));
+
+static CORE_ADDR ksym_lookup PARAMS ((const char *));
+
+static int read_pcb PARAMS ((int, CORE_ADDR));
+
+static struct proc * curProc PARAMS ((void));
+
+static int set_proc_context PARAMS ((CORE_ADDR paddr));
+
+static void kcore_open PARAMS ((char *filename, int from_tty));
+
+static void kcore_detach PARAMS ((char *args, int from_tty));
+
+static void set_proc_cmd PARAMS ((char *arg, int from_tty));
+
+static void set_cpu_cmd PARAMS ((char *arg, int from_tty));
+
+static CORE_ADDR kvtophys PARAMS ((int, CORE_ADDR));
+
+static int physrd PARAMS ((int, u_int, char*, int));
+
+static int kvm_open PARAMS ((const char *efile, char *cfile, char *sfile,
+ int perm, char *errout));
+
+static int kvm_close PARAMS ((int fd));
+
+static int kvm_write PARAMS ((int core_kd, CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int kvm_read PARAMS ((int core_kd, CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int kvm_uread PARAMS ((int core_kd, struct proc *p,
+ CORE_ADDR memaddr, char *myaddr,
+ int len));
+
+static int kernel_core_file_hook PARAMS ((int fd, CORE_ADDR addr,
+ char *buf, int len));
+
+static CORE_ADDR kvm_getpcpu PARAMS ((int cfd, int cpuid));
+
+static struct kinfo_proc * kvm_getprocs PARAMS ((int cfd, int op,
+ CORE_ADDR proc, int *cnt));
+
+extern struct target_ops kcore_ops; /* Forward decl */
+
+/* Non-zero means we are debugging a kernel core file */
+int kernel_debugging = 0;
+int kernel_writablecore = 0;
+
+static char *core_file;
+static int core_kd = -1;
+static struct proc *cur_proc;
+static CORE_ADDR kernel_start;
+
+static CORE_ADDR pcpu;
+#define PCPU_OFFSET(name) \
+ offsetof(struct pcpu, pc_ ## name)
+
+/*
+ * Symbol names of kernel entry points. Use special frames.
+ */
+#define KSYM_TRAP "calltrap"
+#define KSYM_INTR "Xintr"
+#define KSYM_FASTINTR "Xfastintr"
+#define KSYM_SYSCALL "Xsyscall"
+
+/*
+ * Read the "thing" at kernel address 'addr' into the space pointed to
+ * by point. The length of the "thing" is determined by the type of p.
+ * Result is non-zero if transfer fails.
+ */
+#define kvread(addr, p) \
+ (target_read_memory ((CORE_ADDR)(addr), (char *)(p), sizeof(*(p))))
+
+
+
+/*
+ * The following is FreeBSD-specific hackery to decode special frames
+ * and elide the assembly-language stub. This could be made faster by
+ * defining a frame_type field in the machine-dependent frame information,
+ * but we don't think that's too important right now.
+ */
+enum frametype { tf_normal, tf_trap, tf_interrupt, tf_syscall };
+
+CORE_ADDR
+fbsd_kern_frame_saved_pc (fr)
+struct frame_info *fr;
+{
+ struct minimal_symbol *sym;
+ CORE_ADDR this_saved_pc;
+ enum frametype frametype;
+
+ this_saved_pc = read_memory_integer (fr->frame + 4, 4);
+ sym = lookup_minimal_symbol_by_pc (this_saved_pc);
+ frametype = tf_normal;
+ if (sym != NULL) {
+ if (strcmp (SYMBOL_NAME(sym), KSYM_TRAP) == 0)
+ frametype = tf_trap;
+ else if (strncmp (SYMBOL_NAME(sym), KSYM_INTR,
+ strlen(KSYM_INTR)) == 0 || strncmp (SYMBOL_NAME(sym),
+ KSYM_FASTINTR, strlen(KSYM_FASTINTR)) == 0)
+ frametype = tf_interrupt;
+ else if (strcmp (SYMBOL_NAME(sym), KSYM_SYSCALL) == 0)
+ frametype = tf_syscall;
+ }
+
+ switch (frametype) {
+ case tf_normal:
+ return (this_saved_pc);
+
+#define oEIP offsetof(struct trapframe, tf_eip)
+
+ case tf_trap:
+ return (read_memory_integer (fr->frame + 8 + oEIP, 4));
+
+ case tf_interrupt:
+ return (read_memory_integer (fr->frame + 12 + oEIP, 4));
+
+ case tf_syscall:
+ return (read_memory_integer (fr->frame + 8 + oEIP, 4));
+#undef oEIP
+ }
+}
+
+static CORE_ADDR
+ksym_lookup (name)
+const char *name;
+{
+ struct minimal_symbol *sym;
+
+ sym = lookup_minimal_symbol (name, NULL, NULL);
+ if (sym == NULL)
+ error ("kernel symbol `%s' not found.", name);
+
+ return SYMBOL_VALUE_ADDRESS (sym);
+}
+
+static struct proc *
+curProc ()
+{
+ struct proc *p;
+ struct thread *td;
+ CORE_ADDR addr = pcpu + PCPU_OFFSET (curthread);
+
+ if (kvread (addr, &td))
+ error ("cannot read thread pointer at %x\n", addr);
+ addr = (CORE_ADDR)td + offsetof(struct thread, td_proc);
+ if (kvread (addr, &p))
+ error ("cannot read proc pointer at %x\n", addr);
+ return p;
+}
+
+/*
+ * Set the process context to that of the proc structure at
+ * system address paddr.
+ */
+static int
+set_proc_context (paddr)
+ CORE_ADDR paddr;
+{
+ struct proc p;
+
+ if (paddr < kernel_start)
+ return (1);
+
+ cur_proc = (struct proc *)paddr;
+#ifdef notyet
+ set_kernel_boundaries (cur_proc);
+#endif
+
+ /* Fetch all registers from core file */
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ return (0);
+}
+
+/* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+/* ARGSUSED */
+static void
+kcore_close (quitting)
+ int quitting;
+{
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ if (core_kd)
+ {
+ kvm_close (core_kd);
+ free (core_file);
+ core_file = NULL;
+ core_kd = -1;
+ }
+}
+
+/* This routine opens and sets up the core file bfd */
+
+static void
+kcore_open (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ const char *p;
+ struct cleanup *old_chain;
+ char buf[256], *cp;
+ int ontop;
+ CORE_ADDR addr;
+ struct pcb pcb;
+
+ target_preopen (from_tty);
+
+ unpush_target (&kcore_ops);
+
+ if (!filename)
+ {
+ /*error (core_kd?*/
+ error ( (core_kd >= 0)?
+ "No core file specified. (Use `detach' to stop debugging a core file.)"
+ : "No core file specified.");
+ }
+
+ filename = tilde_expand (filename);
+ if (filename[0] != '/')
+ {
+ cp = concat (current_directory, "/", filename, NULL);
+ free (filename);
+ filename = cp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ /*
+ * gdb doesn't really do anything if the exec-file couldn't
+ * be opened (in that case exec_bfd is NULL). Usually that's
+ * no big deal, but kvm_open needs the exec-file's name,
+ * which results in dereferencing a NULL pointer, a real NO-NO !
+ * So, check here if the open of the exec-file succeeded.
+ */
+ if (exec_bfd == NULL) /* the open failed */
+ error ("kgdb could not open the exec-file, please check the name you used !");
+
+ core_kd = kvm_open (exec_bfd->filename, filename, NULL,
+ kernel_writablecore? O_RDWR : O_RDONLY, "kgdb: ");
+ if (core_kd < 0)
+ perror_with_name (filename);
+
+ /* Looks semi-reasonable. Toss the old core file and work on the new. */
+
+ discard_cleanups (old_chain); /* Don't free filename any more */
+ core_file = filename;
+ ontop = !push_target (&kcore_ops);
+
+ kernel_start = bfd_get_start_address (exec_bfd); /* XXX */
+
+ /* print out the panic string if there is one */
+ if (kvread (ksym_lookup ("panicstr"), &addr) == 0
+ && addr != 0
+ && target_read_memory (addr, buf, sizeof (buf)) == 0)
+ {
+ for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++)
+ if (!isascii (*cp) || (!isprint (*cp) && !isspace (*cp)))
+ *cp = '?';
+ *cp = '\0';
+ if (buf[0] != '\0')
+ printf ("panicstr: %s\n", buf);
+ }
+
+ /* Print all the panic messages if possible. */
+ if (symfile_objfile != NULL)
+ {
+ printf ("panic messages:\n---\n");
+ snprintf (buf, sizeof buf,
+ "/sbin/dmesg -N %s -M %s | \
+ /usr/bin/awk '/^(panic:|Fatal trap) / { printing = 1 } \
+ { if (printing) print $0 }'",
+ symfile_objfile->name, filename);
+ fflush(stdout);
+ system (buf);
+ printf ("---\n");
+ }
+
+ if (!ontop)
+ {
+ warning ("you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''", target_longname);
+ return;
+ }
+
+ /* we may need this later */
+ cur_proc = (struct proc *)curProc ();
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+kcore_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Too many arguments");
+ unpush_target (&kcore_ops);
+ reinit_frame_cache ();
+ if (from_tty)
+ printf_filtered ("No kernel 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_kcore_registers (regno)
+ int regno;
+{
+ struct pcb *pcbaddr;
+ struct thread *mainthread;
+
+ /* find the pcb for the current process */
+ if (cur_proc == NULL)
+ error ("get_kcore_registers no proc");
+ if (kvread (&TAILQ_FIRST(&cur_proc->p_threads), &mainthread)) /* XXXKSE */
+ error ("cannot read main thread for proc at %#x", cur_proc);
+ if (kvread (&mainthread->td_pcb, &pcbaddr)) /* XXXKSE */
+ error ("cannot read pcb pointer for proc at %#x", cur_proc);
+ if (read_pcb (core_kd, (CORE_ADDR)pcbaddr) < 0)
+ error ("cannot read pcb at %#x", pcbaddr);
+}
+
+static void
+kcore_files_info (t)
+ struct target_ops *t;
+{
+ printf ("\t`%s'\n", core_file);
+}
+
+static CORE_ADDR
+ksym_maxuseraddr()
+{
+ static CORE_ADDR maxuseraddr;
+ struct minimal_symbol *sym;
+
+ if (maxuseraddr == 0)
+ {
+ sym = lookup_minimal_symbol ("PTmap", NULL, NULL);
+ if (sym == NULL) {
+ maxuseraddr = VM_MAXUSER_ADDRESS;
+ } else {
+ maxuseraddr = SYMBOL_VALUE_ADDRESS (sym);
+ }
+ }
+ return maxuseraddr;
+}
+
+static int
+kcore_xfer_kmem (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ int ns;
+ int nu;
+
+ if (memaddr >= ksym_maxuseraddr())
+ nu = 0;
+ else
+ {
+ nu = xfer_umem (memaddr, myaddr, len, write);
+ if (nu <= 0)
+ return (0);
+ if (nu == len)
+ return (nu);
+ memaddr += nu;
+ if (memaddr != ksym_maxuseraddr())
+ return (nu);
+ myaddr += nu;
+ len -= nu;
+ }
+
+ ns = (write ? kvm_write : kvm_read) (core_kd, memaddr, myaddr, len);
+ if (ns < 0)
+ ns = 0;
+
+ return (nu + ns);
+}
+
+static int
+xfer_umem (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write; /* ignored */
+{
+ int n;
+ struct proc proc;
+
+ if (cur_proc == NULL || kvread (cur_proc, &proc))
+ error ("cannot read proc at %#x", cur_proc);
+ n = kvm_uread (core_kd, &proc, memaddr, myaddr, len) ;
+
+ if (n < 0)
+ return 0;
+ return n;
+}
+
+static CORE_ADDR
+ksym_kernbase()
+{
+ static CORE_ADDR kernbase;
+ struct minimal_symbol *sym;
+
+ if (kernbase == 0)
+ {
+ sym = lookup_minimal_symbol ("kernbase", NULL, NULL);
+ if (sym == NULL) {
+ kernbase = KERNBASE;
+ } else {
+ kernbase = SYMBOL_VALUE_ADDRESS (sym);
+ }
+ }
+ return kernbase;
+}
+
+#define KERNOFF (ksym_kernbase())
+#define INKERNEL(x) ((x) >= KERNOFF)
+
+static CORE_ADDR sbr;
+static CORE_ADDR curpcb;
+static int found_pcb;
+static int devmem;
+static int kfd;
+static struct pcb pcb;
+
+static void
+set_proc_cmd (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR paddr;
+ struct kinfo_proc *kp;
+ int cnt = 0;
+
+ if (!arg)
+ error_no_arg ("proc address for new current process");
+ if (!kernel_debugging)
+ error ("not debugging kernel");
+
+ paddr = (CORE_ADDR)parse_and_eval_address (arg);
+ /* assume it's a proc pointer if it's in the kernel */
+ if (paddr >= kernel_start) {
+ if (set_proc_context(paddr))
+ error("invalid proc address");
+ } else {
+ kp = kvm_getprocs(core_kd, KERN_PROC_PID, paddr, &cnt);
+ if (!cnt)
+ error("invalid pid");
+ if (set_proc_context((CORE_ADDR)kp->ki_paddr))
+ error("invalid proc address");
+ }
+}
+
+static void
+set_cpu_cmd (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR paddr;
+ CORE_ADDR pcaddr;
+ struct kinfo_proc *kp;
+ int cpu, cfd;
+
+ if (!arg)
+ error_no_arg ("cpu number");
+ if (!kernel_debugging)
+ error ("not debugging kernel");
+
+ cfd = core_kd;
+ cpu = (int)parse_and_eval_address (arg);
+ if ((pcaddr = kvm_getpcpu (cfd, cpu)) == NULL)
+ error ("cpu number out of range");
+
+ pcpu = pcaddr;
+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb));
+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb);
+
+ if (!devmem)
+ paddr = ksym_lookup ("dumppcb") - KERNOFF;
+ else
+ paddr = kvtophys (cfd, curpcb);
+ read_pcb (cfd, paddr);
+ printf ("initial pcb at %lx\n", (unsigned long)paddr);
+
+ if ((cur_proc = curProc()))
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* substitutes for the stuff in libkvm which doesn't work */
+/* most of this was taken from the old kgdb */
+
+/* we don't need all this stuff, but the call should look the same */
+
+static int
+kvm_open (efile, cfile, sfile, perm, errout)
+ const char *efile;
+ char *cfile;
+ char *sfile; /* makes this kvm_open more compatible to the one in libkvm */
+ int perm;
+ char *errout; /* makes this kvm_open more compatible to the one in libkvm */
+{
+ struct stat stb;
+ int cfd;
+ CORE_ADDR paddr;
+
+ if ((cfd = open (cfile, perm, 0)) < 0)
+ return (cfd);
+
+ if ((pcpu = kvm_getpcpu (cfd, 0)) == NULL)
+ return (-1);
+
+ fstat (cfd, &stb);
+ if ((stb.st_mode & S_IFMT) == S_IFCHR
+ && stb.st_rdev == makedev (2, 0))
+ {
+ devmem = 1;
+ kfd = open (_PATH_KMEM, perm, 0);
+ }
+
+ physrd (cfd, ksym_lookup ("IdlePTD") - KERNOFF, (char*)&sbr, sizeof sbr);
+ printf ("IdlePTD at physical address 0x%08lx\n", (unsigned long)sbr);
+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb));
+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb);
+
+ found_pcb = 1; /* for vtophys */
+ if (!devmem)
+ paddr = ksym_lookup ("dumppcb") - KERNOFF;
+ else
+ paddr = kvtophys (cfd, curpcb);
+ read_pcb (cfd, paddr);
+ printf ("initial pcb at physical address 0x%08lx\n", (unsigned long)paddr);
+
+ return (cfd);
+}
+
+static int
+kvm_close (fd)
+ int fd;
+{
+ return (close (fd));
+}
+
+static int
+kvm_write (core_kd, memaddr, myaddr, len)
+ int core_kd;
+ CORE_ADDR memaddr;
+ char *myaddr;
+{
+ int cc;
+
+ if (devmem)
+ {
+ if (kfd > 0)
+ {
+ /*
+ * Just like kvm_read, only we write.
+ */
+ errno = 0;
+ if (lseek (kfd, (off_t)memaddr, 0) < 0
+ && errno != 0)
+ {
+ error ("kvm_write:invalid address (%x)", memaddr);
+ return (0);
+ }
+ cc = write (kfd, myaddr, len);
+ if (cc < 0)
+ {
+ error ("kvm_write:write failed");
+ return (0);
+ }
+ else if (cc < len)
+ error ("kvm_write:short write");
+ return (cc);
+ }
+ else
+ return (0);
+ }
+ else
+ {
+ printf ("kvm_write not implemented for dead kernels\n");
+ return (0);
+ }
+ /* NOTREACHED */
+}
+
+static int
+kvm_read (core_kd, memaddr, myaddr, len)
+ int core_kd;
+ CORE_ADDR memaddr;
+ char *myaddr;
+{
+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len));
+}
+
+static int
+kvm_uread (core_kd, p, memaddr, myaddr, len)
+ int core_kd;
+ register struct proc *p;
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register char *cp;
+ char procfile[MAXPATHLEN];
+ ssize_t amount;
+ int fd;
+
+ if (devmem)
+ {
+ sprintf (procfile, "/proc/%d/mem", p->p_pid);
+ fd = open (procfile, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ error ("cannot open %s", procfile);
+ close (fd);
+ return (0);
+ }
+
+ cp = myaddr;
+ while (len > 0)
+ {
+ errno = 0;
+ if (lseek (fd, (off_t)memaddr, 0) == -1 && errno != 0)
+ {
+ error ("invalid address (%x) in %s", memaddr, procfile);
+ break;
+ }
+ amount = read (fd, cp, len);
+ if (amount < 0)
+ {
+ error ("error reading %s", procfile);
+ break;
+ }
+ if (amount == 0)
+ {
+ error ("EOF reading %s", procfile);
+ break;
+ }
+ cp += amount;
+ memaddr += amount;
+ len -= amount;
+ }
+
+ close (fd);
+ return ((ssize_t) (cp - myaddr));
+ }
+ else
+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len));
+}
+
+static struct kinfo_proc kp;
+
+/*
+ * try to do what kvm_proclist in libkvm would do
+ */
+static int
+kvm_proclist (cfd, pid, p, cnt)
+int cfd, pid, *cnt;
+struct proc *p;
+{
+ struct proc lp;
+
+ for (; p != NULL; p = LIST_NEXT(&lp, p_list)) {
+ if (!kvm_read(cfd, (CORE_ADDR)p, (char *)&lp, sizeof (lp)))
+ return (0);
+ if (lp.p_pid != pid)
+ continue;
+ kp.ki_paddr = p;
+ *cnt = 1;
+ return (1);
+ }
+ *cnt = 0;
+ return (0);
+}
+
+/*
+ * try to do what kvm_deadprocs in libkvm would do
+ */
+static struct kinfo_proc *
+kvm_deadprocs (cfd, pid, cnt)
+int cfd, pid, *cnt;
+{
+ CORE_ADDR allproc, zombproc;
+ struct proc *p;
+
+ allproc = ksym_lookup("allproc");
+ if (kvm_read(cfd, allproc, (char *)&p, sizeof (p)) == 0)
+ return (NULL);
+ kvm_proclist (cfd, pid, p, cnt);
+ if (!*cnt) {
+ zombproc = ksym_lookup("zombproc");
+ if (kvm_read(cfd, zombproc, (char *)&p, sizeof (p)) == 0)
+ return (NULL);
+ kvm_proclist (cfd, pid, p, cnt);
+ }
+ return (&kp);
+}
+
+static CORE_ADDR
+kvm_getpcpu (cfd, cpuid)
+int cfd, cpuid;
+{
+ SLIST_HEAD(, pcpu) pcpu_head;
+ struct pcpu lpc;
+ struct pcpu *pc;
+
+ physrd (cfd, ksym_lookup ("cpuhead") - KERNOFF, (char*)&pcpu_head,
+ sizeof pcpu_head);
+ pc = SLIST_FIRST (&pcpu_head);
+ for (; pc != NULL; pc = SLIST_NEXT (&lpc, pc_allcpu))
+ {
+ kvm_read (cfd, (CORE_ADDR)pc, (char*)&lpc, sizeof lpc);
+ if (lpc.pc_cpuid == cpuid)
+ break;
+ }
+
+ return ((CORE_ADDR)pc);
+}
+
+/*
+ * try to do what kvm_getprocs in libkvm would do
+ */
+static struct kinfo_proc *
+kvm_getprocs (cfd, op, proc, cnt)
+int cfd, op, *cnt;
+CORE_ADDR proc;
+{
+ int mib[4], size;
+
+ *cnt = 0;
+ /* assume it's a pid */
+ if (devmem) { /* "live" kernel, use sysctl */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = (int)proc;
+ size = sizeof (kp);
+ if (sysctl (mib, 4, &kp, &size, NULL, 0) < 0) {
+ perror("sysctl");
+ *cnt = 0;
+ return (NULL);
+ }
+ if (!size)
+ *cnt = 0;
+ else
+ *cnt = 1;
+ return (&kp);
+ } else
+ return (kvm_deadprocs (cfd, (int)proc, cnt));
+}
+
+static int
+physrd (cfd, addr, dat, len)
+ int cfd;
+ u_int addr;
+ char *dat;
+ int len;
+{
+ if (lseek (cfd, (off_t)addr, L_SET) == -1)
+ return (-1);
+ return (read (cfd, dat, len));
+}
+
+static CORE_ADDR
+kvtophys (fd, addr)
+ int fd;
+ CORE_ADDR addr;
+{
+ CORE_ADDR v;
+ unsigned int pte;
+ static CORE_ADDR PTD = -1;
+ CORE_ADDR current_ptd;
+
+ /*
+ * We may no longer have a linear system page table...
+ *
+ * Here's the scoop. IdlePTD contains the physical address
+ * of a page table directory that always maps the kernel.
+ * IdlePTD is in memory that is mapped 1-to-1, so we can
+ * find it easily given its 'virtual' address from ksym_lookup().
+ * For hysterical reasons, the value of IdlePTD is stored in sbr.
+ *
+ * To look up a kernel address, we first convert it to a 1st-level
+ * address and look it up in IdlePTD. This gives us the physical
+ * address of a page table page; we extract the 2nd-level part of
+ * VA and read the 2nd-level pte. Finally, we add the offset part
+ * of the VA into the physical address from the pte and return it.
+ *
+ * User addresses are a little more complicated. If we don't have
+ * a current PCB from read_pcb(), we use PTD, which is the (fixed)
+ * virtual address of the current ptd. Since it's NOT in 1-to-1
+ * kernel space, we must look it up using IdlePTD. If we do have
+ * a pcb, we get the ptd from pcb_ptd.
+ */
+
+ if (INKERNEL (addr))
+ current_ptd = sbr;
+ else if (found_pcb == 0)
+ {
+ if (PTD == -1)
+ PTD = kvtophys (fd, ksym_lookup ("PTD"));
+ current_ptd = PTD;
+ }
+ else
+ current_ptd = pcb.pcb_cr3;
+
+ /*
+ * Read the first-level page table (ptd).
+ */
+ v = current_ptd + ( (unsigned)addr >> PDRSHIFT) * sizeof pte;
+ if (physrd (fd, v, (char *)&pte, sizeof pte) < 0 || (pte&PG_V) == 0)
+ return (~0);
+
+ if (pte & PG_PS)
+ {
+ /*
+ * No second-level page table; ptd describes one 4MB page.
+ * (We assume that the kernel wouldn't set PG_PS without enabling
+ * it cr0, and that the kernel doesn't support 36-bit physical
+ * addresses).
+ */
+#define PAGE4M_MASK (NBPDR - 1)
+#define PG_FRAME4M (~PAGE4M_MASK)
+ addr = (pte & PG_FRAME4M) + (addr & PAGE4M_MASK);
+ }
+ else
+ {
+ /*
+ * Read the second-level page table.
+ */
+ v = (pte&PG_FRAME) + ((addr >> PAGE_SHIFT)&(NPTEPG-1)) * sizeof pte;
+ if (physrd (fd, v, (char *) &pte, sizeof (pte)) < 0 || (pte&PG_V) == 0)
+ return (~0);
+
+ addr = (pte & PG_FRAME) + (addr & PAGE_MASK);
+ }
+#if 0
+ printf ("vtophys (%x) -> %x\n", oldaddr, addr);
+#endif
+ return (addr);
+}
+
+static int
+read_pcb (fd, uaddr)
+ int fd;
+ CORE_ADDR uaddr;
+{
+ int i;
+ int noreg;
+ CORE_ADDR nuaddr = uaddr;
+
+ /* need this for the `proc' command to work */
+ if (INKERNEL(uaddr))
+ nuaddr = kvtophys(fd, uaddr);
+
+ if (physrd (fd, nuaddr, (char *)&pcb, sizeof pcb) < 0)
+ {
+ error ("cannot read pcb at %x\n", uaddr);
+ return (-1);
+ }
+
+ /*
+ * get the register values out of the sys pcb and
+ * store them where `read_register' will find them.
+ */
+ /*
+ * XXX many registers aren't available.
+ * XXX for the non-core case, the registers are stale - they are for
+ * the last context switch to the debugger.
+ * XXX gcc's register numbers aren't all #defined in tm-i386.h.
+ */
+ noreg = 0;
+ for (i = 0; i < 3; ++i) /* eax,ecx,edx */
+ supply_register (i, (char *)&noreg);
+ supply_register (3, (char *)&pcb.pcb_ebx);
+ supply_register (SP_REGNUM, (char *)&pcb.pcb_esp);
+ supply_register (FP_REGNUM, (char *)&pcb.pcb_ebp);
+ supply_register (6, (char *)&pcb.pcb_esi);
+ supply_register (7, (char *)&pcb.pcb_edi);
+ supply_register (PC_REGNUM, (char *)&pcb.pcb_eip);
+ for (i = 9; i < 14; ++i) /* eflags, cs, ss, ds, es, fs */
+ supply_register (i, (char *)&noreg);
+ supply_register (15, (char *)&pcb.pcb_gs);
+
+ /* XXX 80387 registers? */
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local
+ * buffer 'buf'. Return numbert of bytes if read ok, 0 otherwise. On read
+ * errors, portion of buffer not read is zeroed.
+ */
+
+static int
+kernel_core_file_hook (fd, addr, buf, len)
+ int fd;
+ CORE_ADDR addr;
+ char *buf;
+ int len;
+{
+ int i;
+ CORE_ADDR paddr;
+ register char *cp;
+ int cc;
+
+ cp = buf;
+
+ while (len > 0)
+ {
+ paddr = kvtophys (fd, addr);
+ if (paddr == ~0)
+ {
+ memset (buf, '\000', len);
+ break;
+ }
+ /* we can't read across a page boundary */
+ i = min (len, PAGE_SIZE - (addr & PAGE_MASK));
+ if ( (cc = physrd (fd, paddr, cp, i)) <= 0)
+ {
+ memset (cp, '\000', len);
+ return (cp - buf);
+ }
+ cp += cc;
+ addr += cc;
+ len -= cc;
+ }
+ return (cp - buf);
+}
+
+static struct target_ops kcore_ops;
+
+void
+_initialize_kcorelow()
+{
+ kcore_ops.to_shortname = "kcore";
+ kcore_ops.to_longname = "Kernel core dump file";
+ kcore_ops.to_doc =
+ "Use a core file as a target. Specify the filename of the core file.";
+ kcore_ops.to_open = kcore_open;
+ kcore_ops.to_close = kcore_close;
+ kcore_ops.to_attach = find_default_attach;
+ kcore_ops.to_detach = kcore_detach;
+ kcore_ops.to_fetch_registers = get_kcore_registers;
+ kcore_ops.to_xfer_memory = kcore_xfer_kmem;
+ kcore_ops.to_files_info = kcore_files_info;
+ kcore_ops.to_create_inferior = find_default_create_inferior;
+ kcore_ops.to_stratum = kcore_stratum;
+ kcore_ops.to_has_memory = 1;
+ kcore_ops.to_has_stack = 1;
+ kcore_ops.to_has_registers = 1;
+ kcore_ops.to_magic = OPS_MAGIC;
+
+ add_target (&kcore_ops);
+ add_com ("proc", class_obscure, set_proc_cmd, "Set current process context");
+ add_com ("cpu", class_obscure, set_cpu_cmd, "Set current cpu");
+}
diff --git a/gnu/usr.bin/binutils/gdb/i386/nm.h b/gnu/usr.bin/binutils/gdb/i386/nm.h
new file mode 100644
index 0000000..65f872b
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/i386/nm.h
@@ -0,0 +1,168 @@
+/* $FreeBSD$ */
+/* 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
+
+#define ATTACH_DETACH
+
+/* Be shared lib aware */
+#include "solib.h"
+#ifdef FREEBSD_ELF
+#define SVR4_SHARED_LIBS
+#endif
+
+/* 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));
+
+/* We define our own fetch/store methods */
+#define FETCH_INFERIOR_REGISTERS
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+#define PTRACE_ARG3_TYPE char*
+
+#ifndef FREEBSD_ELF
+
+/* 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
+
+#endif
+
+/* 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));
+
+#define ADDITIONAL_OPTIONS \
+ {"kernel", no_argument, &kernel_debugging, 1}, \
+ {"k", no_argument, &kernel_debugging, 1}, \
+ {"wcore", no_argument, &kernel_writablecore, 1}, \
+ {"w", no_argument, &kernel_writablecore, 1},
+
+#define ADDITIONAL_OPTION_HELP \
+ "\
+ --kernel Enable kernel debugging.\n\
+ --wcore Make core file writable (only works for /dev/mem).\n\
+ This option only works while debugging a kernel !!\n\
+"
+
+extern int kernel_debugging;
+extern int kernel_writablecore;
+
+#define DEFAULT_PROMPT kernel_debugging?"(kgdb) ":"(gdb) "
+
+/* misuse START_PROGRESS to test whether we're running as kgdb */
+/* START_PROGRESS is called at the top of main */
+#undef START_PROGRESS
+#define START_PROGRESS(STR,N) \
+ if (!strcmp(STR, "kgdb")) \
+ kernel_debugging = 1;
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
+#ifdef PT_GETDBREGS
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+extern int can_watch PARAMS((int type, int cnt, int othertype));
+extern int stopped_by_watchpoint PARAMS((void));
+extern int insert_watchpoint PARAMS((int addr, int len, int type));
+extern int remove_watchpoint PARAMS((int addr, int len, int type));
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ can_watch(type, cnt, ot)
+
+/* 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) \
+ stopped_by_watchpoint()
+
+/* Use these macros for watchpoint insertion/removal. */
+
+#define target_insert_watchpoint(addr, len, type) \
+ insert_watchpoint(addr, len, type)
+
+#define target_remove_watchpoint(addr, len, type) \
+ remove_watchpoint(addr, len, type)
+
+#endif /* PT_GETDBREGS */
+
+#endif /* NM_FREEBSD_H */
diff --git a/gnu/usr.bin/binutils/gdb/i386/tm.h b/gnu/usr.bin/binutils/gdb/i386/tm.h
new file mode 100644
index 0000000..ac2f86f
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/i386/tm.h
@@ -0,0 +1,70 @@
+/* $FreeBSD$ */
+/* 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. */
+
+#ifndef TM_FBSD_H
+#define TM_FBSD_H 1
+
+#include "i386/tm-i386bsd.h"
+
+#undef NUM_REGS
+#define NUM_REGS 16
+
+extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
+
+#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
+
+extern void i386_float_info PARAMS ((void));
+
+#define FLOAT_INFO i386_float_info ()
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) STREQ (name, "_DYNAMIC")
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+extern CORE_ADDR fbsd_kern_frame_saved_pc (struct frame_info *);
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) \
+ (kernel_debugging ? fbsd_kern_frame_saved_pc(FRAME) : \
+ (((FRAME)->signal_handler_caller \
+ ? fbsd_sigtramp_saved_pc (FRAME) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)) \
+ ))
+
+/* On FreeBSD, sigtramp has size 0x48 and is immediately below the
+ ps_strings struct which has size 0x10 and is at the top of the
+ user stack. */
+
+#undef SIGTRAMP_START
+#undef SIGTRAMP_END
+#define SIGTRAMP_START(pc) 0xbfbfffa8
+#define SIGTRAMP_END(pc) 0xbfbffff0
+#undef SIGCONTEXT_PC_OFFSET
+#define OSIGCONTEXT_PC_OFFSET 20
+#define NSIGCONTEXT_PC_OFFSET 76
+#define OSIGCODE_MAGIC_OFFSET 20
+
+struct objfile;
+void freebsd_uthread_new_objfile PARAMS ((struct objfile *objfile));
+#define target_new_objfile(OBJFILE) freebsd_uthread_new_objfile (OBJFILE)
+
+extern char *freebsd_uthread_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) freebsd_uthread_pid_to_str (PID)
+
+#endif /* ifndef TM_FBSD_H */
diff --git a/gnu/usr.bin/binutils/gdb/i386/version.c b/gnu/usr.bin/binutils/gdb/i386/version.c
new file mode 100644
index 0000000..b779482
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/i386/version.c
@@ -0,0 +1,4 @@
+/* $FreeBSD$ */
+char *version = "4.18 (FreeBSD)";
+char *host_name = "i386-unknown-freebsd";
+char *target_name = "i386-unknown-freebsd";
diff --git a/gnu/usr.bin/binutils/gdb/i386/xm.h b/gnu/usr.bin/binutils/gdb/i386/xm.h
new file mode 100644
index 0000000..8a852a2
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/i386/xm.h
@@ -0,0 +1,23 @@
+/* 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, to avoid "INT_MIN
+ redefined" warnings from defs.h */
diff --git a/gnu/usr.bin/binutils/gdb/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
new file mode 100644
index 0000000..a695ab4
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
@@ -0,0 +1,1045 @@
+/* Live and postmortem kernel debugging functions for FreeBSD.
+ 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. */
+
+/* $FreeBSD$ */
+
+#include "defs.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <sys/sysctl.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+#include <sys/stat.h>
+#include <unistd.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/tss.h>
+#include <machine/frame.h>
+#define _KERNEL
+#include <sys/pcpu.h>
+#undef _KERNEL
+
+static void kcore_files_info PARAMS ((struct target_ops *));
+
+static void kcore_close PARAMS ((int));
+
+static void get_kcore_registers PARAMS ((int));
+
+static int kcore_xfer_kmem PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static int xfer_umem PARAMS ((CORE_ADDR, char *, int, int));
+
+static CORE_ADDR ksym_lookup PARAMS ((const char *));
+
+static int read_pcb PARAMS ((int, CORE_ADDR));
+
+static struct proc * curProc PARAMS ((void));
+
+static int set_proc_context PARAMS ((CORE_ADDR paddr));
+
+static void kcore_open PARAMS ((char *filename, int from_tty));
+
+static void kcore_detach PARAMS ((char *args, int from_tty));
+
+static void set_proc_cmd PARAMS ((char *arg, int from_tty));
+
+static void set_cpu_cmd PARAMS ((char *arg, int from_tty));
+
+static CORE_ADDR kvtophys PARAMS ((int, CORE_ADDR));
+
+static int physrd PARAMS ((int, u_int, char*, int));
+
+static int kvm_open PARAMS ((const char *efile, char *cfile, char *sfile,
+ int perm, char *errout));
+
+static int kvm_close PARAMS ((int fd));
+
+static int kvm_write PARAMS ((int core_kd, CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int kvm_read PARAMS ((int core_kd, CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int kvm_uread PARAMS ((int core_kd, struct proc *p,
+ CORE_ADDR memaddr, char *myaddr,
+ int len));
+
+static int kernel_core_file_hook PARAMS ((int fd, CORE_ADDR addr,
+ char *buf, int len));
+
+static CORE_ADDR kvm_getpcpu PARAMS ((int cfd, int cpuid));
+
+static struct kinfo_proc * kvm_getprocs PARAMS ((int cfd, int op,
+ CORE_ADDR proc, int *cnt));
+
+extern struct target_ops kcore_ops; /* Forward decl */
+
+/* Non-zero means we are debugging a kernel core file */
+int kernel_debugging = 0;
+int kernel_writablecore = 0;
+
+static char *core_file;
+static int core_kd = -1;
+static struct proc *cur_proc;
+static CORE_ADDR kernel_start;
+
+static CORE_ADDR pcpu;
+#define PCPU_OFFSET(name) \
+ offsetof(struct pcpu, pc_ ## name)
+
+/*
+ * Symbol names of kernel entry points. Use special frames.
+ */
+#define KSYM_TRAP "calltrap"
+#define KSYM_INTR "Xintr"
+#define KSYM_FASTINTR "Xfastintr"
+#define KSYM_SYSCALL "Xsyscall"
+
+/*
+ * Read the "thing" at kernel address 'addr' into the space pointed to
+ * by point. The length of the "thing" is determined by the type of p.
+ * Result is non-zero if transfer fails.
+ */
+#define kvread(addr, p) \
+ (target_read_memory ((CORE_ADDR)(addr), (char *)(p), sizeof(*(p))))
+
+
+
+/*
+ * The following is FreeBSD-specific hackery to decode special frames
+ * and elide the assembly-language stub. This could be made faster by
+ * defining a frame_type field in the machine-dependent frame information,
+ * but we don't think that's too important right now.
+ */
+enum frametype { tf_normal, tf_trap, tf_interrupt, tf_syscall };
+
+CORE_ADDR
+fbsd_kern_frame_saved_pc (fr)
+struct frame_info *fr;
+{
+ struct minimal_symbol *sym;
+ CORE_ADDR this_saved_pc;
+ enum frametype frametype;
+
+ this_saved_pc = read_memory_integer (fr->frame + 4, 4);
+ sym = lookup_minimal_symbol_by_pc (this_saved_pc);
+ frametype = tf_normal;
+ if (sym != NULL) {
+ if (strcmp (SYMBOL_NAME(sym), KSYM_TRAP) == 0)
+ frametype = tf_trap;
+ else if (strncmp (SYMBOL_NAME(sym), KSYM_INTR,
+ strlen(KSYM_INTR)) == 0 || strncmp (SYMBOL_NAME(sym),
+ KSYM_FASTINTR, strlen(KSYM_FASTINTR)) == 0)
+ frametype = tf_interrupt;
+ else if (strcmp (SYMBOL_NAME(sym), KSYM_SYSCALL) == 0)
+ frametype = tf_syscall;
+ }
+
+ switch (frametype) {
+ case tf_normal:
+ return (this_saved_pc);
+
+#define oEIP offsetof(struct trapframe, tf_eip)
+
+ case tf_trap:
+ return (read_memory_integer (fr->frame + 8 + oEIP, 4));
+
+ case tf_interrupt:
+ return (read_memory_integer (fr->frame + 12 + oEIP, 4));
+
+ case tf_syscall:
+ return (read_memory_integer (fr->frame + 8 + oEIP, 4));
+#undef oEIP
+ }
+}
+
+static CORE_ADDR
+ksym_lookup (name)
+const char *name;
+{
+ struct minimal_symbol *sym;
+
+ sym = lookup_minimal_symbol (name, NULL, NULL);
+ if (sym == NULL)
+ error ("kernel symbol `%s' not found.", name);
+
+ return SYMBOL_VALUE_ADDRESS (sym);
+}
+
+static struct proc *
+curProc ()
+{
+ struct proc *p;
+ struct thread *td;
+ CORE_ADDR addr = pcpu + PCPU_OFFSET (curthread);
+
+ if (kvread (addr, &td))
+ error ("cannot read thread pointer at %x\n", addr);
+ addr = (CORE_ADDR)td + offsetof(struct thread, td_proc);
+ if (kvread (addr, &p))
+ error ("cannot read proc pointer at %x\n", addr);
+ return p;
+}
+
+/*
+ * Set the process context to that of the proc structure at
+ * system address paddr.
+ */
+static int
+set_proc_context (paddr)
+ CORE_ADDR paddr;
+{
+ struct proc p;
+
+ if (paddr < kernel_start)
+ return (1);
+
+ cur_proc = (struct proc *)paddr;
+#ifdef notyet
+ set_kernel_boundaries (cur_proc);
+#endif
+
+ /* Fetch all registers from core file */
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ return (0);
+}
+
+/* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+/* ARGSUSED */
+static void
+kcore_close (quitting)
+ int quitting;
+{
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ if (core_kd)
+ {
+ kvm_close (core_kd);
+ free (core_file);
+ core_file = NULL;
+ core_kd = -1;
+ }
+}
+
+/* This routine opens and sets up the core file bfd */
+
+static void
+kcore_open (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ const char *p;
+ struct cleanup *old_chain;
+ char buf[256], *cp;
+ int ontop;
+ CORE_ADDR addr;
+ struct pcb pcb;
+
+ target_preopen (from_tty);
+
+ unpush_target (&kcore_ops);
+
+ if (!filename)
+ {
+ /*error (core_kd?*/
+ error ( (core_kd >= 0)?
+ "No core file specified. (Use `detach' to stop debugging a core file.)"
+ : "No core file specified.");
+ }
+
+ filename = tilde_expand (filename);
+ if (filename[0] != '/')
+ {
+ cp = concat (current_directory, "/", filename, NULL);
+ free (filename);
+ filename = cp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ /*
+ * gdb doesn't really do anything if the exec-file couldn't
+ * be opened (in that case exec_bfd is NULL). Usually that's
+ * no big deal, but kvm_open needs the exec-file's name,
+ * which results in dereferencing a NULL pointer, a real NO-NO !
+ * So, check here if the open of the exec-file succeeded.
+ */
+ if (exec_bfd == NULL) /* the open failed */
+ error ("kgdb could not open the exec-file, please check the name you used !");
+
+ core_kd = kvm_open (exec_bfd->filename, filename, NULL,
+ kernel_writablecore? O_RDWR : O_RDONLY, "kgdb: ");
+ if (core_kd < 0)
+ perror_with_name (filename);
+
+ /* Looks semi-reasonable. Toss the old core file and work on the new. */
+
+ discard_cleanups (old_chain); /* Don't free filename any more */
+ core_file = filename;
+ ontop = !push_target (&kcore_ops);
+
+ kernel_start = bfd_get_start_address (exec_bfd); /* XXX */
+
+ /* print out the panic string if there is one */
+ if (kvread (ksym_lookup ("panicstr"), &addr) == 0
+ && addr != 0
+ && target_read_memory (addr, buf, sizeof (buf)) == 0)
+ {
+ for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++)
+ if (!isascii (*cp) || (!isprint (*cp) && !isspace (*cp)))
+ *cp = '?';
+ *cp = '\0';
+ if (buf[0] != '\0')
+ printf ("panicstr: %s\n", buf);
+ }
+
+ /* Print all the panic messages if possible. */
+ if (symfile_objfile != NULL)
+ {
+ printf ("panic messages:\n---\n");
+ snprintf (buf, sizeof buf,
+ "/sbin/dmesg -N %s -M %s | \
+ /usr/bin/awk '/^(panic:|Fatal trap) / { printing = 1 } \
+ { if (printing) print $0 }'",
+ symfile_objfile->name, filename);
+ fflush(stdout);
+ system (buf);
+ printf ("---\n");
+ }
+
+ if (!ontop)
+ {
+ warning ("you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''", target_longname);
+ return;
+ }
+
+ /* we may need this later */
+ cur_proc = (struct proc *)curProc ();
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+kcore_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Too many arguments");
+ unpush_target (&kcore_ops);
+ reinit_frame_cache ();
+ if (from_tty)
+ printf_filtered ("No kernel 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_kcore_registers (regno)
+ int regno;
+{
+ struct pcb *pcbaddr;
+ struct thread *mainthread;
+
+ /* find the pcb for the current process */
+ if (cur_proc == NULL)
+ error ("get_kcore_registers no proc");
+ if (kvread (&TAILQ_FIRST(&cur_proc->p_threads), &mainthread)) /* XXXKSE */
+ error ("cannot read main thread for proc at %#x", cur_proc);
+ if (kvread (&mainthread->td_pcb, &pcbaddr)) /* XXXKSE */
+ error ("cannot read pcb pointer for proc at %#x", cur_proc);
+ if (read_pcb (core_kd, (CORE_ADDR)pcbaddr) < 0)
+ error ("cannot read pcb at %#x", pcbaddr);
+}
+
+static void
+kcore_files_info (t)
+ struct target_ops *t;
+{
+ printf ("\t`%s'\n", core_file);
+}
+
+static CORE_ADDR
+ksym_maxuseraddr()
+{
+ static CORE_ADDR maxuseraddr;
+ struct minimal_symbol *sym;
+
+ if (maxuseraddr == 0)
+ {
+ sym = lookup_minimal_symbol ("PTmap", NULL, NULL);
+ if (sym == NULL) {
+ maxuseraddr = VM_MAXUSER_ADDRESS;
+ } else {
+ maxuseraddr = SYMBOL_VALUE_ADDRESS (sym);
+ }
+ }
+ return maxuseraddr;
+}
+
+static int
+kcore_xfer_kmem (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ int ns;
+ int nu;
+
+ if (memaddr >= ksym_maxuseraddr())
+ nu = 0;
+ else
+ {
+ nu = xfer_umem (memaddr, myaddr, len, write);
+ if (nu <= 0)
+ return (0);
+ if (nu == len)
+ return (nu);
+ memaddr += nu;
+ if (memaddr != ksym_maxuseraddr())
+ return (nu);
+ myaddr += nu;
+ len -= nu;
+ }
+
+ ns = (write ? kvm_write : kvm_read) (core_kd, memaddr, myaddr, len);
+ if (ns < 0)
+ ns = 0;
+
+ return (nu + ns);
+}
+
+static int
+xfer_umem (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write; /* ignored */
+{
+ int n;
+ struct proc proc;
+
+ if (cur_proc == NULL || kvread (cur_proc, &proc))
+ error ("cannot read proc at %#x", cur_proc);
+ n = kvm_uread (core_kd, &proc, memaddr, myaddr, len) ;
+
+ if (n < 0)
+ return 0;
+ return n;
+}
+
+static CORE_ADDR
+ksym_kernbase()
+{
+ static CORE_ADDR kernbase;
+ struct minimal_symbol *sym;
+
+ if (kernbase == 0)
+ {
+ sym = lookup_minimal_symbol ("kernbase", NULL, NULL);
+ if (sym == NULL) {
+ kernbase = KERNBASE;
+ } else {
+ kernbase = SYMBOL_VALUE_ADDRESS (sym);
+ }
+ }
+ return kernbase;
+}
+
+#define KERNOFF (ksym_kernbase())
+#define INKERNEL(x) ((x) >= KERNOFF)
+
+static CORE_ADDR sbr;
+static CORE_ADDR curpcb;
+static int found_pcb;
+static int devmem;
+static int kfd;
+static struct pcb pcb;
+
+static void
+set_proc_cmd (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR paddr;
+ struct kinfo_proc *kp;
+ int cnt = 0;
+
+ if (!arg)
+ error_no_arg ("proc address for new current process");
+ if (!kernel_debugging)
+ error ("not debugging kernel");
+
+ paddr = (CORE_ADDR)parse_and_eval_address (arg);
+ /* assume it's a proc pointer if it's in the kernel */
+ if (paddr >= kernel_start) {
+ if (set_proc_context(paddr))
+ error("invalid proc address");
+ } else {
+ kp = kvm_getprocs(core_kd, KERN_PROC_PID, paddr, &cnt);
+ if (!cnt)
+ error("invalid pid");
+ if (set_proc_context((CORE_ADDR)kp->ki_paddr))
+ error("invalid proc address");
+ }
+}
+
+static void
+set_cpu_cmd (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR paddr;
+ CORE_ADDR pcaddr;
+ struct kinfo_proc *kp;
+ int cpu, cfd;
+
+ if (!arg)
+ error_no_arg ("cpu number");
+ if (!kernel_debugging)
+ error ("not debugging kernel");
+
+ cfd = core_kd;
+ cpu = (int)parse_and_eval_address (arg);
+ if ((pcaddr = kvm_getpcpu (cfd, cpu)) == NULL)
+ error ("cpu number out of range");
+
+ pcpu = pcaddr;
+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb));
+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb);
+
+ if (!devmem)
+ paddr = ksym_lookup ("dumppcb") - KERNOFF;
+ else
+ paddr = kvtophys (cfd, curpcb);
+ read_pcb (cfd, paddr);
+ printf ("initial pcb at %lx\n", (unsigned long)paddr);
+
+ if ((cur_proc = curProc()))
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* substitutes for the stuff in libkvm which doesn't work */
+/* most of this was taken from the old kgdb */
+
+/* we don't need all this stuff, but the call should look the same */
+
+static int
+kvm_open (efile, cfile, sfile, perm, errout)
+ const char *efile;
+ char *cfile;
+ char *sfile; /* makes this kvm_open more compatible to the one in libkvm */
+ int perm;
+ char *errout; /* makes this kvm_open more compatible to the one in libkvm */
+{
+ struct stat stb;
+ int cfd;
+ CORE_ADDR paddr;
+
+ if ((cfd = open (cfile, perm, 0)) < 0)
+ return (cfd);
+
+ if ((pcpu = kvm_getpcpu (cfd, 0)) == NULL)
+ return (-1);
+
+ fstat (cfd, &stb);
+ if ((stb.st_mode & S_IFMT) == S_IFCHR
+ && stb.st_rdev == makedev (2, 0))
+ {
+ devmem = 1;
+ kfd = open (_PATH_KMEM, perm, 0);
+ }
+
+ physrd (cfd, ksym_lookup ("IdlePTD") - KERNOFF, (char*)&sbr, sizeof sbr);
+ printf ("IdlePTD at physical address 0x%08lx\n", (unsigned long)sbr);
+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb));
+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb);
+
+ found_pcb = 1; /* for vtophys */
+ if (!devmem)
+ paddr = ksym_lookup ("dumppcb") - KERNOFF;
+ else
+ paddr = kvtophys (cfd, curpcb);
+ read_pcb (cfd, paddr);
+ printf ("initial pcb at physical address 0x%08lx\n", (unsigned long)paddr);
+
+ return (cfd);
+}
+
+static int
+kvm_close (fd)
+ int fd;
+{
+ return (close (fd));
+}
+
+static int
+kvm_write (core_kd, memaddr, myaddr, len)
+ int core_kd;
+ CORE_ADDR memaddr;
+ char *myaddr;
+{
+ int cc;
+
+ if (devmem)
+ {
+ if (kfd > 0)
+ {
+ /*
+ * Just like kvm_read, only we write.
+ */
+ errno = 0;
+ if (lseek (kfd, (off_t)memaddr, 0) < 0
+ && errno != 0)
+ {
+ error ("kvm_write:invalid address (%x)", memaddr);
+ return (0);
+ }
+ cc = write (kfd, myaddr, len);
+ if (cc < 0)
+ {
+ error ("kvm_write:write failed");
+ return (0);
+ }
+ else if (cc < len)
+ error ("kvm_write:short write");
+ return (cc);
+ }
+ else
+ return (0);
+ }
+ else
+ {
+ printf ("kvm_write not implemented for dead kernels\n");
+ return (0);
+ }
+ /* NOTREACHED */
+}
+
+static int
+kvm_read (core_kd, memaddr, myaddr, len)
+ int core_kd;
+ CORE_ADDR memaddr;
+ char *myaddr;
+{
+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len));
+}
+
+static int
+kvm_uread (core_kd, p, memaddr, myaddr, len)
+ int core_kd;
+ register struct proc *p;
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register char *cp;
+ char procfile[MAXPATHLEN];
+ ssize_t amount;
+ int fd;
+
+ if (devmem)
+ {
+ sprintf (procfile, "/proc/%d/mem", p->p_pid);
+ fd = open (procfile, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ error ("cannot open %s", procfile);
+ close (fd);
+ return (0);
+ }
+
+ cp = myaddr;
+ while (len > 0)
+ {
+ errno = 0;
+ if (lseek (fd, (off_t)memaddr, 0) == -1 && errno != 0)
+ {
+ error ("invalid address (%x) in %s", memaddr, procfile);
+ break;
+ }
+ amount = read (fd, cp, len);
+ if (amount < 0)
+ {
+ error ("error reading %s", procfile);
+ break;
+ }
+ if (amount == 0)
+ {
+ error ("EOF reading %s", procfile);
+ break;
+ }
+ cp += amount;
+ memaddr += amount;
+ len -= amount;
+ }
+
+ close (fd);
+ return ((ssize_t) (cp - myaddr));
+ }
+ else
+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len));
+}
+
+static struct kinfo_proc kp;
+
+/*
+ * try to do what kvm_proclist in libkvm would do
+ */
+static int
+kvm_proclist (cfd, pid, p, cnt)
+int cfd, pid, *cnt;
+struct proc *p;
+{
+ struct proc lp;
+
+ for (; p != NULL; p = LIST_NEXT(&lp, p_list)) {
+ if (!kvm_read(cfd, (CORE_ADDR)p, (char *)&lp, sizeof (lp)))
+ return (0);
+ if (lp.p_pid != pid)
+ continue;
+ kp.ki_paddr = p;
+ *cnt = 1;
+ return (1);
+ }
+ *cnt = 0;
+ return (0);
+}
+
+/*
+ * try to do what kvm_deadprocs in libkvm would do
+ */
+static struct kinfo_proc *
+kvm_deadprocs (cfd, pid, cnt)
+int cfd, pid, *cnt;
+{
+ CORE_ADDR allproc, zombproc;
+ struct proc *p;
+
+ allproc = ksym_lookup("allproc");
+ if (kvm_read(cfd, allproc, (char *)&p, sizeof (p)) == 0)
+ return (NULL);
+ kvm_proclist (cfd, pid, p, cnt);
+ if (!*cnt) {
+ zombproc = ksym_lookup("zombproc");
+ if (kvm_read(cfd, zombproc, (char *)&p, sizeof (p)) == 0)
+ return (NULL);
+ kvm_proclist (cfd, pid, p, cnt);
+ }
+ return (&kp);
+}
+
+static CORE_ADDR
+kvm_getpcpu (cfd, cpuid)
+int cfd, cpuid;
+{
+ SLIST_HEAD(, pcpu) pcpu_head;
+ struct pcpu lpc;
+ struct pcpu *pc;
+
+ physrd (cfd, ksym_lookup ("cpuhead") - KERNOFF, (char*)&pcpu_head,
+ sizeof pcpu_head);
+ pc = SLIST_FIRST (&pcpu_head);
+ for (; pc != NULL; pc = SLIST_NEXT (&lpc, pc_allcpu))
+ {
+ kvm_read (cfd, (CORE_ADDR)pc, (char*)&lpc, sizeof lpc);
+ if (lpc.pc_cpuid == cpuid)
+ break;
+ }
+
+ return ((CORE_ADDR)pc);
+}
+
+/*
+ * try to do what kvm_getprocs in libkvm would do
+ */
+static struct kinfo_proc *
+kvm_getprocs (cfd, op, proc, cnt)
+int cfd, op, *cnt;
+CORE_ADDR proc;
+{
+ int mib[4], size;
+
+ *cnt = 0;
+ /* assume it's a pid */
+ if (devmem) { /* "live" kernel, use sysctl */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = (int)proc;
+ size = sizeof (kp);
+ if (sysctl (mib, 4, &kp, &size, NULL, 0) < 0) {
+ perror("sysctl");
+ *cnt = 0;
+ return (NULL);
+ }
+ if (!size)
+ *cnt = 0;
+ else
+ *cnt = 1;
+ return (&kp);
+ } else
+ return (kvm_deadprocs (cfd, (int)proc, cnt));
+}
+
+static int
+physrd (cfd, addr, dat, len)
+ int cfd;
+ u_int addr;
+ char *dat;
+ int len;
+{
+ if (lseek (cfd, (off_t)addr, L_SET) == -1)
+ return (-1);
+ return (read (cfd, dat, len));
+}
+
+static CORE_ADDR
+kvtophys (fd, addr)
+ int fd;
+ CORE_ADDR addr;
+{
+ CORE_ADDR v;
+ unsigned int pte;
+ static CORE_ADDR PTD = -1;
+ CORE_ADDR current_ptd;
+
+ /*
+ * We may no longer have a linear system page table...
+ *
+ * Here's the scoop. IdlePTD contains the physical address
+ * of a page table directory that always maps the kernel.
+ * IdlePTD is in memory that is mapped 1-to-1, so we can
+ * find it easily given its 'virtual' address from ksym_lookup().
+ * For hysterical reasons, the value of IdlePTD is stored in sbr.
+ *
+ * To look up a kernel address, we first convert it to a 1st-level
+ * address and look it up in IdlePTD. This gives us the physical
+ * address of a page table page; we extract the 2nd-level part of
+ * VA and read the 2nd-level pte. Finally, we add the offset part
+ * of the VA into the physical address from the pte and return it.
+ *
+ * User addresses are a little more complicated. If we don't have
+ * a current PCB from read_pcb(), we use PTD, which is the (fixed)
+ * virtual address of the current ptd. Since it's NOT in 1-to-1
+ * kernel space, we must look it up using IdlePTD. If we do have
+ * a pcb, we get the ptd from pcb_ptd.
+ */
+
+ if (INKERNEL (addr))
+ current_ptd = sbr;
+ else if (found_pcb == 0)
+ {
+ if (PTD == -1)
+ PTD = kvtophys (fd, ksym_lookup ("PTD"));
+ current_ptd = PTD;
+ }
+ else
+ current_ptd = pcb.pcb_cr3;
+
+ /*
+ * Read the first-level page table (ptd).
+ */
+ v = current_ptd + ( (unsigned)addr >> PDRSHIFT) * sizeof pte;
+ if (physrd (fd, v, (char *)&pte, sizeof pte) < 0 || (pte&PG_V) == 0)
+ return (~0);
+
+ if (pte & PG_PS)
+ {
+ /*
+ * No second-level page table; ptd describes one 4MB page.
+ * (We assume that the kernel wouldn't set PG_PS without enabling
+ * it cr0, and that the kernel doesn't support 36-bit physical
+ * addresses).
+ */
+#define PAGE4M_MASK (NBPDR - 1)
+#define PG_FRAME4M (~PAGE4M_MASK)
+ addr = (pte & PG_FRAME4M) + (addr & PAGE4M_MASK);
+ }
+ else
+ {
+ /*
+ * Read the second-level page table.
+ */
+ v = (pte&PG_FRAME) + ((addr >> PAGE_SHIFT)&(NPTEPG-1)) * sizeof pte;
+ if (physrd (fd, v, (char *) &pte, sizeof (pte)) < 0 || (pte&PG_V) == 0)
+ return (~0);
+
+ addr = (pte & PG_FRAME) + (addr & PAGE_MASK);
+ }
+#if 0
+ printf ("vtophys (%x) -> %x\n", oldaddr, addr);
+#endif
+ return (addr);
+}
+
+static int
+read_pcb (fd, uaddr)
+ int fd;
+ CORE_ADDR uaddr;
+{
+ int i;
+ int noreg;
+ CORE_ADDR nuaddr = uaddr;
+
+ /* need this for the `proc' command to work */
+ if (INKERNEL(uaddr))
+ nuaddr = kvtophys(fd, uaddr);
+
+ if (physrd (fd, nuaddr, (char *)&pcb, sizeof pcb) < 0)
+ {
+ error ("cannot read pcb at %x\n", uaddr);
+ return (-1);
+ }
+
+ /*
+ * get the register values out of the sys pcb and
+ * store them where `read_register' will find them.
+ */
+ /*
+ * XXX many registers aren't available.
+ * XXX for the non-core case, the registers are stale - they are for
+ * the last context switch to the debugger.
+ * XXX gcc's register numbers aren't all #defined in tm-i386.h.
+ */
+ noreg = 0;
+ for (i = 0; i < 3; ++i) /* eax,ecx,edx */
+ supply_register (i, (char *)&noreg);
+ supply_register (3, (char *)&pcb.pcb_ebx);
+ supply_register (SP_REGNUM, (char *)&pcb.pcb_esp);
+ supply_register (FP_REGNUM, (char *)&pcb.pcb_ebp);
+ supply_register (6, (char *)&pcb.pcb_esi);
+ supply_register (7, (char *)&pcb.pcb_edi);
+ supply_register (PC_REGNUM, (char *)&pcb.pcb_eip);
+ for (i = 9; i < 14; ++i) /* eflags, cs, ss, ds, es, fs */
+ supply_register (i, (char *)&noreg);
+ supply_register (15, (char *)&pcb.pcb_gs);
+
+ /* XXX 80387 registers? */
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local
+ * buffer 'buf'. Return numbert of bytes if read ok, 0 otherwise. On read
+ * errors, portion of buffer not read is zeroed.
+ */
+
+static int
+kernel_core_file_hook (fd, addr, buf, len)
+ int fd;
+ CORE_ADDR addr;
+ char *buf;
+ int len;
+{
+ int i;
+ CORE_ADDR paddr;
+ register char *cp;
+ int cc;
+
+ cp = buf;
+
+ while (len > 0)
+ {
+ paddr = kvtophys (fd, addr);
+ if (paddr == ~0)
+ {
+ memset (buf, '\000', len);
+ break;
+ }
+ /* we can't read across a page boundary */
+ i = min (len, PAGE_SIZE - (addr & PAGE_MASK));
+ if ( (cc = physrd (fd, paddr, cp, i)) <= 0)
+ {
+ memset (cp, '\000', len);
+ return (cp - buf);
+ }
+ cp += cc;
+ addr += cc;
+ len -= cc;
+ }
+ return (cp - buf);
+}
+
+static struct target_ops kcore_ops;
+
+void
+_initialize_kcorelow()
+{
+ kcore_ops.to_shortname = "kcore";
+ kcore_ops.to_longname = "Kernel core dump file";
+ kcore_ops.to_doc =
+ "Use a core file as a target. Specify the filename of the core file.";
+ kcore_ops.to_open = kcore_open;
+ kcore_ops.to_close = kcore_close;
+ kcore_ops.to_attach = find_default_attach;
+ kcore_ops.to_detach = kcore_detach;
+ kcore_ops.to_fetch_registers = get_kcore_registers;
+ kcore_ops.to_xfer_memory = kcore_xfer_kmem;
+ kcore_ops.to_files_info = kcore_files_info;
+ kcore_ops.to_create_inferior = find_default_create_inferior;
+ kcore_ops.to_stratum = kcore_stratum;
+ kcore_ops.to_has_memory = 1;
+ kcore_ops.to_has_stack = 1;
+ kcore_ops.to_has_registers = 1;
+ kcore_ops.to_magic = OPS_MAGIC;
+
+ add_target (&kcore_ops);
+ add_com ("proc", class_obscure, set_proc_cmd, "Set current process context");
+ add_com ("cpu", class_obscure, set_cpu_cmd, "Set current cpu");
+}
diff --git a/gnu/usr.bin/binutils/gdb5/Makefile b/gnu/usr.bin/binutils/gdb5/Makefile
new file mode 100644
index 0000000..b7be700
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/Makefile
@@ -0,0 +1,115 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils
+
+.if ${MACHINE_ARCH} == "i386"
+CFLAGS+= -Dprint_insn_i386=print_insn_i386_att
+.endif
+
+PROG= gdb
+XSRCS= annotate.c 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 copying.c core-regset.c \
+ corefile.c corelow.c cp-valprint.c dcache.c dbxread.c \
+ demangle.c dwarfread.c dwarf2read.c elfread.c environ.c eval.c \
+ exec.c expprint.c f-exp.y f-lang.c f-typeprint.c f-valprint.c \
+ findvar.c fork-child.c freebsd-uthread.c gdbarch.c gdbtypes.c \
+ infcmd.c inflow.c infptrace.c infrun.c inftarg.c language.c \
+ jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c nlmread.c \
+ m2-lang.c m2-exp.y m2-typeprint.c m2-valprint.c main.c maint.c \
+ mdebugread.c mem-break.c minsyms.c objfiles.c parse.c \
+ printcmd.c remote.c remote-utils.c scm-exp.c scm-lang.c \
+ scm-valprint.c solib.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 \
+ version.c serial.c ser-unix.c ser-tcp.c
+SRCS= init.c ${XSRCS}
+SRCS+= wait.h
+
+.if exists(${.CURDIR}/Makefile.${MACHINE_ARCH})
+.include "${.CURDIR}/Makefile.${MACHINE_ARCH}"
+.endif
+
+#CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${.CURDIR}/${MACHINE_ARCH}
+CFLAGS+= -I${SRCDIR}/binutils
+CFLAGS+= -I${SRCDIR}/bfd
+CFLAGS+= -I${GDBDIR}/gdb
+CFLAGS+= -I${GDBDIR}/gdb/config
+DPADD= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libopcodes/libopcodes.a
+DPADD+= ${LIBREADLINE}
+DPADD+= ${LIBGNUREGEX}
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+DPADD+= ${LIBTERMCAP}
+LDADD+= ${RELTOP}/libbfd/libbfd.a
+LDADD+= ${RELTOP}/libopcodes/libopcodes.a
+LDADD+= -lreadline
+LDADD+= -lgnuregex
+LDADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD+= -ltermcap
+
+GDBDIR= ${.CURDIR}/../../../../contrib/gdb.291
+.PATH: ${GDBDIR}/gdb
+.PATH: ${SRCDIR}/opcodes
+
+CFLAGS+= -DFREEBSD_ELF
+
+CFLAGS+= -I$(.CURDIR) -I${DESTDIR}/usr/include/readline
+# use phkmalloc
+CFLAGS+= -DNO_MMALLOC
+# uncomment the next line if you want to debug gdb
+#CFLAGS+= -g
+YFLAGS=
+
+CLEANFILES= init.c init.c-tmp wait.h
+
+# 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: ${XSRCS}
+ @${ECHO} Making ${.TARGET}
+ @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 'void initialize_all_files () {' >>init.c-tmp
+ @for i in ${.ALLSRC} ; do \
+ filename=`echo $$i | sed \
+ -e '/^Onindy.c/d' \
+ -e '/^nindy.c/d' \
+ -e '/ttyflush.c/d' \
+ -e '/xdr_ld.c/d' \
+ -e '/xdr_ptrace.c/d' \
+ -e '/xdr_rdb.c/d' \
+ -e '/udr.c/d' \
+ -e '/udip2soc.c/d' \
+ -e '/udi2go32.c/d' \
+ -e '/version.c/d' \
+ -e '/^[a-z0-9A-Z_]*_[SU].c/d' \
+ -e '/[a-z0-9A-Z_]*-exp.tab.c/d'` ; \
+ case $$filename in \
+ "") ;; \
+ *) sed <$$filename >>init.c-tmp -n \
+ -e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (); \1 ();}/p' ; ;; \
+ esac ; \
+ done
+ @echo '}' >>init.c-tmp
+ @mv init.c-tmp ${.TARGET}
+
+.PRECIOUS: init.c
+
+wait.h:
+ ln -sf ${.CURDIR}/../../../../sys/sys/wait.h ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/gdb5/Makefile.alpha b/gnu/usr.bin/binutils/gdb5/Makefile.alpha
new file mode 100644
index 0000000..bb11105
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/Makefile.alpha
@@ -0,0 +1,8 @@
+#
+# $FreeBSD$
+#
+
+XSRCS+= freebsd-nat.c alpha-tdep.c kvm-fbsd.c
+LDADD+= -lkvm
+
+.PATH: ${.CURDIR}/alpha
diff --git a/gnu/usr.bin/binutils/gdb5/Makefile.i386 b/gnu/usr.bin/binutils/gdb5/Makefile.i386
new file mode 100644
index 0000000..607463b
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/Makefile.i386
@@ -0,0 +1,7 @@
+#
+# $FreeBSD$
+#
+
+XSRCS+= freebsd-nat.c i386-tdep.c i387-tdep.c kvm-fbsd.c
+
+.PATH: ${.CURDIR}/i386
diff --git a/gnu/usr.bin/binutils/gdb5/Makefile.ia64 b/gnu/usr.bin/binutils/gdb5/Makefile.ia64
new file mode 100644
index 0000000..160e966
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/Makefile.ia64
@@ -0,0 +1,8 @@
+#
+# $FreeBSD$
+#
+
+XSRCS+= freebsd-nat.c ia64-tdep.c kvm-fbsd.c
+LDADD+= -lkvm
+
+.PATH: ${.CURDIR}/ia64
diff --git a/gnu/usr.bin/binutils/gdb5/alpha/freebsd-nat.c b/gnu/usr.bin/binutils/gdb5/alpha/freebsd-nat.c
new file mode 100644
index 0000000..4bfd8ed
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/alpha/freebsd-nat.c
@@ -0,0 +1,175 @@
+/* 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. */
+
+/* $FreeBSD$ */
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <string.h>
+#include "gdbcore.h"
+#include "value.h"
+#include "inferior.h"
+
+#if defined(HAVE_GREGSET_T)
+#include <sys/procfs.h>
+#endif
+
+int kernel_debugging = 0;
+
+/* 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;
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+
+ for (r = 0; r < 31; r++)
+ memcpy (&registers[REGISTER_BYTE (r)],
+ &regs.r_regs[r], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&registers[REGISTER_BYTE (r + FP0_REGNUM)],
+ &fpregs.fpr_regs[r], sizeof(u_int64_t));
+ memcpy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &regs.r_regs[31], sizeof(u_int64_t));
+
+ memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, sizeof(u_int64_t));
+ memset (&registers[REGISTER_BYTE (FP_REGNUM)], 0, sizeof(u_int64_t));
+
+ registers_fetched ();
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ for (r = 0; r < 31; r++)
+ memcpy (&regs.r_regs[r],
+ &registers[REGISTER_BYTE (r)], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&fpregs.fpr_regs[r],
+ &registers[REGISTER_BYTE (r + FP0_REGNUM)], sizeof(u_int64_t));
+ memcpy (&regs.r_regs[31],
+ &registers[REGISTER_BYTE (PC_REGNUM)], sizeof(u_int64_t));
+
+ ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+}
+
+#ifdef HAVE_GREGSET_T
+void
+supply_gregset (gp)
+ gregset_t *gp;
+{
+ int regno = 0;
+
+ /* These must be ordered the same as REGISTER_NAMES in
+ config/alpha/tm-alpha.h. */
+ for (regno = 0; regno < 31; regno++)
+ supply_register (regno, (char *)&gp->r_regs[regno]);
+ supply_register (PC_REGNUM, (char *)&gp->r_regs[regno]);
+}
+#endif /* HAVE_GREGSET_T */
+
+#ifdef HAVE_FPREGSET_T
+void
+supply_fpregset (fp)
+ fpregset_t *fp;
+{
+ int regno = 0;
+
+ for (regno = 0; regno < 32; regno++)
+ supply_register (regno + 32, (char *)&fp->fpr_regs[regno]);
+}
+#endif /* HAVE_FPREGSET_T */
+
+/*
+ * Get registers from a kernel crash dump or live kernel.
+ * Called by kvm-fbsd.c:get_kcore_registers().
+ */
+fetch_kcore_registers (pcbp)
+ struct pcb *pcbp;
+{
+
+ /* First clear out any garbage. */
+ memset(registers, '\0', REGISTER_BYTES);
+
+ /* SP */
+ *(long *) &registers[REGISTER_BYTE (SP_REGNUM)] =
+ pcbp->pcb_hw.apcb_ksp;
+
+ /* S0 through S6 */
+ memcpy (&registers[REGISTER_BYTE (S0_REGNUM)],
+ &pcbp->pcb_context[0], 7 * sizeof(long));
+
+ /* PC */
+ *(long *) &registers[REGISTER_BYTE (PC_REGNUM)] =
+ pcbp->pcb_context[7];
+
+ registers_fetched ();
+}
+
diff --git a/gnu/usr.bin/binutils/gdb5/alpha/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb5/alpha/kvm-fbsd.c
new file mode 100644
index 0000000..6da1a8e
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/alpha/kvm-fbsd.c
@@ -0,0 +1,438 @@
+/* Kernel core dump functions below target vector, for GDB.
+ Copyright 1986, 1987, 1989, 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.
+*/
+
+/* $FreeBSD$ */
+
+/*
+ * This works like "remote" but, you use it like this:
+ * target kcore /dev/mem
+ * or
+ * target kcore /var/crash/host/core.0
+ *
+ * This way makes it easy to short-circut the whole bfd monster,
+ * and direct the inferior stuff to our libkvm implementation.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <paths.h>
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+
+static void
+kcore_files_info PARAMS ((struct target_ops *));
+
+static void
+kcore_close PARAMS ((int));
+
+static void
+get_kcore_registers PARAMS ((int));
+
+static int
+xfer_mem PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static int
+xfer_umem PARAMS ((CORE_ADDR, char *, int, int));
+
+static char *core_file;
+static kvm_t *core_kd;
+static struct pcb cur_pcb;
+
+static struct target_ops kcore_ops;
+int kernel_writablecore;
+
+/*
+ * Read the "thing" at kernel address 'addr' into the space pointed to
+ * by point. The length of the "thing" is determined by the type of p.
+ * Result is non-zero if transfer fails.
+ */
+#define kvread(addr, p) \
+(target_read_memory((CORE_ADDR)(addr), (char *)(p), sizeof(*(p))))
+
+
+CORE_ADDR
+ksym_lookup(name)
+ const char *name;
+{
+ struct minimal_symbol *sym;
+
+ sym = lookup_minimal_symbol(name, NULL, NULL);
+ if (sym == NULL)
+ error("kernel symbol `%s' not found.", name);
+
+ return SYMBOL_VALUE_ADDRESS(sym);
+}
+
+/*
+ * Provide the address of an initial PCB to use.
+ * If this is a crash dump, try for "dumppcb".
+ * If no "dumppcb" or it's /dev/mem, use proc0.
+ * Return the core address of the PCB we found.
+ */
+static CORE_ADDR
+initial_pcb()
+{
+ struct minimal_symbol *sym;
+ CORE_ADDR addr;
+ void *val;
+
+ /* Make sure things are open... */
+ if (!core_kd || !core_file)
+ return (0);
+
+ /* If this is NOT /dev/mem try for dumppcb. */
+ if (strncmp(core_file, _PATH_DEV, sizeof _PATH_DEV - 1)) {
+ sym = lookup_minimal_symbol("dumppcb", NULL, NULL);
+ if (sym != NULL) {
+ addr = SYMBOL_VALUE_ADDRESS(sym);
+ return (addr);
+ }
+ }
+
+ /*
+ * OK, just use proc0pcb. Note that curproc might
+ * not exist, and if it does, it will point to gdb.
+ * Therefore, just use proc0 and let the user set
+ * some other context if they care about it.
+ */
+ addr = ksym_lookup("proc0paddr");
+ if (kvread(addr, &val)) {
+ error("cannot read proc0paddr pointer at %x\n", addr);
+ val = 0;
+ }
+
+ return ((CORE_ADDR)val);
+}
+
+/*
+ * Set the current context to that of the PCB struct
+ * at the system address passed.
+ */
+static int
+set_context(addr)
+ CORE_ADDR addr;
+{
+
+ if (kvread(addr, &cur_pcb))
+ error("cannot read pcb at %#x", addr);
+
+ /* Fetch all registers from core file */
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ return (0);
+}
+
+/* Discard all vestiges of any previous core file and mark data and stack
+ spaces as empty. */
+
+/* ARGSUSED */
+static void
+kcore_close (quitting)
+ int quitting;
+{
+
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ if (core_kd) {
+ kvm_close(core_kd);
+ free(core_file);
+ core_file = NULL;
+ core_kd = NULL;
+ }
+}
+
+/* This routine opens and sets up the core file bfd. */
+
+static void
+kcore_open (filename, from_tty)
+ char *filename; /* the core file */
+ int from_tty;
+{
+ kvm_t *kd;
+ const char *p;
+ struct cleanup *old_chain;
+ char buf[256], *cp;
+ int ontop;
+ CORE_ADDR addr;
+
+ target_preopen (from_tty);
+
+ /* The exec file is required for symbols. */
+ if (exec_bfd == NULL)
+ error("No kernel exec file specified");
+
+ if (core_kd) {
+ error ("No core file specified."
+ " (Use `detach' to stop debugging a core file.)");
+ return;
+ }
+
+ if (!filename) {
+ error ("No core file specified.");
+ return;
+ }
+
+ filename = tilde_expand (filename);
+ if (filename[0] != '/') {
+ cp = concat (current_directory, "/", filename, NULL);
+ free (filename);
+ filename = cp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ kd = kvm_open (bfd_get_filename(exec_bfd), filename, NULL,
+ kernel_writablecore ? O_RDWR: O_RDONLY, 0);
+ if (kd == NULL) {
+ perror_with_name (filename);
+ return;
+ }
+
+ /* Looks semi-reasonable. Toss the old core file and work on the new. */
+
+ discard_cleanups (old_chain); /* Don't free filename any more */
+ core_file = filename;
+ unpush_target (&kcore_ops);
+ ontop = !push_target (&kcore_ops);
+
+ /* Note unpush_target (above) calls kcore_close. */
+ core_kd = kd;
+
+ /* print out the panic string if there is one */
+ if (kvread(ksym_lookup("panicstr"), &addr) == 0 &&
+ addr != 0 &&
+ target_read_memory(addr, buf, sizeof(buf)) == 0) {
+
+ for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
+ if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
+ *cp = '?';
+ *cp = '\0';
+ if (buf[0] != '\0')
+ printf_filtered("panic: %s\n", buf);
+ }
+
+ if (!ontop) {
+ warning (
+"you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''", target_longname);
+ return;
+ }
+
+ /* Now, set up process context, and print the top of stack */
+ (void)set_context(initial_pcb());
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+kcore_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Too many arguments");
+ unpush_target (&kcore_ops);
+ reinit_frame_cache ();
+ if (from_tty)
+ printf_filtered ("No kernel 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_kcore_registers (regno)
+ int regno;
+{
+
+ /*
+ * XXX - Only read the pcb when set_context() is called.
+ * When looking at a live kernel this may be a problem,
+ * but the user can do another "proc" or "pcb" command to
+ * grab a new copy of the pcb...
+ */
+
+ /*
+ * Zero out register set then fill in the ones we know about.
+ */
+ fetch_kcore_registers (&cur_pcb);
+}
+
+static void
+kcore_files_info (t)
+ struct target_ops *t;
+{
+ printf_filtered ("\t`%s'\n", core_file);
+}
+
+/* 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;
+}
+
+static int
+xfer_kmem (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ int n;
+
+#if 0 /* XXX */
+ if (it is a user address)
+ return xfer_umem(memaddr, myaddr, len, write);
+#endif
+
+ if (core_kd == NULL)
+ return 0;
+
+ if (write)
+ n = kvm_write(core_kd, memaddr, myaddr, len);
+ else
+ n = kvm_read (core_kd, memaddr, myaddr, len) ;
+ if (n < 0) {
+ fprintf_unfiltered (gdb_stderr, "can not access 0x%x, %s\n",
+ memaddr, kvm_geterr(core_kd));
+ n = 0;
+ }
+
+ return n;
+}
+
+#if 0 /* XXX */
+static int
+xfer_umem (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write; /* ignored */
+{
+ int n;
+ struct proc proc;
+
+ if (kvread(cur_proc, &proc))
+ error("cannot read proc at %#x", cur_proc);
+ n = kvm_uread(core_kd, &proc, memaddr, myaddr, len) ;
+
+ if (n < 0)
+ return 0;
+ return n;
+}
+#endif
+
+static void
+set_proc_cmd(arg)
+ char *arg;
+{
+ CORE_ADDR addr;
+ void *val;
+
+ if (!arg)
+ error_no_arg("proc address for the new context");
+
+ if (core_kd == NULL)
+ error("no kernel core file");
+
+ addr = (CORE_ADDR)parse_and_eval_address(arg);
+
+ /* Read the PCB address in proc structure. */
+ addr += (int) &((struct proc *)0)->p_addr;
+ if (kvread(addr, &val))
+ error("cannot read u area ptr");
+
+ if (set_context((CORE_ADDR)val))
+ error("invalid proc address");
+}
+
+static void
+set_pcb_cmd(arg)
+ char *arg;
+{
+ CORE_ADDR addr;
+ void *val;
+
+ if (!arg)
+ error_no_arg("pcb address for the new context");
+
+ if (core_kd == NULL)
+ error("no kernel core file");
+
+ addr = (CORE_ADDR)parse_and_eval_address(arg);
+
+ if (set_context(addr))
+ error("invalid pcb address");
+}
+
+
+
+void
+_initialize_kcorelow()
+{
+ kcore_ops.to_shortname = "kcore";
+ kcore_ops.to_longname = "Kernel core dump file";
+ kcore_ops.to_doc =
+ "Use a core file as a target. Specify the filename of the core file.";
+ kcore_ops.to_open = kcore_open;
+ kcore_ops.to_close = kcore_close;
+ kcore_ops.to_attach = find_default_attach;
+ kcore_ops.to_detach = kcore_detach;
+ kcore_ops.to_fetch_registers = get_kcore_registers;
+ kcore_ops.to_xfer_memory = xfer_kmem;
+ kcore_ops.to_files_info = kcore_files_info;
+ kcore_ops.to_create_inferior = find_default_create_inferior;
+ kcore_ops.to_stratum = kcore_stratum;
+ kcore_ops.to_has_memory = 1;
+ kcore_ops.to_has_stack = 1;
+ kcore_ops.to_has_registers = 1;
+ kcore_ops.to_magic = OPS_MAGIC;
+
+ add_target (&kcore_ops);
+ add_com ("proc", class_obscure, set_proc_cmd, "Set current process context");
+}
diff --git a/gnu/usr.bin/binutils/gdb5/alpha/nm.h b/gnu/usr.bin/binutils/gdb5/alpha/nm.h
new file mode 100644
index 0000000..4bc1dea
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/alpha/nm.h
@@ -0,0 +1,96 @@
+/* Native definitions for alpha running FreeBSD.
+ 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 */
+
+/* $FreeBSD$ */
+
+#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
+
+/* We define our own fetch/store methods */
+#define FETCH_INFERIOR_REGISTERS
+
+extern CORE_ADDR alpha_u_regs_offset();
+#define U_REGS_OFFSET alpha_u_regs_offset()
+
+#define PTRACE_ARG3_TYPE char*
+
+/* ptrace transfers longs, the ptrace man page is lying. */
+
+#define PTRACE_XFER_TYPE int
+
+/* 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))
+
+extern int kernel_debugging;
+extern int kernel_writablecore;
+
+#define ADDITIONAL_OPTIONS \
+ {"kernel", no_argument, &kernel_debugging, 1}, \
+ {"k", no_argument, &kernel_debugging, 1}, \
+ {"wcore", no_argument, &kernel_writablecore, 1}, \
+ {"w", no_argument, &kernel_writablecore, 1},
+
+#define ADDITIONAL_OPTION_HELP \
+ "\
+ --kernel Enable kernel debugging.\n\
+ --wcore Make core file writable (only works for /dev/mem).\n\
+ This option only works while debugging a kernel !!\n\
+"
+
+#define DEFAULT_PROMPT kernel_debugging?"(kgdb) ":"(gdb) "
+
+/* misuse START_PROGRESS to test whether we're running as kgdb */
+/* START_PROGRESS is called at the top of main */
+#undef START_PROGRESS
+#define START_PROGRESS(STR,N) \
+ if (!strcmp(STR, "kgdb")) \
+ kernel_debugging = 1;
+
diff --git a/gnu/usr.bin/binutils/gdb5/alpha/tm.h b/gnu/usr.bin/binutils/gdb5/alpha/tm.h
new file mode 100644
index 0000000..596a0ef02
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/alpha/tm.h
@@ -0,0 +1,45 @@
+/* $FreeBSD$ */
+/* Definitions to make GDB run on an Alpha box under FreeBSD. 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_FREEBSDALPHA_H
+#define TM_FREEBSDALPHA_H
+
+#include "alpha/tm-alpha.h"
+#ifndef S0_REGNUM
+#define S0_REGNUM (T7_REGNUM+1)
+#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 FreeBSD and most implementations. */
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+struct objfile;
+void freebsd_uthread_new_objfile PARAMS ((struct objfile *objfile));
+#define target_new_objfile(OBJFILE) freebsd_uthread_new_objfile (OBJFILE)
+
+extern char *freebsd_uthread_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) freebsd_uthread_pid_to_str (PID)
+
+#endif /* TM_FREEBSDALPHA_H */
diff --git a/gnu/usr.bin/binutils/gdb5/alpha/version.c b/gnu/usr.bin/binutils/gdb5/alpha/version.c
new file mode 100644
index 0000000..84b5d88
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/alpha/version.c
@@ -0,0 +1,5 @@
+/* $FreeBSD$ */
+
+char *version = "4.18";
+char *host_name = "alpha-unknown-freebsd";
+char *target_name = "alpha-unknown-freebsd";
diff --git a/gnu/usr.bin/binutils/gdb5/alpha/xm.h b/gnu/usr.bin/binutils/gdb5/alpha/xm.h
new file mode 100644
index 0000000..1bd0118
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/alpha/xm.h
@@ -0,0 +1,32 @@
+/* Host definitions for GDB running on an Alpha under FreeBSD
+ 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. */
+
+/* $FreeBSD$ */
+
+#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
+
+#include <limits.h>
diff --git a/gnu/usr.bin/binutils/gdb5/config.h b/gnu/usr.bin/binutils/gdb5/config.h
new file mode 100644
index 0000000..eb6ff3c
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/config.h
@@ -0,0 +1,328 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* 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. */
+#define HAVE_ALLOCA 1
+
+/* 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. */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* 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). */
+#define RETSIGTYPE void
+
+/* 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. */
+#define STDC_HEADERS 1
+
+/* 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. */
+#define CC_HAS_LONG_LONG 1
+
+/* Define if the "ll" format works to print long long ints. */
+#define PRINTF_HAS_LONG_LONG 1
+
+/* Define if the "%Lg" format works to print long doubles. */
+#define PRINTF_HAS_LONG_DOUBLE 1
+
+/* Define if the "%Lg" format works to scan long doubles. */
+#define SCANF_HAS_LONG_DOUBLE 1
+
+/* 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. */
+#define HAVE_BCOPY 1
+
+/* Define if you have the btowc function. */
+/* #undef HAVE_BTOWC */
+
+/* Define if you have the bzero function. */
+#define HAVE_BZERO 1
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the isascii function. */
+#define HAVE_ISASCII 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setpgid function. */
+#define HAVE_SETPGID 1
+
+/* Define if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* 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. */
+#define HAVE_CTYPE_H 1
+
+/* Define if you have the <curses.h> header file. */
+#define HAVE_CURSES_H 1
+
+/* Define if you have the <endian.h> header file. */
+/* #undef HAVE_ENDIAN_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <link.h> header file. */
+#define HAVE_LINK_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* 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. */
+#define HAVE_SGTTY_H 1
+
+/* Define if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/debugreg.h> header file. */
+/* #undef HAVE_SYS_DEBUGREG_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/procfs.h> header file. */
+#define HAVE_SYS_PROCFS_H 1
+
+/* Define if you have the <sys/ptrace.h> header file. */
+#define HAVE_SYS_PTRACE_H 1
+
+/* 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. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have the <term.h> header file. */
+#define HAVE_TERM_H 1
+
+/* Define if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* 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). */
+#define HAVE_LIBM 1
+
+/* 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. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+#define ENABLE_NLS 1
+
+/* 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. */
+#define HAVE_GREGSET_T 1
+
+/* Define if <sys/procfs.h> has fpregset_t. */
+#define HAVE_FPREGSET_T 1
+
diff --git a/gnu/usr.bin/binutils/gdb5/freebsd-uthread.c b/gnu/usr.bin/binutils/gdb5/freebsd-uthread.c
new file mode 100644
index 0000000..1c1ea78
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/freebsd-uthread.c
@@ -0,0 +1,1139 @@
+/* $FreeBSD$ */
+/* Low level interface for debugging FreeBSD user 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 FreeBSD user-mode thread implementation.
+
+ FreeBSD threads are true user-mode threads, which are invoked via
+ the pthread_* 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.
+
+ Based largely on hpux-thread.c
+
+ */
+
+
+#include "defs.h"
+#include <sys/queue.h>
+#include <signal.h>
+#include <setjmp.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_freebsd_uthread PARAMS ((void));
+
+static int main_pid = -1; /* Real process ID */
+
+/* Set to true while we are part-way through attaching */
+static int freebsd_uthread_attaching;
+
+static int freebsd_uthread_active = 0;
+static CORE_ADDR P_thread_list;
+static CORE_ADDR P_thread_run;
+
+static struct cleanup * save_inferior_pid PARAMS ((void));
+
+static void restore_inferior_pid PARAMS ((int pid));
+
+static void freebsd_uthread_resume PARAMS ((int pid, int step,
+ enum target_signal signo));
+
+static void init_freebsd_uthread_ops PARAMS ((void));
+
+static struct target_ops freebsd_uthread_ops;
+static struct target_thread_vector freebsd_uthread_vec;
+
+/*
+
+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 ((make_cleanup_func) restore_inferior_pid,
+ (void *)(intptr_t) inferior_pid);
+}
+
+static void
+restore_inferior_pid (pid)
+ int pid;
+{
+ inferior_pid = pid;
+}
+
+static int find_active_thread PARAMS ((void));
+
+struct cached_pthread {
+ u_int64_t uniqueid;
+ int state;
+ CORE_ADDR name;
+ int ctxtype;
+ union {
+ ucontext_t uc;
+ jmp_buf jb;
+ } ctx;
+};
+
+static int cached_thread;
+static struct cached_pthread cached_pthread;
+static CORE_ADDR cached_pthread_addr;
+
+#define THREADID_TID(id) ((id) >> 17)
+#define THREADID_PID(id) ((id) & ((1 << 17) - 1))
+
+LIST_HEAD(idmaplist, idmap);
+
+struct idmap {
+ LIST_ENTRY(idmap) link;
+ u_int64_t uniqueid;
+ int tid;
+};
+
+#define MAPHASH_SIZE 257
+#define TID_MIN 1
+#define TID_MAX 16383
+
+static int tid_to_hash[TID_MAX + 1]; /* set to map_hash index */
+static struct idmaplist map_hash[MAPHASH_SIZE];
+static int next_free_tid = TID_MIN; /* first available tid */
+static int last_free_tid = TID_MIN; /* first unavailable */
+
+static CORE_ADDR P_thread_next_offset;
+static CORE_ADDR P_thread_uniqueid_offset;
+static CORE_ADDR P_thread_state_offset;
+static CORE_ADDR P_thread_name_offset;
+static CORE_ADDR P_thread_ctxtype_offset;
+static CORE_ADDR P_thread_ctx_offset;
+static CORE_ADDR P_thread_PS_RUNNING_value;
+static CORE_ADDR P_thread_PS_DEAD_value;
+static CORE_ADDR P_thread_CTX_JB_NOSIG_value;
+static CORE_ADDR P_thread_CTX_JB_value;
+static CORE_ADDR P_thread_CTX_SJB_value;
+static CORE_ADDR P_thread_CTX_UC_value;
+
+static int next_offset;
+static int uniqueid_offset;
+static int state_offset;
+static int name_offset;
+static int ctxtype_offset;
+static int ctx_offset;
+static int PS_RUNNING_value;
+static int PS_DEAD_value;
+static int CTX_JB_NOSIG_value;
+static int CTX_JB_value;
+static int CTX_SJB_value;
+static int CTX_UC_value;
+
+#define UNIQUEID_HASH(id) (id % MAPHASH_SIZE)
+#define TID_ADD1(tid) (((tid) + 1) == TID_MAX + 1 \
+ ? TID_MIN : (tid) + 1)
+#define IS_TID_FREE(tid) (tid_to_hash[tid] == -1)
+
+static int
+get_new_tid(h)
+ int h;
+{
+ int tid = next_free_tid;
+
+ tid_to_hash[tid] = h;
+ next_free_tid = TID_ADD1(next_free_tid);
+ if (next_free_tid == last_free_tid)
+ {
+ int i;
+
+ for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i))
+ if (IS_TID_FREE(i))
+ break;
+ if (TID_ADD1(i) == last_free_tid)
+ {
+ error("too many threads");
+ return 0;
+ }
+ next_free_tid = i;
+ for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i))
+ ;
+ last_free_tid = i;
+ }
+
+ return tid;
+}
+
+static int
+find_pid(uniqueid)
+ u_int64_t uniqueid;
+{
+ int h = UNIQUEID_HASH(uniqueid);
+ struct idmap *im;
+
+ LIST_FOREACH(im, &map_hash[h], link)
+ if (im->uniqueid == uniqueid)
+ return (im->tid << 17) + main_pid;
+
+ im = xmalloc(sizeof(struct idmap));
+ im->uniqueid = uniqueid;
+ im->tid = get_new_tid(h);
+ LIST_INSERT_HEAD(&map_hash[h], im, link);
+
+ return (im->tid << 17) + main_pid;
+}
+
+static void
+free_pid(pid)
+ int pid;
+{
+ int tid = THREADID_TID(pid);
+ int h = tid_to_hash[tid];
+ struct idmap *im;
+
+ if (!tid) return;
+
+ LIST_FOREACH(im, &map_hash[h], link)
+ if (im->tid == tid)
+ break;
+
+ if (!im) return;
+
+ LIST_REMOVE(im, link);
+ tid_to_hash[tid] = -1;
+ free(im);
+}
+
+#define READ_OFFSET(field) read_memory(P_thread_##field##_offset, \
+ (char *) &field##_offset, \
+ sizeof(field##_offset))
+
+#define READ_VALUE(name) read_memory(P_thread_##name##_value, \
+ (char *) &name##_value, \
+ sizeof(name##_value))
+
+static void
+read_thread_offsets ()
+{
+ READ_OFFSET(next);
+ READ_OFFSET(uniqueid);
+ READ_OFFSET(state);
+ READ_OFFSET(name);
+ READ_OFFSET(ctxtype);
+ READ_OFFSET(ctx);
+
+ READ_VALUE(PS_RUNNING);
+ READ_VALUE(PS_DEAD);
+ READ_VALUE(CTX_JB_NOSIG);
+ READ_VALUE(CTX_JB);
+ READ_VALUE(CTX_SJB);
+ READ_VALUE(CTX_UC);
+}
+
+#define READ_FIELD(ptr, T, field, result) \
+ read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result)
+
+static u_int64_t
+read_pthread_uniqueid (ptr)
+ CORE_ADDR ptr;
+{
+ u_int64_t uniqueid;
+ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
+ return uniqueid;
+}
+
+static CORE_ADDR
+read_pthread_next (ptr)
+ CORE_ADDR ptr;
+{
+ CORE_ADDR next;
+ READ_FIELD(ptr, CORE_ADDR, next, next);
+ return next;
+}
+
+static void
+read_cached_pthread (ptr, cache)
+ CORE_ADDR ptr;
+ struct cached_pthread *cache;
+{
+ READ_FIELD(ptr, u_int64_t, uniqueid, cache->uniqueid);
+ READ_FIELD(ptr, int, state, cache->state);
+ READ_FIELD(ptr, CORE_ADDR, name, cache->name);
+ READ_FIELD(ptr, int, ctxtype, cache->ctxtype);
+ READ_FIELD(ptr, ucontext_t, ctx, cache->ctx);
+}
+
+static int
+find_active_thread ()
+{
+ CORE_ADDR ptr;
+
+ if (main_pid == -1)
+ return -1;
+
+ read_memory ((CORE_ADDR)P_thread_run,
+ (char *)&ptr,
+ sizeof ptr);
+
+ return find_pid(read_pthread_uniqueid(ptr));
+}
+
+static CORE_ADDR find_pthread_addr PARAMS ((int thread));
+static struct cached_pthread * find_pthread PARAMS ((int thread));
+
+static CORE_ADDR
+find_pthread_addr (thread)
+ int thread;
+{
+ CORE_ADDR ptr;
+
+ if (thread == cached_thread)
+ return cached_pthread_addr;
+
+ read_memory ((CORE_ADDR)P_thread_list,
+ (char *)&ptr,
+ sizeof ptr);
+
+ while (ptr != 0)
+ {
+ if (find_pid(read_pthread_uniqueid(ptr)) == thread)
+ {
+ cached_thread = thread;
+ cached_pthread_addr = ptr;
+ read_cached_pthread(ptr, &cached_pthread);
+ return ptr;
+ }
+ ptr = read_pthread_next(ptr);
+ }
+
+ return NULL;
+}
+
+static struct cached_pthread *
+find_pthread (thread)
+ int thread;
+{
+ CORE_ADDR ptr;
+
+ if (thread == cached_thread)
+ return &cached_pthread;
+
+ read_memory ((CORE_ADDR)P_thread_list,
+ (char *)&ptr,
+ sizeof ptr);
+
+ while (ptr != 0)
+ {
+ if (find_pid(read_pthread_uniqueid(ptr)) == thread)
+ {
+ cached_thread = thread;
+ cached_pthread_addr = ptr;
+ read_cached_pthread(ptr, &cached_pthread);
+ return &cached_pthread;
+ }
+ ptr = read_pthread_next(ptr);
+ }
+
+#if 0
+ error ("Can't find pthread %d,%d",
+ THREADID_TID(thread), THREADID_PID(thread));
+#endif
+ 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
+freebsd_uthread_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
+freebsd_uthread_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ child_ops.to_attach (args, from_tty);
+ push_target (&freebsd_uthread_ops);
+ freebsd_uthread_attaching = 1;
+}
+
+/* After an attach, see if the target is threaded */
+
+static void
+freebsd_uthread_post_attach (pid)
+ int pid;
+{
+ if (freebsd_uthread_active)
+ {
+ read_thread_offsets ();
+
+ main_pid = pid;
+
+ bind_target_thread_vector (&freebsd_uthread_vec);
+
+ inferior_pid = find_active_thread ();
+
+ add_thread (inferior_pid);
+ }
+ else
+ {
+ unpush_target (&freebsd_uthread_ops);
+ push_target (&child_ops);
+ }
+
+ freebsd_uthread_attaching = 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 the normal ptrace (PTRACE_TRACEME). */
+
+static void
+freebsd_uthread_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
+freebsd_uthread_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
+{
+ struct cleanup *old_chain;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_resume (pid, step, signo);
+ return;
+ }
+
+ old_chain = save_inferior_pid ();
+
+ pid = inferior_pid = main_pid;
+
+ child_ops.to_resume (pid, step, signo);
+
+ cached_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
+freebsd_uthread_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int rtnval;
+ struct cleanup *old_chain;
+
+ if (freebsd_uthread_attaching)
+ {
+ return child_ops.to_wait (pid, ourstatus);
+ }
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ if (pid != -1)
+ pid = main_pid;
+
+ rtnval = child_ops.to_wait (pid, ourstatus);
+
+ if (rtnval >= 0)
+ {
+ rtnval = find_active_thread ();
+ if (!in_thread_list (rtnval))
+ add_thread (rtnval);
+ }
+
+ do_cleanups (old_chain);
+
+ return rtnval;
+}
+
+#ifdef __i386__
+
+static char sigmap[NUM_REGS] = /* map reg to sigcontext */
+{
+ 12, /* eax */
+ 11, /* ecx */
+ 10, /* edx */
+ 9, /* ebx */
+ 8, /* esp */
+ 7, /* ebp */
+ 6, /* esi */
+ 5, /* edi */
+ 15, /* eip */
+ 17, /* eflags */
+ 16, /* cs */
+ 19, /* ss */
+ 4, /* ds */
+ 3, /* es */
+ 2, /* fs */
+ 1, /* gs */
+};
+
+static char jmpmap[NUM_REGS] = /* map reg to jmp_buf */
+{
+ 6, /* eax */
+ -1, /* ecx */
+ -1, /* edx */
+ 1, /* ebx */
+ 2, /* esp */
+ 3, /* ebp */
+ 4, /* esi */
+ 5, /* edi */
+ 0, /* eip */
+ -1, /* eflags */
+ -1, /* cs */
+ -1, /* ss */
+ -1, /* ds */
+ -1, /* es */
+ -1, /* fs */
+ -1, /* gs */
+};
+
+#endif
+
+#ifdef __alpha__
+
+static char sigmap[NUM_REGS] = /* map reg to sigcontext */
+{
+ 1, 2, 3, 4, 5, 6, 7, 8, /* v0 - t6 */
+ 9, 10, 11, 12, 13, 14, 15, 16, /* t7 - fp */
+ 17, 18, 19, 20, 21, 22, 23, 24, /* a0 - t9 */
+ 25, 26, 27, 28, 29, 30, 31, 32, /* t10 - zero */
+ 38, 39, 40, 41, 42, 43, 44, 45, /* f0 - f7 */
+ 46, 47, 48, 49, 50, 51, 52, 53, /* f8 - f15 */
+ 54, 55, 56, 57, 58, 59, 60, 61, /* f16 - f23 */
+ 62, 63, 64, 65, 66, 67, 68, 69, /* f24 - f31 */
+ 33, -1 /* pc, vfp */
+};
+static char jmpmap[NUM_REGS] = {
+ 4, 5, 6, 7, 8, 9, 10, 11, /* v0 - t6 */
+ 12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */
+ 20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */
+ 28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */
+ 37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */
+ 45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */
+ 53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */
+ 61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */
+ 2, -1, /* pc, vfp */
+};
+
+#endif
+
+static void
+freebsd_uthread_fetch_registers (regno)
+ int regno;
+{
+ struct cached_pthread *thread;
+ struct cleanup *old_chain;
+ int active;
+ int first_regno, last_regno;
+ register_t *regbase;
+ char *regmap;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_fetch_registers (regno);
+ return;
+ }
+
+ thread = find_pthread (inferior_pid);
+
+ old_chain = save_inferior_pid ();
+
+ active = (inferior_pid == find_active_thread());
+
+ inferior_pid = main_pid;
+
+ if (active)
+ {
+ 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;
+ }
+
+ if (thread->ctxtype == CTX_UC_value)
+ {
+ regbase = (register_t*) &thread->ctx.uc.uc_mcontext;
+ regmap = sigmap;
+ }
+ else
+ {
+ regbase = (register_t*) &thread->ctx.jb[0];
+ regmap = jmpmap;
+ }
+
+ for (regno = first_regno; regno <= last_regno; regno++)
+ {
+ if (regmap[regno] == -1)
+ child_ops.to_fetch_registers (regno);
+ else
+ supply_register (regno, (char*) &regbase[regmap[regno]]);
+ }
+
+ do_cleanups (old_chain);
+}
+
+static void
+freebsd_uthread_store_registers (regno)
+ int regno;
+{
+ struct cached_pthread *thread;
+ CORE_ADDR ptr;
+ struct cleanup *old_chain;
+ int first_regno, last_regno;
+ u_int32_t *regbase;
+ char *regmap;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_store_registers (regno);
+ return;
+ }
+
+ thread = find_pthread (inferior_pid);
+
+ old_chain = save_inferior_pid ();
+
+ inferior_pid = main_pid;
+
+ if (thread->state == PS_RUNNING_value)
+ {
+ 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;
+ }
+
+ if (thread->ctxtype == CTX_UC_value)
+ {
+ regbase = (u_int32_t*) &thread->ctx.uc.uc_mcontext;
+ regmap = sigmap;
+ }
+ else
+ {
+ regbase = (u_int32_t*) &thread->ctx.jb[0];
+ regmap = jmpmap;
+ }
+
+ ptr = find_pthread_addr (inferior_pid);
+ for (regno = first_regno; regno <= last_regno; regno++)
+ {
+ if (regmap[regno] == -1)
+ child_ops.to_store_registers (regno);
+ else
+ {
+ u_int32_t *reg = &regbase[regmap[regno]];
+ int off;
+
+ /* Hang onto cached value */
+ memcpy(reg, registers + REGISTER_BYTE (regno),
+ REGISTER_RAW_SIZE (regno));
+
+ /* And push out to inferior */
+ off = (char *) reg - (char *) thread;
+ write_memory (ptr + off,
+ 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
+freebsd_uthread_prepare_to_store ()
+{
+ struct cleanup *old_chain;
+
+ if (freebsd_uthread_attaching)
+ {
+ child_ops.to_prepare_to_store ();
+ return;
+ }
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ child_ops.to_prepare_to_store ();
+
+ do_cleanups (old_chain);
+}
+
+static int
+freebsd_uthread_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;
+
+ if (freebsd_uthread_attaching)
+ {
+ return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
+ }
+
+ 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
+freebsd_uthread_files_info (ignore)
+ struct target_ops *ignore;
+{
+ child_ops.to_files_info (ignore);
+}
+
+static void
+freebsd_uthread_kill_inferior ()
+{
+ inferior_pid = main_pid;
+ child_ops.to_kill ();
+}
+
+static void
+freebsd_uthread_notice_signals (pid)
+ int pid;
+{
+ struct cleanup *old_chain;
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ child_ops.to_notice_signals (pid);
+
+ do_cleanups (old_chain);
+}
+
+/* Fork an inferior process, and start debugging it with /proc. */
+
+static void
+freebsd_uthread_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ child_ops.to_create_inferior (exec_file, allargs, env);
+
+ if (inferior_pid && freebsd_uthread_active)
+ {
+ read_thread_offsets ();
+
+ main_pid = inferior_pid;
+
+ push_target (&freebsd_uthread_ops);
+ bind_target_thread_vector (&freebsd_uthread_vec);
+
+ inferior_pid = find_active_thread ();
+
+ add_thread (inferior_pid);
+ }
+}
+
+/* This routine is called to find out if the inferior is using threads.
+ We check for the _thread_run and _thread_list globals. */
+
+void
+freebsd_uthread_new_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct minimal_symbol *ms;
+
+ if (!objfile)
+ {
+ freebsd_uthread_active = 0;
+ return;
+ }
+
+ ms = lookup_minimal_symbol ("_thread_run", NULL, objfile);
+
+ if (!ms)
+ return;
+
+ P_thread_run = SYMBOL_VALUE_ADDRESS (ms);
+
+ ms = lookup_minimal_symbol ("_thread_list", NULL, objfile);
+
+ if (!ms)
+ return;
+
+ P_thread_list = SYMBOL_VALUE_ADDRESS (ms);
+
+#define OFFSET_SYM(field) "_thread_" #field "_offset"
+#define LOOKUP_OFFSET(field) \
+ do { \
+ ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile); \
+ if (!ms) \
+ return; \
+ P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms); \
+ } while (0);
+
+#define VALUE_SYM(name) "_thread_" #name "_value"
+#define LOOKUP_VALUE(name) \
+ do { \
+ ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile); \
+ if (!ms) \
+ return; \
+ P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms); \
+ } while (0);
+
+ LOOKUP_OFFSET(next);
+ LOOKUP_OFFSET(uniqueid);
+ LOOKUP_OFFSET(state);
+ LOOKUP_OFFSET(name);
+ LOOKUP_OFFSET(ctxtype);
+ LOOKUP_OFFSET(ctx);
+
+ LOOKUP_VALUE(PS_RUNNING);
+ LOOKUP_VALUE(PS_DEAD);
+ LOOKUP_VALUE(CTX_JB_NOSIG);
+ LOOKUP_VALUE(CTX_JB);
+ LOOKUP_VALUE(CTX_SJB);
+ LOOKUP_VALUE(CTX_UC);
+
+ freebsd_uthread_active = 1;
+}
+
+int
+freebsd_uthread_has_exited (pid, wait_status, exit_status)
+ int pid;
+ int wait_status;
+ int * exit_status;
+{
+ int t = child_ops.to_has_exited (pid, wait_status, exit_status);
+ if (t)
+ main_pid = -1;
+ return t;
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+freebsd_uthread_mourn_inferior ()
+{
+ inferior_pid = main_pid; /* don't bother to restore inferior_pid */
+ child_ops.to_mourn_inferior ();
+ unpush_target (&freebsd_uthread_ops);
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
+
+static int
+freebsd_uthread_can_run ()
+{
+ return child_suppress_run;
+}
+
+static int
+freebsd_uthread_thread_alive (pid)
+ int pid;
+{
+ struct cleanup *old_chain;
+ struct cached_pthread *thread;
+ int ret = 0;
+
+ if (freebsd_uthread_attaching)
+ return 1;
+
+ /*
+ * We can get called from child_ops.to_wait() which passes the underlying
+ * pid (without a thread number).
+ */
+ if (THREADID_TID(pid) == 0)
+ return 1;
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ if (find_pthread_addr (pid) != 0)
+ {
+ thread = find_pthread (pid);
+ ret = (thread->state != PS_DEAD_value);
+ }
+
+ do_cleanups (old_chain);
+
+ if (!ret)
+ free_pid(pid);
+
+ return ret;
+}
+
+static void
+freebsd_uthread_stop ()
+{
+ struct cleanup *old_chain;
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ child_ops.to_stop ();
+
+ do_cleanups (old_chain);
+}
+
+static int
+freebsd_uthread_find_new_threads ()
+{
+ CORE_ADDR ptr;
+ int state;
+ u_int64_t uniqueid;
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ read_memory ((CORE_ADDR)P_thread_list,
+ (char *)&ptr,
+ sizeof ptr);
+
+ while (ptr != 0)
+ {
+ READ_FIELD(ptr, int, state, state);
+ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
+ if (state != PS_DEAD_value &&
+ !in_thread_list (find_pid(uniqueid)))
+ add_thread (find_pid(uniqueid));
+ ptr = read_pthread_next(ptr);
+ }
+
+ do_cleanups (old_chain);
+
+ return 0;
+}
+
+/* MUST MATCH enum pthread_state */
+static const char *statenames[] = {
+ "RUNNING",
+ "SIGTHREAD",
+ "MUTEX_WAIT",
+ "COND_WAIT",
+ "FDLR_WAIT",
+ "FDLW_WAIT",
+ "FDR_WAIT",
+ "FDW_WAIT",
+ "POLL_WAIT",
+ "FILE_WAIT",
+ "SELECT_WAIT",
+ "SLEEP_WAIT",
+ "WAIT_WAIT",
+ "SIGSUSPEND",
+ "SIGWAIT",
+ "SPINBLOCK",
+ "JOIN",
+ "SUSPENDED",
+ "DEAD",
+ "DEADLOCK",
+};
+
+static int
+freebsd_uthread_get_thread_info (ref, selection, info)
+ gdb_threadref *ref;
+ int selection;
+ struct gdb_ext_thread_info *info;
+{
+ int pid = *ref;
+ struct cached_pthread *thread = find_pthread (pid);
+ struct cleanup *old_chain;
+
+ old_chain = save_inferior_pid ();
+ inferior_pid = main_pid;
+
+ memset(&info->threadid, 0, OPAQUETHREADBYTES);
+
+ memcpy(&info->threadid, ref, sizeof *ref);
+ info->active = thread->state == PS_RUNNING_value;
+ strcpy(info->display, statenames[thread->state]);
+ if (thread->name)
+ read_memory ((CORE_ADDR) thread->name, info->shortname, 32);
+ else
+ strcpy(info->shortname, "");
+
+ do_cleanups (old_chain);
+ return (0);
+}
+
+char *
+freebsd_uthread_pid_to_str (pid)
+ int pid;
+{
+ static char buf[30];
+
+ if (STREQ (current_target.to_shortname, "freebsd-uthreads"))
+ sprintf (buf, "process %d, thread %d\0",
+ THREADID_PID(pid), THREADID_TID(pid));
+ else
+ sprintf (buf, "process %d\0", pid);
+
+ return buf;
+}
+
+
+static void
+init_freebsd_uthread_ops ()
+{
+ freebsd_uthread_ops.to_shortname = "freebsd-uthreads";
+ freebsd_uthread_ops.to_longname = "FreeBSD uthreads";
+ freebsd_uthread_ops.to_doc = "FreeBSD user threads support.";
+ freebsd_uthread_ops.to_open = freebsd_uthread_open;
+ freebsd_uthread_ops.to_attach = freebsd_uthread_attach;
+ freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach;
+ freebsd_uthread_ops.to_detach = freebsd_uthread_detach;
+ freebsd_uthread_ops.to_resume = freebsd_uthread_resume;
+ freebsd_uthread_ops.to_wait = freebsd_uthread_wait;
+ freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers;
+ freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers;
+ freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store;
+ freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory;
+ freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info;
+ freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ freebsd_uthread_ops.to_terminal_init = terminal_init_inferior;
+ freebsd_uthread_ops.to_terminal_inferior = terminal_inferior;
+ freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ freebsd_uthread_ops.to_terminal_ours = terminal_ours;
+ freebsd_uthread_ops.to_terminal_info = child_terminal_info;
+ freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior;
+ freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior;
+ freebsd_uthread_ops.to_has_exited = freebsd_uthread_has_exited;
+ freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior;
+ freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run;
+ freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals;
+ freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive;
+ freebsd_uthread_ops.to_stop = freebsd_uthread_stop;
+ freebsd_uthread_ops.to_stratum = process_stratum;
+ freebsd_uthread_ops.to_has_all_memory = 1;
+ freebsd_uthread_ops.to_has_memory = 1;
+ freebsd_uthread_ops.to_has_stack = 1;
+ freebsd_uthread_ops.to_has_registers = 1;
+ freebsd_uthread_ops.to_has_execution = 1;
+ freebsd_uthread_ops.to_has_thread_control = 0;
+ freebsd_uthread_ops.to_magic = OPS_MAGIC;
+
+ freebsd_uthread_vec.find_new_threads = freebsd_uthread_find_new_threads;
+ freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info;
+}
+
+void
+_initialize_freebsd_uthread ()
+{
+ init_freebsd_uthread_ops ();
+ add_target (&freebsd_uthread_ops);
+
+ child_suppress_run = 1;
+}
diff --git a/gnu/usr.bin/binutils/gdb5/i386/freebsd-nat.c b/gnu/usr.bin/binutils/gdb5/i386/freebsd-nat.c
new file mode 100644
index 0000000..f309508
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/i386/freebsd-nat.c
@@ -0,0 +1,672 @@
+/* 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. */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include "gdbcore.h"
+#include "value.h"
+#include "inferior.h"
+
+#if defined(HAVE_GREGSET_T) || defined(HAVE_FPREGSET_T)
+#include <sys/procfs.h>
+#endif
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'tEAX' come from <machine/reg.h> */
+static int tregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS,
+ tDS, tES, tFS, tGS,
+};
+
+static struct save87 pcb_savefpu;
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (&registers[REGISTER_BYTE (r)], ((int *)&inferior_registers) + tregmap[r], 4);
+
+ registers_fetched ();
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (((int *)&inferior_registers) + tregmap[r], &registers[REGISTER_BYTE (r)], 4);
+
+ ptrace (PT_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+}
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them.
+ Extract the floating point state out of the core file and store
+ it where `float_info' will find it.
+
+ 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 int cregno;
+ register int addr;
+ int bad_reg = -1;
+ int offset;
+ struct user *tmp_uaddr;
+
+ /*
+ * First get virtual address of user structure. Then calculate offset.
+ */
+ memcpy(&tmp_uaddr,
+ &((struct user *) core_reg_sect)->u_kproc.ki_addr,
+ sizeof(tmp_uaddr));
+ offset = -reg_addr - (int) tmp_uaddr;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ cregno = tregmap[regno];
+ if (cregno == tGS)
+ addr = offsetof (struct user, u_pcb) + offsetof (struct pcb, pcb_gs);
+ else
+ addr = offset + 4 * cregno;
+ 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.", gdb_register_names[bad_reg]);
+ }
+
+ addr = offsetof (struct user, u_pcb) + offsetof (struct pcb, pcb_savefpu);
+ memcpy (&pcb_savefpu, core_reg_sect + addr, sizeof pcb_savefpu);
+}
+
+#ifdef FLOAT_INFO
+#include "expression.h"
+#include "language.h" /* for local_hex_string */
+#include "floatformat.h"
+
+#include <sys/param.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
+
+static void
+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 */
+}
+
+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 instruction: ");
+ 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--)
+ {
+ int exp;
+ int mantissa_or;
+ int normal;
+ char *sign;
+ int st_regno;
+ unsigned short *usregs;
+ double val;
+
+ /* The physical regno `fpreg' is only relevant as an index into the
+ * tag word. Logical `%st' numbers are required for indexing ep->regs.
+ */
+ st_regno = (fpreg + 8 - top) & 7;
+
+ printf_unfiltered ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : " ");
+
+ 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[st_regno][i]);
+
+ printf_unfiltered (" ");
+
+ /*
+ * Handle weird cases better than floatformat_to_double () and
+ * printf ().
+ */
+ usregs = (unsigned short *) ep->regs[st_regno];
+ sign = usregs[4] & 0x8000 ? "-" : "";
+ exp = usregs[4] & 0x7fff;
+ normal = usregs[3] & 0x8000;
+ mantissa_or = usregs[0] | usregs[1] | usregs[2] | (usregs[3] & 0x7fff);
+ if (exp == 0)
+ {
+ if (normal)
+ printf_unfiltered ("Pseudo Denormal (0 as a double)");
+ else if (mantissa_or == 0)
+ printf_unfiltered ("%s0", sign);
+ else
+ printf_unfiltered ("Denormal (0 as a double)");
+ }
+ else if (exp == 0x7fff)
+ {
+ if (!normal)
+ printf_unfiltered ("Pseudo ");
+ if (mantissa_or == 0)
+ printf_unfiltered ("%sInf", sign);
+ else
+ printf_unfiltered ("%s NaN",
+ usregs[3] & 0x4000 ? "Quiet" : "Signaling");
+ if (!normal)
+ printf_unfiltered (" (NaN)");
+ }
+ else if (!normal)
+ printf_unfiltered ("Unnormal (NaN)");
+ else
+ {
+#if 0
+ /* Use this we stop trapping on overflow. */
+ floatformat_to_double(&floatformat_i387_ext,
+ (char *) ep->regs[st_regno], &val);
+#else
+ i387_to_double((char *) ep->regs[st_regno], (char *) &val);
+#endif
+ printf_unfiltered ("%g", val);
+ }
+ printf_unfiltered ("\n");
+ }
+}
+
+void
+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 != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+ ptrace(PT_GETFPREGS, pid, &buf[0], sizeof(struct fpreg));
+ fpstatep = (struct fpstate *)&buf[0];
+ }
+ else
+ fpstatep = &pcb_savefpu;
+
+ print_387_status (fpstatep->sv_ex_sw, (struct env387 *)fpstatep);
+}
+#endif /* FLOAT_INFO */
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#ifdef SETUP_ARBITRARY_FRAME
+#include "frame.h"
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+ int argc;
+ CORE_ADDR *argv;
+{
+ if (argc != 2)
+ error ("i386 frame specifications require two arguments: sp and pc");
+
+ return create_new_frame (argv[0], argv[1]);
+}
+#endif /* SETUP_ARBITRARY_FRAME */
+
+#ifdef HAVE_GREGSET_T
+void
+supply_gregset (gp)
+ gregset_t *gp;
+{
+ int regno = 0;
+
+ /* These must be ordered the same as REGISTER_NAMES in
+ config/i386/tm-i386.h. */
+ supply_register (regno++, (char *)&gp->r_eax);
+ supply_register (regno++, (char *)&gp->r_ecx);
+ supply_register (regno++, (char *)&gp->r_edx);
+ supply_register (regno++, (char *)&gp->r_ebx);
+ supply_register (regno++, (char *)&gp->r_esp);
+ supply_register (regno++, (char *)&gp->r_ebp);
+ supply_register (regno++, (char *)&gp->r_esi);
+ supply_register (regno++, (char *)&gp->r_edi);
+ supply_register (regno++, (char *)&gp->r_eip);
+ supply_register (regno++, (char *)&gp->r_eflags);
+ supply_register (regno++, (char *)&gp->r_cs);
+ supply_register (regno++, (char *)&gp->r_ss);
+ supply_register (regno++, (char *)&gp->r_ds);
+ supply_register (regno++, (char *)&gp->r_es);
+ supply_register (regno++, (char *)&gp->r_fs);
+ supply_register (regno++, (char *)&gp->r_gs);
+}
+#endif /* HAVE_GREGSET_T */
+
+#ifdef HAVE_FPREGSET_T
+void
+supply_fpregset (fp)
+ fpregset_t *fp;
+{
+ memcpy (&pcb_savefpu, fp, sizeof pcb_savefpu);
+}
+#endif /* HAVE_FPREGSET_T */
+
+/* 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);
+}
+
+#ifdef PT_GETDBREGS
+
+/*
+ * 0: no trace output
+ * 1: trace watchpoint requests
+ * 2: trace `watchpoint hit?' tests, too
+ */
+#define WATCHPOINT_DEBUG 0
+
+#include "breakpoint.h"
+
+int
+can_watch(type, cnt, ot)
+ int type, cnt, ot;
+{
+ int rv;
+ static int cnt_watch, cnt_awatch;
+
+ switch (type)
+ {
+ case bp_hardware_watchpoint:
+ cnt_watch = cnt;
+ break;
+
+ case bp_access_watchpoint:
+ cnt_awatch = cnt;
+ break;
+
+ default:
+ rv = 0;
+ goto overandout;
+ }
+
+ rv = cnt_watch + cnt_awatch <= 4? 1: -1;
+
+ overandout:
+#if WATCHPOINT_DEBUG
+ printf_filtered("can_watch(%d, %d, %d) = %d (counts: w: %d, rw: %d)\n",
+ type, cnt, ot, rv, cnt_watch, cnt_awatch);
+#endif
+
+ return rv;
+}
+
+int
+stopped_by_watchpoint()
+{
+ struct dbreg dbr;
+ extern int inferior_pid;
+
+ if (current_target.to_shortname == 0 ||
+ ! (strcmp(current_target.to_shortname, "child") == 0 ||
+ strcmp(current_target.to_shortname, "freebsd-uthreads") == 0))
+ return 0;
+
+ if (inferior_pid != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+
+ if (ptrace(PT_GETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_GETDBREGS) failed");
+ return 0;
+ }
+#if WATCHPOINT_DEBUG > 1
+ printf_filtered("stopped_by_watchpoint(): DR6 = %#x\n", dbr.dr6);
+#endif
+ /*
+ * If a hardware watchpoint was hit, one of the lower 4 bits in
+ * DR6 is set (the actual bit indicates which of DR0...DR3 triggered
+ * the trap).
+ */
+ return dbr.dr6 & 0x0f;
+ }
+ else
+ {
+ warning("Can't set a watchpoint on a core file.");
+ return 0;
+ }
+}
+
+int
+insert_watchpoint(addr, len, type)
+ int addr, len, type;
+{
+ struct dbreg dbr;
+ extern int inferior_pid;
+
+ if (current_target.to_shortname == 0 ||
+ ! (strcmp(current_target.to_shortname, "child") == 0 ||
+ strcmp(current_target.to_shortname, "freebsd-uthreads") == 0))
+ return 0;
+
+ if (inferior_pid != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+ int i, mask;
+ unsigned int sbits;
+
+ if (ptrace(PT_GETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_GETDBREGS) failed");
+ return 0;
+ }
+
+ for (i = 0, mask = 0x03; i < 4; i++, mask <<= 2)
+ if ((dbr.dr7 & mask) == 0)
+ break;
+ if (i >= 4) {
+ warning("no more hardware watchpoints available");
+ return -1;
+ }
+
+ /* paranoia */
+ if (len > 4)
+ {
+ warning("watchpoint length %d unsupported, using lenght = 4",
+ len);
+ len = 4;
+ }
+ else if (len == 3)
+ {
+ warning("weird watchpoint length 3, using 2");
+ len = 2;
+ }
+ else if (len == 0)
+ {
+ warning("weird watchpoint length 0, using 1");
+ len = 1;
+ }
+
+ switch (len)
+ {
+ case 1: sbits = 0; break;
+ case 2: sbits = 4; break;
+ case 4: sbits = 0x0c; break;
+ }
+
+ /*
+ * The `type' value is 0 for `watch on write', 1 for `watch on
+ * read', 2 for `watch on both'. The i386 debug register
+ * breakpoint types are 0 for `execute' (not used in GDB), 1 for
+ * `write', and 4 for `read/write'. Plain `read' trapping is
+ * not supported on i386, value 3 is illegal.
+ */
+ switch (type)
+ {
+ default:
+ warning("weird watchpoint type %d, using a write watchpoint");
+ /* FALLTHROUGH */
+ case 0:
+ sbits |= 1;
+ break;
+
+ case 2:
+ sbits |= 3;
+ break;
+ }
+ sbits <<= 4 * i + 16;
+ sbits |= 1 << 2 * i;
+
+ dbr.dr7 |= sbits;
+ *(&dbr.dr0 + i) = (unsigned int)addr;
+
+#if WATCHPOINT_DEBUG
+ printf_filtered("insert_watchpoint(), inserting DR7 = %#x, DR%d = %#x\n",
+ dbr.dr7, i, addr);
+#endif
+ if (ptrace(PT_SETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_SETDBREGS) failed");
+ return 0;
+ }
+ }
+ else
+ {
+ warning("Can't set a watchpoint on a core file.");
+ return 0;
+ }
+}
+
+int
+remove_watchpoint(addr, len, type)
+ int addr, len, type;
+{
+ struct dbreg dbr;
+ extern int inferior_pid;
+
+ if (current_target.to_shortname == 0 ||
+ ! (strcmp(current_target.to_shortname, "child") == 0 ||
+ strcmp(current_target.to_shortname, "freebsd-uthreads") == 0))
+ return 0;
+
+ if (inferior_pid != 0 && core_bfd == NULL)
+ {
+ int pid = inferior_pid & ((1 << 17) - 1); /* XXX extract pid from tid */
+ int i;
+ unsigned int sbits, *dbregp;
+
+ if (ptrace(PT_GETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_GETDBREGS) failed");
+ return 0;
+ }
+
+ for (i = 0, dbregp = &dbr.dr0; i < 4; i++, dbregp++)
+ if (*dbregp == (unsigned int)addr)
+ break;
+ if (i >= 4)
+ {
+ warning("watchpoint for address %#x not found", addr);
+ return -1;
+ }
+
+ *dbregp = 0;
+ sbits = 0xf << (4 * i + 16);
+ sbits |= 3 << 2 * i;
+ dbr.dr7 &= ~sbits;
+
+#if WATCHPOINT_DEBUG
+ printf_filtered("remove_watchpoint(): removing watchpoint for %#x, DR7 = %#x\n",
+ addr, dbr.dr7);
+#endif
+ if (ptrace(PT_SETDBREGS, pid, (caddr_t)&dbr, 0) == -1)
+ {
+ perror("ptrace(PT_SETDBREGS) failed");
+ return 0;
+ }
+ }
+ else
+ {
+ warning("Can't set a watchpoint on a core file.");
+ return 0;
+ }
+}
+
+#endif /* PT_GETDBREGS */
diff --git a/gnu/usr.bin/binutils/gdb5/i386/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb5/i386/kvm-fbsd.c
new file mode 100644
index 0000000..9f2d69d
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/i386/kvm-fbsd.c
@@ -0,0 +1,995 @@
+/* Live and postmortem kernel debugging functions for FreeBSD.
+ 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. */
+
+/* $FreeBSD$ */
+
+#include "defs.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <sys/sysctl.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+#include <sys/stat.h>
+#include <unistd.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <machine/vmparam.h>
+#include <machine/pcb.h>
+#include <machine/tss.h>
+#include <machine/frame.h>
+#include <machine/globaldata.h>
+
+static void kcore_files_info PARAMS ((struct target_ops *));
+
+static void kcore_close PARAMS ((int));
+
+static void get_kcore_registers PARAMS ((int));
+
+static int kcore_xfer_kmem PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static int xfer_umem PARAMS ((CORE_ADDR, char *, int, int));
+
+static CORE_ADDR ksym_lookup PARAMS ((const char *));
+
+static int read_pcb PARAMS ((int, CORE_ADDR));
+
+static struct proc * curProc PARAMS ((void));
+
+static int set_proc_context PARAMS ((CORE_ADDR paddr));
+
+static void kcore_open PARAMS ((char *filename, int from_tty));
+
+static void kcore_detach PARAMS ((char *args, int from_tty));
+
+static void set_proc_cmd PARAMS ((char *arg, int from_tty));
+
+static void set_cpu_cmd PARAMS ((char *arg, int from_tty));
+
+static CORE_ADDR kvtophys PARAMS ((int, CORE_ADDR));
+
+static int physrd PARAMS ((int, u_int, char*, int));
+
+static int kvm_open PARAMS ((const char *efile, char *cfile, char *sfile,
+ int perm, char *errout));
+
+static int kvm_close PARAMS ((int fd));
+
+static int kvm_write PARAMS ((int core_kd, CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int kvm_read PARAMS ((int core_kd, CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int kvm_uread PARAMS ((int core_kd, struct proc *p,
+ CORE_ADDR memaddr, char *myaddr,
+ int len));
+
+static int kernel_core_file_hook PARAMS ((int fd, CORE_ADDR addr,
+ char *buf, int len));
+
+static CORE_ADDR kvm_getpcpu PARAMS ((int cfd, int cpuid));
+
+static struct kinfo_proc * kvm_getprocs PARAMS ((int cfd, int op,
+ CORE_ADDR proc, int *cnt));
+
+extern struct target_ops kcore_ops; /* Forward decl */
+
+/* Non-zero means we are debugging a kernel core file */
+int kernel_debugging = 0;
+int kernel_writablecore = 0;
+
+static char *core_file;
+static int core_kd = -1;
+static struct proc *cur_proc;
+static CORE_ADDR kernel_start;
+
+static CORE_ADDR pcpu;
+#define PCPU_OFFSET(name) \
+ offsetof(struct globaldata, gd_ ## name)
+
+/*
+ * Symbol names of kernel entry points. Use special frames.
+ */
+#define KSYM_TRAP "calltrap"
+#define KSYM_INTERRUPT "Xresume"
+#define KSYM_SYSCALL "Xsyscall"
+
+/*
+ * Read the "thing" at kernel address 'addr' into the space pointed to
+ * by point. The length of the "thing" is determined by the type of p.
+ * Result is non-zero if transfer fails.
+ */
+#define kvread(addr, p) \
+ (target_read_memory ((CORE_ADDR)(addr), (char *)(p), sizeof(*(p))))
+
+
+
+/*
+ * The following is FreeBSD-specific hackery to decode special frames
+ * and elide the assembly-language stub. This could be made faster by
+ * defining a frame_type field in the machine-dependent frame information,
+ * but we don't think that's too important right now.
+ */
+enum frametype { tf_normal, tf_trap, tf_interrupt, tf_syscall };
+
+CORE_ADDR
+fbsd_kern_frame_saved_pc (fr)
+struct frame_info *fr;
+{
+ struct minimal_symbol *sym;
+ CORE_ADDR this_saved_pc;
+ enum frametype frametype;
+
+ this_saved_pc = read_memory_integer (fr->frame + 4, 4);
+ sym = lookup_minimal_symbol_by_pc (this_saved_pc);
+ frametype = tf_normal;
+ if (sym != NULL) {
+ if (strcmp (SYMBOL_NAME(sym), KSYM_TRAP) == 0)
+ frametype = tf_trap;
+ else if (strncmp (SYMBOL_NAME(sym), KSYM_INTERRUPT, 7) == 0)
+ frametype = tf_interrupt;
+ else if (strcmp (SYMBOL_NAME(sym), KSYM_SYSCALL) == 0)
+ frametype = tf_syscall;
+ }
+
+ switch (frametype) {
+ case tf_normal:
+ return (this_saved_pc);
+
+#define oEIP offsetof(struct trapframe, tf_eip)
+
+ case tf_trap:
+ return (read_memory_integer (fr->frame + 8 + oEIP, 4));
+
+ case tf_interrupt:
+ return (read_memory_integer (fr->frame + 16 + oEIP, 4));
+
+ case tf_syscall:
+ return (read_memory_integer (fr->frame + 8 + oEIP, 4));
+#undef oEIP
+ }
+}
+
+static CORE_ADDR
+ksym_lookup (name)
+const char *name;
+{
+ struct minimal_symbol *sym;
+
+ sym = lookup_minimal_symbol (name, NULL, NULL);
+ if (sym == NULL)
+ error ("kernel symbol `%s' not found.", name);
+
+ return SYMBOL_VALUE_ADDRESS (sym);
+}
+
+static struct proc *
+curProc ()
+{
+ struct proc *p;
+ CORE_ADDR addr = pcpu + PCPU_OFFSET (curproc);
+
+ if (kvread (addr, &p))
+ error ("cannot read proc pointer at %x\n", addr);
+ return p;
+}
+
+/*
+ * Set the process context to that of the proc structure at
+ * system address paddr.
+ */
+static int
+set_proc_context (paddr)
+ CORE_ADDR paddr;
+{
+ struct proc p;
+
+ if (paddr < kernel_start)
+ return (1);
+
+ cur_proc = (struct proc *)paddr;
+#ifdef notyet
+ set_kernel_boundaries (cur_proc);
+#endif
+
+ /* Fetch all registers from core file */
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ return (0);
+}
+
+/* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+/* ARGSUSED */
+static void
+kcore_close (quitting)
+ int quitting;
+{
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ if (core_kd)
+ {
+ kvm_close (core_kd);
+ free (core_file);
+ core_file = NULL;
+ core_kd = -1;
+ }
+}
+
+/* This routine opens and sets up the core file bfd */
+
+static void
+kcore_open (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ const char *p;
+ struct cleanup *old_chain;
+ char buf[256], *cp;
+ int ontop;
+ CORE_ADDR addr;
+ struct pcb pcb;
+
+ target_preopen (from_tty);
+
+ unpush_target (&kcore_ops);
+
+ if (!filename)
+ {
+ /*error (core_kd?*/
+ error ( (core_kd >= 0)?
+ "No core file specified. (Use `detach' to stop debugging a core file.)"
+ : "No core file specified.");
+ }
+
+ filename = tilde_expand (filename);
+ if (filename[0] != '/')
+ {
+ cp = concat (current_directory, "/", filename, NULL);
+ free (filename);
+ filename = cp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ /*
+ * gdb doesn't really do anything if the exec-file couldn't
+ * be opened (in that case exec_bfd is NULL). Usually that's
+ * no big deal, but kvm_open needs the exec-file's name,
+ * which results in dereferencing a NULL pointer, a real NO-NO !
+ * So, check here if the open of the exec-file succeeded.
+ */
+ if (exec_bfd == NULL) /* the open failed */
+ error ("kgdb could not open the exec-file, please check the name you used !");
+
+ core_kd = kvm_open (exec_bfd->filename, filename, NULL,
+ kernel_writablecore? O_RDWR : O_RDONLY, "kgdb: ");
+ if (core_kd < 0)
+ perror_with_name (filename);
+
+ /* Looks semi-reasonable. Toss the old core file and work on the new. */
+
+ discard_cleanups (old_chain); /* Don't free filename any more */
+ core_file = filename;
+ ontop = !push_target (&kcore_ops);
+
+ kernel_start = bfd_get_start_address (exec_bfd); /* XXX */
+
+ /* print out the panic string if there is one */
+ if (kvread (ksym_lookup ("panicstr"), &addr) == 0
+ && addr != 0
+ && target_read_memory (addr, buf, sizeof (buf)) == 0)
+ {
+ for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++)
+ if (!isascii (*cp) || (!isprint (*cp) && !isspace (*cp)))
+ *cp = '?';
+ *cp = '\0';
+ if (buf[0] != '\0')
+ printf ("panicstr: %s\n", buf);
+ }
+
+ /* Print all the panic messages if possible. */
+ if (symfile_objfile != NULL)
+ {
+ printf ("panic messages:\n---\n");
+ snprintf (buf, sizeof buf,
+ "/sbin/dmesg -N %s -M %s | \
+ /usr/bin/awk '/^(panic:|Fatal trap) / { printing = 1 } \
+ { if (printing) print $0 }'",
+ symfile_objfile->name, filename);
+ fflush(stdout);
+ system (buf);
+ printf ("---\n");
+ }
+
+ if (!ontop)
+ {
+ warning ("you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''", target_longname);
+ return;
+ }
+
+ /* we may need this later */
+ cur_proc = (struct proc *)curProc ();
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+kcore_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Too many arguments");
+ unpush_target (&kcore_ops);
+ reinit_frame_cache ();
+ if (from_tty)
+ printf_filtered ("No kernel 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_kcore_registers (regno)
+ int regno;
+{
+ struct user *uaddr;
+
+ /* find the pcb for the current process */
+ if (cur_proc == NULL || kvread (&cur_proc->p_addr, &uaddr))
+ error ("cannot read u area ptr for proc at %#x", cur_proc);
+ if (read_pcb (core_kd, (CORE_ADDR)&uaddr->u_pcb) < 0)
+ error ("cannot read pcb at %#x", &uaddr->u_pcb);
+}
+
+static void
+kcore_files_info (t)
+ struct target_ops *t;
+{
+ printf ("\t`%s'\n", core_file);
+}
+
+static int
+kcore_xfer_kmem (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ int ns;
+ int nu;
+
+ if (memaddr >= (CORE_ADDR)VM_MAXUSER_ADDRESS)
+ nu = 0;
+ else
+ {
+ nu = xfer_umem (memaddr, myaddr, len, write);
+ if (nu <= 0)
+ return (0);
+ if (nu == len)
+ return (nu);
+ memaddr += nu;
+ if (memaddr != (CORE_ADDR)VM_MAXUSER_ADDRESS)
+ return (nu);
+ myaddr += nu;
+ len -= nu;
+ }
+
+ ns = (write ? kvm_write : kvm_read) (core_kd, memaddr, myaddr, len);
+ if (ns < 0)
+ ns = 0;
+
+ return (nu + ns);
+}
+
+static int
+xfer_umem (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write; /* ignored */
+{
+ int n;
+ struct proc proc;
+
+ if (cur_proc == NULL || kvread (cur_proc, &proc))
+ error ("cannot read proc at %#x", cur_proc);
+ n = kvm_uread (core_kd, &proc, memaddr, myaddr, len) ;
+
+ if (n < 0)
+ return 0;
+ return n;
+}
+
+#define KERNOFF ((unsigned)KERNBASE)
+#define INKERNEL(x) ((x) >= KERNOFF)
+
+static CORE_ADDR sbr;
+static CORE_ADDR curpcb;
+static int found_pcb;
+static int devmem;
+static int kfd;
+static struct pcb pcb;
+
+static void
+set_proc_cmd (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR paddr;
+ struct kinfo_proc *kp;
+ int cnt = 0;
+
+ if (!arg)
+ error_no_arg ("proc address for new current process");
+ if (!kernel_debugging)
+ error ("not debugging kernel");
+
+ paddr = (CORE_ADDR)parse_and_eval_address (arg);
+ /* assume it's a proc pointer if it's in the kernel */
+ if (paddr >= kernel_start) {
+ if (set_proc_context(paddr))
+ error("invalid proc address");
+ } else {
+ kp = kvm_getprocs(core_kd, KERN_PROC_PID, paddr, &cnt);
+ if (!cnt)
+ error("invalid pid");
+ if (set_proc_context((CORE_ADDR)kp->ki_paddr))
+ error("invalid proc address");
+ }
+}
+
+static void
+set_cpu_cmd (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR paddr;
+ CORE_ADDR pcaddr;
+ struct kinfo_proc *kp;
+ int cpu, cfd;
+
+ if (!arg)
+ error_no_arg ("cpu number");
+ if (!kernel_debugging)
+ error ("not debugging kernel");
+
+ cfd = core_kd;
+ cpu = (int)parse_and_eval_address (arg);
+ if ((pcaddr = kvm_getpcpu (cfd, cpu)) == NULL)
+ error ("cpu number out of range");
+
+ pcpu = pcaddr;
+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb));
+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb);
+
+ if (!devmem)
+ paddr = ksym_lookup ("dumppcb") - KERNOFF;
+ else
+ paddr = kvtophys (cfd, curpcb);
+ read_pcb (cfd, paddr);
+ printf ("initial pcb at %lx\n", (unsigned long)paddr);
+
+ if ((cur_proc = curProc()))
+ target_fetch_registers (-1);
+
+ /* Now, set up the frame cache, and print the top of stack */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* substitutes for the stuff in libkvm which doesn't work */
+/* most of this was taken from the old kgdb */
+
+/* we don't need all this stuff, but the call should look the same */
+
+static int
+kvm_open (efile, cfile, sfile, perm, errout)
+ const char *efile;
+ char *cfile;
+ char *sfile; /* makes this kvm_open more compatible to the one in libkvm */
+ int perm;
+ char *errout; /* makes this kvm_open more compatible to the one in libkvm */
+{
+ struct stat stb;
+ int cfd;
+ CORE_ADDR paddr;
+
+ if ((cfd = open (cfile, perm, 0)) < 0)
+ return (cfd);
+
+ if ((pcpu = kvm_getpcpu (cfd, 0)) == NULL)
+ return (-1);
+
+ fstat (cfd, &stb);
+ if ((stb.st_mode & S_IFMT) == S_IFCHR
+ && stb.st_rdev == makedev (2, 0))
+ {
+ devmem = 1;
+ kfd = open (_PATH_KMEM, perm, 0);
+ }
+
+ physrd (cfd, ksym_lookup ("IdlePTD") - KERNOFF, (char*)&sbr, sizeof sbr);
+ printf ("IdlePTD %lu\n", (unsigned long)sbr);
+ curpcb = kvtophys(cfd, pcpu + PCPU_OFFSET (curpcb));
+ physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb);
+
+ found_pcb = 1; /* for vtophys */
+ if (!devmem)
+ paddr = ksym_lookup ("dumppcb") - KERNOFF;
+ else
+ paddr = kvtophys (cfd, curpcb);
+ read_pcb (cfd, paddr);
+ printf ("initial pcb at %lx\n", (unsigned long)paddr);
+
+ return (cfd);
+}
+
+static int
+kvm_close (fd)
+ int fd;
+{
+ return (close (fd));
+}
+
+static int
+kvm_write (core_kd, memaddr, myaddr, len)
+ int core_kd;
+ CORE_ADDR memaddr;
+ char *myaddr;
+{
+ int cc;
+
+ if (devmem)
+ {
+ if (kfd > 0)
+ {
+ /*
+ * Just like kvm_read, only we write.
+ */
+ errno = 0;
+ if (lseek (kfd, (off_t)memaddr, 0) < 0
+ && errno != 0)
+ {
+ error ("kvm_write:invalid address (%x)", memaddr);
+ return (0);
+ }
+ cc = write (kfd, myaddr, len);
+ if (cc < 0)
+ {
+ error ("kvm_write:write failed");
+ return (0);
+ }
+ else if (cc < len)
+ error ("kvm_write:short write");
+ return (cc);
+ }
+ else
+ return (0);
+ }
+ else
+ {
+ printf ("kvm_write not implemented for dead kernels\n");
+ return (0);
+ }
+ /* NOTREACHED */
+}
+
+static int
+kvm_read (core_kd, memaddr, myaddr, len)
+ int core_kd;
+ CORE_ADDR memaddr;
+ char *myaddr;
+{
+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len));
+}
+
+static int
+kvm_uread (core_kd, p, memaddr, myaddr, len)
+ int core_kd;
+ register struct proc *p;
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register char *cp;
+ char procfile[MAXPATHLEN];
+ ssize_t amount;
+ int fd;
+
+ if (devmem)
+ {
+ sprintf (procfile, "/proc/%d/mem", p->p_pid);
+ fd = open (procfile, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ error ("cannot open %s", procfile);
+ close (fd);
+ return (0);
+ }
+
+ cp = myaddr;
+ while (len > 0)
+ {
+ errno = 0;
+ if (lseek (fd, (off_t)memaddr, 0) == -1 && errno != 0)
+ {
+ error ("invalid address (%x) in %s", memaddr, procfile);
+ break;
+ }
+ amount = read (fd, cp, len);
+ if (amount < 0)
+ {
+ error ("error reading %s", procfile);
+ break;
+ }
+ if (amount == 0)
+ {
+ error ("EOF reading %s", procfile);
+ break;
+ }
+ cp += amount;
+ memaddr += amount;
+ len -= amount;
+ }
+
+ close (fd);
+ return ((ssize_t) (cp - myaddr));
+ }
+ else
+ return (kernel_core_file_hook (core_kd, memaddr, myaddr, len));
+}
+
+static struct kinfo_proc kp;
+
+/*
+ * try to do what kvm_proclist in libkvm would do
+ */
+static int
+kvm_proclist (cfd, pid, p, cnt)
+int cfd, pid, *cnt;
+struct proc *p;
+{
+ struct proc lp;
+
+ for (; p != NULL; p = LIST_NEXT(&lp, p_list)) {
+ if (!kvm_read(cfd, (CORE_ADDR)p, (char *)&lp, sizeof (lp)))
+ return (0);
+ if (lp.p_pid != pid)
+ continue;
+ kp.ki_paddr = p;
+ *cnt = 1;
+ return (1);
+ }
+ *cnt = 0;
+ return (0);
+}
+
+/*
+ * try to do what kvm_deadprocs in libkvm would do
+ */
+static struct kinfo_proc *
+kvm_deadprocs (cfd, pid, cnt)
+int cfd, pid, *cnt;
+{
+ CORE_ADDR allproc, zombproc;
+ struct proc *p;
+
+ allproc = ksym_lookup("allproc");
+ if (kvm_read(cfd, allproc, (char *)&p, sizeof (p)) == 0)
+ return (NULL);
+ kvm_proclist (cfd, pid, p, cnt);
+ if (!*cnt) {
+ zombproc = ksym_lookup("zombproc");
+ if (kvm_read(cfd, zombproc, (char *)&p, sizeof (p)) == 0)
+ return (NULL);
+ kvm_proclist (cfd, pid, p, cnt);
+ }
+ return (&kp);
+}
+
+static CORE_ADDR
+kvm_getpcpu (cfd, cpuid)
+int cfd, cpuid;
+{
+ SLIST_HEAD(, globaldata) pcpu_head;
+ struct globaldata lgd;
+ struct globaldata *gd;
+
+ physrd (cfd, ksym_lookup ("cpuhead") - KERNOFF, (char*)&pcpu_head,
+ sizeof pcpu_head);
+ gd = SLIST_FIRST (&pcpu_head);
+ for (; gd != NULL; gd = SLIST_NEXT (&lgd, gd_allcpu))
+ {
+ kvm_read (cfd, (CORE_ADDR)gd, (char*)&lgd, sizeof lgd);
+ if (lgd.gd_cpuid == cpuid)
+ break;
+ }
+
+ return ((CORE_ADDR)gd);
+}
+
+/*
+ * try to do what kvm_getprocs in libkvm would do
+ */
+static struct kinfo_proc *
+kvm_getprocs (cfd, op, proc, cnt)
+int cfd, op, *cnt;
+CORE_ADDR proc;
+{
+ int mib[4], size;
+
+ *cnt = 0;
+ /* assume it's a pid */
+ if (devmem) { /* "live" kernel, use sysctl */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = (int)proc;
+ size = sizeof (kp);
+ if (sysctl (mib, 4, &kp, &size, NULL, 0) < 0) {
+ perror("sysctl");
+ *cnt = 0;
+ return (NULL);
+ }
+ if (!size)
+ *cnt = 0;
+ else
+ *cnt = 1;
+ return (&kp);
+ } else
+ return (kvm_deadprocs (cfd, (int)proc, cnt));
+}
+
+static int
+physrd (cfd, addr, dat, len)
+ int cfd;
+ u_int addr;
+ char *dat;
+ int len;
+{
+ if (lseek (cfd, (off_t)addr, L_SET) == -1)
+ return (-1);
+ return (read (cfd, dat, len));
+}
+
+static CORE_ADDR
+kvtophys (fd, addr)
+ int fd;
+ CORE_ADDR addr;
+{
+ CORE_ADDR v;
+ unsigned int pte;
+ static CORE_ADDR PTD = -1;
+ CORE_ADDR current_ptd;
+
+ /*
+ * We may no longer have a linear system page table...
+ *
+ * Here's the scoop. IdlePTD contains the physical address
+ * of a page table directory that always maps the kernel.
+ * IdlePTD is in memory that is mapped 1-to-1, so we can
+ * find it easily given its 'virtual' address from ksym_lookup().
+ * For hysterical reasons, the value of IdlePTD is stored in sbr.
+ *
+ * To look up a kernel address, we first convert it to a 1st-level
+ * address and look it up in IdlePTD. This gives us the physical
+ * address of a page table page; we extract the 2nd-level part of
+ * VA and read the 2nd-level pte. Finally, we add the offset part
+ * of the VA into the physical address from the pte and return it.
+ *
+ * User addresses are a little more complicated. If we don't have
+ * a current PCB from read_pcb(), we use PTD, which is the (fixed)
+ * virtual address of the current ptd. Since it's NOT in 1-to-1
+ * kernel space, we must look it up using IdlePTD. If we do have
+ * a pcb, we get the ptd from pcb_ptd.
+ */
+
+ if (INKERNEL (addr))
+ current_ptd = sbr;
+ else if (found_pcb == 0)
+ {
+ if (PTD == -1)
+ PTD = kvtophys (fd, ksym_lookup ("PTD"));
+ current_ptd = PTD;
+ }
+ else
+ current_ptd = pcb.pcb_cr3;
+
+ /*
+ * Read the first-level page table (ptd).
+ */
+ v = current_ptd + ( (unsigned)addr >> PDRSHIFT) * sizeof pte;
+ if (physrd (fd, v, (char *)&pte, sizeof pte) < 0 || (pte&PG_V) == 0)
+ return (~0);
+
+ if (pte & PG_PS)
+ {
+ /*
+ * No second-level page table; ptd describes one 4MB page.
+ * (We assume that the kernel wouldn't set PG_PS without enabling
+ * it cr0, and that the kernel doesn't support 36-bit physical
+ * addresses).
+ */
+#define PAGE4M_MASK (NBPDR - 1)
+#define PG_FRAME4M (~PAGE4M_MASK)
+ addr = (pte & PG_FRAME4M) + (addr & PAGE4M_MASK);
+ }
+ else
+ {
+ /*
+ * Read the second-level page table.
+ */
+ v = (pte&PG_FRAME) + ((addr >> PAGE_SHIFT)&(NPTEPG-1)) * sizeof pte;
+ if (physrd (fd, v, (char *) &pte, sizeof (pte)) < 0 || (pte&PG_V) == 0)
+ return (~0);
+
+ addr = (pte & PG_FRAME) + (addr & PAGE_MASK);
+ }
+#if 0
+ printf ("vtophys (%x) -> %x\n", oldaddr, addr);
+#endif
+ return (addr);
+}
+
+static int
+read_pcb (fd, uaddr)
+ int fd;
+ CORE_ADDR uaddr;
+{
+ int i;
+ int noreg;
+ CORE_ADDR nuaddr = uaddr;
+
+ /* need this for the `proc' command to work */
+ if (INKERNEL(uaddr))
+ nuaddr = kvtophys(fd, uaddr);
+
+ if (physrd (fd, nuaddr, (char *)&pcb, sizeof pcb) < 0)
+ {
+ error ("cannot read pcb at %x\n", uaddr);
+ return (-1);
+ }
+
+ /*
+ * get the register values out of the sys pcb and
+ * store them where `read_register' will find them.
+ */
+ /*
+ * XXX many registers aren't available.
+ * XXX for the non-core case, the registers are stale - they are for
+ * the last context switch to the debugger.
+ * XXX gcc's register numbers aren't all #defined in tm-i386.h.
+ */
+ noreg = 0;
+ for (i = 0; i < 3; ++i) /* eax,ecx,edx */
+ supply_register (i, (char *)&noreg);
+ supply_register (3, (char *)&pcb.pcb_ebx);
+ supply_register (SP_REGNUM, (char *)&pcb.pcb_esp);
+ supply_register (FP_REGNUM, (char *)&pcb.pcb_ebp);
+ supply_register (6, (char *)&pcb.pcb_esi);
+ supply_register (7, (char *)&pcb.pcb_edi);
+ supply_register (PC_REGNUM, (char *)&pcb.pcb_eip);
+ for (i = 9; i < 14; ++i) /* eflags, cs, ss, ds, es, fs */
+ supply_register (i, (char *)&noreg);
+ supply_register (15, (char *)&pcb.pcb_gs);
+
+ /* XXX 80387 registers? */
+}
+
+/*
+ * read len bytes from kernel virtual address 'addr' into local
+ * buffer 'buf'. Return numbert of bytes if read ok, 0 otherwise. On read
+ * errors, portion of buffer not read is zeroed.
+ */
+
+static int
+kernel_core_file_hook (fd, addr, buf, len)
+ int fd;
+ CORE_ADDR addr;
+ char *buf;
+ int len;
+{
+ int i;
+ CORE_ADDR paddr;
+ register char *cp;
+ int cc;
+
+ cp = buf;
+
+ while (len > 0)
+ {
+ paddr = kvtophys (fd, addr);
+ if (paddr == ~0)
+ {
+ memset (buf, '\000', len);
+ break;
+ }
+ /* we can't read across a page boundary */
+ i = min (len, PAGE_SIZE - (addr & PAGE_MASK));
+ if ( (cc = physrd (fd, paddr, cp, i)) <= 0)
+ {
+ memset (cp, '\000', len);
+ return (cp - buf);
+ }
+ cp += cc;
+ addr += cc;
+ len -= cc;
+ }
+ return (cp - buf);
+}
+
+static struct target_ops kcore_ops;
+
+void
+_initialize_kcorelow()
+{
+ kcore_ops.to_shortname = "kcore";
+ kcore_ops.to_longname = "Kernel core dump file";
+ kcore_ops.to_doc =
+ "Use a core file as a target. Specify the filename of the core file.";
+ kcore_ops.to_open = kcore_open;
+ kcore_ops.to_close = kcore_close;
+ kcore_ops.to_attach = find_default_attach;
+ kcore_ops.to_detach = kcore_detach;
+ kcore_ops.to_fetch_registers = get_kcore_registers;
+ kcore_ops.to_xfer_memory = kcore_xfer_kmem;
+ kcore_ops.to_files_info = kcore_files_info;
+ kcore_ops.to_create_inferior = find_default_create_inferior;
+ kcore_ops.to_stratum = kcore_stratum;
+ kcore_ops.to_has_memory = 1;
+ kcore_ops.to_has_stack = 1;
+ kcore_ops.to_has_registers = 1;
+ kcore_ops.to_magic = OPS_MAGIC;
+
+ add_target (&kcore_ops);
+ add_com ("proc", class_obscure, set_proc_cmd, "Set current process context");
+ add_com ("cpu", class_obscure, set_cpu_cmd, "Set current cpu");
+}
diff --git a/gnu/usr.bin/binutils/gdb5/i386/nm.h b/gnu/usr.bin/binutils/gdb5/i386/nm.h
new file mode 100644
index 0000000..8710860
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/i386/nm.h
@@ -0,0 +1,169 @@
+/* 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. */
+
+/* $FreeBSD$ */
+
+#ifndef NM_FREEBSD_H
+#define NM_FREEBSD_H
+
+#define ATTACH_DETACH
+
+/* Be shared lib aware */
+#include "solib.h"
+#ifdef FREEBSD_ELF
+#define SVR4_SHARED_LIBS
+#endif
+
+/* 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));
+
+/* We define our own fetch/store methods */
+#define FETCH_INFERIOR_REGISTERS
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+#define PTRACE_ARG3_TYPE char*
+
+#ifndef FREEBSD_ELF
+
+/* 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
+
+#endif
+
+/* 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));
+
+#define ADDITIONAL_OPTIONS \
+ {"kernel", no_argument, &kernel_debugging, 1}, \
+ {"k", no_argument, &kernel_debugging, 1}, \
+ {"wcore", no_argument, &kernel_writablecore, 1}, \
+ {"w", no_argument, &kernel_writablecore, 1},
+
+#define ADDITIONAL_OPTION_HELP \
+ "\
+ --kernel Enable kernel debugging.\n\
+ --wcore Make core file writable (only works for /dev/mem).\n\
+ This option only works while debugging a kernel !!\n\
+"
+
+extern int kernel_debugging;
+extern int kernel_writablecore;
+
+#define DEFAULT_PROMPT kernel_debugging?"(kgdb) ":"(gdb) "
+
+/* misuse START_PROGRESS to test whether we're running as kgdb */
+/* START_PROGRESS is called at the top of main */
+#undef START_PROGRESS
+#define START_PROGRESS(STR,N) \
+ if (!strcmp(STR, "kgdb")) \
+ kernel_debugging = 1;
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
+#ifdef PT_GETDBREGS
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+extern int can_watch PARAMS((int type, int cnt, int othertype));
+extern int stopped_by_watchpoint PARAMS((void));
+extern int insert_watchpoint PARAMS((int addr, int len, int type));
+extern int remove_watchpoint PARAMS((int addr, int len, int type));
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \
+ can_watch(type, cnt, ot)
+
+/* 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) \
+ stopped_by_watchpoint()
+
+/* Use these macros for watchpoint insertion/removal. */
+
+#define target_insert_watchpoint(addr, len, type) \
+ insert_watchpoint(addr, len, type)
+
+#define target_remove_watchpoint(addr, len, type) \
+ remove_watchpoint(addr, len, type)
+
+#endif /* PT_GETDBREGS */
+
+#endif /* NM_FREEBSD_H */
diff --git a/gnu/usr.bin/binutils/gdb5/i386/tm.h b/gnu/usr.bin/binutils/gdb5/i386/tm.h
new file mode 100644
index 0000000..69dfa44
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/i386/tm.h
@@ -0,0 +1,66 @@
+/* $FreeBSD$ */
+/* 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. */
+
+#ifndef TM_FBSD_H
+#define TM_FBSD_H 1
+
+#include "i386/tm-i386bsd.h"
+
+#undef NUM_REGS
+#define NUM_REGS 16
+
+extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
+
+#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
+
+extern void i386_float_info PARAMS ((void));
+
+#define FLOAT_INFO i386_float_info ()
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) STREQ (name, "_DYNAMIC")
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+extern CORE_ADDR fbsd_kern_frame_saved_pc (struct frame_info *);
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) \
+ (kernel_debugging ? fbsd_kern_frame_saved_pc(FRAME) : \
+ (((FRAME)->signal_handler_caller \
+ ? sigtramp_saved_pc (FRAME) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)) \
+ ))
+
+/* On FreeBSD, sigtramp has size 0x18 and is immediately below the
+ ps_strings struct which has size 0x10 and is at the top of the
+ user stack. */
+
+#undef SIGTRAMP_START
+#undef SIGTRAMP_END
+#define SIGTRAMP_START(pc) 0xbfbfdfd8
+#define SIGTRAMP_END(pc) 0xbfbfdff0
+
+struct objfile;
+void freebsd_uthread_new_objfile PARAMS ((struct objfile *objfile));
+#define target_new_objfile(OBJFILE) freebsd_uthread_new_objfile (OBJFILE)
+
+extern char *freebsd_uthread_pid_to_str PARAMS ((int pid));
+#define target_pid_to_str(PID) freebsd_uthread_pid_to_str (PID)
+
+#endif /* ifndef TM_FBSD_H */
diff --git a/gnu/usr.bin/binutils/gdb5/i386/version.c b/gnu/usr.bin/binutils/gdb5/i386/version.c
new file mode 100644
index 0000000..ea043bd
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/i386/version.c
@@ -0,0 +1,5 @@
+/* $FreeBSD$ */
+
+char *version = "4.18";
+char *host_name = "i386-unknown-freebsd";
+char *target_name = "i386-unknown-freebsd";
diff --git a/gnu/usr.bin/binutils/gdb5/i386/xm.h b/gnu/usr.bin/binutils/gdb5/i386/xm.h
new file mode 100644
index 0000000..6ff268d
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdb5/i386/xm.h
@@ -0,0 +1,25 @@
+/* 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. */
+
+/* $FreeBSD$ */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include <machine/limits.h> /* for INT_MIN, to avoid "INT_MIN
+ redefined" warnings from defs.h */
diff --git a/gnu/usr.bin/binutils/gdbreplay/Makefile b/gnu/usr.bin/binutils/gdbreplay/Makefile
new file mode 100644
index 0000000..7a7d356
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdbreplay/Makefile
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+# Not elf specific so don't install in /usr/libexec/elf
+BINDIR=/usr/bin
+
+GDBDIR= ${.CURDIR}/../../../../contrib/gdb
+.PATH: ${GDBDIR}/gdb/gdbserver
+.PATH: ${GDBDIR}/gdb
+
+PROG= gdbreplay
+NOMAN= yes
+
+SRCS= gdbreplay.c
+
+CFLAGS+= -I${.CURDIR}/../gdb/${MACHINE_ARCH}
+CFLAGS+= -I${GDBDIR}/gdb
+CFLAGS+= -I${GDBDIR}/gdb/config
+CFLAGS+= -I${GDBDIR}/gdb/gdbserver
+CFLAGS+= -DNO_MMALLOC
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/gdbreplay5/Makefile b/gnu/usr.bin/binutils/gdbreplay5/Makefile
new file mode 100644
index 0000000..6028edc
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdbreplay5/Makefile
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+# Not elf specific so don't install in /usr/libexec/elf
+BINDIR=/usr/bin
+
+GDBDIR= ${.CURDIR}/../../../../contrib/gdb.291
+.PATH: ${GDBDIR}/gdb/gdbserver
+.PATH: ${GDBDIR}/gdb
+
+PROG= gdbreplay
+NOMAN= yes
+
+SRCS= gdbreplay.c
+
+CFLAGS+= -I${.CURDIR}/../gdb/${MACHINE_ARCH}
+CFLAGS+= -I${GDBDIR}/gdb
+CFLAGS+= -I${GDBDIR}/gdb/config
+CFLAGS+= -I${GDBDIR}/gdb/gdbserver
+CFLAGS+= -DNO_MMALLOC
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/gdbserver/Makefile b/gnu/usr.bin/binutils/gdbserver/Makefile
new file mode 100644
index 0000000..bb620a9
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdbserver/Makefile
@@ -0,0 +1,24 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+# Not elf specific so don't install in /usr/libexec/elf
+BINDIR=/usr/bin
+
+GDBDIR= ${.CURDIR}/../../../../contrib/gdb
+.PATH: ${GDBDIR}/gdb/gdbserver
+.PATH: ${GDBDIR}/gdb
+
+PROG= gdbserver
+
+SRCS= remote-utils.c utils.c server.c
+SRCS+= low-fbsd.c
+
+CFLAGS+= -I${.CURDIR}/../gdb/${MACHINE_ARCH}
+CFLAGS+= -I${GDBDIR}/gdb
+CFLAGS+= -I${GDBDIR}/gdb/config
+CFLAGS+= -I${GDBDIR}/gdb/gdbserver
+CFLAGS+= -I../libbfd # for BFD's config.h
+CFLAGS+= -DNO_MMALLOC
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/gdbserver/low-fbsd.c b/gnu/usr.bin/binutils/gdbserver/low-fbsd.c
new file mode 100644
index 0000000..2f1af94
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdbserver/low-fbsd.c
@@ -0,0 +1,341 @@
+/* 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. */
+
+/* $FreeBSD$ */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+#include <string.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 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);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror(errno));
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (PT_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;
+ int 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,
+ (PTRACE_ARG3_TYPE) 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#if defined(__i386__)
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'tEAX' come from <machine/reg.h> */
+static int tregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS,
+ tDS, tES, tFS, tGS,
+};
+
+static struct save87 pcb_savefpu;
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (&registers[REGISTER_BYTE (r)], ((int *)&inferior_registers) + tregmap[r], 4);
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (((int *)&inferior_registers) + tregmap[r], &registers[REGISTER_BYTE (r)], 4);
+
+ ptrace (PT_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+}
+
+#elif defined(__alpha__)
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+
+ for (r = 0; r < 31; r++)
+ memcpy (&registers[REGISTER_BYTE (r)],
+ &regs.r_regs[r], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&registers[REGISTER_BYTE (r + FP0_REGNUM)],
+ &fpregs.fpr_regs[r], sizeof(u_int64_t));
+ memcpy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &regs.r_regs[31], sizeof(u_int64_t));
+
+ memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, sizeof(u_int64_t));
+ memset (&registers[REGISTER_BYTE (FP_REGNUM)], 0, sizeof(u_int64_t));
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ for (r = 0; r < 31; r++)
+ memcpy (&regs.r_regs[r],
+ &registers[REGISTER_BYTE (r)], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&fpregs.fpr_regs[r],
+ &registers[REGISTER_BYTE (r + FP0_REGNUM)], sizeof(u_int64_t));
+ memcpy (&regs.r_regs[31],
+ &registers[REGISTER_BYTE (PC_REGNUM)], sizeof(u_int64_t));
+
+ ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+}
+
+#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 (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) 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 (PT_READ_I, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (PT_READ_I, 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))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_I, inferior_pid, (PTRACE_ARG3_TYPE) 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/gnu/usr.bin/binutils/gdbserver5/Makefile b/gnu/usr.bin/binutils/gdbserver5/Makefile
new file mode 100644
index 0000000..45aa3a4
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdbserver5/Makefile
@@ -0,0 +1,24 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+# Not elf specific so don't install in /usr/libexec/elf
+BINDIR=/usr/bin
+
+GDBDIR= ${.CURDIR}/../../../../contrib/gdb.291
+.PATH: ${GDBDIR}/gdb/gdbserver
+.PATH: ${GDBDIR}/gdb
+
+PROG= gdbserver
+
+SRCS= remote-utils.c utils.c server.c
+SRCS+= low-fbsd.c
+
+CFLAGS+= -I${.CURDIR}/../gdb/${MACHINE_ARCH}
+CFLAGS+= -I${GDBDIR}/gdb
+CFLAGS+= -I${GDBDIR}/gdb/config
+CFLAGS+= -I${GDBDIR}/gdb/gdbserver
+CFLAGS+= -I../libbfd # for BFD's config.h
+CFLAGS+= -DNO_MMALLOC
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/gdbserver5/low-fbsd.c b/gnu/usr.bin/binutils/gdbserver5/low-fbsd.c
new file mode 100644
index 0000000..2f1af94
--- /dev/null
+++ b/gnu/usr.bin/binutils/gdbserver5/low-fbsd.c
@@ -0,0 +1,341 @@
+/* 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. */
+
+/* $FreeBSD$ */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+#include <string.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 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);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror(errno));
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (PT_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;
+ int 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,
+ (PTRACE_ARG3_TYPE) 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#if defined(__i386__)
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'tEAX' come from <machine/reg.h> */
+static int tregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS,
+ tDS, tES, tFS, tGS,
+};
+
+static struct save87 pcb_savefpu;
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (&registers[REGISTER_BYTE (r)], ((int *)&inferior_registers) + tregmap[r], 4);
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg inferior_registers; /* ptrace order, not gcc/gdb order */
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ for (r = 0; r < NUM_REGS; r++)
+ memcpy (((int *)&inferior_registers) + tregmap[r], &registers[REGISTER_BYTE (r)], 4);
+
+ ptrace (PT_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+}
+
+#elif defined(__alpha__)
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+
+ for (r = 0; r < 31; r++)
+ memcpy (&registers[REGISTER_BYTE (r)],
+ &regs.r_regs[r], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&registers[REGISTER_BYTE (r + FP0_REGNUM)],
+ &fpregs.fpr_regs[r], sizeof(u_int64_t));
+ memcpy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &regs.r_regs[31], sizeof(u_int64_t));
+
+ memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, sizeof(u_int64_t));
+ memset (&registers[REGISTER_BYTE (FP_REGNUM)], 0, sizeof(u_int64_t));
+}
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct reg regs; /* ptrace order, not gcc/gdb order */
+ struct fpreg fpregs;
+ int r;
+
+ for (r = 0; r < 31; r++)
+ memcpy (&regs.r_regs[r],
+ &registers[REGISTER_BYTE (r)], sizeof(u_int64_t));
+ for (r = 0; r < 32; r++)
+ memcpy (&fpregs.fpr_regs[r],
+ &registers[REGISTER_BYTE (r + FP0_REGNUM)], sizeof(u_int64_t));
+ memcpy (&regs.r_regs[31],
+ &registers[REGISTER_BYTE (PC_REGNUM)], sizeof(u_int64_t));
+
+ ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ ptrace (PT_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0);
+}
+
+#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 (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) 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 (PT_READ_I, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (PT_READ_I, 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))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_I, inferior_pid, (PTRACE_ARG3_TYPE) 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/gnu/usr.bin/binutils/ld/Makefile b/gnu/usr.bin/binutils/ld/Makefile
new file mode 100644
index 0000000..38e31ee
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile
@@ -0,0 +1,58 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/ld
+
+PROG= ld
+SCRIPTDIR= /usr/libdata/ldscripts
+SRCS+= ldcref.c ldctor.c ldemul.c ldemul-list.h ldexp.c ldfile.c \
+ ldgram.y ldlang.c ldlex.l ldmain.c ldmisc.c \
+ ldver.c ldwrite.c lexsup.c mri.c
+
+.if defined(BOOTSTRAPPING) && !exists(/usr/include/elf-hints.h)
+SRCS+= elf-hints.h
+CLEANFILES+= elf-hints.h
+
+elf-hints.h:
+ ln -sf ${.CURDIR}/../../../../include/${.TARGET} .
+.endif
+
+WARNS= 1
+CFLAGS+= -DSCRIPTDIR=\"${TOOLS_PREFIX}/usr/libdata\"
+CFLAGS+= -DBFD_VERSION_STRING=\"${VERSION}\"
+CFLAGS+= -I${SRCDIR}/ld -I${SRCDIR}/bfd
+NOSHARED?= yes
+DPADD= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+CLEANDIRS+= ldscripts
+CLEANFILES+= ldemul-list.h stringify.sed
+
+# If set, BINUTILSDISTDIR is the path to a directory containing the full GNU
+# binutils release. FreeBSD only distributes the bits that are required to
+# build native architectures. BINUTILSDISTDIR is needed to build cross tools.
+.if defined(BINUTILSDISTDIR) && exists(${BINUTILSDISTDIR})
+.PATH: ${BINUTILSDISTDIR}/ld
+CFLAGS+= -I${BINUTILSDISTDIR}/ld
+.endif
+
+EMXFR=
+EMLST=
+.for _e in ${EMS}
+EMXFR+= extern ld_emulation_xfer_type ld_${_e}_emulation;
+EMLST+= &ld_${_e}_emulation,
+.endfor
+
+ldemul-list.h:
+ echo "${EMXFR}" > ${.TARGET}
+ echo "#define EMULATION_LIST ${EMLST} 0" >> ${.TARGET}
+
+stringify.sed:
+ ln -sf ${SRCDIR}/ld/emultempl/astring.sed ${.TARGET}
+
+afterinstall:
+ ${INSTALL} ${COPY} -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \
+ ${LDSCRIPTS:S|^|ldscripts/|} ${DESTDIR}${SCRIPTDIR}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/ld/Makefile.alpha b/gnu/usr.bin/binutils/ld/Makefile.alpha
new file mode 100644
index 0000000..8993179
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile.alpha
@@ -0,0 +1,31 @@
+# $FreeBSD$
+
+TARGET_TUPLE?= alpha-unknown-freebsd
+
+.if ${TARGET_ARCH} == "alpha"
+NATIVE_EMULATION= elf64alpha
+HOST= ${TARGET_TUPLE}
+CFLAGS+= -DDEFAULT_EMULATION=\"${NATIVE_EMULATION}\"
+CFLAGS+= -DTARGET=\"${TARGET_TUPLE}\"
+_alpha_path= \"${TOOLS_PREFIX}/usr/lib\"
+.else
+_alpha_path= \"/usr/cross/alpha-freebsd/usr/lib\"
+.endif
+EMS+= ${NATIVE_EMULATION}
+LDSCRIPTS+= ${NATIVE_EMULATION}.x ${NATIVE_EMULATION}.xbn ${NATIVE_EMULATION}.xn ${NATIVE_EMULATION}.xr \
+ ${NATIVE_EMULATION}.xs ${NATIVE_EMULATION}.xu alpha.x alpha.xbn \
+ alpha.xn alpha.xr alpha.xu ${NATIVE_EMULATION}.xc ${NATIVE_EMULATION}.xsc
+SRCS+= e${NATIVE_EMULATION}.c ealpha.c
+CLEANFILES+= e${NATIVE_EMULATION}.c ealpha.c
+
+e${NATIVE_EMULATION}.c: emulparams/${NATIVE_EMULATION}.sh emultempl/elf32.em \
+ scripttempl/elf.sc genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_alpha_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ ${NATIVE_EMULATION} "" ${NATIVE_EMULATION} ${TARGET_TUPLE}
+
+ealpha.c: emulparams/${NATIVE_EMULATION}.sh emultempl/elf32.em scripttempl/elf.sc \
+ genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_alpha_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ ${NATIVE_EMULATION} "" alpha ${TARGET_TUPLE}
diff --git a/gnu/usr.bin/binutils/ld/Makefile.i386 b/gnu/usr.bin/binutils/ld/Makefile.i386
new file mode 100644
index 0000000..2c9b608
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile.i386
@@ -0,0 +1,42 @@
+# $FreeBSD$
+
+TARGET_TUPLE?= i386-unknown-freebsd
+
+.if ${TARGET_ARCH} == "i386"
+NATIVE_EMULATION= elf_i386
+HOST= ${TARGET_TUPLE}
+CFLAGS+= -DDEFAULT_EMULATION=\"${NATIVE_EMULATION}\"
+CFLAGS+= -DTARGET=\"${TARGET_TUPLE}\"
+_i386_path= \"${TOOLS_PREFIX}/usr/lib\"
+.else
+_i386_path= \"/usr/cross/i386-freebsd/usr/lib\"
+.endif
+EMS+= ${NATIVE_EMULATION}
+LDSCRIPTS+= ${NATIVE_EMULATION}.x ${NATIVE_EMULATION}.xbn ${NATIVE_EMULATION}.xn ${NATIVE_EMULATION}.xr \
+ ${NATIVE_EMULATION}.xs ${NATIVE_EMULATION}.xu ${NATIVE_EMULATION}.xc ${NATIVE_EMULATION}.xsc
+SRCS+= e${NATIVE_EMULATION}.c
+CLEANFILES+= e${NATIVE_EMULATION}.c
+
+e${NATIVE_EMULATION}.c: emulparams/${NATIVE_EMULATION}.sh emultempl/elf32.em scripttempl/elf.sc \
+ genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_i386_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ "${NATIVE_EMULATION}" "" ${NATIVE_EMULATION} "${TARGET_TUPLE}"
+
+.if defined(BINUTILSDISTDIR) && exists(${BINUTILSDISTDIR})
+EMS+= i386pe
+LDSCRIPTS+= i386pe.x \
+ i386pe.xbn \
+ i386pe.xn \
+ i386pe.xr \
+ i386pe.xu
+SRCS+= ei386pe.c
+CLEANFILES+= ei386pe.c
+
+ei386pe.c: emulparams/i386pe.sh emultempl/pe.em scripttempl/pe.sc \
+ genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${BINUTILSDISTDIR}/ld \
+ /usr/cross/winnt/lib ${HOST} ${TARGET_TUPLE}winnt \
+ ${TARGET_TUPLE}winnt i386pe "" i386pe \
+ ${TARGET_TUPLE}winnt
+.endif
diff --git a/gnu/usr.bin/binutils/ld/Makefile.ia64 b/gnu/usr.bin/binutils/ld/Makefile.ia64
new file mode 100644
index 0000000..28eb477
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile.ia64
@@ -0,0 +1,25 @@
+# $FreeBSD$
+
+TARGET_TUPLE?= ia64-unknown-freebsd
+
+.if ${TARGET_ARCH} == "ia64"
+NATIVE_EMULATION= elf64_ia64
+HOST= ${TARGET_TUPLE} # do what?? how does this work for a cross-build??
+CFLAGS+= -DDEFAULT_EMULATION=\"${NATIVE_EMULATION}\"
+CFLAGS+= -DTARGET=\"${TARGET_TUPLE}\"
+_ia64_path= \"${TOOLS_PREFIX}/usr/lib\"
+.else
+_ia64_path= \"/usr/cross/ia64-freebsd/usr/lib\"
+.endif
+
+EMS+= ${NATIVE_EMULATION}
+LDSCRIPTS+= ${NATIVE_EMULATION}.x ${NATIVE_EMULATION}.xbn ${NATIVE_EMULATION}.xn ${NATIVE_EMULATION}.xr \
+ ${NATIVE_EMULATION}.xs ${NATIVE_EMULATION}.xu ${NATIVE_EMULATION}.xc ${NATIVE_EMULATION}.xsc
+SRCS+= e${NATIVE_EMULATION}.c
+CLEANFILES+= e${NATIVE_EMULATION}.c
+
+e${NATIVE_EMULATION}.c: emulparams/${NATIVE_EMULATION}.sh emultempl/elf32.em scripttempl/elf.sc \
+ genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_ia64_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ "${NATIVE_EMULATION}" "" ${NATIVE_EMULATION} "${TARGET_TUPLE}"
diff --git a/gnu/usr.bin/binutils/ld/Makefile.m68k b/gnu/usr.bin/binutils/ld/Makefile.m68k
new file mode 100644
index 0000000..4b6e9c7
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile.m68k
@@ -0,0 +1,52 @@
+# $FreeBSD$
+
+.if ${TARGET_ARCH} == "m68k"
+HOST= m68k-unknown-freebsd
+CFLAGS+= -DDEFAULT_EMULATION=\"elf_m68k\"
+CFLAGS+= -DTARGET=\"m68k-unknown-freebsd\"
+_m68k_path= \"${TOOLS_PREFIX}/usr/lib\"
+.else
+_m68k_path= \"/usr/cross/m68k-freebsd/usr/lib\"
+.endif
+EMS+= ld_m68kelf_emulation \
+ ld_m68klynx_emulation \
+ ld_m68knbsd_emulation
+LDSCRIPTS+= m68kelf.x \
+ m68kelf.xbn \
+ m68kelf.xn \
+ m68kelf.xr \
+ m68kelf.xs \
+ m68kelf.xu \
+ m68klynx.x \
+ m68klynx.xbn \
+ m68klynx.xn \
+ m68klynx.xr \
+ m68klynx.xu \
+ m68knbsd.x \
+ m68knbsd.xbn \
+ m68knbsd.xn \
+ m68knbsd.xr \
+ m68knbsd.xu
+SRCS+= em68kelf.c \
+ em68klynx.c \
+ em68knbsd.c
+CLEANFILES+= em68kelf.c \
+ em68klynx.c \
+ em68knbsd.c
+
+em68kelf.c: emulparams/m68kelf.sh emultempl/elf32.em scripttempl/elf.sc \
+ genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${BINUTILSDISTDIR}/ld \
+ ${_m68k_path} notused notused notused m68kelf "" m68kelf
+
+em68klynx.c: emulparams/m68klynx.sh emultempl/generic.em \
+ scripttempl/m68klynx.sc genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${BINUTILSDISTDIR}/ld \
+ /usr/cross/m68k-lynx/usr/lib notused notused notused \
+ m68klynx "" m68klynx
+
+em68knbsd.c: emulparams/m68knbsd.sh emultempl/generic.em scripttempl/aout.sc \
+ genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${BINUTILSDISTDIR}/ld \
+ /usr/cross/m68k-netbsdaout/usr/lib notused notused notused \
+ m68knbsd "" m68knbsd
diff --git a/gnu/usr.bin/binutils/ld/Makefile.powerpc b/gnu/usr.bin/binutils/ld/Makefile.powerpc
new file mode 100644
index 0000000..8ed05ef
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile.powerpc
@@ -0,0 +1,29 @@
+# $FreeBSD$
+
+TARGET_TUPLE?= powerpc-unknown-freebsd
+
+.if ${TARGET_ARCH} == "powerpc"
+NATIVE_EMULATION= elf32ppc
+HOST= ${TARGET_TUPLE}
+CFLAGS+= -DDEFAULT_EMULATION=\"${NATIVE_EMULATION}\"
+CFLAGS+= -DTARGET=\"${TARGET_TUPLE}\"
+_powerpc_path= \"${TOOLS_PREFIX}/usr/lib\"
+.else
+_powerpc_path= \"/usr/cross/powerpc-freebsd/usr/lib\"
+.endif
+EMS+= ${NATIVE_EMULATION}
+LDSCRIPTS+= ${NATIVE_EMULATION}.x \
+ ${NATIVE_EMULATION}.xbn \
+ ${NATIVE_EMULATION}.xn \
+ ${NATIVE_EMULATION}.xr \
+ ${NATIVE_EMULATION}.xs \
+ ${NATIVE_EMULATION}.xu \
+ ${NATIVE_EMULATION}.xsc
+SRCS+= e${NATIVE_EMULATION}.c
+CLEANFILES+= e${NATIVE_EMULATION}.c
+
+e${NATIVE_EMULATION}.c: emulparams/${NATIVE_EMULATION}.sh emultempl/elf32.em \
+ scripttempl/elfppc.sc genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_powerpc_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ ${NATIVE_EMULATION} "" ${NATIVE_EMULATION} ${TARGET_TUPLE}
diff --git a/gnu/usr.bin/binutils/ld/Makefile.sparc64 b/gnu/usr.bin/binutils/ld/Makefile.sparc64
new file mode 100644
index 0000000..07016e1
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile.sparc64
@@ -0,0 +1,37 @@
+# $FreeBSD$
+
+TARGET_TUPLE?= sparc64-unknown-freebsd
+
+.if ${TARGET_ARCH} == "sparc64"
+NATIVE_EMULATION= elf64_sparc
+HOST= ${TARGET_TUPLE}
+CFLAGS+= -DDEFAULT_EMULATION=\"${NATIVE_EMULATION}\"
+CFLAGS+= -DTARGET=\"${TARGET_TUPLE}\"
+_sparc_path= \"${TOOLS_PREFIX}/usr/lib\"
+.else
+_sparc_path= \"/usr/cross/sparc-freebsd/usr/lib\"
+.endif
+
+EMS+= ${NATIVE_EMULATION}
+LDSCRIPTS+= ${NATIVE_EMULATION}.x ${NATIVE_EMULATION}.xbn ${NATIVE_EMULATION}.xn ${NATIVE_EMULATION}.xr \
+ ${NATIVE_EMULATION}.xs ${NATIVE_EMULATION}.xu ${NATIVE_EMULATION}.xc ${NATIVE_EMULATION}.xsc
+SRCS+= e${NATIVE_EMULATION}.c
+CLEANFILES+= e${NATIVE_EMULATION}.c
+
+EMS+= elf32_sparc
+LDSCRIPTS+= elf32_sparc.x elf32_sparc.xbn elf32_sparc.xn elf32_sparc.xr \
+ elf32_sparc.xs elf32_sparc.xu elf32_sparc.xc elf32_sparc.xsc
+SRCS+= eelf32_sparc.c
+CLEANFILES+= eelf32_sparc.c
+
+e${NATIVE_EMULATION}.c: emulparams/${NATIVE_EMULATION}.sh emultempl/elf32.em \
+ scripttempl/elf.sc genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_sparc_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ ${NATIVE_EMULATION} "" ${NATIVE_EMULATION} ${TARGET_TUPLE}
+
+eelf32_sparc.c: emulparams/elf32_sparc.sh emultempl/elf32.em \
+ scripttempl/elf.sc genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_sparc_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ elf32_sparc "" elf32_sparc ${TARGET_TUPLE}
diff --git a/gnu/usr.bin/binutils/ld/Makefile.x86-64 b/gnu/usr.bin/binutils/ld/Makefile.x86-64
new file mode 100644
index 0000000..c7a75f4
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/Makefile.x86-64
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+TARGET_TUPLE?= x86_64-obrien-freebsd
+
+NATIVE_EMULATION= elf_x86_64_fbsd
+HOST= ${TARGET_TUPLE}
+CFLAGS+= -DDEFAULT_EMULATION=\"${NATIVE_EMULATION}\"
+CFLAGS+= -DTARGET=\"${TARGET_TUPLE}\"
+_x86_64_path= \"${TOOLS_PREFIX}/usr/lib\"
+EMS+= ${NATIVE_EMULATION}
+LDSCRIPTS+= ${NATIVE_EMULATION}.x ${NATIVE_EMULATION}.xbn ${NATIVE_EMULATION}.xn ${NATIVE_EMULATION}.xr \
+ ${NATIVE_EMULATION}.xs ${NATIVE_EMULATION}.xu ${NATIVE_EMULATION}.xc ${NATIVE_EMULATION}.xsc
+SRCS+= e${NATIVE_EMULATION}.c
+CLEANFILES+= e${NATIVE_EMULATION}.c
+
+e${NATIVE_EMULATION}.c: emulparams/${NATIVE_EMULATION}.sh emultempl/elf32.em scripttempl/elf.sc \
+ genscripts.sh stringify.sed
+ sh ${.CURDIR}/genscripts.sh ${SRCDIR}/ld ${_x86_64_path} \
+ ${HOST} ${TARGET_TUPLE} ${TARGET_TUPLE} \
+ "${NATIVE_EMULATION}" "" ${NATIVE_EMULATION} "${TARGET_TUPLE}"
diff --git a/gnu/usr.bin/binutils/ld/config.h b/gnu/usr.bin/binutils/ld/config.h
new file mode 100644
index 0000000..2cfddb1
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/config.h
@@ -0,0 +1,174 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* 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 to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Name of package */
+#define PACKAGE "ld"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Use b modifier when opening binary files? */
+/* #undef USE_BINARY_FOPEN */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if free is not declared in system header files. */
+/* #undef NEED_DECLARATION_FREE */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if getenv is not declared in system header files. */
+/* #undef NEED_DECLARATION_GETENV */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Additional extension a shared object might have. */
+/* #undef EXTRA_SHLIB_EXTENSION */
+
diff --git a/gnu/usr.bin/binutils/ld/genscripts.sh b/gnu/usr.bin/binutils/ld/genscripts.sh
new file mode 100755
index 0000000..e73097b
--- /dev/null
+++ b/gnu/usr.bin/binutils/ld/genscripts.sh
@@ -0,0 +1,162 @@
+#!/bin/sh
+# genscripts.sh - generate the ld-emulation-target specific files
+#
+# Usage: genscripts.sh srcdir libdir host target target_alias \
+# default_emulation native_lib_dirs this_emulation
+#
+# Sample usage:
+# genscripts.sh /djm/ld-devo/devo/ld /usr/local/lib sparc-sun-sunos4.1.3 \
+# sparc-sun-sunos4.1.3 sparc-sun-sunos4.1.3 sun4 "" sun3 sparc-sun-sunos4.1.3
+# produces sun3.x sun3.xbn sun3.xn sun3.xr sun3.xu em_sun3.c
+#
+# $FreeBSD$
+#
+# This is a cut-down version of the GNU script. Instead of jumping through
+# hoops for all possible combinations of paths, just use the libdir
+# argument in place of LIB_PATH.
+#
+# The host, target and target_alias arguments are not used in this version.
+#
+
+srcdir=$1
+libdir=$2
+host=$3
+target=$4
+target_alias=$5
+EMULATION_LIBPATH=$6
+NATIVE_LIB_DIRS=$7
+EMULATION_NAME=$8
+
+# Include the emulation-specific parameters:
+. ${srcdir}/emulparams/${EMULATION_NAME}.sh
+
+if test -d ldscripts; then
+ true
+else
+ mkdir ldscripts
+fi
+
+# Set the library search path, for libraries named by -lfoo.
+# If LIB_PATH is defined (e.g., by Makefile) and non-empty, it is used.
+# Otherwise, the default is set here.
+#
+# The format is the usual list of colon-separated directories.
+# To force a logically empty LIB_PATH, do LIBPATH=":".
+
+LIB_SEARCH_DIRS=`echo ${libdir} | tr ':' ' ' | sed -e 's/\([^ ][^ ]*\)/SEARCH_DIR(\1);/g'`
+
+# Generate 5 or 6 script files from a master script template in
+# ${srcdir}/scripttempl/${SCRIPT_NAME}.sh. Which one of the 5 or 6
+# script files is actually used depends on command line options given
+# to ld. (SCRIPT_NAME was set in the emulparams_file.)
+#
+# A .x script file is the default script.
+# A .xr script is for linking without relocation (-r flag).
+# A .xu script is like .xr, but *do* create constructors (-Ur flag).
+# A .xn script is for linking with -n flag (mix text and data on same page).
+# A .xbn script is for linking with -N flag (mix text and data on same page).
+# A .xs script is for generating a shared library with the --shared
+# flag; it is only generated if $GENERATE_SHLIB_SCRIPT is set by the
+# emulation parameters.
+# A .xc script is for linking with -z combreloc; it is only generated if
+# $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or
+# $SCRIPT_NAME is "elf".
+# A .xsc script is for linking with --shared -z combreloc; it is generated
+# if $GENERATE_COMBRELOC_SCRIPT is set by the emulation parameters or
+# $SCRIPT_NAME is "elf" and $GENERATE_SHLIB_SCRIPT is set by the emulation
+# parameters too.
+
+if [ "x$SCRIPT_NAME" = "xelf" ]; then
+ GENERATE_COMBRELOC_SCRIPT=yes
+fi
+
+SEGMENT_SIZE=${SEGMENT_SIZE-${TARGET_PAGE_SIZE}}
+
+# Determine DATA_ALIGNMENT for the 5 variants, using
+# values specified in the emulparams/<emulation>.sh file or default.
+
+DATA_ALIGNMENT_="${DATA_ALIGNMENT_-${DATA_ALIGNMENT-ALIGN(${SEGMENT_SIZE})}}"
+DATA_ALIGNMENT_n="${DATA_ALIGNMENT_n-${DATA_ALIGNMENT_}}"
+DATA_ALIGNMENT_N="${DATA_ALIGNMENT_N-${DATA_ALIGNMENT-.}}"
+DATA_ALIGNMENT_r="${DATA_ALIGNMENT_r-${DATA_ALIGNMENT-}}"
+DATA_ALIGNMENT_u="${DATA_ALIGNMENT_u-${DATA_ALIGNMENT_r}}"
+
+LD_FLAG=r
+DATA_ALIGNMENT=${DATA_ALIGNMENT_r}
+DEFAULT_DATA_ALIGNMENT="ALIGN(${SEGMENT_SIZE})"
+( echo "/* Script for ld -r: link without relocation */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xr
+
+LD_FLAG=u
+DATA_ALIGNMENT=${DATA_ALIGNMENT_u}
+CONSTRUCTING=" "
+( echo "/* Script for ld -Ur: link w/out relocation, do create constructors */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xu
+
+LD_FLAG=
+DATA_ALIGNMENT=${DATA_ALIGNMENT_}
+RELOCATING=" "
+( echo "/* Default linker script, for normal executables */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.x
+
+LD_FLAG=n
+DATA_ALIGNMENT=${DATA_ALIGNMENT_n}
+TEXT_START_ADDR=${NONPAGED_TEXT_START_ADDR-${TEXT_START_ADDR}}
+( echo "/* Script for -n: mix text and data on same page */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xn
+
+LD_FLAG=N
+DATA_ALIGNMENT=${DATA_ALIGNMENT_N}
+( echo "/* Script for -N: mix text and data on same page; don't align data */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xbn
+
+if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
+ DATA_ALIGNMENT=${DATA_ALIGNMENT_c-${DATA_ALIGNMENT_}}
+ LD_FLAG=c
+ COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp
+ ( echo "/* Script for -z combreloc: combine and sort reloc sections */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+ ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xc
+ rm -f ${COMBRELOC}
+ COMBRELOC=
+fi
+
+if test -n "$GENERATE_SHLIB_SCRIPT"; then
+ LD_FLAG=shared
+ DATA_ALIGNMENT=${DATA_ALIGNMENT_s-${DATA_ALIGNMENT_}}
+ CREATE_SHLIB=" "
+ # Note that TEXT_START_ADDR is set to NONPAGED_TEXT_START_ADDR.
+ (
+ echo "/* Script for ld --shared: link shared library */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+ ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xs
+ if test -n "$GENERATE_COMBRELOC_SCRIPT"; then
+ LD_FLAG=cshared
+ DATA_ALIGNMENT=${DATA_ALIGNMENT_sc-${DATA_ALIGNMENT}}
+ COMBRELOC=ldscripts/${EMULATION_NAME}.xc.tmp
+ ( echo "/* Script for --shared -z combreloc: shared library, combine & sort relocs */"
+ . ${srcdir}/emulparams/${EMULATION_NAME}.sh
+ . ${srcdir}/scripttempl/${SCRIPT_NAME}.sc
+ ) | sed -e '/^ *$/d;s/[ ]*$//' > ldscripts/${EMULATION_NAME}.xsc
+ rm -f ${COMBRELOC}
+ COMBRELOC=
+ fi
+fi
+
+for i in $EMULATION_LIBPATH ; do
+ test "$i" = "$EMULATION_NAME" && COMPILE_IN=true
+done
+# Generate e${EMULATION_NAME}.c.
+. ${srcdir}/emultempl/${TEMPLATE_NAME-generic}.em
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile b/gnu/usr.bin/binutils/libbfd/Makefile
new file mode 100644
index 0000000..2aea1f4
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/Makefile
@@ -0,0 +1,64 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/bfd ${SRCDIR}/opcodes
+
+LIB= bfd
+SRCS+= archive.c archive64.c archures.c bfd.c binary.c cache.c \
+ coffgen.c corefile.c elf.c elf-eh-frame.c elf-strtab.c format.c \
+ hash.c ihex.c init.c libbfd.c linker.c merge.c opncls.c reloc.c \
+ section.c srec.c stab-syms.c stabs.c syms.c targets.c tekhex.c \
+ targmatch.h dwarf1.c dwarf2.c config.h
+.if (${TARGET_ARCH} == "alpha")
+WARNS= 2
+.endif
+CFLAGS+= -I${SRCDIR}/bfd
+CFLAGS+= -DBFD_VERSION=\"${VERSION_DATE}\" -DBFD_VERSION_DATE=${VERSION_DATE}
+CFLAGS+= -DBFD_VERSION_STRING=\"${VERSION}\"
+INTERNALLIB= true
+CLEANFILES+= config.h targmatch.h
+
+# If set, BINUTILSDISTDIR is the path to a directory containing the full GNU
+# binutils release. FreeBSD only distributes the bits that are required to
+# build native architectures. BINUTILSDISTDIR is needed to build cross tools.
+.if defined(BINUTILSDISTDIR) && exists(${BINUTILSDISTDIR})
+.PATH: ${BINUTILSDISTDIR}/bfd ${BINUTILSDISTDIR}/opcodes
+CFLAGS+= -I${BINUTILSDISTDIR}/bfd -I${BINUTILSDISTDIR}/include -I.
+.endif
+
+SELARCH=
+.if ${BINUTIL_ARCH} == "sparc64"
+SELARCH= &bfd_sparc_arch
+.else
+.for _a in ${ARCHS}
+.if ${SELARCH} == ""
+SELARCH+= &bfd_${_a}_arch
+.else
+SELARCH+= ,&bfd_${_a}_arch
+.endif
+.endfor
+.endif
+CFLAGS+= -DSELECT_ARCHITECTURES="${SELARCH}"
+
+SELVEC=
+.for _v in ${VECS}
+.if ${SELVEC} == ""
+SELVEC+= &${_v}
+.else
+SELVEC+= ,&${_v}
+.endif
+.endfor
+CFLAGS+= -DSELECT_VECS="${SELVEC}"
+
+targmatch.h: targmatch.sed config.bfd
+ sed -f ${.ALLSRC:M*.sed} ${.ALLSRC:M*.bfd} > ${.TARGET}
+
+config.h: config.h.fbsd
+.if ${BINUTIL_ARCH} == "i386"
+ sed -e 's,!!TRAD_HEADER!!,"hosts/i386bsd.h",g' ${.ALLSRC} > ${.TARGET}
+.else
+ sed -e 's,!!TRAD_HEADER!!,,g' ${.ALLSRC} > ${.TARGET}
+.endif
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.alpha b/gnu/usr.bin/binutils/libbfd/Makefile.alpha
new file mode 100644
index 0000000..e864910
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/Makefile.alpha
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+SRCS+= coff-alpha.c cpu-alpha.c ecoff.c ecofflink.c elf64-alpha.c \
+ elf64-target.h elf64.c elflink.c
+VECS+= bfd_elf64_alpha_vec ecoffalpha_little_vec
+.if ${TARGET_ARCH} == "alpha"
+CFLAGS+= -DDEFAULT_VECTOR=bfd_elf64_alpha_vec
+.endif
+CFLAGS+= -DHAVE_bfd_elf64_alpha_vec
+CFLAGS+= -DHAVE_ecoffalpha_little_vec
+CLEANFILES+= elf64-target.h
+
+elf64-target.h: elfxx-target.h
+ sed -e s/NN/64/g ${.ALLSRC} > ${.TARGET}
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.i386 b/gnu/usr.bin/binutils/libbfd/Makefile.i386
new file mode 100644
index 0000000..03c15c1
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/Makefile.i386
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+SRCS+= cpu-i386.c elf32-i386.c elf32-target.h elf32.c elflink.c
+VECS+= bfd_elf32_i386_vec
+.if ${TARGET_ARCH} == "i386"
+CFLAGS+= -DDEFAULT_VECTOR=bfd_elf32_i386_vec
+.endif
+CFLAGS+= -DHAVE_bfd_elf32_i386_vec
+
+.if defined(BINUTILSDISTDIR) && exists(${BINUTILSDISTDIR})
+SRCS+= pe-i386.c pei-i386.c
+VECS+= i386pe_vec i386pei_vec
+CFLAGS+= -DHAVE_i386pe_vec -DHAVE_i386pei_vec
+.endif
+
+CLEANFILES+= elf32-target.h
+
+elf32-target.h: elfxx-target.h
+ sed -e s/NN/32/g ${.ALLSRC} > ${.TARGET}
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.ia64 b/gnu/usr.bin/binutils/libbfd/Makefile.ia64
new file mode 100644
index 0000000..0a08943
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/Makefile.ia64
@@ -0,0 +1,39 @@
+# $FreeBSD$
+
+SRCS+= cofflink.c cpu-ia64.c efi-app-ia64.c elf32.c elf32-gen.c elf64.c \
+ elf64-gen.c elf64-ia64.c elflink.c
+#SRCS+= coff-ia64.c elf32-ia64.c
+
+VECS+= bfd_efi_app_ia64_vec \
+ bfd_elf64_ia64_little_vec bfd_elf64_ia64_big_vec \
+ bfd_elf64_little_generic_vec bfd_elf64_big_generic_vec \
+ bfd_elf32_little_generic_vec bfd_elf32_big_generic_vec
+
+.if ${TARGET_ARCH} == "ia64"
+CFLAGS+= -DDEFAULT_VECTOR=bfd_elf64_ia64_little_vec
+.endif
+CFLAGS+= -DHAVE_bfd_elf64_ia64_little_vec -DHAVE_bfd_elf64_ia64_big_vec \
+ -DHAVE_bfd_efi_app_ia64_vec \
+ -DHAVE_bfd_elf64_little_generic_vec -DHAVE_bfd_elf64_big_generic_vec \
+ -DHAVE_bfd_elf32_little_generic_vec -DHAVE_bfd_elf32_big_generic_vec
+
+GENSRCS= elf32-target.h elf64-target.h elf64-ia64.c pepigen.c # peigen.c
+SRCS+= ${GENSRCS}
+CLEANFILES+= ${GENSRCS}
+
+elf32-target.h: elfxx-target.h
+ sed -e s/NN/32/g ${.ALLSRC} > ${.TARGET}
+
+elf64-target.h: elfxx-target.h
+ sed -e s/NN/64/g ${.ALLSRC} > ${.TARGET}
+
+
+elf64-ia64.c: elfxx-ia64.c
+ sed -e s/NN/64/g -e 's/^.*#.*define.*ELF_DYNAMIC_INTERPRETER.*$$//g' \
+ ${.ALLSRC} > ${.TARGET}
+
+pepigen.c: peXXigen.c
+ sed -e s/XX/pep/g ${.ALLSRC} > ${.TARGET}
+
+peigen.c: peXXigen.c
+ sed -e s/XX/pe/g ${.ALLSRC} > ${.TARGET}
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.powerpc b/gnu/usr.bin/binutils/libbfd/Makefile.powerpc
new file mode 100644
index 0000000..282cd5a
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/Makefile.powerpc
@@ -0,0 +1,26 @@
+# $FreeBSD$
+
+SRCS+= \
+ cpu-powerpc.c \
+ cpu-rs6000.c \
+ elf32.c \
+ elf32-gen.c \
+ elf32-ppc.c \
+ elf32-target.h \
+ elflink.c \
+ ppcboot.c \
+ #xcofflink.c
+VECS+= bfd_elf32_powerpc_vec \
+ bfd_elf32_powerpcle_vec \
+ ppcboot_vec
+
+.if ${TARGET_ARCH} == "powerpc"
+CFLAGS+= -DDEFAULT_VECTOR=bfd_elf32_powerpc_vec
+.endif
+CFLAGS+= -DHAVE_bfd_elf32_powerpc_vec \
+ -DHAVE_bfd_elf32_powerpcle_vec \
+ -DHAVE_ppcboot_vec
+CLEANFILES+= elf32-target.h
+
+elf32-target.h: elfxx-target.h
+ sed -e s/NN/32/g ${.ALLSRC} > ${.TARGET}
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.sparc64 b/gnu/usr.bin/binutils/libbfd/Makefile.sparc64
new file mode 100644
index 0000000..a5a3d2b
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/Makefile.sparc64
@@ -0,0 +1,27 @@
+# $FreeBSD$
+
+SRCS+= aout32.c \
+ cpu-sparc.c \
+ elf32-sparc.c \
+ elf32-target.h \
+ elf32.c \
+ elf64-sparc.c \
+ elf64-target.h \
+ elf64.c \
+ elflink.c \
+ sparcnetbsd.c \
+ sunos.c
+VECS+= bfd_elf32_sparc_vec bfd_elf64_sparc_vec sparcnetbsd_vec sunos_big_vec
+
+.if ${TARGET_ARCH} == "sparc64"
+CFLAGS+= -DDEFAULT_VECTOR=bfd_elf64_sparc_vec
+.endif
+CFLAGS+= -DHAVE_bfd_elf32_sparc_vec -DHAVE_bfd_elf64_sparc_vec \
+ -DHAVE_sparcnetbsd_vec -DHAVE_sunos_big_vec
+CLEANFILES+= elf32-target.h elf64-target.h
+
+elf32-target.h: elfxx-target.h
+ sed -e s/NN/32/g ${.ALLSRC} > ${.TARGET}
+
+elf64-target.h: elfxx-target.h
+ sed -e s/NN/64/g ${.ALLSRC} > ${.TARGET}
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.x86-64 b/gnu/usr.bin/binutils/libbfd/Makefile.x86-64
new file mode 100644
index 0000000..70f2811
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/Makefile.x86-64
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+SRCS+= cpu-i386.c elf64-x86-64.c elf64-target.h elf64-gen.c elf64.c \
+ elf32-i386.c elf32-target.h elf32.c efi-app-ia32.c elf32-gen.c elflink.c
+VECS+= bfd_elf64_x86_64_vec bfd_elf32_i386_vec
+CFLAGS+= -DDEFAULT_VECTOR=bfd_elf64_x86_64_vec
+CFLAGS+= -DHAVE_bfd_elf64_x86_64_vec -DHAVE_bfd_elf32_i386_vec -DHAVE_bfd_efi_app_ia32_vec -DHAVE_bfd_elf64_little_generic_vec -DHAVE_bfd_elf64_big_generic_vec -DHAVE_bfd_elf32_little_generic_vec -DHAVE_bfd_elf32_big_generic_vec
+
+CLEANFILES+= elf64-target.h elf32-target.h
+
+elf64-target.h: elfxx-target.h
+ sed -e s/NN/64/g ${.ALLSRC} > ${.TARGET}
+
+elf32-target.h: elfxx-target.h
+ sed -e s/NN/32/g ${.ALLSRC} > ${.TARGET}
diff --git a/gnu/usr.bin/binutils/libbfd/alpha/bfd.h b/gnu/usr.bin/binutils/libbfd/alpha/bfd.h
new file mode 100644
index 0000000..88ac097
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/alpha/bfd.h
@@ -0,0 +1,3921 @@
+/* $FreeBSD$ */
+
+/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
+ generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+ "section.c", "archures.c", "reloc.c", "syms.c", "bfd.c", "archive.c",
+ "corefile.c", "targets.c" and "format.c".
+ Run "make headers" in your build bfd/ to regenerate. */
+
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FreeBSD does not adhere to the System V 64-bit ABI. */
+#define ELF_DYNAMIC_INTERPRETER "/usr/libexec/ld-elf.so.1"
+
+#include "ansidecl.h"
+#include "symcat.h"
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This hack is to avoid a problem with some strict ANSI C preprocessors.
+ The problem is, "32_" is not a valid preprocessing token, and we don't
+ want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will
+ cause the inner CONCAT2 macros to be evaluated first, producing
+ still-valid pp-tokens. Then the final concatenation can be done. */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* #define BFD_VERSION 212000000 */
+/* #define BFD_VERSION_DATE 20020309 */
+/* #define BFD_VERSION_STRING "2.12" */
+
+/* The word size used by BFD on the host. This may be 64 with a 32
+ bit target if the host is 64 bit, or if other 64 bit targets have
+ been selected with --enable-targets, or if --enable-64-bit-bfd. */
+#define BFD_ARCH_SIZE 64
+
+/* The word size of the default bfd target. */
+#define BFD_DEFAULT_TARGET_SIZE 64
+
+#if defined(__i386__) || defined(__powerpc__)
+#define BFD_HOST_64BIT_LONG 0
+#else
+#define BFD_HOST_64BIT_LONG 1
+#endif /* 32-bit host */
+#if 0
+#define BFD_HOST_64_BIT
+#define BFD_HOST_U_64_BIT
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* Forward declaration. */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+/* And even worse if your compiler provides a stdbool.h that conflicts
+ with these definitions... gcc 2.95 and later do. If so, it must
+ be included first. -drow */
+#if defined (__GNUG__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+#define TRUE_FALSE_ALREADY_DEFINED
+#else
+#if defined (__bool_true_false_are_defined)
+/* We have <stdbool.h>. */
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, BFD_HOST_64_BIT must be
+ defined above. */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+# define BFD_HOST_64_BIT long
+# define BFD_HOST_U_64_BIT unsigned long
+# else
+# ifdef __GNUC__
+# if __GNUC__ >= 2
+# define BFD_HOST_64_BIT long long
+# define BFD_HOST_U_64_BIT unsigned long long
+# endif /* __GNUC__ >= 2 */
+# endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf (s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf (s, "%08lx", x)
+
+#endif /* not BFD64 */
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef bfd_signed_vma file_ptr;
+typedef bfd_vma ufile_ptr;
+
+extern void bfd_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
+extern void bfd_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/* File formats. */
+
+typedef enum bfd_format
+{
+ bfd_unknown = 0, /* File format is unknown. */
+ bfd_object, /* Linker/assember/compiler output. */
+ bfd_archive, /* Object archive file. */
+ bfd_core, /* Core dump. */
+ bfd_type_end /* Marks the end; don't use it! */
+}
+bfd_format;
+
+/* Values that may appear in the flags field of a BFD. These also
+ appear in the object_flags field of the bfd_target structure, where
+ they indicate the set of flags used by that backend (not all flags
+ are meaningful for all object file formats) (FIXME: at the moment,
+ the object_flags values have mostly just been copied from backend
+ to another, and are not necessarily correct). */
+
+/* No flags. */
+#define BFD_NO_FLAGS 0x00
+
+/* BFD contains relocation entries. */
+#define HAS_RELOC 0x01
+
+/* BFD is directly executable. */
+#define EXEC_P 0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+ COFF header). */
+#define HAS_LINENO 0x04
+
+/* BFD has debugging information. */
+#define HAS_DEBUG 0x08
+
+/* BFD has symbols. */
+#define HAS_SYMS 0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+ header). */
+#define HAS_LOCALS 0x20
+
+/* BFD is a dynamic object. */
+#define DYNAMIC 0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+ like an a.out NMAGIC file) (the linker sets this by default, but
+ clears it for -r or -N). */
+#define WP_TEXT 0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+ linker sets this by default, but clears it for -r or -n or -N). */
+#define D_PAGED 0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+ do something) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+ traditional format. For example, this is used to request that when
+ writing out an a.out object the symbols not be hashed to eliminate
+ duplicates. */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* Symbols and relocation. */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+ target specific parts are in libcoff.h, libaout.h, etc. */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol. */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym
+{
+ char *name;
+ file_ptr file_offset; /* Look here to find the file. */
+}
+carsym; /* To make these you call a carsymogen. */
+
+/* Used in generating armaps (archive tables of contents).
+ Perhaps just a forward definition would do? */
+struct orl /* Output ranlib. */
+{
+ char **name; /* Symbol name. */
+ union
+ {
+ file_ptr pos;
+ bfd *abfd;
+ } u; /* bfd* or file position. */
+ int namidx; /* Index into string table. */
+};
+
+/* Linenumber stuff. */
+typedef struct lineno_cache_entry
+{
+ unsigned int line_number; /* Linenumber from start of function. */
+ union
+ {
+ struct symbol_cache_entry *sym; /* Function name. */
+ bfd_vma offset; /* Offset into section. */
+ } u;
+}
+alent;
+
+/* Object and core file sections. */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ const char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ const char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines. There is no way to free up a hash table. */
+
+/* An element in the hash table. Most uses will actually use a larger
+ structure, and an instance of this will be the first field. */
+
+struct bfd_hash_entry
+{
+ /* Next entry for this hash code. */
+ struct bfd_hash_entry *next;
+ /* String being hashed. */
+ const char *string;
+ /* Hash code. This is the full hash code, not the index into the
+ table. */
+ unsigned long hash;
+};
+
+/* A hash table. */
+
+struct bfd_hash_table
+{
+ /* The hash array. */
+ struct bfd_hash_entry **table;
+ /* The number of slots in the hash table. */
+ unsigned int size;
+ /* A function used to create new elements in the hash table. The
+ first entry is itself a pointer to an element. When this
+ function is first invoked, this pointer will be NULL. However,
+ having the pointer permits a hierarchy of method functions to be
+ built each of which calls the function in the superclass. Thus
+ each function should be written to allocate a new block of memory
+ only if the argument is NULL. */
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+ /* An objalloc for this hash table. This is a struct objalloc *,
+ but we use PTR to avoid requiring the inclusion of objalloc.h. */
+ PTR memory;
+};
+
+/* Initialize a hash table. */
+extern boolean bfd_hash_table_init
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+
+/* Initialize a hash table specifying a size. */
+extern boolean bfd_hash_table_init_n
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int size));
+
+/* Free up a hash table. */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table. If CREATE is true, a new entry
+ will be created for this string if one does not already exist. The
+ COPY argument must be true if this routine should copy the string
+ into newly allocated memory when adding an entry. */
+extern struct bfd_hash_entry *bfd_hash_lookup
+ PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+ boolean copy));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry. */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Grab some space for a hash table entry. */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+ unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+ element. If the function returns false, the traversal stops. The
+ INFO argument is passed to the function. */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+ boolean (*) (struct bfd_hash_entry *,
+ PTR),
+ PTR info));
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities. */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_bread PARAMS ((PTR, bfd_size_type, bfd *));
+extern bfd_size_type bfd_bwrite PARAMS ((const PTR, bfd_size_type, bfd *));
+extern int bfd_seek PARAMS ((bfd *, file_ptr, int));
+extern ufile_ptr bfd_tell PARAMS ((bfd *));
+extern int bfd_flush PARAMS ((bfd *));
+extern int bfd_stat PARAMS ((bfd *, struct stat *));
+
+/* Deprecated old routines. */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated
+ PARAMS ((const char *, const char *, int, const char *));
+
+/* Cast from const char * to char * so that caller can assign to
+ a char * without a warning. */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_family_coff(abfd) \
+ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean) (bool)), true)
+
+extern boolean bfd_cache_close PARAMS ((bfd *abfd));
+/* NB: This declaration should match the autogenerated one in libbfd.h. */
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+bfd_vma bfd_getb64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb16 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void bfd_putb64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb16 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl16 PARAMS ((bfd_vma, unsigned char *));
+
+/* Byte swapping routines which take size and endiannes as arguments. */
+
+bfd_vma bfd_get_bits PARAMS ((bfd_byte *, int, boolean));
+void bfd_put_bits PARAMS ((bfd_vma, bfd_byte *, int, boolean));
+
+/* Externally visible ECOFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+ PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+ unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+ PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ bfd *input_bfd, struct ecoff_debug_info *input_debug,
+ const struct ecoff_debug_swap *input_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ boolean relocateable,
+ boolean (*get_extr) (struct symbol_cache_entry *,
+ struct ecoff_extr *),
+ void (*set_index) (struct symbol_cache_entry *,
+ bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+ PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+ PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Return an upper bound on the number of bytes required to store a
+ copy of ABFD's program header table entries. Return -1 if an error
+ occurs; bfd_get_error will return an appropriate code. */
+extern long bfd_get_elf_phdr_upper_bound PARAMS ((bfd *abfd));
+
+/* Copy ABFD's program header table entries to *PHDRS. The entries
+ will be stored as an array of Elf_Internal_Phdr structures, as
+ defined in include/elf/internal.h. To find out how large the
+ buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+ Return the number of program header table entries read, or -1 if an
+ error occurs; bfd_get_error will return an appropriate code. */
+extern int bfd_get_elf_phdrs PARAMS ((bfd *abfd, void *phdrs));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf. */
+extern int bfd_get_arch_size PARAMS ((bfd *));
+
+/* Return true if address "naturally" sign extends, or -1 if not elf. */
+extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+
+extern boolean bfd_m68k_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+extern boolean bfd_mips_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+ struct sec **));
+
+/* Linux shared library support routines for the linker. */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window
+{
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+}
+bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *, unsigned int));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+extern boolean bfd_xcoff_link_generate_rtinit
+ PARAMS ((bfd *, const char *, const char *));
+
+/* Externally visible COFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+ PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+ PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+ PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+extern boolean bfd_m68k_coff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* PE ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_pe_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_pe_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_pe_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support. Called from linker. */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* TI COFF load page support. */
+extern void bfd_ticoff_set_section_load_page
+ PARAMS ((struct sec *, int));
+
+extern int bfd_ticoff_get_section_load_page
+ PARAMS ((struct sec *));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((const char *filename, const char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((const char *filename, const char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((const char *filename, const char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((const char *filename, bfd *templ));
+
+boolean
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+/* Byte swapping macros for user section data. */
+
+#define bfd_put_8(abfd, val, ptr) \
+ ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val)))
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr) \
+ ( (bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \
+ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \
+ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \
+ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \
+ : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr) \
+ ( (bits) == 8 ? bfd_put_8 (abfd, val, ptr) \
+ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \
+ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \
+ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \
+ : (abort (), (void) 0))
+
+
+/* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx16, (val, ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx16, (ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx32, (val, ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx32, (ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx64, (val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx64, (ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr))
+
+/* Refinements on the above, which should eventually go away. Save
+ cluttering the source with (bfd_vma) and (bfd_byte *) casts. */
+
+#define H_PUT_64(abfd, val, where) \
+ bfd_h_put_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_32(abfd, val, where) \
+ bfd_h_put_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_16(abfd, val, where) \
+ bfd_h_put_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_8 bfd_h_put_8
+
+#define H_PUT_S64(abfd, val, where) \
+ bfd_h_put_signed_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S32(abfd, val, where) \
+ bfd_h_put_signed_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S16(abfd, val, where) \
+ bfd_h_put_signed_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S8 bfd_h_put_signed_8
+
+#define H_GET_64(abfd, where) \
+ bfd_h_get_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_32(abfd, where) \
+ bfd_h_get_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_16(abfd, where) \
+ bfd_h_get_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_8 bfd_h_get_8
+
+#define H_GET_S64(abfd, where) \
+ bfd_h_get_signed_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S32(abfd, where) \
+ bfd_h_get_signed_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S16(abfd, where) \
+ bfd_h_get_signed_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S8 bfd_h_get_signed_8
+
+
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+typedef struct sec
+{
+ /* The name of the section; the name isn't a copy, the pointer is
+ the same as that passed to bfd_make_section. */
+ const char *name;
+
+ /* A unique sequence number. */
+ int id;
+
+ /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */
+ int index;
+
+ /* The next section in the list belonging to the BFD, or NULL. */
+ struct sec *next;
+
+ /* The field flags contains attributes of the section. Some
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* Tells the OS to allocate space for this section when loading.
+ This is clear for a section containing debug information only. */
+#define SEC_ALLOC 0x001
+
+ /* Tells the OS to load the section from the file when loading.
+ This is clear for a .bss section. */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there is
+ some relocation information too. */
+#define SEC_RELOC 0x004
+
+ /* ELF reserves 4 processor specific bits and 8 operating system
+ specific bits in sh_flags; at present we can get away with just
+ one in communicating between the assembler and BFD, but this
+ isn't a good long-term solution. */
+#define SEC_ARCH_BIT_0 0x008
+
+ /* A signal to the OS that the section contains read only data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+ the symbol to it, and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constructor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker to not output the section
+ even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a COFF shared library section. This flag is
+ only for the linker. If this type of section appears in
+ the input file, the linker must copy it to the output file
+ without changing the vma or size. FIXME: Although this
+ was originally intended to be general, it really is COFF
+ specific (and the flag was renamed to indicate this). It
+ might be cleaner to have some more general mechanism to
+ allow the back end to control what the linker does with
+ sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+ /* The section has GOT references. This flag is only for the
+ linker, and is currently only used by the elf32-hppa back end.
+ It will be set if global offset table references were detected
+ in this section, which indicate to the linker that the section
+ contains PIC code, and must be handled specially when doing a
+ static link. */
+#define SEC_HAS_GOT_REF 0x4000
+
+ /* The section contains common symbols (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* The contents of this section are held in memory pointed to
+ by the contents field. This is checked by bfd_get_section_contents,
+ and the data is retrieved from memory if appropriate. */
+#define SEC_IN_MEMORY 0x20000
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted based on the sum of
+ the symbol and addend values specified by the associated relocation
+ entries. Entries without associated relocation entries will be
+ appended to the end of the section in an unspecified order. */
+#define SEC_SORT_ENTRIES 0x80000
+
+ /* When linking, duplicate sections of the same name should be
+ discarded, rather than being combined into a single section as
+ is usually done. This is similar to how common symbols are
+ handled. See SEC_LINK_DUPLICATES below. */
+#define SEC_LINK_ONCE 0x100000
+
+ /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+ should handle duplicate sections. */
+#define SEC_LINK_DUPLICATES 0x600000
+
+ /* This value for SEC_LINK_DUPLICATES means that duplicate
+ sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if there are any duplicate sections, although
+ it should still only link one copy. */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections are a different size. */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections contain different
+ contents. */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+ /* This section was created by the linker as part of dynamic
+ relocation or other arcane processing. It is skipped when
+ going through the first-pass output, trusting that someone
+ else up the line will take care of it later. */
+#define SEC_LINKER_CREATED 0x800000
+
+ /* This section should not be subject to garbage collection. */
+#define SEC_KEEP 0x1000000
+
+ /* This section contains "short" data, and should be placed
+ "near" the GP. */
+#define SEC_SMALL_DATA 0x2000000
+
+ /* This section contains data which may be shared with other
+ executables or shared objects. */
+#define SEC_SHARED 0x4000000
+
+ /* When a section with this flag is being linked, then if the size of
+ the input section is less than a page, it should not cross a page
+ boundary. If the size of the input section is one page or more, it
+ should be aligned on a page boundary. */
+#define SEC_BLOCK 0x8000000
+
+ /* Conditionally link this section; do not link if there are no
+ references found to any symbol in the section. */
+#define SEC_CLINK 0x10000000
+
+ /* Attempt to merge identical entities in the section.
+ Entity size is given in the entsize field. */
+#define SEC_MERGE 0x20000000
+
+ /* If given with SEC_MERGE, entities to merge are zero terminated
+ strings where entsize specifies character size instead of fixed
+ size entries. */
+#define SEC_STRINGS 0x40000000
+
+ /* This section contains data about section groups. */
+#define SEC_GROUP 0x80000000
+
+ /* End of section flags. */
+
+ /* Some internal packed boolean fields. */
+
+ /* See the vma field. */
+ unsigned int user_set_vma : 1;
+
+ /* Whether relocations have been processed. */
+ unsigned int reloc_done : 1;
+
+ /* A mark flag used by some of the linker backends. */
+ unsigned int linker_mark : 1;
+
+ /* Another mark flag used by some of the linker backends. Set for
+ output sections that have an input section. */
+ unsigned int linker_has_input : 1;
+
+ /* A mark flag used by some linker backends for garbage collection. */
+ unsigned int gc_mark : 1;
+
+ /* Used by the ELF code to mark sections which have been allocated
+ to segments. */
+ unsigned int segment_mark : 1;
+
+ /* End of internal packed boolean fields. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+ bfd_vma vma;
+
+ /* The load address of the section - where it would be in a
+ rom image; really only used for writing section header
+ information. */
+ bfd_vma lma;
+
+ /* The size of the section in octets, as it will be output.
+ Contains a value even if the section has no contents (e.g., the
+ size of <<.bss>>). This will be filled in after relocation. */
+ bfd_size_type _cooked_size;
+
+ /* The original size on disk of the section, in octets. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset in *bytes* into the output section of the first byte in the
+ input section (byte ==> smallest addressable unit on the
+ target). In most cases, if this was going to start at the
+ 100th octet (8-bit quantity) in the output section, this value
+ would be 100. However, if the target byte size is 16 bits
+ (bfd_octets_per_byte is "2"), this value would be 50. */
+ bfd_vma output_offset;
+
+ /* The output section through which to map on output. */
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent of 2 -
+ e.g., 3 aligns to 2^3 (or 8). */
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above. */
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data. */
+ file_ptr filepos;
+
+ /* File position of relocation info. */
+ file_ptr rel_filepos;
+
+ /* File position of line data. */
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications. */
+ PTR userdata;
+
+ /* If the SEC_IN_MEMORY flag is set, this points to the actual
+ contents. */
+ unsigned char *contents;
+
+ /* Attached line number information. */
+ alent *lineno;
+
+ /* Number of line number records. */
+ unsigned int lineno_count;
+
+ /* Entity size for merging purposes. */
+ unsigned int entsize;
+
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct bfd_comdat_info *comdat;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out. */
+ file_ptr moving_line_filepos;
+
+ /* What the section number is in the target world. */
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+ bfd *owner;
+
+ /* A symbol which points at this section only. */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ struct bfd_link_order *link_order_head;
+ struct bfd_link_order *link_order_tail;
+} asection;
+
+/* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. New code should use the section_ptr macros rather
+ than referring directly to the const sections. The const sections
+ may eventually vanish. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* The absolute section. */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+/* Pointer to the undefined section. */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+/* Pointer to the common section. */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section. */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC) \
+ ( ((SEC) == bfd_abs_section_ptr) \
+ || ((SEC) == bfd_und_section_ptr) \
+ || ((SEC) == bfd_com_section_ptr) \
+ || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+ ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \
+ : (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section)->reloc_done ? (section)->_cooked_size \
+ : (abort (), (bfd_size_type) 1))
+
+/* Macros to handle insertion and deletion of a bfd's sections. These
+ only handle the list pointers, ie. do not adjust section_count,
+ target_index etc. */
+#define bfd_section_list_remove(ABFD, PS) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = *_ps; \
+ *_ps = _s->next; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = _ps; \
+ } \
+ while (0)
+#define bfd_section_list_insert(ABFD, PS, S) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = S; \
+ _s->next = *_ps; \
+ *_ps = _s; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = &_s->next; \
+ } \
+ while (0)
+
+void
+bfd_section_list_clear PARAMS ((bfd *));
+
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, const char *name));
+
+char *
+bfd_get_unique_section_name PARAMS ((bfd *abfd,
+ const char *templat,
+ int *count));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, const char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func) (bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR data, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_get_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec,
+ bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+ BFD_SEND (obfd, _bfd_copy_private_section_data, \
+ (ibfd, isection, obfd, osection))
+void
+_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
+
+enum bfd_architecture
+{
+ bfd_arch_unknown, /* File arch not known. */
+ bfd_arch_obscure, /* Arch known, not one of these. */
+ bfd_arch_m68k, /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32 8
+#define bfd_mach_mcf5200 9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307 11
+#define bfd_mach_mcf5407 12
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+#define bfd_mach_i960_jx 7
+#define bfd_mach_i960_hx 8
+
+ bfd_arch_or32, /* OpenRISC 32 */
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+#define bfd_mach_sparc 1
+/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
+#define bfd_mach_sparc_sparclet 2
+#define bfd_mach_sparc_sparclite 3
+#define bfd_mach_sparc_v8plus 4
+#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_sparclite_le 6
+#define bfd_mach_sparc_v9 7
+#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
+#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
+/* Nonzero if MACH has the v9 instruction set. */
+#define bfd_mach_sparc_v9_p(mach) \
+ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
+ && (mach) != bfd_mach_sparc_sparclite_le)
+ bfd_arch_mips, /* MIPS Rxxxx */
+#define bfd_mach_mips3000 3000
+#define bfd_mach_mips3900 3900
+#define bfd_mach_mips4000 4000
+#define bfd_mach_mips4010 4010
+#define bfd_mach_mips4100 4100
+#define bfd_mach_mips4111 4111
+#define bfd_mach_mips4300 4300
+#define bfd_mach_mips4400 4400
+#define bfd_mach_mips4600 4600
+#define bfd_mach_mips4650 4650
+#define bfd_mach_mips5000 5000
+#define bfd_mach_mips6000 6000
+#define bfd_mach_mips8000 8000
+#define bfd_mach_mips10000 10000
+#define bfd_mach_mips12000 12000
+#define bfd_mach_mips16 16
+#define bfd_mach_mips5 5
+#define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32 32
+#define bfd_mach_mipsisa64 64
+ bfd_arch_i386, /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+#define bfd_mach_x86_64 3
+#define bfd_mach_x86_64_intel_syntax 4
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_i370, /* IBM 360/370 Mainframes */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ bfd_arch_h8300, /* Hitachi H8/300 */
+#define bfd_mach_h8300 1
+#define bfd_mach_h8300h 2
+#define bfd_mach_h8300s 3
+ bfd_arch_pdp11, /* DEC PDP-11 */
+ bfd_arch_powerpc, /* PowerPC */
+#define bfd_mach_ppc 0
+#define bfd_mach_ppc64 1
+#define bfd_mach_ppc_403 403
+#define bfd_mach_ppc_403gc 4030
+#define bfd_mach_ppc_505 505
+#define bfd_mach_ppc_601 601
+#define bfd_mach_ppc_602 602
+#define bfd_mach_ppc_603 603
+#define bfd_mach_ppc_ec603e 6031
+#define bfd_mach_ppc_604 604
+#define bfd_mach_ppc_620 620
+#define bfd_mach_ppc_630 630
+#define bfd_mach_ppc_750 750
+#define bfd_mach_ppc_860 860
+#define bfd_mach_ppc_a35 35
+#define bfd_mach_ppc_rs64ii 642
+#define bfd_mach_ppc_rs64iii 643
+#define bfd_mach_ppc_7400 7400
+ bfd_arch_rs6000, /* IBM RS/6000 */
+#define bfd_mach_rs6k 0
+#define bfd_mach_rs6k_rs1 6001
+#define bfd_mach_rs6k_rsc 6003
+#define bfd_mach_rs6k_rs2 6002
+ bfd_arch_hppa, /* HP PA RISC */
+ bfd_arch_d10v, /* Mitsubishi D10V */
+#define bfd_mach_d10v 0
+#define bfd_mach_d10v_ts2 2
+#define bfd_mach_d10v_ts3 3
+ bfd_arch_d30v, /* Mitsubishi D30V */
+ bfd_arch_m68hc11, /* Motorola 68HC11 */
+ bfd_arch_m68hc12, /* Motorola 68HC12 */
+ bfd_arch_z8k, /* Zilog Z8000 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+#define bfd_mach_sh 0
+#define bfd_mach_sh2 0x20
+#define bfd_mach_sh_dsp 0x2d
+#define bfd_mach_sh3 0x30
+#define bfd_mach_sh3_dsp 0x3d
+#define bfd_mach_sh3e 0x3e
+#define bfd_mach_sh4 0x40
+#define bfd_mach_sh5 0x50
+ bfd_arch_alpha, /* Dec Alpha */
+#define bfd_mach_alpha_ev4 0x10
+#define bfd_mach_alpha_ev5 0x20
+#define bfd_mach_alpha_ev6 0x30
+ bfd_arch_arm, /* Advanced Risc Machines ARM. */
+#define bfd_mach_arm_2 1
+#define bfd_mach_arm_2a 2
+#define bfd_mach_arm_3 3
+#define bfd_mach_arm_3M 4
+#define bfd_mach_arm_4 5
+#define bfd_mach_arm_4T 6
+#define bfd_mach_arm_5 7
+#define bfd_mach_arm_5T 8
+#define bfd_mach_arm_5TE 9
+#define bfd_mach_arm_XScale 10
+ bfd_arch_ns32k, /* National Semiconductors ns32000 */
+ bfd_arch_w65, /* WDC 65816 */
+ bfd_arch_tic30, /* Texas Instruments TMS320C30 */
+ bfd_arch_tic54x, /* Texas Instruments TMS320C54X */
+ bfd_arch_tic80, /* TI TMS320c80 (MVP) */
+ bfd_arch_v850, /* NEC V850 */
+#define bfd_mach_v850 0
+#define bfd_mach_v850e 'E'
+#define bfd_mach_v850ea 'A'
+ bfd_arch_arc, /* ARC Cores */
+#define bfd_mach_arc_5 0
+#define bfd_mach_arc_6 1
+#define bfd_mach_arc_7 2
+#define bfd_mach_arc_8 3
+ bfd_arch_m32r, /* Mitsubishi M32R/D */
+#define bfd_mach_m32r 0 /* For backwards compatibility. */
+#define bfd_mach_m32rx 'x'
+ bfd_arch_mn10200, /* Matsushita MN10200 */
+ bfd_arch_mn10300, /* Matsushita MN10300 */
+#define bfd_mach_mn10300 300
+#define bfd_mach_am33 330
+ bfd_arch_fr30,
+#define bfd_mach_fr30 0x46523330
+ bfd_arch_mcore,
+ bfd_arch_ia64, /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64 0
+#define bfd_mach_ia64_elf32 1
+ bfd_arch_pj,
+ bfd_arch_avr, /* Atmel AVR microcontrollers. */
+#define bfd_mach_avr1 1
+#define bfd_mach_avr2 2
+#define bfd_mach_avr3 3
+#define bfd_mach_avr4 4
+#define bfd_mach_avr5 5
+ bfd_arch_cris, /* Axis CRIS */
+ bfd_arch_s390, /* IBM s390 */
+#define bfd_mach_s390_esa 0
+#define bfd_mach_s390_esame 1
+ bfd_arch_openrisc, /* OpenRISC */
+ bfd_arch_mmix, /* Donald Knuth's educational processor. */
+ bfd_arch_xstormy16,
+#define bfd_mach_xstormy16 0
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ unsigned long mach;
+ const char *arch_name;
+ const char *printable_name;
+ unsigned int section_align_power;
+ /* True if this is the default machine for the architecture. */
+ boolean the_default;
+ const struct bfd_arch_info * (*compatible)
+ PARAMS ((const struct bfd_arch_info *a,
+ const struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+ const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ const bfd *abfd,
+ const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch PARAMS ((enum bfd_architecture
+ arch,
+ unsigned long machine));
+
+const char *
+bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+unsigned int
+bfd_octets_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_mach_octets_per_byte PARAMS ((enum bfd_architecture arch,
+ unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected. */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions. */
+ bfd_reloc_continue,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_notsupported,
+
+ /* Unused. */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ symbols. If this type is returned, the error_message argument
+ to bfd_perform_relocation will be set. */
+ bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+ /* A pointer into the canonical table of pointers. */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section. */
+ bfd_size_type address;
+
+ /* addend for relocation value. */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation. */
+ reloc_howto_type *howto;
+
+}
+arelent;
+
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+ /* The type field has mainly a documentary use - the back end can
+ do what it wants with it, though normally the back end's
+ external idea of what a reloc number is stored
+ in this field. For example, a PC relative word relocation
+ in a coff environment has the type 023 - because that's
+ what the outside world calls a R_PCRWORD reloc. */
+ unsigned int type;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ power-of-two measure. To get the number of bytes operated
+ on by a type of relocation, use bfd_get_reloc_size. */
+ int size;
+
+ /* The number of bits in the item to be relocated. This is used
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ called rather than the normal function. This allows really
+ strange relocation methods to be accomodated (e.g., i960 callj
+ instructions). */
+ bfd_reloc_status_type (*special_function)
+ PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
+ bfd *, char **));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* Some formats record a relocation addend in the section contents
+ rather than with the relocation. For ELF formats this is the
+ distinction between USE_REL and USE_RELA (though the code checks
+ for USE_REL == 1/0). The value of this field is TRUE if the
+ addend is recorded with the section contents; when performing a
+ partial link (ld -r) the section contents (the data) will be
+ modified. The value of this field is FALSE if addends are
+ recorded with the relocation (in arelent.addend); when performing
+ a partial link the relocation will be modified.
+ All relocations for all ELF USE_RELA targets should set this field
+ to FALSE (values of TRUE should be looked on with suspicion).
+ However, the converse is not true: not all relocations of all ELF
+ USE_REL targets set this field to TRUE. Why this is so is peculiar
+ to each particular target. For relocs that aren't used in partial
+ links (e.g. GOT stuff) it doesn't matter what this is set to. */
+ boolean partial_inplace;
+
+ /* The src_mask selects which parts of the read in data
+ are to be used in the relocation sum. E.g., if this was an 8 bit
+ byte of data which we read and relocated, this would be
+ 0x000000ff. When we have relocs which have an addend, such as
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* The dst_mask selects which parts of the instruction are replaced
+ into the instruction. In most cases src_mask == dst_mask,
+ except in the above special case, where dst_mask would be
+ 0x000000ff, and src_mask would be 0x00000000. */
+ bfd_vma dst_mask;
+
+ /* When some formats create PC relative instructions, they leave
+ the value of the pc of the place being relocated in the offset
+ slot of the instruction, so that a PC relative relocation can
+ be made just by adding in an ordinary offset (e.g., sun3 a.out).
+ Some formats leave the displacement part of an instruction
+ empty (e.g., m88k bcs); this flag signals the fact. */
+ boolean pcrel_offset;
+};
+
+#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC }
+#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \
+ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \
+ NAME, false, 0, 0, IN)
+
+#define EMPTY_HOWTO(C) \
+ HOWTO ((C), 0, 0, 0, false, 0, complain_overflow_dont, NULL, \
+ NULL, false, 0, 0, false)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *) NULL) \
+ { \
+ if (bfd_is_com_section (symbol->section)) \
+ { \
+ relocation = 0; \
+ } \
+ else \
+ { \
+ relocation = symbol->value; \
+ } \
+ } \
+ }
+
+unsigned int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain
+{
+ arelent relent;
+ struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type
+bfd_check_overflow PARAMS ((enum complain_overflow how,
+ unsigned int bitsize,
+ unsigned int rightshift,
+ unsigned int addrsize,
+ bfd_vma relocation));
+
+bfd_reloc_status_type
+bfd_perform_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+bfd_reloc_status_type
+bfd_install_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message));
+
+enum bfd_reloc_code_real {
+ _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_26,
+ BFD_RELOC_24,
+ BFD_RELOC_16,
+ BFD_RELOC_14,
+ BFD_RELOC_8,
+
+/* PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_12_PCREL,
+ BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+ BFD_RELOC_32_GOT_PCREL,
+ BFD_RELOC_16_GOT_PCREL,
+ BFD_RELOC_8_GOT_PCREL,
+ BFD_RELOC_32_GOTOFF,
+ BFD_RELOC_16_GOTOFF,
+ BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF,
+ BFD_RELOC_8_GOTOFF,
+ BFD_RELOC_64_PLT_PCREL,
+ BFD_RELOC_32_PLT_PCREL,
+ BFD_RELOC_24_PLT_PCREL,
+ BFD_RELOC_16_PLT_PCREL,
+ BFD_RELOC_8_PLT_PCREL,
+ BFD_RELOC_64_PLTOFF,
+ BFD_RELOC_32_PLTOFF,
+ BFD_RELOC_16_PLTOFF,
+ BFD_RELOC_LO16_PLTOFF,
+ BFD_RELOC_HI16_PLTOFF,
+ BFD_RELOC_HI16_S_PLTOFF,
+ BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+ BFD_RELOC_68K_GLOB_DAT,
+ BFD_RELOC_68K_JMP_SLOT,
+ BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_LO16_BASEREL,
+ BFD_RELOC_HI16_BASEREL,
+ BFD_RELOC_HI16_S_BASEREL,
+ BFD_RELOC_8_BASEREL,
+ BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+ BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+ BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_16_PCREL_S2,
+ BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC. */
+ BFD_RELOC_HI22,
+ BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register. These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+ BFD_RELOC_GPREL16,
+ BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+ BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations. There is probably some overlap with other
+relocation types already defined. */
+ BFD_RELOC_NONE,
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA16,
+ BFD_RELOC_SPARC_UA32,
+ BFD_RELOC_SPARC_UA64,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+ BFD_RELOC_SPARC_10,
+ BFD_RELOC_SPARC_11,
+ BFD_RELOC_SPARC_OLO10,
+ BFD_RELOC_SPARC_HH22,
+ BFD_RELOC_SPARC_HM10,
+ BFD_RELOC_SPARC_LM22,
+ BFD_RELOC_SPARC_PC_HH22,
+ BFD_RELOC_SPARC_PC_HM10,
+ BFD_RELOC_SPARC_PC_LM22,
+ BFD_RELOC_SPARC_WDISP16,
+ BFD_RELOC_SPARC_WDISP19,
+ BFD_RELOC_SPARC_7,
+ BFD_RELOC_SPARC_6,
+ BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+ BFD_RELOC_SPARC_PLT32,
+ BFD_RELOC_SPARC_PLT64,
+ BFD_RELOC_SPARC_HIX22,
+ BFD_RELOC_SPARC_LOX10,
+ BFD_RELOC_SPARC_H44,
+ BFD_RELOC_SPARC_M44,
+ BFD_RELOC_SPARC_L44,
+ BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+ BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol. The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+ BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs. The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+ BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+ BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol. The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references. The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch) */
+ BFD_RELOC_ALPHA_LITERAL,
+ BFD_RELOC_ALPHA_ELF_LITERAL,
+ BFD_RELOC_ALPHA_LITUSE,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+ BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_CODEADDR,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register. */
+ BFD_RELOC_ALPHA_GPREL_HI16,
+ BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD. */
+ BFD_RELOC_ALPHA_BRSGP,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+ BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+ BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+ BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+ BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result. If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+ BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+ BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+ BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+ BFD_RELOC_PCREL_LO16,
+
+/* Relocation against a MIPS literal section. */
+ BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+ BFD_RELOC_MIPS_GOT16,
+ BFD_RELOC_MIPS_CALL16,
+ BFD_RELOC_MIPS_GOT_HI16,
+ BFD_RELOC_MIPS_GOT_LO16,
+ BFD_RELOC_MIPS_CALL_HI16,
+ BFD_RELOC_MIPS_CALL_LO16,
+ BFD_RELOC_MIPS_SUB,
+ BFD_RELOC_MIPS_GOT_PAGE,
+ BFD_RELOC_MIPS_GOT_OFST,
+ BFD_RELOC_MIPS_GOT_DISP,
+ BFD_RELOC_MIPS_SHIFT5,
+ BFD_RELOC_MIPS_SHIFT6,
+ BFD_RELOC_MIPS_INSERT_A,
+ BFD_RELOC_MIPS_INSERT_B,
+ BFD_RELOC_MIPS_DELETE,
+ BFD_RELOC_MIPS_HIGHEST,
+ BFD_RELOC_MIPS_HIGHER,
+ BFD_RELOC_MIPS_SCN_DISP,
+ BFD_RELOC_MIPS_REL16,
+ BFD_RELOC_MIPS_RELGOT,
+ BFD_RELOC_MIPS_JALR,
+ BFD_RELOC_SH_GOT_LOW16,
+ BFD_RELOC_SH_GOT_MEDLOW16,
+ BFD_RELOC_SH_GOT_MEDHI16,
+ BFD_RELOC_SH_GOT_HI16,
+ BFD_RELOC_SH_GOTPLT_LOW16,
+ BFD_RELOC_SH_GOTPLT_MEDLOW16,
+ BFD_RELOC_SH_GOTPLT_MEDHI16,
+ BFD_RELOC_SH_GOTPLT_HI16,
+ BFD_RELOC_SH_PLT_LOW16,
+ BFD_RELOC_SH_PLT_MEDLOW16,
+ BFD_RELOC_SH_PLT_MEDHI16,
+ BFD_RELOC_SH_PLT_HI16,
+ BFD_RELOC_SH_GOTOFF_LOW16,
+ BFD_RELOC_SH_GOTOFF_MEDLOW16,
+ BFD_RELOC_SH_GOTOFF_MEDHI16,
+ BFD_RELOC_SH_GOTOFF_HI16,
+ BFD_RELOC_SH_GOTPC_LOW16,
+ BFD_RELOC_SH_GOTPC_MEDLOW16,
+ BFD_RELOC_SH_GOTPC_MEDHI16,
+ BFD_RELOC_SH_GOTPC_HI16,
+ BFD_RELOC_SH_COPY64,
+ BFD_RELOC_SH_GLOB_DAT64,
+ BFD_RELOC_SH_JMP_SLOT64,
+ BFD_RELOC_SH_RELATIVE64,
+ BFD_RELOC_SH_GOT10BY4,
+ BFD_RELOC_SH_GOT10BY8,
+ BFD_RELOC_SH_GOTPLT10BY4,
+ BFD_RELOC_SH_GOTPLT10BY8,
+ BFD_RELOC_SH_GOTPLT32,
+ BFD_RELOC_SH_SHMEDIA_CODE,
+ BFD_RELOC_SH_IMMU5,
+ BFD_RELOC_SH_IMMS6,
+ BFD_RELOC_SH_IMMS6BY32,
+ BFD_RELOC_SH_IMMU6,
+ BFD_RELOC_SH_IMMS10,
+ BFD_RELOC_SH_IMMS10BY2,
+ BFD_RELOC_SH_IMMS10BY4,
+ BFD_RELOC_SH_IMMS10BY8,
+ BFD_RELOC_SH_IMMS16,
+ BFD_RELOC_SH_IMMU16,
+ BFD_RELOC_SH_IMM_LOW16,
+ BFD_RELOC_SH_IMM_LOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDLOW16,
+ BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDHI16,
+ BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+ BFD_RELOC_SH_IMM_HI16,
+ BFD_RELOC_SH_IMM_HI16_PCREL,
+ BFD_RELOC_SH_PT_16,
+
+
+/* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ BFD_RELOC_386_GOTOFF,
+ BFD_RELOC_386_GOTPC,
+
+/* x86-64/elf relocations */
+ BFD_RELOC_X86_64_GOT32,
+ BFD_RELOC_X86_64_PLT32,
+ BFD_RELOC_X86_64_COPY,
+ BFD_RELOC_X86_64_GLOB_DAT,
+ BFD_RELOC_X86_64_JUMP_SLOT,
+ BFD_RELOC_X86_64_RELATIVE,
+ BFD_RELOC_X86_64_GOTPCREL,
+ BFD_RELOC_X86_64_32S,
+
+/* ns32k relocations */
+ BFD_RELOC_NS32K_IMM_8,
+ BFD_RELOC_NS32K_IMM_16,
+ BFD_RELOC_NS32K_IMM_32,
+ BFD_RELOC_NS32K_IMM_8_PCREL,
+ BFD_RELOC_NS32K_IMM_16_PCREL,
+ BFD_RELOC_NS32K_IMM_32_PCREL,
+ BFD_RELOC_NS32K_DISP_8,
+ BFD_RELOC_NS32K_DISP_16,
+ BFD_RELOC_NS32K_DISP_32,
+ BFD_RELOC_NS32K_DISP_8_PCREL,
+ BFD_RELOC_NS32K_DISP_16_PCREL,
+ BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* PDP11 relocations */
+ BFD_RELOC_PDP11_DISP_8_PCREL,
+ BFD_RELOC_PDP11_DISP_6_PCREL,
+
+/* Picojava relocs. Not all of these appear in object files. */
+ BFD_RELOC_PJ_CODE_HI16,
+ BFD_RELOC_PJ_CODE_LO16,
+ BFD_RELOC_PJ_CODE_DIR16,
+ BFD_RELOC_PJ_CODE_DIR32,
+ BFD_RELOC_PJ_CODE_REL16,
+ BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+ BFD_RELOC_PPC_B26,
+ BFD_RELOC_PPC_BA26,
+ BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_B16,
+ BFD_RELOC_PPC_B16_BRTAKEN,
+ BFD_RELOC_PPC_B16_BRNTAKEN,
+ BFD_RELOC_PPC_BA16,
+ BFD_RELOC_PPC_BA16_BRTAKEN,
+ BFD_RELOC_PPC_BA16_BRNTAKEN,
+ BFD_RELOC_PPC_COPY,
+ BFD_RELOC_PPC_GLOB_DAT,
+ BFD_RELOC_PPC_JMP_SLOT,
+ BFD_RELOC_PPC_RELATIVE,
+ BFD_RELOC_PPC_LOCAL24PC,
+ BFD_RELOC_PPC_EMB_NADDR32,
+ BFD_RELOC_PPC_EMB_NADDR16,
+ BFD_RELOC_PPC_EMB_NADDR16_LO,
+ BFD_RELOC_PPC_EMB_NADDR16_HI,
+ BFD_RELOC_PPC_EMB_NADDR16_HA,
+ BFD_RELOC_PPC_EMB_SDAI16,
+ BFD_RELOC_PPC_EMB_SDA2I16,
+ BFD_RELOC_PPC_EMB_SDA2REL,
+ BFD_RELOC_PPC_EMB_SDA21,
+ BFD_RELOC_PPC_EMB_MRKREF,
+ BFD_RELOC_PPC_EMB_RELSEC16,
+ BFD_RELOC_PPC_EMB_RELST_LO,
+ BFD_RELOC_PPC_EMB_RELST_HI,
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
+ BFD_RELOC_PPC64_HIGHER,
+ BFD_RELOC_PPC64_HIGHER_S,
+ BFD_RELOC_PPC64_HIGHEST,
+ BFD_RELOC_PPC64_HIGHEST_S,
+ BFD_RELOC_PPC64_TOC16_LO,
+ BFD_RELOC_PPC64_TOC16_HI,
+ BFD_RELOC_PPC64_TOC16_HA,
+ BFD_RELOC_PPC64_TOC,
+ BFD_RELOC_PPC64_PLTGOT16,
+ BFD_RELOC_PPC64_PLTGOT16_LO,
+ BFD_RELOC_PPC64_PLTGOT16_HI,
+ BFD_RELOC_PPC64_PLTGOT16_HA,
+ BFD_RELOC_PPC64_ADDR16_DS,
+ BFD_RELOC_PPC64_ADDR16_LO_DS,
+ BFD_RELOC_PPC64_GOT16_DS,
+ BFD_RELOC_PPC64_GOT16_LO_DS,
+ BFD_RELOC_PPC64_PLT16_LO_DS,
+ BFD_RELOC_PPC64_SECTOFF_DS,
+ BFD_RELOC_PPC64_SECTOFF_LO_DS,
+ BFD_RELOC_PPC64_TOC16_DS,
+ BFD_RELOC_PPC64_TOC16_LO_DS,
+ BFD_RELOC_PPC64_PLTGOT16_DS,
+ BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* IBM 370/390 relocations */
+ BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+ BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. */
+ BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BLX,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_ADRL_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_ADR_IMM,
+ BFD_RELOC_ARM_LDR_IMM,
+ BFD_RELOC_ARM_LITERAL,
+ BFD_RELOC_ARM_IN_POOL,
+ BFD_RELOC_ARM_OFFSET_IMM8,
+ BFD_RELOC_ARM_HWLITERAL,
+ BFD_RELOC_ARM_THUMB_ADD,
+ BFD_RELOC_ARM_THUMB_IMM,
+ BFD_RELOC_ARM_THUMB_SHIFT,
+ BFD_RELOC_ARM_THUMB_OFFSET,
+ BFD_RELOC_ARM_GOT12,
+ BFD_RELOC_ARM_GOT32,
+ BFD_RELOC_ARM_JUMP_SLOT,
+ BFD_RELOC_ARM_COPY,
+ BFD_RELOC_ARM_GLOB_DAT,
+ BFD_RELOC_ARM_PLT32,
+ BFD_RELOC_ARM_RELATIVE,
+ BFD_RELOC_ARM_GOTOFF,
+ BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs. Not all of these appear in object files. */
+ BFD_RELOC_SH_PCDISP8BY2,
+ BFD_RELOC_SH_PCDISP12BY2,
+ BFD_RELOC_SH_IMM4,
+ BFD_RELOC_SH_IMM4BY2,
+ BFD_RELOC_SH_IMM4BY4,
+ BFD_RELOC_SH_IMM8,
+ BFD_RELOC_SH_IMM8BY2,
+ BFD_RELOC_SH_IMM8BY4,
+ BFD_RELOC_SH_PCRELIMM8BY2,
+ BFD_RELOC_SH_PCRELIMM8BY4,
+ BFD_RELOC_SH_SWITCH16,
+ BFD_RELOC_SH_SWITCH32,
+ BFD_RELOC_SH_USES,
+ BFD_RELOC_SH_COUNT,
+ BFD_RELOC_SH_ALIGN,
+ BFD_RELOC_SH_CODE,
+ BFD_RELOC_SH_DATA,
+ BFD_RELOC_SH_LABEL,
+ BFD_RELOC_SH_LOOP_START,
+ BFD_RELOC_SH_LOOP_END,
+ BFD_RELOC_SH_COPY,
+ BFD_RELOC_SH_GLOB_DAT,
+ BFD_RELOC_SH_JMP_SLOT,
+ BFD_RELOC_SH_RELATIVE,
+ BFD_RELOC_SH_GOTPC,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
+be zero and is not stored in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BRANCH9,
+ BFD_RELOC_THUMB_PCREL_BRANCH12,
+ BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* ARC Cores relocs.
+ARC 22 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+ BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch. The lowest two bits must be zero and are not
+stored in the instruction. The high 24 bits are installed in bits 23
+through 0. */
+ BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+ BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+ BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the
+right 3 bitsassumed to be 0. */
+ BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+ BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+ BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+ BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+ BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+ BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+ BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+ BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+ BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+ BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+ BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+ BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+ BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+ BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+ BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+ BFD_RELOC_TIC30_LDP,
+
+/* This is a 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x. */
+ BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+ BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+ BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+ BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+ BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+ BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+ BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+ BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+ BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+ BFD_RELOC_MCORE_PCREL_IMM8BY4,
+ BFD_RELOC_MCORE_PCREL_IMM11BY2,
+ BFD_RELOC_MCORE_PCREL_IMM4BY2,
+ BFD_RELOC_MCORE_PCREL_32,
+ BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+ BFD_RELOC_MCORE_RVA,
+
+/* These are relocations for the GETA instruction. */
+ BFD_RELOC_MMIX_GETA,
+ BFD_RELOC_MMIX_GETA_1,
+ BFD_RELOC_MMIX_GETA_2,
+ BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction. */
+ BFD_RELOC_MMIX_CBRANCH,
+ BFD_RELOC_MMIX_CBRANCH_J,
+ BFD_RELOC_MMIX_CBRANCH_1,
+ BFD_RELOC_MMIX_CBRANCH_2,
+ BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction. */
+ BFD_RELOC_MMIX_PUSHJ,
+ BFD_RELOC_MMIX_PUSHJ_1,
+ BFD_RELOC_MMIX_PUSHJ_2,
+ BFD_RELOC_MMIX_PUSHJ_3,
+
+/* These are relocations for the JMP instruction. */
+ BFD_RELOC_MMIX_JMP,
+ BFD_RELOC_MMIX_JMP_1,
+ BFD_RELOC_MMIX_JMP_2,
+ BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch. */
+ BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction. */
+ BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255. */
+ BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register. */
+ BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation. */
+ BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register. It does not modify contents. */
+ BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits. */
+ BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits. */
+ BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits. */
+ BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits. */
+ BFD_RELOC_AVR_CALL,
+
+/* Direct 12 bit. */
+ BFD_RELOC_390_12,
+
+/* 12 bit GOT offset. */
+ BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime. */
+ BFD_RELOC_390_COPY,
+
+/* Create GOT entry. */
+ BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry. */
+ BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base. */
+ BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT. */
+ BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset. */
+ BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1. */
+ BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1. */
+ BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1. */
+ BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset. */
+ BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry. */
+ BFD_RELOC_390_GOTENT,
+
+/* These two relocations are used by the linker to determine which of
+the entries in a C++ virtual function table are actually used. When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table. The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry. The reloc's symbol should refer to the
+table of the class mentioned in the code. Off of that base, an offset
+describes the entry that is being used. For Rela hosts, this offset
+is stored in the reloc's addend. For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+ BFD_RELOC_VTABLE_INHERIT,
+ BFD_RELOC_VTABLE_ENTRY,
+
+/* Intel IA64 Relocations. */
+ BFD_RELOC_IA64_IMM14,
+ BFD_RELOC_IA64_IMM22,
+ BFD_RELOC_IA64_IMM64,
+ BFD_RELOC_IA64_DIR32MSB,
+ BFD_RELOC_IA64_DIR32LSB,
+ BFD_RELOC_IA64_DIR64MSB,
+ BFD_RELOC_IA64_DIR64LSB,
+ BFD_RELOC_IA64_GPREL22,
+ BFD_RELOC_IA64_GPREL64I,
+ BFD_RELOC_IA64_GPREL32MSB,
+ BFD_RELOC_IA64_GPREL32LSB,
+ BFD_RELOC_IA64_GPREL64MSB,
+ BFD_RELOC_IA64_GPREL64LSB,
+ BFD_RELOC_IA64_LTOFF22,
+ BFD_RELOC_IA64_LTOFF64I,
+ BFD_RELOC_IA64_PLTOFF22,
+ BFD_RELOC_IA64_PLTOFF64I,
+ BFD_RELOC_IA64_PLTOFF64MSB,
+ BFD_RELOC_IA64_PLTOFF64LSB,
+ BFD_RELOC_IA64_FPTR64I,
+ BFD_RELOC_IA64_FPTR32MSB,
+ BFD_RELOC_IA64_FPTR32LSB,
+ BFD_RELOC_IA64_FPTR64MSB,
+ BFD_RELOC_IA64_FPTR64LSB,
+ BFD_RELOC_IA64_PCREL21B,
+ BFD_RELOC_IA64_PCREL21BI,
+ BFD_RELOC_IA64_PCREL21M,
+ BFD_RELOC_IA64_PCREL21F,
+ BFD_RELOC_IA64_PCREL22,
+ BFD_RELOC_IA64_PCREL60B,
+ BFD_RELOC_IA64_PCREL64I,
+ BFD_RELOC_IA64_PCREL32MSB,
+ BFD_RELOC_IA64_PCREL32LSB,
+ BFD_RELOC_IA64_PCREL64MSB,
+ BFD_RELOC_IA64_PCREL64LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR22,
+ BFD_RELOC_IA64_LTOFF_FPTR64I,
+ BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+ BFD_RELOC_IA64_SEGREL32MSB,
+ BFD_RELOC_IA64_SEGREL32LSB,
+ BFD_RELOC_IA64_SEGREL64MSB,
+ BFD_RELOC_IA64_SEGREL64LSB,
+ BFD_RELOC_IA64_SECREL32MSB,
+ BFD_RELOC_IA64_SECREL32LSB,
+ BFD_RELOC_IA64_SECREL64MSB,
+ BFD_RELOC_IA64_SECREL64LSB,
+ BFD_RELOC_IA64_REL32MSB,
+ BFD_RELOC_IA64_REL32LSB,
+ BFD_RELOC_IA64_REL64MSB,
+ BFD_RELOC_IA64_REL64LSB,
+ BFD_RELOC_IA64_LTV32MSB,
+ BFD_RELOC_IA64_LTV32LSB,
+ BFD_RELOC_IA64_LTV64MSB,
+ BFD_RELOC_IA64_LTV64LSB,
+ BFD_RELOC_IA64_IPLTMSB,
+ BFD_RELOC_IA64_IPLTLSB,
+ BFD_RELOC_IA64_COPY,
+ BFD_RELOC_IA64_TPREL22,
+ BFD_RELOC_IA64_TPREL64MSB,
+ BFD_RELOC_IA64_TPREL64LSB,
+ BFD_RELOC_IA64_LTOFF_TP22,
+ BFD_RELOC_IA64_LTOFF22X,
+ BFD_RELOC_IA64_LDXMOV,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits high part of an absolute address. */
+ BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits low part of an absolute address. */
+ BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bits of a value. */
+ BFD_RELOC_M68HC11_3B,
+
+/* These relocs are only used within the CRIS assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_CRIS_BDISP8,
+ BFD_RELOC_CRIS_UNSIGNED_5,
+ BFD_RELOC_CRIS_SIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS. */
+ BFD_RELOC_CRIS_COPY,
+ BFD_RELOC_CRIS_GLOB_DAT,
+ BFD_RELOC_CRIS_JUMP_SLOT,
+ BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT. */
+ BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT. */
+ BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation. */
+ BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations. */
+ BFD_RELOC_860_COPY,
+ BFD_RELOC_860_GLOB_DAT,
+ BFD_RELOC_860_JUMP_SLOT,
+ BFD_RELOC_860_RELATIVE,
+ BFD_RELOC_860_PC26,
+ BFD_RELOC_860_PLT26,
+ BFD_RELOC_860_PC16,
+ BFD_RELOC_860_LOW0,
+ BFD_RELOC_860_SPLIT0,
+ BFD_RELOC_860_LOW1,
+ BFD_RELOC_860_SPLIT1,
+ BFD_RELOC_860_LOW2,
+ BFD_RELOC_860_SPLIT2,
+ BFD_RELOC_860_LOW3,
+ BFD_RELOC_860_LOGOT0,
+ BFD_RELOC_860_SPGOT0,
+ BFD_RELOC_860_LOGOT1,
+ BFD_RELOC_860_SPGOT1,
+ BFD_RELOC_860_LOGOTOFF0,
+ BFD_RELOC_860_SPGOTOFF0,
+ BFD_RELOC_860_LOGOTOFF1,
+ BFD_RELOC_860_SPGOTOFF1,
+ BFD_RELOC_860_LOGOTOFF2,
+ BFD_RELOC_860_LOGOTOFF3,
+ BFD_RELOC_860_LOPC,
+ BFD_RELOC_860_HIGHADJ,
+ BFD_RELOC_860_HAGOT,
+ BFD_RELOC_860_HAGOTOFF,
+ BFD_RELOC_860_HAPC,
+ BFD_RELOC_860_HIGH,
+ BFD_RELOC_860_HIGOT,
+ BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations. */
+ BFD_RELOC_OPENRISC_ABS_26,
+ BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations. */
+ BFD_RELOC_H8_DIR16A8,
+ BFD_RELOC_H8_DIR16R8,
+ BFD_RELOC_H8_DIR24A8,
+ BFD_RELOC_H8_DIR24R8,
+ BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations. */
+ BFD_RELOC_XSTORMY16_REL_12,
+ BFD_RELOC_XSTORMY16_24,
+ BFD_RELOC_XSTORMY16_FPTR16,
+ BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+ /* A pointer to the BFD which owns the symbol. This information
+ is necessary so that a back end can work out what additional
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+ struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+ /* The text of the symbol. The name is left alone, and not copied; the
+ application may not alter it. */
+ const char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol. */
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ value is the offset into the section of the data. */
+#define BSF_GLOBAL 0x02
+
+ /* The symbol has global scope and is exported. The value is
+ the offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* No real difference. */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>>. */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning, unless BSF_DEBUGGING_RELOC is also set. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. The name is a
+ warning. The name of the next symbol is the one to warn about;
+ if a reference is made to a symbol with the same name as the next
+ symbol, a warning is issued by the linker. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. This symbol is an indirect
+ pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ /* Symbol is from dynamic linking information. */
+#define BSF_DYNAMIC 0x8000
+
+ /* The symbol denotes a data object. Used in ELF, and perhaps
+ others someday. */
+#define BSF_OBJECT 0x10000
+
+ /* This symbol is a debugging symbol. The value is the offset
+ into the section of the data. BSF_DEBUGGING should be set
+ as well. */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+ flagword flags;
+
+ /* A pointer to the section to which this symbol is
+ relative. This will always be non NULL, there are special
+ sections for undefined and absolute symbols. */
+ struct sec *section;
+
+ /* Back end special data. */
+ union
+ {
+ PTR p;
+ bfd_vma i;
+ }
+ udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+boolean
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+ BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+ (abfd, location))
+
+boolean
+bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((bfd *abfd, PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *
+_bfd_generic_make_empty_symbol PARAMS ((bfd *));
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+boolean
+bfd_is_undefined_symclass PARAMS ((int symclass));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+ (ibfd, isymbol, obfd, osymbol))
+
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ const char *filename;
+
+ /* A pointer to the target jump table. */
+ const struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char *",
+ and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ PTR iostream;
+
+ /* Is the file descriptor being cached? That is, can it be closed as
+ needed, and re-opened when accessed later? */
+ boolean cacheable;
+
+ /* Marks whether there was a default target specified when the
+ BFD was opened. This is used to select which matching algorithm
+ to use to choose the back end. */
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs. */
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here... */
+ ufile_ptr where;
+
+ /* ... and here: (``once'' means at least once). */
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time. */
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true. */
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension. */
+ int ifd;
+
+ /* The format which belongs to the BFD. (object, core, etc.) */
+ bfd_format format;
+
+ /* The direction with which the BFD was opened. */
+ enum bfd_direction
+ {
+ no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3
+ }
+ direction;
+
+ /* Format_specific flags. */
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+ ufile_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ from happening. */
+ boolean output_has_begun;
+
+ /* A hash table for section names. */
+ struct bfd_hash_table section_htab;
+
+ /* Pointer to linked list of sections. */
+ struct sec *sections;
+
+ /* The place where we add to the section list. */
+ struct sec **section_tail;
+
+ /* The number of sections. */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output. */
+ unsigned int symcount;
+
+ /* Symbol table for output BFD (with symcount entries). */
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information. */
+ const struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives. */
+ PTR arelt_data;
+ struct _bfd *my_archive; /* The containing archive BFD. */
+ struct _bfd *next; /* The next BFD in the archive. */
+ struct _bfd *archive_head; /* The first BFD in the archive. */
+ boolean has_armap;
+
+ /* A chain of BFD structures involved in a link. */
+ struct _bfd *link_next;
+
+ /* A field used by _bfd_generic_link_add_archive_symbols. This will
+ be used only for archive elements. */
+ int archive_pass;
+
+ /* Used by the back end to hold private data. */
+ union
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct pe_tdata *pe_obj_data;
+ struct xcoff_tdata *xcoff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct ihex_data_struct *ihex_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct mmo_data_struct *mmo_data;
+ struct sun_core_struct *sun_core_data;
+ struct sco5_core_struct *sco5_core_data;
+ struct trad_core_struct *trad_core_data;
+ struct som_data_struct *som_data;
+ struct hpux_core_struct *hpux_core_data;
+ struct hppabsd_core_struct *hppabsd_core_data;
+ struct sgi_core_struct *sgi_core_data;
+ struct lynx_core_struct *lynx_core_data;
+ struct osf_core_struct *osf_core_data;
+ struct cisco_core_struct *cisco_core_data;
+ struct versados_data_struct *versados_data;
+ struct netbsd_core_struct *netbsd_core_data;
+ PTR any;
+ }
+ tdata;
+
+ /* Used by the application to hold private data. */
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes. This is a
+ struct objalloc *, but we use PTR to avoid requiring the inclusion of
+ objalloc.h. */
+ PTR memory;
+};
+
+typedef enum bfd_error
+{
+ bfd_error_no_error = 0,
+ bfd_error_system_call,
+ bfd_error_invalid_target,
+ bfd_error_wrong_format,
+ bfd_error_wrong_object_format,
+ bfd_error_invalid_operation,
+ bfd_error_no_memory,
+ bfd_error_no_symbols,
+ bfd_error_no_armap,
+ bfd_error_no_more_archived_files,
+ bfd_error_malformed_archive,
+ bfd_error_file_not_recognized,
+ bfd_error_file_ambiguously_recognized,
+ bfd_error_no_contents,
+ bfd_error_nonrepresentable_section,
+ bfd_error_no_debug_section,
+ bfd_error_bad_value,
+ bfd_error_file_truncated,
+ bfd_error_file_too_big,
+ bfd_error_invalid_error_code
+}
+bfd_error_type;
+
+bfd_error_type
+bfd_get_error PARAMS ((void));
+
+void
+bfd_set_error PARAMS ((bfd_error_type error_tag));
+
+const char *
+bfd_errmsg PARAMS ((bfd_error_type error_tag));
+
+void
+bfd_perror PARAMS ((const char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+bfd_error_handler_type
+bfd_get_error_handler PARAMS ((void));
+
+const char *
+bfd_archive_filename PARAMS ((bfd *));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+void
+bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count));
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+int
+bfd_get_arch_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_sign_extend_vma PARAMS ((bfd *abfd));
+
+boolean
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+bfd_set_gp_size PARAMS ((bfd *abfd, unsigned int i));
+
+bfd_vma
+bfd_scan_vma PARAMS ((const char *string, const char **end, int base));
+
+boolean
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+ BFD_SEND (abfd, _bfd_set_private_flags, \
+ (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_merge_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+ BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+ BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *,
+ boolean, asymbol **));
+
+boolean
+bfd_alt_mach_code PARAMS ((bfd *abfd, int index));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+const char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+ ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ ((*((bfd)->xvec->message)) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+
+enum bfd_flavour
+{
+ bfd_target_unknown_flavour,
+ bfd_target_aout_flavour,
+ bfd_target_coff_flavour,
+ bfd_target_ecoff_flavour,
+ bfd_target_xcoff_flavour,
+ bfd_target_elf_flavour,
+ bfd_target_ieee_flavour,
+ bfd_target_nlm_flavour,
+ bfd_target_oasys_flavour,
+ bfd_target_tekhex_flavour,
+ bfd_target_srec_flavour,
+ bfd_target_ihex_flavour,
+ bfd_target_som_flavour,
+ bfd_target_os9k_flavour,
+ bfd_target_versados_flavour,
+ bfd_target_msdos_flavour,
+ bfd_target_ovax_flavour,
+ bfd_target_evax_flavour,
+ bfd_target_mmo_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+/* Forward declaration. */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+ /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */
+ char *name;
+
+ /* The "flavour" of a back end is a general indication about
+ the contents of a file. */
+ enum bfd_flavour flavour;
+
+ /* The order of bytes within the data area of a file. */
+ enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file. */
+ enum bfd_endian header_byteorder;
+
+ /* A mask of all the flags which an executable may have set -
+ from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>. */
+ flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+ the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>. */
+ flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+ (if any), perhaps `_'. */
+ char symbol_leading_char;
+
+ /* The pad character for file names within an archive header. */
+ char ar_pad_char;
+
+ /* The maximum number of characters in an archive header. */
+ unsigned short ar_max_namelen;
+
+ /* Entries for byte swapping for data. These are different from the
+ other entry points, since they don't take a BFD asthe first argument.
+ Certain other handlers could do the same. */
+ bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Byte swapping for the headers. */
+ bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Format dependent routines: these are vectors of entry points
+ within the target vector structure, one for each format to check. */
+
+ /* Check the format of a file being read. Return a <<bfd_target *>> or zero. */
+ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Set the format of a file being written. */
+ boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Write cached information into a file being written, at <<bfd_close>>. */
+ boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+
+ /* Generic entry points. */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+CONCAT2 (NAME,_close_and_cleanup), \
+CONCAT2 (NAME,_bfd_free_cached_info), \
+CONCAT2 (NAME,_new_section_hook), \
+CONCAT2 (NAME,_get_section_contents), \
+CONCAT2 (NAME,_get_section_contents_in_window)
+
+ /* Called when the BFD is being closed to do any necessary cleanup. */
+ boolean (*_close_and_cleanup) PARAMS ((bfd *));
+ /* Ask the BFD to free all cached information. */
+ boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+ /* Called when a new section is created. */
+ boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+ /* Read the contents of a section. */
+ boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type));
+
+ /* Entry points to copy private data. */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+CONCAT2 (NAME,_bfd_copy_private_bfd_data), \
+CONCAT2 (NAME,_bfd_merge_private_bfd_data), \
+CONCAT2 (NAME,_bfd_copy_private_section_data), \
+CONCAT2 (NAME,_bfd_copy_private_symbol_data), \
+CONCAT2 (NAME,_bfd_set_private_flags), \
+CONCAT2 (NAME,_bfd_print_private_bfd_data) \
+ /* Called to copy BFD general private data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to merge BFD general private data from one object file
+ to a common output file when linking. */
+ boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to copy BFD private section data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+ bfd *, sec_ptr));
+ /* Called to copy BFD private symbol data from one symbol
+ to another. */
+ boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+ /* Called to set private backend flags. */
+ boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+ /* Called to print private BFD data. */
+ boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+ /* Core file entry points. */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+CONCAT2 (NAME,_core_file_failing_command), \
+CONCAT2 (NAME,_core_file_failing_signal), \
+CONCAT2 (NAME,_core_file_matches_executable_p)
+ char * (*_core_file_failing_command) PARAMS ((bfd *));
+ int (*_core_file_failing_signal) PARAMS ((bfd *));
+ boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+ /* Archive entry points. */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+CONCAT2 (NAME,_slurp_armap), \
+CONCAT2 (NAME,_slurp_extended_name_table), \
+CONCAT2 (NAME,_construct_extended_name_table), \
+CONCAT2 (NAME,_truncate_arname), \
+CONCAT2 (NAME,_write_armap), \
+CONCAT2 (NAME,_read_ar_hdr), \
+CONCAT2 (NAME,_openr_next_archived_file), \
+CONCAT2 (NAME,_get_elt_at_index), \
+CONCAT2 (NAME,_generic_stat_arch_elt), \
+CONCAT2 (NAME,_update_armap_timestamp)
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ boolean (*_bfd_construct_extended_name_table)
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, const char *, char *));
+ boolean (*write_armap)
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+ PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *, bfd *));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+ bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+ boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+ /* Entry points used for symbols. */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+CONCAT2 (NAME,_get_symtab_upper_bound), \
+CONCAT2 (NAME,_get_symtab), \
+CONCAT2 (NAME,_make_empty_symbol), \
+CONCAT2 (NAME,_print_symbol), \
+CONCAT2 (NAME,_get_symbol_info), \
+CONCAT2 (NAME,_bfd_is_local_label_name), \
+CONCAT2 (NAME,_get_lineno), \
+CONCAT2 (NAME,_find_nearest_line), \
+CONCAT2 (NAME,_bfd_make_debug_symbol), \
+CONCAT2 (NAME,_read_minisymbols), \
+CONCAT2 (NAME,_minisymbol_to_symbol)
+ long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+ long (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+ struct symbol_cache_entry *
+ (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+ void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ struct symbol_cache_entry *,
+ symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+ boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+ alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+ boolean (*_bfd_find_nearest_line)
+ PARAMS ((bfd *, struct sec *, struct symbol_cache_entry **, bfd_vma,
+ const char **, const char **, unsigned int *));
+ /* Back-door to allow format-aware applications to create debug symbols
+ while using BFD for everything else. Currently used by the assembler
+ when creating COFF files. */
+ asymbol *(*_bfd_make_debug_symbol) PARAMS ((bfd *, void *,
+ unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+ BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+ long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+ unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+ asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+ /* Routines for relocs. */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+CONCAT2 (NAME,_get_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_reloc), \
+CONCAT2 (NAME,_bfd_reloc_type_lookup)
+ long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+ long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+ struct symbol_cache_entry **));
+ /* See documentation on reloc types. */
+ reloc_howto_type *
+ (*reloc_type_lookup) PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+ /* Routines used when writing an object file. */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+CONCAT2 (NAME,_set_arch_mach), \
+CONCAT2 (NAME,_set_section_contents)
+ boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+ boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+
+ /* Routines used by the linker. */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+CONCAT2 (NAME,_sizeof_headers), \
+CONCAT2 (NAME,_bfd_get_relocated_section_contents), \
+CONCAT2 (NAME,_bfd_relax_section), \
+CONCAT2 (NAME,_bfd_link_hash_table_create), \
+CONCAT2 (NAME,_bfd_link_add_symbols), \
+CONCAT2 (NAME,_bfd_final_link), \
+CONCAT2 (NAME,_bfd_link_split_section), \
+CONCAT2 (NAME,_bfd_gc_sections), \
+CONCAT2 (NAME,_bfd_merge_sections)
+ int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+ bfd_byte *(*_bfd_get_relocated_section_contents)
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, struct symbol_cache_entry **));
+
+ boolean (*_bfd_relax_section)
+ PARAMS ((bfd *, struct sec *, struct bfd_link_info *, boolean *));
+
+ /* Create a hash table for the linker. Different backends store
+ different information in this table. */
+ struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+ /* Add symbols from this object file into the hash table. */
+ boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Do a link based on the link_order structures attached to each
+ section of the BFD. */
+ boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Should this section be split up into smaller pieces during linking. */
+ boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+ /* Remove sections that are not referenced from the output. */
+ boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Attempt to merge SEC_MERGE sections. */
+ boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Routines to handle dynamic symbols and relocs. */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+CONCAT2 (NAME,_get_dynamic_symtab_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_symtab), \
+CONCAT2 (NAME,_get_dynamic_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_reloc)
+ /* Get the amount of memory required to hold the dynamic symbols. */
+ long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic symbols. */
+ long (*_bfd_canonicalize_dynamic_symtab)
+ PARAMS ((bfd *, struct symbol_cache_entry **));
+ /* Get the amount of memory required to hold the dynamic relocs. */
+ long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic relocs. */
+ long (*_bfd_canonicalize_dynamic_reloc)
+ PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+ /* Opposite endian version of this target. */
+ const struct bfd_target * alternative_target;
+
+ /* Data for use by back-end routines, which isn't
+ generic enough to belong in this structure. */
+ PTR backend_data;
+
+} bfd_target;
+
+boolean
+bfd_set_default_target PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((const char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target *
+bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+const char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gnu/usr.bin/binutils/libbfd/config.h.fbsd b/gnu/usr.bin/binutils/libbfd/config.h.fbsd
new file mode 100644
index 0000000..c5ff152
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/config.h.fbsd
@@ -0,0 +1,267 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the fcntl function. */
+#define HAVE_FCNTL 1
+
+/* Define if you have the fdopen function. */
+#define HAVE_FDOPEN 1
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getgid function. */
+#define HAVE_GETGID 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getuid function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the madvise function. */
+#define HAVE_MADVISE 1
+
+/* Define if you have the mprotect function. */
+#define HAVE_MPROTECT 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setitimer function. */
+#define HAVE_SETITIMER 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the sysconf function. */
+#define HAVE_SYSCONF 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/procfs.h> header file. */
+#define HAVE_SYS_PROCFS_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Name of package */
+#define PACKAGE "bfd"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Use b modifier when opening binary files? */
+/* #undef USE_BINARY_FOPEN */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* 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 getenv is not declared in system header files. */
+/* #undef NEED_DECLARATION_GETENV */
+
+/* Define if <sys/procfs.h> has prstatus_t. */
+#define HAVE_PRSTATUS_T 1
+
+/* Define if <sys/procfs.h> has prstatus32_t. */
+/* #undef HAVE_PRSTATUS32_T */
+
+/* Define if <sys/procfs.h> has prstatus_t.pr_who. */
+/* #undef HAVE_PRSTATUS_T_PR_WHO */
+
+/* Define if <sys/procfs.h> has prstatus32_t.pr_who. */
+/* #undef HAVE_PRSTATUS32_T_PR_WHO */
+
+/* Define if <sys/procfs.h> has pstatus_t. */
+/* #undef HAVE_PSTATUS_T */
+
+/* Define if <sys/procfs.h> has pxstatus_t. */
+/* #undef HAVE_PXSTATUS_T */
+
+/* Define if <sys/procfs.h> has pstatus32_t. */
+/* #undef HAVE_PSTATUS32_T */
+
+/* Define if <sys/procfs.h> has prpsinfo_t. */
+#define HAVE_PRPSINFO_T 1
+
+/* Define if <sys/procfs.h> has prpsinfo32_t. */
+/* #undef HAVE_PRPSINFO32_T */
+
+/* Define if <sys/procfs.h> has psinfo_t. */
+/* #undef HAVE_PSINFO_T */
+
+/* Define if <sys/procfs.h> has psinfo32_t. */
+/* #undef HAVE_PSINFO32_T */
+
+/* Define if <sys/procfs.h> has lwpstatus_t. */
+/* #undef HAVE_LWPSTATUS_T */
+
+/* Define if <sys/procfs.h> has lwpxstatus_t. */
+/* #undef HAVE_LWPXSTATUS_T */
+
+/* Define if <sys/procfs.h> has lwpstatus_t.pr_context. */
+/* #undef HAVE_LWPSTATUS_T_PR_CONTEXT */
+
+/* Define if <sys/procfs.h> has lwpstatus_t.pr_reg. */
+/* #undef HAVE_LWPSTATUS_T_PR_REG */
+
+/* Define if <sys/procfs.h> has win32_pstatus_t. */
+/* #undef HAVE_WIN32_PSTATUS_T */
+
+/* Name of host specific header file to include in trad-core.c. */
+#define TRAD_HEADER !!TRAD_HEADER!!
+
+/* Use mmap if it's available? */
+/* #undef USE_MMAP */
+
diff --git a/gnu/usr.bin/binutils/libbfd/i386/bfd.h b/gnu/usr.bin/binutils/libbfd/i386/bfd.h
new file mode 100644
index 0000000..e5e018b
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/i386/bfd.h
@@ -0,0 +1,3921 @@
+/* $FreeBSD$ */
+
+/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
+ generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+ "section.c", "archures.c", "reloc.c", "syms.c", "bfd.c", "archive.c",
+ "corefile.c", "targets.c" and "format.c".
+ Run "make headers" in your build bfd/ to regenerate. */
+
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FreeBSD does not adhere to the Intel386 System V ABI. */
+#define ELF_DYNAMIC_INTERPRETER "/usr/libexec/ld-elf.so.1"
+
+#include "ansidecl.h"
+#include "symcat.h"
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This hack is to avoid a problem with some strict ANSI C preprocessors.
+ The problem is, "32_" is not a valid preprocessing token, and we don't
+ want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will
+ cause the inner CONCAT2 macros to be evaluated first, producing
+ still-valid pp-tokens. Then the final concatenation can be done. */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* #define BFD_VERSION 212000000 */
+/* #define BFD_VERSION_DATE 20020309 */
+/* #define BFD_VERSION_STRING "2.12" */
+
+/* The word size used by BFD on the host. This may be 64 with a 32
+ bit target if the host is 64 bit, or if other 64 bit targets have
+ been selected with --enable-targets, or if --enable-64-bit-bfd. */
+#define BFD_ARCH_SIZE 32
+
+/* The word size of the default bfd target. */
+#define BFD_DEFAULT_TARGET_SIZE 32
+
+#if defined(__alpha__) || defined(__sparc64__)
+#define BFD_HOST_64BIT_LONG 1
+#else
+#define BFD_HOST_64BIT_LONG 0
+#endif /* 64-bit host */
+#if 0
+#define BFD_HOST_64_BIT
+#define BFD_HOST_U_64_BIT
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* Forward declaration. */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+/* And even worse if your compiler provides a stdbool.h that conflicts
+ with these definitions... gcc 2.95 and later do. If so, it must
+ be included first. -drow */
+#if defined (__GNUG__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+#define TRUE_FALSE_ALREADY_DEFINED
+#else
+#if defined (__bool_true_false_are_defined)
+/* We have <stdbool.h>. */
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, BFD_HOST_64_BIT must be
+ defined above. */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+# define BFD_HOST_64_BIT long
+# define BFD_HOST_U_64_BIT unsigned long
+# else
+# ifdef __GNUC__
+# if __GNUC__ >= 2
+# define BFD_HOST_64_BIT long long
+# define BFD_HOST_U_64_BIT unsigned long long
+# endif /* __GNUC__ >= 2 */
+# endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf (s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf (s, "%08lx", x)
+
+#endif /* not BFD64 */
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef bfd_signed_vma file_ptr;
+typedef bfd_vma ufile_ptr;
+
+extern void bfd_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
+extern void bfd_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/* File formats. */
+
+typedef enum bfd_format
+{
+ bfd_unknown = 0, /* File format is unknown. */
+ bfd_object, /* Linker/assember/compiler output. */
+ bfd_archive, /* Object archive file. */
+ bfd_core, /* Core dump. */
+ bfd_type_end /* Marks the end; don't use it! */
+}
+bfd_format;
+
+/* Values that may appear in the flags field of a BFD. These also
+ appear in the object_flags field of the bfd_target structure, where
+ they indicate the set of flags used by that backend (not all flags
+ are meaningful for all object file formats) (FIXME: at the moment,
+ the object_flags values have mostly just been copied from backend
+ to another, and are not necessarily correct). */
+
+/* No flags. */
+#define BFD_NO_FLAGS 0x00
+
+/* BFD contains relocation entries. */
+#define HAS_RELOC 0x01
+
+/* BFD is directly executable. */
+#define EXEC_P 0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+ COFF header). */
+#define HAS_LINENO 0x04
+
+/* BFD has debugging information. */
+#define HAS_DEBUG 0x08
+
+/* BFD has symbols. */
+#define HAS_SYMS 0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+ header). */
+#define HAS_LOCALS 0x20
+
+/* BFD is a dynamic object. */
+#define DYNAMIC 0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+ like an a.out NMAGIC file) (the linker sets this by default, but
+ clears it for -r or -N). */
+#define WP_TEXT 0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+ linker sets this by default, but clears it for -r or -n or -N). */
+#define D_PAGED 0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+ do something) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+ traditional format. For example, this is used to request that when
+ writing out an a.out object the symbols not be hashed to eliminate
+ duplicates. */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* Symbols and relocation. */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+ target specific parts are in libcoff.h, libaout.h, etc. */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol. */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym
+{
+ char *name;
+ file_ptr file_offset; /* Look here to find the file. */
+}
+carsym; /* To make these you call a carsymogen. */
+
+/* Used in generating armaps (archive tables of contents).
+ Perhaps just a forward definition would do? */
+struct orl /* Output ranlib. */
+{
+ char **name; /* Symbol name. */
+ union
+ {
+ file_ptr pos;
+ bfd *abfd;
+ } u; /* bfd* or file position. */
+ int namidx; /* Index into string table. */
+};
+
+/* Linenumber stuff. */
+typedef struct lineno_cache_entry
+{
+ unsigned int line_number; /* Linenumber from start of function. */
+ union
+ {
+ struct symbol_cache_entry *sym; /* Function name. */
+ bfd_vma offset; /* Offset into section. */
+ } u;
+}
+alent;
+
+/* Object and core file sections. */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ const char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ const char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines. There is no way to free up a hash table. */
+
+/* An element in the hash table. Most uses will actually use a larger
+ structure, and an instance of this will be the first field. */
+
+struct bfd_hash_entry
+{
+ /* Next entry for this hash code. */
+ struct bfd_hash_entry *next;
+ /* String being hashed. */
+ const char *string;
+ /* Hash code. This is the full hash code, not the index into the
+ table. */
+ unsigned long hash;
+};
+
+/* A hash table. */
+
+struct bfd_hash_table
+{
+ /* The hash array. */
+ struct bfd_hash_entry **table;
+ /* The number of slots in the hash table. */
+ unsigned int size;
+ /* A function used to create new elements in the hash table. The
+ first entry is itself a pointer to an element. When this
+ function is first invoked, this pointer will be NULL. However,
+ having the pointer permits a hierarchy of method functions to be
+ built each of which calls the function in the superclass. Thus
+ each function should be written to allocate a new block of memory
+ only if the argument is NULL. */
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+ /* An objalloc for this hash table. This is a struct objalloc *,
+ but we use PTR to avoid requiring the inclusion of objalloc.h. */
+ PTR memory;
+};
+
+/* Initialize a hash table. */
+extern boolean bfd_hash_table_init
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+
+/* Initialize a hash table specifying a size. */
+extern boolean bfd_hash_table_init_n
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int size));
+
+/* Free up a hash table. */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table. If CREATE is true, a new entry
+ will be created for this string if one does not already exist. The
+ COPY argument must be true if this routine should copy the string
+ into newly allocated memory when adding an entry. */
+extern struct bfd_hash_entry *bfd_hash_lookup
+ PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+ boolean copy));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry. */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Grab some space for a hash table entry. */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+ unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+ element. If the function returns false, the traversal stops. The
+ INFO argument is passed to the function. */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+ boolean (*) (struct bfd_hash_entry *,
+ PTR),
+ PTR info));
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities. */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_bread PARAMS ((PTR, bfd_size_type, bfd *));
+extern bfd_size_type bfd_bwrite PARAMS ((const PTR, bfd_size_type, bfd *));
+extern int bfd_seek PARAMS ((bfd *, file_ptr, int));
+extern ufile_ptr bfd_tell PARAMS ((bfd *));
+extern int bfd_flush PARAMS ((bfd *));
+extern int bfd_stat PARAMS ((bfd *, struct stat *));
+
+/* Deprecated old routines. */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated
+ PARAMS ((const char *, const char *, int, const char *));
+
+/* Cast from const char * to char * so that caller can assign to
+ a char * without a warning. */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_family_coff(abfd) \
+ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean) (bool)), true)
+
+extern boolean bfd_cache_close PARAMS ((bfd *abfd));
+/* NB: This declaration should match the autogenerated one in libbfd.h. */
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+bfd_vma bfd_getb64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb16 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void bfd_putb64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb16 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl16 PARAMS ((bfd_vma, unsigned char *));
+
+/* Byte swapping routines which take size and endiannes as arguments. */
+
+bfd_vma bfd_get_bits PARAMS ((bfd_byte *, int, boolean));
+void bfd_put_bits PARAMS ((bfd_vma, bfd_byte *, int, boolean));
+
+/* Externally visible ECOFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+ PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+ unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+ PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ bfd *input_bfd, struct ecoff_debug_info *input_debug,
+ const struct ecoff_debug_swap *input_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ boolean relocateable,
+ boolean (*get_extr) (struct symbol_cache_entry *,
+ struct ecoff_extr *),
+ void (*set_index) (struct symbol_cache_entry *,
+ bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+ PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+ PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Return an upper bound on the number of bytes required to store a
+ copy of ABFD's program header table entries. Return -1 if an error
+ occurs; bfd_get_error will return an appropriate code. */
+extern long bfd_get_elf_phdr_upper_bound PARAMS ((bfd *abfd));
+
+/* Copy ABFD's program header table entries to *PHDRS. The entries
+ will be stored as an array of Elf_Internal_Phdr structures, as
+ defined in include/elf/internal.h. To find out how large the
+ buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+ Return the number of program header table entries read, or -1 if an
+ error occurs; bfd_get_error will return an appropriate code. */
+extern int bfd_get_elf_phdrs PARAMS ((bfd *abfd, void *phdrs));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf. */
+extern int bfd_get_arch_size PARAMS ((bfd *));
+
+/* Return true if address "naturally" sign extends, or -1 if not elf. */
+extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+
+extern boolean bfd_m68k_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+extern boolean bfd_mips_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+ struct sec **));
+
+/* Linux shared library support routines for the linker. */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window
+{
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+}
+bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *, unsigned int));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+extern boolean bfd_xcoff_link_generate_rtinit
+ PARAMS ((bfd *, const char *, const char *));
+
+/* Externally visible COFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+ PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+ PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+ PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+extern boolean bfd_m68k_coff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* PE ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_pe_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_pe_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_pe_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support. Called from linker. */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* TI COFF load page support. */
+extern void bfd_ticoff_set_section_load_page
+ PARAMS ((struct sec *, int));
+
+extern int bfd_ticoff_get_section_load_page
+ PARAMS ((struct sec *));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((const char *filename, const char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((const char *filename, const char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((const char *filename, const char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((const char *filename, bfd *templ));
+
+boolean
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+/* Byte swapping macros for user section data. */
+
+#define bfd_put_8(abfd, val, ptr) \
+ ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val)))
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr) \
+ ( (bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \
+ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \
+ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \
+ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \
+ : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr) \
+ ( (bits) == 8 ? bfd_put_8 (abfd, val, ptr) \
+ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \
+ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \
+ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \
+ : (abort (), (void) 0))
+
+
+/* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx16, (val, ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx16, (ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx32, (val, ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx32, (ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx64, (val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx64, (ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr))
+
+/* Refinements on the above, which should eventually go away. Save
+ cluttering the source with (bfd_vma) and (bfd_byte *) casts. */
+
+#define H_PUT_64(abfd, val, where) \
+ bfd_h_put_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_32(abfd, val, where) \
+ bfd_h_put_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_16(abfd, val, where) \
+ bfd_h_put_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_8 bfd_h_put_8
+
+#define H_PUT_S64(abfd, val, where) \
+ bfd_h_put_signed_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S32(abfd, val, where) \
+ bfd_h_put_signed_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S16(abfd, val, where) \
+ bfd_h_put_signed_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S8 bfd_h_put_signed_8
+
+#define H_GET_64(abfd, where) \
+ bfd_h_get_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_32(abfd, where) \
+ bfd_h_get_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_16(abfd, where) \
+ bfd_h_get_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_8 bfd_h_get_8
+
+#define H_GET_S64(abfd, where) \
+ bfd_h_get_signed_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S32(abfd, where) \
+ bfd_h_get_signed_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S16(abfd, where) \
+ bfd_h_get_signed_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S8 bfd_h_get_signed_8
+
+
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+typedef struct sec
+{
+ /* The name of the section; the name isn't a copy, the pointer is
+ the same as that passed to bfd_make_section. */
+ const char *name;
+
+ /* A unique sequence number. */
+ int id;
+
+ /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */
+ int index;
+
+ /* The next section in the list belonging to the BFD, or NULL. */
+ struct sec *next;
+
+ /* The field flags contains attributes of the section. Some
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* Tells the OS to allocate space for this section when loading.
+ This is clear for a section containing debug information only. */
+#define SEC_ALLOC 0x001
+
+ /* Tells the OS to load the section from the file when loading.
+ This is clear for a .bss section. */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there is
+ some relocation information too. */
+#define SEC_RELOC 0x004
+
+ /* ELF reserves 4 processor specific bits and 8 operating system
+ specific bits in sh_flags; at present we can get away with just
+ one in communicating between the assembler and BFD, but this
+ isn't a good long-term solution. */
+#define SEC_ARCH_BIT_0 0x008
+
+ /* A signal to the OS that the section contains read only data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+ the symbol to it, and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constructor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker to not output the section
+ even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a COFF shared library section. This flag is
+ only for the linker. If this type of section appears in
+ the input file, the linker must copy it to the output file
+ without changing the vma or size. FIXME: Although this
+ was originally intended to be general, it really is COFF
+ specific (and the flag was renamed to indicate this). It
+ might be cleaner to have some more general mechanism to
+ allow the back end to control what the linker does with
+ sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+ /* The section has GOT references. This flag is only for the
+ linker, and is currently only used by the elf32-hppa back end.
+ It will be set if global offset table references were detected
+ in this section, which indicate to the linker that the section
+ contains PIC code, and must be handled specially when doing a
+ static link. */
+#define SEC_HAS_GOT_REF 0x4000
+
+ /* The section contains common symbols (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* The contents of this section are held in memory pointed to
+ by the contents field. This is checked by bfd_get_section_contents,
+ and the data is retrieved from memory if appropriate. */
+#define SEC_IN_MEMORY 0x20000
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted based on the sum of
+ the symbol and addend values specified by the associated relocation
+ entries. Entries without associated relocation entries will be
+ appended to the end of the section in an unspecified order. */
+#define SEC_SORT_ENTRIES 0x80000
+
+ /* When linking, duplicate sections of the same name should be
+ discarded, rather than being combined into a single section as
+ is usually done. This is similar to how common symbols are
+ handled. See SEC_LINK_DUPLICATES below. */
+#define SEC_LINK_ONCE 0x100000
+
+ /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+ should handle duplicate sections. */
+#define SEC_LINK_DUPLICATES 0x600000
+
+ /* This value for SEC_LINK_DUPLICATES means that duplicate
+ sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if there are any duplicate sections, although
+ it should still only link one copy. */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections are a different size. */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections contain different
+ contents. */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+ /* This section was created by the linker as part of dynamic
+ relocation or other arcane processing. It is skipped when
+ going through the first-pass output, trusting that someone
+ else up the line will take care of it later. */
+#define SEC_LINKER_CREATED 0x800000
+
+ /* This section should not be subject to garbage collection. */
+#define SEC_KEEP 0x1000000
+
+ /* This section contains "short" data, and should be placed
+ "near" the GP. */
+#define SEC_SMALL_DATA 0x2000000
+
+ /* This section contains data which may be shared with other
+ executables or shared objects. */
+#define SEC_SHARED 0x4000000
+
+ /* When a section with this flag is being linked, then if the size of
+ the input section is less than a page, it should not cross a page
+ boundary. If the size of the input section is one page or more, it
+ should be aligned on a page boundary. */
+#define SEC_BLOCK 0x8000000
+
+ /* Conditionally link this section; do not link if there are no
+ references found to any symbol in the section. */
+#define SEC_CLINK 0x10000000
+
+ /* Attempt to merge identical entities in the section.
+ Entity size is given in the entsize field. */
+#define SEC_MERGE 0x20000000
+
+ /* If given with SEC_MERGE, entities to merge are zero terminated
+ strings where entsize specifies character size instead of fixed
+ size entries. */
+#define SEC_STRINGS 0x40000000
+
+ /* This section contains data about section groups. */
+#define SEC_GROUP 0x80000000
+
+ /* End of section flags. */
+
+ /* Some internal packed boolean fields. */
+
+ /* See the vma field. */
+ unsigned int user_set_vma : 1;
+
+ /* Whether relocations have been processed. */
+ unsigned int reloc_done : 1;
+
+ /* A mark flag used by some of the linker backends. */
+ unsigned int linker_mark : 1;
+
+ /* Another mark flag used by some of the linker backends. Set for
+ output sections that have an input section. */
+ unsigned int linker_has_input : 1;
+
+ /* A mark flag used by some linker backends for garbage collection. */
+ unsigned int gc_mark : 1;
+
+ /* Used by the ELF code to mark sections which have been allocated
+ to segments. */
+ unsigned int segment_mark : 1;
+
+ /* End of internal packed boolean fields. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+ bfd_vma vma;
+
+ /* The load address of the section - where it would be in a
+ rom image; really only used for writing section header
+ information. */
+ bfd_vma lma;
+
+ /* The size of the section in octets, as it will be output.
+ Contains a value even if the section has no contents (e.g., the
+ size of <<.bss>>). This will be filled in after relocation. */
+ bfd_size_type _cooked_size;
+
+ /* The original size on disk of the section, in octets. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset in *bytes* into the output section of the first byte in the
+ input section (byte ==> smallest addressable unit on the
+ target). In most cases, if this was going to start at the
+ 100th octet (8-bit quantity) in the output section, this value
+ would be 100. However, if the target byte size is 16 bits
+ (bfd_octets_per_byte is "2"), this value would be 50. */
+ bfd_vma output_offset;
+
+ /* The output section through which to map on output. */
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent of 2 -
+ e.g., 3 aligns to 2^3 (or 8). */
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above. */
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data. */
+ file_ptr filepos;
+
+ /* File position of relocation info. */
+ file_ptr rel_filepos;
+
+ /* File position of line data. */
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications. */
+ PTR userdata;
+
+ /* If the SEC_IN_MEMORY flag is set, this points to the actual
+ contents. */
+ unsigned char *contents;
+
+ /* Attached line number information. */
+ alent *lineno;
+
+ /* Number of line number records. */
+ unsigned int lineno_count;
+
+ /* Entity size for merging purposes. */
+ unsigned int entsize;
+
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct bfd_comdat_info *comdat;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out. */
+ file_ptr moving_line_filepos;
+
+ /* What the section number is in the target world. */
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+ bfd *owner;
+
+ /* A symbol which points at this section only. */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ struct bfd_link_order *link_order_head;
+ struct bfd_link_order *link_order_tail;
+} asection;
+
+/* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. New code should use the section_ptr macros rather
+ than referring directly to the const sections. The const sections
+ may eventually vanish. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* The absolute section. */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+/* Pointer to the undefined section. */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+/* Pointer to the common section. */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section. */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC) \
+ ( ((SEC) == bfd_abs_section_ptr) \
+ || ((SEC) == bfd_und_section_ptr) \
+ || ((SEC) == bfd_com_section_ptr) \
+ || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+ ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \
+ : (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section)->reloc_done ? (section)->_cooked_size \
+ : (abort (), (bfd_size_type) 1))
+
+/* Macros to handle insertion and deletion of a bfd's sections. These
+ only handle the list pointers, ie. do not adjust section_count,
+ target_index etc. */
+#define bfd_section_list_remove(ABFD, PS) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = *_ps; \
+ *_ps = _s->next; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = _ps; \
+ } \
+ while (0)
+#define bfd_section_list_insert(ABFD, PS, S) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = S; \
+ _s->next = *_ps; \
+ *_ps = _s; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = &_s->next; \
+ } \
+ while (0)
+
+void
+bfd_section_list_clear PARAMS ((bfd *));
+
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, const char *name));
+
+char *
+bfd_get_unique_section_name PARAMS ((bfd *abfd,
+ const char *templat,
+ int *count));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, const char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func) (bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR data, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_get_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec,
+ bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+ BFD_SEND (obfd, _bfd_copy_private_section_data, \
+ (ibfd, isection, obfd, osection))
+void
+_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
+
+enum bfd_architecture
+{
+ bfd_arch_unknown, /* File arch not known. */
+ bfd_arch_obscure, /* Arch known, not one of these. */
+ bfd_arch_m68k, /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32 8
+#define bfd_mach_mcf5200 9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307 11
+#define bfd_mach_mcf5407 12
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+#define bfd_mach_i960_jx 7
+#define bfd_mach_i960_hx 8
+
+ bfd_arch_or32, /* OpenRISC 32 */
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+#define bfd_mach_sparc 1
+/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
+#define bfd_mach_sparc_sparclet 2
+#define bfd_mach_sparc_sparclite 3
+#define bfd_mach_sparc_v8plus 4
+#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_sparclite_le 6
+#define bfd_mach_sparc_v9 7
+#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
+#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
+/* Nonzero if MACH has the v9 instruction set. */
+#define bfd_mach_sparc_v9_p(mach) \
+ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
+ && (mach) != bfd_mach_sparc_sparclite_le)
+ bfd_arch_mips, /* MIPS Rxxxx */
+#define bfd_mach_mips3000 3000
+#define bfd_mach_mips3900 3900
+#define bfd_mach_mips4000 4000
+#define bfd_mach_mips4010 4010
+#define bfd_mach_mips4100 4100
+#define bfd_mach_mips4111 4111
+#define bfd_mach_mips4300 4300
+#define bfd_mach_mips4400 4400
+#define bfd_mach_mips4600 4600
+#define bfd_mach_mips4650 4650
+#define bfd_mach_mips5000 5000
+#define bfd_mach_mips6000 6000
+#define bfd_mach_mips8000 8000
+#define bfd_mach_mips10000 10000
+#define bfd_mach_mips12000 12000
+#define bfd_mach_mips16 16
+#define bfd_mach_mips5 5
+#define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32 32
+#define bfd_mach_mipsisa64 64
+ bfd_arch_i386, /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+#define bfd_mach_x86_64 3
+#define bfd_mach_x86_64_intel_syntax 4
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_i370, /* IBM 360/370 Mainframes */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ bfd_arch_h8300, /* Hitachi H8/300 */
+#define bfd_mach_h8300 1
+#define bfd_mach_h8300h 2
+#define bfd_mach_h8300s 3
+ bfd_arch_pdp11, /* DEC PDP-11 */
+ bfd_arch_powerpc, /* PowerPC */
+#define bfd_mach_ppc 0
+#define bfd_mach_ppc64 1
+#define bfd_mach_ppc_403 403
+#define bfd_mach_ppc_403gc 4030
+#define bfd_mach_ppc_505 505
+#define bfd_mach_ppc_601 601
+#define bfd_mach_ppc_602 602
+#define bfd_mach_ppc_603 603
+#define bfd_mach_ppc_ec603e 6031
+#define bfd_mach_ppc_604 604
+#define bfd_mach_ppc_620 620
+#define bfd_mach_ppc_630 630
+#define bfd_mach_ppc_750 750
+#define bfd_mach_ppc_860 860
+#define bfd_mach_ppc_a35 35
+#define bfd_mach_ppc_rs64ii 642
+#define bfd_mach_ppc_rs64iii 643
+#define bfd_mach_ppc_7400 7400
+ bfd_arch_rs6000, /* IBM RS/6000 */
+#define bfd_mach_rs6k 0
+#define bfd_mach_rs6k_rs1 6001
+#define bfd_mach_rs6k_rsc 6003
+#define bfd_mach_rs6k_rs2 6002
+ bfd_arch_hppa, /* HP PA RISC */
+ bfd_arch_d10v, /* Mitsubishi D10V */
+#define bfd_mach_d10v 0
+#define bfd_mach_d10v_ts2 2
+#define bfd_mach_d10v_ts3 3
+ bfd_arch_d30v, /* Mitsubishi D30V */
+ bfd_arch_m68hc11, /* Motorola 68HC11 */
+ bfd_arch_m68hc12, /* Motorola 68HC12 */
+ bfd_arch_z8k, /* Zilog Z8000 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+#define bfd_mach_sh 0
+#define bfd_mach_sh2 0x20
+#define bfd_mach_sh_dsp 0x2d
+#define bfd_mach_sh3 0x30
+#define bfd_mach_sh3_dsp 0x3d
+#define bfd_mach_sh3e 0x3e
+#define bfd_mach_sh4 0x40
+#define bfd_mach_sh5 0x50
+ bfd_arch_alpha, /* Dec Alpha */
+#define bfd_mach_alpha_ev4 0x10
+#define bfd_mach_alpha_ev5 0x20
+#define bfd_mach_alpha_ev6 0x30
+ bfd_arch_arm, /* Advanced Risc Machines ARM. */
+#define bfd_mach_arm_2 1
+#define bfd_mach_arm_2a 2
+#define bfd_mach_arm_3 3
+#define bfd_mach_arm_3M 4
+#define bfd_mach_arm_4 5
+#define bfd_mach_arm_4T 6
+#define bfd_mach_arm_5 7
+#define bfd_mach_arm_5T 8
+#define bfd_mach_arm_5TE 9
+#define bfd_mach_arm_XScale 10
+ bfd_arch_ns32k, /* National Semiconductors ns32000 */
+ bfd_arch_w65, /* WDC 65816 */
+ bfd_arch_tic30, /* Texas Instruments TMS320C30 */
+ bfd_arch_tic54x, /* Texas Instruments TMS320C54X */
+ bfd_arch_tic80, /* TI TMS320c80 (MVP) */
+ bfd_arch_v850, /* NEC V850 */
+#define bfd_mach_v850 0
+#define bfd_mach_v850e 'E'
+#define bfd_mach_v850ea 'A'
+ bfd_arch_arc, /* ARC Cores */
+#define bfd_mach_arc_5 0
+#define bfd_mach_arc_6 1
+#define bfd_mach_arc_7 2
+#define bfd_mach_arc_8 3
+ bfd_arch_m32r, /* Mitsubishi M32R/D */
+#define bfd_mach_m32r 0 /* For backwards compatibility. */
+#define bfd_mach_m32rx 'x'
+ bfd_arch_mn10200, /* Matsushita MN10200 */
+ bfd_arch_mn10300, /* Matsushita MN10300 */
+#define bfd_mach_mn10300 300
+#define bfd_mach_am33 330
+ bfd_arch_fr30,
+#define bfd_mach_fr30 0x46523330
+ bfd_arch_mcore,
+ bfd_arch_ia64, /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64 0
+#define bfd_mach_ia64_elf32 1
+ bfd_arch_pj,
+ bfd_arch_avr, /* Atmel AVR microcontrollers. */
+#define bfd_mach_avr1 1
+#define bfd_mach_avr2 2
+#define bfd_mach_avr3 3
+#define bfd_mach_avr4 4
+#define bfd_mach_avr5 5
+ bfd_arch_cris, /* Axis CRIS */
+ bfd_arch_s390, /* IBM s390 */
+#define bfd_mach_s390_esa 0
+#define bfd_mach_s390_esame 1
+ bfd_arch_openrisc, /* OpenRISC */
+ bfd_arch_mmix, /* Donald Knuth's educational processor. */
+ bfd_arch_xstormy16,
+#define bfd_mach_xstormy16 0
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ unsigned long mach;
+ const char *arch_name;
+ const char *printable_name;
+ unsigned int section_align_power;
+ /* True if this is the default machine for the architecture. */
+ boolean the_default;
+ const struct bfd_arch_info * (*compatible)
+ PARAMS ((const struct bfd_arch_info *a,
+ const struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+ const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ const bfd *abfd,
+ const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch PARAMS ((enum bfd_architecture
+ arch,
+ unsigned long machine));
+
+const char *
+bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+unsigned int
+bfd_octets_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_mach_octets_per_byte PARAMS ((enum bfd_architecture arch,
+ unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected. */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions. */
+ bfd_reloc_continue,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_notsupported,
+
+ /* Unused. */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ symbols. If this type is returned, the error_message argument
+ to bfd_perform_relocation will be set. */
+ bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+ /* A pointer into the canonical table of pointers. */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section. */
+ bfd_size_type address;
+
+ /* addend for relocation value. */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation. */
+ reloc_howto_type *howto;
+
+}
+arelent;
+
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+ /* The type field has mainly a documentary use - the back end can
+ do what it wants with it, though normally the back end's
+ external idea of what a reloc number is stored
+ in this field. For example, a PC relative word relocation
+ in a coff environment has the type 023 - because that's
+ what the outside world calls a R_PCRWORD reloc. */
+ unsigned int type;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ power-of-two measure. To get the number of bytes operated
+ on by a type of relocation, use bfd_get_reloc_size. */
+ int size;
+
+ /* The number of bits in the item to be relocated. This is used
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ called rather than the normal function. This allows really
+ strange relocation methods to be accomodated (e.g., i960 callj
+ instructions). */
+ bfd_reloc_status_type (*special_function)
+ PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
+ bfd *, char **));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* Some formats record a relocation addend in the section contents
+ rather than with the relocation. For ELF formats this is the
+ distinction between USE_REL and USE_RELA (though the code checks
+ for USE_REL == 1/0). The value of this field is TRUE if the
+ addend is recorded with the section contents; when performing a
+ partial link (ld -r) the section contents (the data) will be
+ modified. The value of this field is FALSE if addends are
+ recorded with the relocation (in arelent.addend); when performing
+ a partial link the relocation will be modified.
+ All relocations for all ELF USE_RELA targets should set this field
+ to FALSE (values of TRUE should be looked on with suspicion).
+ However, the converse is not true: not all relocations of all ELF
+ USE_REL targets set this field to TRUE. Why this is so is peculiar
+ to each particular target. For relocs that aren't used in partial
+ links (e.g. GOT stuff) it doesn't matter what this is set to. */
+ boolean partial_inplace;
+
+ /* The src_mask selects which parts of the read in data
+ are to be used in the relocation sum. E.g., if this was an 8 bit
+ byte of data which we read and relocated, this would be
+ 0x000000ff. When we have relocs which have an addend, such as
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* The dst_mask selects which parts of the instruction are replaced
+ into the instruction. In most cases src_mask == dst_mask,
+ except in the above special case, where dst_mask would be
+ 0x000000ff, and src_mask would be 0x00000000. */
+ bfd_vma dst_mask;
+
+ /* When some formats create PC relative instructions, they leave
+ the value of the pc of the place being relocated in the offset
+ slot of the instruction, so that a PC relative relocation can
+ be made just by adding in an ordinary offset (e.g., sun3 a.out).
+ Some formats leave the displacement part of an instruction
+ empty (e.g., m88k bcs); this flag signals the fact. */
+ boolean pcrel_offset;
+};
+
+#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC }
+#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \
+ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \
+ NAME, false, 0, 0, IN)
+
+#define EMPTY_HOWTO(C) \
+ HOWTO ((C), 0, 0, 0, false, 0, complain_overflow_dont, NULL, \
+ NULL, false, 0, 0, false)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *) NULL) \
+ { \
+ if (bfd_is_com_section (symbol->section)) \
+ { \
+ relocation = 0; \
+ } \
+ else \
+ { \
+ relocation = symbol->value; \
+ } \
+ } \
+ }
+
+unsigned int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain
+{
+ arelent relent;
+ struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type
+bfd_check_overflow PARAMS ((enum complain_overflow how,
+ unsigned int bitsize,
+ unsigned int rightshift,
+ unsigned int addrsize,
+ bfd_vma relocation));
+
+bfd_reloc_status_type
+bfd_perform_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+bfd_reloc_status_type
+bfd_install_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message));
+
+enum bfd_reloc_code_real {
+ _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_26,
+ BFD_RELOC_24,
+ BFD_RELOC_16,
+ BFD_RELOC_14,
+ BFD_RELOC_8,
+
+/* PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_12_PCREL,
+ BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+ BFD_RELOC_32_GOT_PCREL,
+ BFD_RELOC_16_GOT_PCREL,
+ BFD_RELOC_8_GOT_PCREL,
+ BFD_RELOC_32_GOTOFF,
+ BFD_RELOC_16_GOTOFF,
+ BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF,
+ BFD_RELOC_8_GOTOFF,
+ BFD_RELOC_64_PLT_PCREL,
+ BFD_RELOC_32_PLT_PCREL,
+ BFD_RELOC_24_PLT_PCREL,
+ BFD_RELOC_16_PLT_PCREL,
+ BFD_RELOC_8_PLT_PCREL,
+ BFD_RELOC_64_PLTOFF,
+ BFD_RELOC_32_PLTOFF,
+ BFD_RELOC_16_PLTOFF,
+ BFD_RELOC_LO16_PLTOFF,
+ BFD_RELOC_HI16_PLTOFF,
+ BFD_RELOC_HI16_S_PLTOFF,
+ BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+ BFD_RELOC_68K_GLOB_DAT,
+ BFD_RELOC_68K_JMP_SLOT,
+ BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_LO16_BASEREL,
+ BFD_RELOC_HI16_BASEREL,
+ BFD_RELOC_HI16_S_BASEREL,
+ BFD_RELOC_8_BASEREL,
+ BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+ BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+ BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_16_PCREL_S2,
+ BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC. */
+ BFD_RELOC_HI22,
+ BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register. These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+ BFD_RELOC_GPREL16,
+ BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+ BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations. There is probably some overlap with other
+relocation types already defined. */
+ BFD_RELOC_NONE,
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA16,
+ BFD_RELOC_SPARC_UA32,
+ BFD_RELOC_SPARC_UA64,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+ BFD_RELOC_SPARC_10,
+ BFD_RELOC_SPARC_11,
+ BFD_RELOC_SPARC_OLO10,
+ BFD_RELOC_SPARC_HH22,
+ BFD_RELOC_SPARC_HM10,
+ BFD_RELOC_SPARC_LM22,
+ BFD_RELOC_SPARC_PC_HH22,
+ BFD_RELOC_SPARC_PC_HM10,
+ BFD_RELOC_SPARC_PC_LM22,
+ BFD_RELOC_SPARC_WDISP16,
+ BFD_RELOC_SPARC_WDISP19,
+ BFD_RELOC_SPARC_7,
+ BFD_RELOC_SPARC_6,
+ BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+ BFD_RELOC_SPARC_PLT32,
+ BFD_RELOC_SPARC_PLT64,
+ BFD_RELOC_SPARC_HIX22,
+ BFD_RELOC_SPARC_LOX10,
+ BFD_RELOC_SPARC_H44,
+ BFD_RELOC_SPARC_M44,
+ BFD_RELOC_SPARC_L44,
+ BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+ BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol. The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+ BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs. The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+ BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+ BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol. The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references. The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch) */
+ BFD_RELOC_ALPHA_LITERAL,
+ BFD_RELOC_ALPHA_ELF_LITERAL,
+ BFD_RELOC_ALPHA_LITUSE,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+ BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_CODEADDR,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register. */
+ BFD_RELOC_ALPHA_GPREL_HI16,
+ BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD. */
+ BFD_RELOC_ALPHA_BRSGP,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+ BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+ BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+ BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+ BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result. If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+ BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+ BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+ BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+ BFD_RELOC_PCREL_LO16,
+
+/* Relocation against a MIPS literal section. */
+ BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+ BFD_RELOC_MIPS_GOT16,
+ BFD_RELOC_MIPS_CALL16,
+ BFD_RELOC_MIPS_GOT_HI16,
+ BFD_RELOC_MIPS_GOT_LO16,
+ BFD_RELOC_MIPS_CALL_HI16,
+ BFD_RELOC_MIPS_CALL_LO16,
+ BFD_RELOC_MIPS_SUB,
+ BFD_RELOC_MIPS_GOT_PAGE,
+ BFD_RELOC_MIPS_GOT_OFST,
+ BFD_RELOC_MIPS_GOT_DISP,
+ BFD_RELOC_MIPS_SHIFT5,
+ BFD_RELOC_MIPS_SHIFT6,
+ BFD_RELOC_MIPS_INSERT_A,
+ BFD_RELOC_MIPS_INSERT_B,
+ BFD_RELOC_MIPS_DELETE,
+ BFD_RELOC_MIPS_HIGHEST,
+ BFD_RELOC_MIPS_HIGHER,
+ BFD_RELOC_MIPS_SCN_DISP,
+ BFD_RELOC_MIPS_REL16,
+ BFD_RELOC_MIPS_RELGOT,
+ BFD_RELOC_MIPS_JALR,
+ BFD_RELOC_SH_GOT_LOW16,
+ BFD_RELOC_SH_GOT_MEDLOW16,
+ BFD_RELOC_SH_GOT_MEDHI16,
+ BFD_RELOC_SH_GOT_HI16,
+ BFD_RELOC_SH_GOTPLT_LOW16,
+ BFD_RELOC_SH_GOTPLT_MEDLOW16,
+ BFD_RELOC_SH_GOTPLT_MEDHI16,
+ BFD_RELOC_SH_GOTPLT_HI16,
+ BFD_RELOC_SH_PLT_LOW16,
+ BFD_RELOC_SH_PLT_MEDLOW16,
+ BFD_RELOC_SH_PLT_MEDHI16,
+ BFD_RELOC_SH_PLT_HI16,
+ BFD_RELOC_SH_GOTOFF_LOW16,
+ BFD_RELOC_SH_GOTOFF_MEDLOW16,
+ BFD_RELOC_SH_GOTOFF_MEDHI16,
+ BFD_RELOC_SH_GOTOFF_HI16,
+ BFD_RELOC_SH_GOTPC_LOW16,
+ BFD_RELOC_SH_GOTPC_MEDLOW16,
+ BFD_RELOC_SH_GOTPC_MEDHI16,
+ BFD_RELOC_SH_GOTPC_HI16,
+ BFD_RELOC_SH_COPY64,
+ BFD_RELOC_SH_GLOB_DAT64,
+ BFD_RELOC_SH_JMP_SLOT64,
+ BFD_RELOC_SH_RELATIVE64,
+ BFD_RELOC_SH_GOT10BY4,
+ BFD_RELOC_SH_GOT10BY8,
+ BFD_RELOC_SH_GOTPLT10BY4,
+ BFD_RELOC_SH_GOTPLT10BY8,
+ BFD_RELOC_SH_GOTPLT32,
+ BFD_RELOC_SH_SHMEDIA_CODE,
+ BFD_RELOC_SH_IMMU5,
+ BFD_RELOC_SH_IMMS6,
+ BFD_RELOC_SH_IMMS6BY32,
+ BFD_RELOC_SH_IMMU6,
+ BFD_RELOC_SH_IMMS10,
+ BFD_RELOC_SH_IMMS10BY2,
+ BFD_RELOC_SH_IMMS10BY4,
+ BFD_RELOC_SH_IMMS10BY8,
+ BFD_RELOC_SH_IMMS16,
+ BFD_RELOC_SH_IMMU16,
+ BFD_RELOC_SH_IMM_LOW16,
+ BFD_RELOC_SH_IMM_LOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDLOW16,
+ BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDHI16,
+ BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+ BFD_RELOC_SH_IMM_HI16,
+ BFD_RELOC_SH_IMM_HI16_PCREL,
+ BFD_RELOC_SH_PT_16,
+
+
+/* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ BFD_RELOC_386_GOTOFF,
+ BFD_RELOC_386_GOTPC,
+
+/* x86-64/elf relocations */
+ BFD_RELOC_X86_64_GOT32,
+ BFD_RELOC_X86_64_PLT32,
+ BFD_RELOC_X86_64_COPY,
+ BFD_RELOC_X86_64_GLOB_DAT,
+ BFD_RELOC_X86_64_JUMP_SLOT,
+ BFD_RELOC_X86_64_RELATIVE,
+ BFD_RELOC_X86_64_GOTPCREL,
+ BFD_RELOC_X86_64_32S,
+
+/* ns32k relocations */
+ BFD_RELOC_NS32K_IMM_8,
+ BFD_RELOC_NS32K_IMM_16,
+ BFD_RELOC_NS32K_IMM_32,
+ BFD_RELOC_NS32K_IMM_8_PCREL,
+ BFD_RELOC_NS32K_IMM_16_PCREL,
+ BFD_RELOC_NS32K_IMM_32_PCREL,
+ BFD_RELOC_NS32K_DISP_8,
+ BFD_RELOC_NS32K_DISP_16,
+ BFD_RELOC_NS32K_DISP_32,
+ BFD_RELOC_NS32K_DISP_8_PCREL,
+ BFD_RELOC_NS32K_DISP_16_PCREL,
+ BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* PDP11 relocations */
+ BFD_RELOC_PDP11_DISP_8_PCREL,
+ BFD_RELOC_PDP11_DISP_6_PCREL,
+
+/* Picojava relocs. Not all of these appear in object files. */
+ BFD_RELOC_PJ_CODE_HI16,
+ BFD_RELOC_PJ_CODE_LO16,
+ BFD_RELOC_PJ_CODE_DIR16,
+ BFD_RELOC_PJ_CODE_DIR32,
+ BFD_RELOC_PJ_CODE_REL16,
+ BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+ BFD_RELOC_PPC_B26,
+ BFD_RELOC_PPC_BA26,
+ BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_B16,
+ BFD_RELOC_PPC_B16_BRTAKEN,
+ BFD_RELOC_PPC_B16_BRNTAKEN,
+ BFD_RELOC_PPC_BA16,
+ BFD_RELOC_PPC_BA16_BRTAKEN,
+ BFD_RELOC_PPC_BA16_BRNTAKEN,
+ BFD_RELOC_PPC_COPY,
+ BFD_RELOC_PPC_GLOB_DAT,
+ BFD_RELOC_PPC_JMP_SLOT,
+ BFD_RELOC_PPC_RELATIVE,
+ BFD_RELOC_PPC_LOCAL24PC,
+ BFD_RELOC_PPC_EMB_NADDR32,
+ BFD_RELOC_PPC_EMB_NADDR16,
+ BFD_RELOC_PPC_EMB_NADDR16_LO,
+ BFD_RELOC_PPC_EMB_NADDR16_HI,
+ BFD_RELOC_PPC_EMB_NADDR16_HA,
+ BFD_RELOC_PPC_EMB_SDAI16,
+ BFD_RELOC_PPC_EMB_SDA2I16,
+ BFD_RELOC_PPC_EMB_SDA2REL,
+ BFD_RELOC_PPC_EMB_SDA21,
+ BFD_RELOC_PPC_EMB_MRKREF,
+ BFD_RELOC_PPC_EMB_RELSEC16,
+ BFD_RELOC_PPC_EMB_RELST_LO,
+ BFD_RELOC_PPC_EMB_RELST_HI,
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
+ BFD_RELOC_PPC64_HIGHER,
+ BFD_RELOC_PPC64_HIGHER_S,
+ BFD_RELOC_PPC64_HIGHEST,
+ BFD_RELOC_PPC64_HIGHEST_S,
+ BFD_RELOC_PPC64_TOC16_LO,
+ BFD_RELOC_PPC64_TOC16_HI,
+ BFD_RELOC_PPC64_TOC16_HA,
+ BFD_RELOC_PPC64_TOC,
+ BFD_RELOC_PPC64_PLTGOT16,
+ BFD_RELOC_PPC64_PLTGOT16_LO,
+ BFD_RELOC_PPC64_PLTGOT16_HI,
+ BFD_RELOC_PPC64_PLTGOT16_HA,
+ BFD_RELOC_PPC64_ADDR16_DS,
+ BFD_RELOC_PPC64_ADDR16_LO_DS,
+ BFD_RELOC_PPC64_GOT16_DS,
+ BFD_RELOC_PPC64_GOT16_LO_DS,
+ BFD_RELOC_PPC64_PLT16_LO_DS,
+ BFD_RELOC_PPC64_SECTOFF_DS,
+ BFD_RELOC_PPC64_SECTOFF_LO_DS,
+ BFD_RELOC_PPC64_TOC16_DS,
+ BFD_RELOC_PPC64_TOC16_LO_DS,
+ BFD_RELOC_PPC64_PLTGOT16_DS,
+ BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* IBM 370/390 relocations */
+ BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+ BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. */
+ BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BLX,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_ADRL_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_ADR_IMM,
+ BFD_RELOC_ARM_LDR_IMM,
+ BFD_RELOC_ARM_LITERAL,
+ BFD_RELOC_ARM_IN_POOL,
+ BFD_RELOC_ARM_OFFSET_IMM8,
+ BFD_RELOC_ARM_HWLITERAL,
+ BFD_RELOC_ARM_THUMB_ADD,
+ BFD_RELOC_ARM_THUMB_IMM,
+ BFD_RELOC_ARM_THUMB_SHIFT,
+ BFD_RELOC_ARM_THUMB_OFFSET,
+ BFD_RELOC_ARM_GOT12,
+ BFD_RELOC_ARM_GOT32,
+ BFD_RELOC_ARM_JUMP_SLOT,
+ BFD_RELOC_ARM_COPY,
+ BFD_RELOC_ARM_GLOB_DAT,
+ BFD_RELOC_ARM_PLT32,
+ BFD_RELOC_ARM_RELATIVE,
+ BFD_RELOC_ARM_GOTOFF,
+ BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs. Not all of these appear in object files. */
+ BFD_RELOC_SH_PCDISP8BY2,
+ BFD_RELOC_SH_PCDISP12BY2,
+ BFD_RELOC_SH_IMM4,
+ BFD_RELOC_SH_IMM4BY2,
+ BFD_RELOC_SH_IMM4BY4,
+ BFD_RELOC_SH_IMM8,
+ BFD_RELOC_SH_IMM8BY2,
+ BFD_RELOC_SH_IMM8BY4,
+ BFD_RELOC_SH_PCRELIMM8BY2,
+ BFD_RELOC_SH_PCRELIMM8BY4,
+ BFD_RELOC_SH_SWITCH16,
+ BFD_RELOC_SH_SWITCH32,
+ BFD_RELOC_SH_USES,
+ BFD_RELOC_SH_COUNT,
+ BFD_RELOC_SH_ALIGN,
+ BFD_RELOC_SH_CODE,
+ BFD_RELOC_SH_DATA,
+ BFD_RELOC_SH_LABEL,
+ BFD_RELOC_SH_LOOP_START,
+ BFD_RELOC_SH_LOOP_END,
+ BFD_RELOC_SH_COPY,
+ BFD_RELOC_SH_GLOB_DAT,
+ BFD_RELOC_SH_JMP_SLOT,
+ BFD_RELOC_SH_RELATIVE,
+ BFD_RELOC_SH_GOTPC,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
+be zero and is not stored in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BRANCH9,
+ BFD_RELOC_THUMB_PCREL_BRANCH12,
+ BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* ARC Cores relocs.
+ARC 22 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+ BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch. The lowest two bits must be zero and are not
+stored in the instruction. The high 24 bits are installed in bits 23
+through 0. */
+ BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+ BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+ BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the
+right 3 bitsassumed to be 0. */
+ BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+ BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+ BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+ BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+ BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+ BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+ BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+ BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+ BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+ BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+ BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+ BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+ BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+ BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+ BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+ BFD_RELOC_TIC30_LDP,
+
+/* This is a 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x. */
+ BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+ BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+ BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+ BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+ BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+ BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+ BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+ BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+ BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+ BFD_RELOC_MCORE_PCREL_IMM8BY4,
+ BFD_RELOC_MCORE_PCREL_IMM11BY2,
+ BFD_RELOC_MCORE_PCREL_IMM4BY2,
+ BFD_RELOC_MCORE_PCREL_32,
+ BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+ BFD_RELOC_MCORE_RVA,
+
+/* These are relocations for the GETA instruction. */
+ BFD_RELOC_MMIX_GETA,
+ BFD_RELOC_MMIX_GETA_1,
+ BFD_RELOC_MMIX_GETA_2,
+ BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction. */
+ BFD_RELOC_MMIX_CBRANCH,
+ BFD_RELOC_MMIX_CBRANCH_J,
+ BFD_RELOC_MMIX_CBRANCH_1,
+ BFD_RELOC_MMIX_CBRANCH_2,
+ BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction. */
+ BFD_RELOC_MMIX_PUSHJ,
+ BFD_RELOC_MMIX_PUSHJ_1,
+ BFD_RELOC_MMIX_PUSHJ_2,
+ BFD_RELOC_MMIX_PUSHJ_3,
+
+/* These are relocations for the JMP instruction. */
+ BFD_RELOC_MMIX_JMP,
+ BFD_RELOC_MMIX_JMP_1,
+ BFD_RELOC_MMIX_JMP_2,
+ BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch. */
+ BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction. */
+ BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255. */
+ BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register. */
+ BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation. */
+ BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register. It does not modify contents. */
+ BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits. */
+ BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits. */
+ BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits. */
+ BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits. */
+ BFD_RELOC_AVR_CALL,
+
+/* Direct 12 bit. */
+ BFD_RELOC_390_12,
+
+/* 12 bit GOT offset. */
+ BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime. */
+ BFD_RELOC_390_COPY,
+
+/* Create GOT entry. */
+ BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry. */
+ BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base. */
+ BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT. */
+ BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset. */
+ BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1. */
+ BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1. */
+ BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1. */
+ BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset. */
+ BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry. */
+ BFD_RELOC_390_GOTENT,
+
+/* These two relocations are used by the linker to determine which of
+the entries in a C++ virtual function table are actually used. When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table. The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry. The reloc's symbol should refer to the
+table of the class mentioned in the code. Off of that base, an offset
+describes the entry that is being used. For Rela hosts, this offset
+is stored in the reloc's addend. For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+ BFD_RELOC_VTABLE_INHERIT,
+ BFD_RELOC_VTABLE_ENTRY,
+
+/* Intel IA64 Relocations. */
+ BFD_RELOC_IA64_IMM14,
+ BFD_RELOC_IA64_IMM22,
+ BFD_RELOC_IA64_IMM64,
+ BFD_RELOC_IA64_DIR32MSB,
+ BFD_RELOC_IA64_DIR32LSB,
+ BFD_RELOC_IA64_DIR64MSB,
+ BFD_RELOC_IA64_DIR64LSB,
+ BFD_RELOC_IA64_GPREL22,
+ BFD_RELOC_IA64_GPREL64I,
+ BFD_RELOC_IA64_GPREL32MSB,
+ BFD_RELOC_IA64_GPREL32LSB,
+ BFD_RELOC_IA64_GPREL64MSB,
+ BFD_RELOC_IA64_GPREL64LSB,
+ BFD_RELOC_IA64_LTOFF22,
+ BFD_RELOC_IA64_LTOFF64I,
+ BFD_RELOC_IA64_PLTOFF22,
+ BFD_RELOC_IA64_PLTOFF64I,
+ BFD_RELOC_IA64_PLTOFF64MSB,
+ BFD_RELOC_IA64_PLTOFF64LSB,
+ BFD_RELOC_IA64_FPTR64I,
+ BFD_RELOC_IA64_FPTR32MSB,
+ BFD_RELOC_IA64_FPTR32LSB,
+ BFD_RELOC_IA64_FPTR64MSB,
+ BFD_RELOC_IA64_FPTR64LSB,
+ BFD_RELOC_IA64_PCREL21B,
+ BFD_RELOC_IA64_PCREL21BI,
+ BFD_RELOC_IA64_PCREL21M,
+ BFD_RELOC_IA64_PCREL21F,
+ BFD_RELOC_IA64_PCREL22,
+ BFD_RELOC_IA64_PCREL60B,
+ BFD_RELOC_IA64_PCREL64I,
+ BFD_RELOC_IA64_PCREL32MSB,
+ BFD_RELOC_IA64_PCREL32LSB,
+ BFD_RELOC_IA64_PCREL64MSB,
+ BFD_RELOC_IA64_PCREL64LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR22,
+ BFD_RELOC_IA64_LTOFF_FPTR64I,
+ BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+ BFD_RELOC_IA64_SEGREL32MSB,
+ BFD_RELOC_IA64_SEGREL32LSB,
+ BFD_RELOC_IA64_SEGREL64MSB,
+ BFD_RELOC_IA64_SEGREL64LSB,
+ BFD_RELOC_IA64_SECREL32MSB,
+ BFD_RELOC_IA64_SECREL32LSB,
+ BFD_RELOC_IA64_SECREL64MSB,
+ BFD_RELOC_IA64_SECREL64LSB,
+ BFD_RELOC_IA64_REL32MSB,
+ BFD_RELOC_IA64_REL32LSB,
+ BFD_RELOC_IA64_REL64MSB,
+ BFD_RELOC_IA64_REL64LSB,
+ BFD_RELOC_IA64_LTV32MSB,
+ BFD_RELOC_IA64_LTV32LSB,
+ BFD_RELOC_IA64_LTV64MSB,
+ BFD_RELOC_IA64_LTV64LSB,
+ BFD_RELOC_IA64_IPLTMSB,
+ BFD_RELOC_IA64_IPLTLSB,
+ BFD_RELOC_IA64_COPY,
+ BFD_RELOC_IA64_TPREL22,
+ BFD_RELOC_IA64_TPREL64MSB,
+ BFD_RELOC_IA64_TPREL64LSB,
+ BFD_RELOC_IA64_LTOFF_TP22,
+ BFD_RELOC_IA64_LTOFF22X,
+ BFD_RELOC_IA64_LDXMOV,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits high part of an absolute address. */
+ BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits low part of an absolute address. */
+ BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bits of a value. */
+ BFD_RELOC_M68HC11_3B,
+
+/* These relocs are only used within the CRIS assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_CRIS_BDISP8,
+ BFD_RELOC_CRIS_UNSIGNED_5,
+ BFD_RELOC_CRIS_SIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS. */
+ BFD_RELOC_CRIS_COPY,
+ BFD_RELOC_CRIS_GLOB_DAT,
+ BFD_RELOC_CRIS_JUMP_SLOT,
+ BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT. */
+ BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT. */
+ BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation. */
+ BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations. */
+ BFD_RELOC_860_COPY,
+ BFD_RELOC_860_GLOB_DAT,
+ BFD_RELOC_860_JUMP_SLOT,
+ BFD_RELOC_860_RELATIVE,
+ BFD_RELOC_860_PC26,
+ BFD_RELOC_860_PLT26,
+ BFD_RELOC_860_PC16,
+ BFD_RELOC_860_LOW0,
+ BFD_RELOC_860_SPLIT0,
+ BFD_RELOC_860_LOW1,
+ BFD_RELOC_860_SPLIT1,
+ BFD_RELOC_860_LOW2,
+ BFD_RELOC_860_SPLIT2,
+ BFD_RELOC_860_LOW3,
+ BFD_RELOC_860_LOGOT0,
+ BFD_RELOC_860_SPGOT0,
+ BFD_RELOC_860_LOGOT1,
+ BFD_RELOC_860_SPGOT1,
+ BFD_RELOC_860_LOGOTOFF0,
+ BFD_RELOC_860_SPGOTOFF0,
+ BFD_RELOC_860_LOGOTOFF1,
+ BFD_RELOC_860_SPGOTOFF1,
+ BFD_RELOC_860_LOGOTOFF2,
+ BFD_RELOC_860_LOGOTOFF3,
+ BFD_RELOC_860_LOPC,
+ BFD_RELOC_860_HIGHADJ,
+ BFD_RELOC_860_HAGOT,
+ BFD_RELOC_860_HAGOTOFF,
+ BFD_RELOC_860_HAPC,
+ BFD_RELOC_860_HIGH,
+ BFD_RELOC_860_HIGOT,
+ BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations. */
+ BFD_RELOC_OPENRISC_ABS_26,
+ BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations. */
+ BFD_RELOC_H8_DIR16A8,
+ BFD_RELOC_H8_DIR16R8,
+ BFD_RELOC_H8_DIR24A8,
+ BFD_RELOC_H8_DIR24R8,
+ BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations. */
+ BFD_RELOC_XSTORMY16_REL_12,
+ BFD_RELOC_XSTORMY16_24,
+ BFD_RELOC_XSTORMY16_FPTR16,
+ BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+ /* A pointer to the BFD which owns the symbol. This information
+ is necessary so that a back end can work out what additional
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+ struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+ /* The text of the symbol. The name is left alone, and not copied; the
+ application may not alter it. */
+ const char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol. */
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ value is the offset into the section of the data. */
+#define BSF_GLOBAL 0x02
+
+ /* The symbol has global scope and is exported. The value is
+ the offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* No real difference. */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>>. */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning, unless BSF_DEBUGGING_RELOC is also set. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. The name is a
+ warning. The name of the next symbol is the one to warn about;
+ if a reference is made to a symbol with the same name as the next
+ symbol, a warning is issued by the linker. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. This symbol is an indirect
+ pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ /* Symbol is from dynamic linking information. */
+#define BSF_DYNAMIC 0x8000
+
+ /* The symbol denotes a data object. Used in ELF, and perhaps
+ others someday. */
+#define BSF_OBJECT 0x10000
+
+ /* This symbol is a debugging symbol. The value is the offset
+ into the section of the data. BSF_DEBUGGING should be set
+ as well. */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+ flagword flags;
+
+ /* A pointer to the section to which this symbol is
+ relative. This will always be non NULL, there are special
+ sections for undefined and absolute symbols. */
+ struct sec *section;
+
+ /* Back end special data. */
+ union
+ {
+ PTR p;
+ bfd_vma i;
+ }
+ udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+boolean
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+ BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+ (abfd, location))
+
+boolean
+bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((bfd *abfd, PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *
+_bfd_generic_make_empty_symbol PARAMS ((bfd *));
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+boolean
+bfd_is_undefined_symclass PARAMS ((int symclass));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+ (ibfd, isymbol, obfd, osymbol))
+
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ const char *filename;
+
+ /* A pointer to the target jump table. */
+ const struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char *",
+ and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ PTR iostream;
+
+ /* Is the file descriptor being cached? That is, can it be closed as
+ needed, and re-opened when accessed later? */
+ boolean cacheable;
+
+ /* Marks whether there was a default target specified when the
+ BFD was opened. This is used to select which matching algorithm
+ to use to choose the back end. */
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs. */
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here... */
+ ufile_ptr where;
+
+ /* ... and here: (``once'' means at least once). */
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time. */
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true. */
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension. */
+ int ifd;
+
+ /* The format which belongs to the BFD. (object, core, etc.) */
+ bfd_format format;
+
+ /* The direction with which the BFD was opened. */
+ enum bfd_direction
+ {
+ no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3
+ }
+ direction;
+
+ /* Format_specific flags. */
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+ ufile_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ from happening. */
+ boolean output_has_begun;
+
+ /* A hash table for section names. */
+ struct bfd_hash_table section_htab;
+
+ /* Pointer to linked list of sections. */
+ struct sec *sections;
+
+ /* The place where we add to the section list. */
+ struct sec **section_tail;
+
+ /* The number of sections. */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output. */
+ unsigned int symcount;
+
+ /* Symbol table for output BFD (with symcount entries). */
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information. */
+ const struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives. */
+ PTR arelt_data;
+ struct _bfd *my_archive; /* The containing archive BFD. */
+ struct _bfd *next; /* The next BFD in the archive. */
+ struct _bfd *archive_head; /* The first BFD in the archive. */
+ boolean has_armap;
+
+ /* A chain of BFD structures involved in a link. */
+ struct _bfd *link_next;
+
+ /* A field used by _bfd_generic_link_add_archive_symbols. This will
+ be used only for archive elements. */
+ int archive_pass;
+
+ /* Used by the back end to hold private data. */
+ union
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct pe_tdata *pe_obj_data;
+ struct xcoff_tdata *xcoff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct ihex_data_struct *ihex_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct mmo_data_struct *mmo_data;
+ struct sun_core_struct *sun_core_data;
+ struct sco5_core_struct *sco5_core_data;
+ struct trad_core_struct *trad_core_data;
+ struct som_data_struct *som_data;
+ struct hpux_core_struct *hpux_core_data;
+ struct hppabsd_core_struct *hppabsd_core_data;
+ struct sgi_core_struct *sgi_core_data;
+ struct lynx_core_struct *lynx_core_data;
+ struct osf_core_struct *osf_core_data;
+ struct cisco_core_struct *cisco_core_data;
+ struct versados_data_struct *versados_data;
+ struct netbsd_core_struct *netbsd_core_data;
+ PTR any;
+ }
+ tdata;
+
+ /* Used by the application to hold private data. */
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes. This is a
+ struct objalloc *, but we use PTR to avoid requiring the inclusion of
+ objalloc.h. */
+ PTR memory;
+};
+
+typedef enum bfd_error
+{
+ bfd_error_no_error = 0,
+ bfd_error_system_call,
+ bfd_error_invalid_target,
+ bfd_error_wrong_format,
+ bfd_error_wrong_object_format,
+ bfd_error_invalid_operation,
+ bfd_error_no_memory,
+ bfd_error_no_symbols,
+ bfd_error_no_armap,
+ bfd_error_no_more_archived_files,
+ bfd_error_malformed_archive,
+ bfd_error_file_not_recognized,
+ bfd_error_file_ambiguously_recognized,
+ bfd_error_no_contents,
+ bfd_error_nonrepresentable_section,
+ bfd_error_no_debug_section,
+ bfd_error_bad_value,
+ bfd_error_file_truncated,
+ bfd_error_file_too_big,
+ bfd_error_invalid_error_code
+}
+bfd_error_type;
+
+bfd_error_type
+bfd_get_error PARAMS ((void));
+
+void
+bfd_set_error PARAMS ((bfd_error_type error_tag));
+
+const char *
+bfd_errmsg PARAMS ((bfd_error_type error_tag));
+
+void
+bfd_perror PARAMS ((const char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+bfd_error_handler_type
+bfd_get_error_handler PARAMS ((void));
+
+const char *
+bfd_archive_filename PARAMS ((bfd *));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+void
+bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count));
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+int
+bfd_get_arch_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_sign_extend_vma PARAMS ((bfd *abfd));
+
+boolean
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+bfd_set_gp_size PARAMS ((bfd *abfd, unsigned int i));
+
+bfd_vma
+bfd_scan_vma PARAMS ((const char *string, const char **end, int base));
+
+boolean
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+ BFD_SEND (abfd, _bfd_set_private_flags, \
+ (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_merge_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+ BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+ BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *,
+ boolean, asymbol **));
+
+boolean
+bfd_alt_mach_code PARAMS ((bfd *abfd, int index));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+const char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+ ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ ((*((bfd)->xvec->message)) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+
+enum bfd_flavour
+{
+ bfd_target_unknown_flavour,
+ bfd_target_aout_flavour,
+ bfd_target_coff_flavour,
+ bfd_target_ecoff_flavour,
+ bfd_target_xcoff_flavour,
+ bfd_target_elf_flavour,
+ bfd_target_ieee_flavour,
+ bfd_target_nlm_flavour,
+ bfd_target_oasys_flavour,
+ bfd_target_tekhex_flavour,
+ bfd_target_srec_flavour,
+ bfd_target_ihex_flavour,
+ bfd_target_som_flavour,
+ bfd_target_os9k_flavour,
+ bfd_target_versados_flavour,
+ bfd_target_msdos_flavour,
+ bfd_target_ovax_flavour,
+ bfd_target_evax_flavour,
+ bfd_target_mmo_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+/* Forward declaration. */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+ /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */
+ char *name;
+
+ /* The "flavour" of a back end is a general indication about
+ the contents of a file. */
+ enum bfd_flavour flavour;
+
+ /* The order of bytes within the data area of a file. */
+ enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file. */
+ enum bfd_endian header_byteorder;
+
+ /* A mask of all the flags which an executable may have set -
+ from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>. */
+ flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+ the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>. */
+ flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+ (if any), perhaps `_'. */
+ char symbol_leading_char;
+
+ /* The pad character for file names within an archive header. */
+ char ar_pad_char;
+
+ /* The maximum number of characters in an archive header. */
+ unsigned short ar_max_namelen;
+
+ /* Entries for byte swapping for data. These are different from the
+ other entry points, since they don't take a BFD asthe first argument.
+ Certain other handlers could do the same. */
+ bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Byte swapping for the headers. */
+ bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Format dependent routines: these are vectors of entry points
+ within the target vector structure, one for each format to check. */
+
+ /* Check the format of a file being read. Return a <<bfd_target *>> or zero. */
+ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Set the format of a file being written. */
+ boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Write cached information into a file being written, at <<bfd_close>>. */
+ boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+
+ /* Generic entry points. */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+CONCAT2 (NAME,_close_and_cleanup), \
+CONCAT2 (NAME,_bfd_free_cached_info), \
+CONCAT2 (NAME,_new_section_hook), \
+CONCAT2 (NAME,_get_section_contents), \
+CONCAT2 (NAME,_get_section_contents_in_window)
+
+ /* Called when the BFD is being closed to do any necessary cleanup. */
+ boolean (*_close_and_cleanup) PARAMS ((bfd *));
+ /* Ask the BFD to free all cached information. */
+ boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+ /* Called when a new section is created. */
+ boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+ /* Read the contents of a section. */
+ boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type));
+
+ /* Entry points to copy private data. */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+CONCAT2 (NAME,_bfd_copy_private_bfd_data), \
+CONCAT2 (NAME,_bfd_merge_private_bfd_data), \
+CONCAT2 (NAME,_bfd_copy_private_section_data), \
+CONCAT2 (NAME,_bfd_copy_private_symbol_data), \
+CONCAT2 (NAME,_bfd_set_private_flags), \
+CONCAT2 (NAME,_bfd_print_private_bfd_data) \
+ /* Called to copy BFD general private data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to merge BFD general private data from one object file
+ to a common output file when linking. */
+ boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to copy BFD private section data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+ bfd *, sec_ptr));
+ /* Called to copy BFD private symbol data from one symbol
+ to another. */
+ boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+ /* Called to set private backend flags. */
+ boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+ /* Called to print private BFD data. */
+ boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+ /* Core file entry points. */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+CONCAT2 (NAME,_core_file_failing_command), \
+CONCAT2 (NAME,_core_file_failing_signal), \
+CONCAT2 (NAME,_core_file_matches_executable_p)
+ char * (*_core_file_failing_command) PARAMS ((bfd *));
+ int (*_core_file_failing_signal) PARAMS ((bfd *));
+ boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+ /* Archive entry points. */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+CONCAT2 (NAME,_slurp_armap), \
+CONCAT2 (NAME,_slurp_extended_name_table), \
+CONCAT2 (NAME,_construct_extended_name_table), \
+CONCAT2 (NAME,_truncate_arname), \
+CONCAT2 (NAME,_write_armap), \
+CONCAT2 (NAME,_read_ar_hdr), \
+CONCAT2 (NAME,_openr_next_archived_file), \
+CONCAT2 (NAME,_get_elt_at_index), \
+CONCAT2 (NAME,_generic_stat_arch_elt), \
+CONCAT2 (NAME,_update_armap_timestamp)
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ boolean (*_bfd_construct_extended_name_table)
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, const char *, char *));
+ boolean (*write_armap)
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+ PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *, bfd *));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+ bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+ boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+ /* Entry points used for symbols. */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+CONCAT2 (NAME,_get_symtab_upper_bound), \
+CONCAT2 (NAME,_get_symtab), \
+CONCAT2 (NAME,_make_empty_symbol), \
+CONCAT2 (NAME,_print_symbol), \
+CONCAT2 (NAME,_get_symbol_info), \
+CONCAT2 (NAME,_bfd_is_local_label_name), \
+CONCAT2 (NAME,_get_lineno), \
+CONCAT2 (NAME,_find_nearest_line), \
+CONCAT2 (NAME,_bfd_make_debug_symbol), \
+CONCAT2 (NAME,_read_minisymbols), \
+CONCAT2 (NAME,_minisymbol_to_symbol)
+ long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+ long (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+ struct symbol_cache_entry *
+ (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+ void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ struct symbol_cache_entry *,
+ symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+ boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+ alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+ boolean (*_bfd_find_nearest_line)
+ PARAMS ((bfd *, struct sec *, struct symbol_cache_entry **, bfd_vma,
+ const char **, const char **, unsigned int *));
+ /* Back-door to allow format-aware applications to create debug symbols
+ while using BFD for everything else. Currently used by the assembler
+ when creating COFF files. */
+ asymbol *(*_bfd_make_debug_symbol) PARAMS ((bfd *, void *,
+ unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+ BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+ long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+ unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+ asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+ /* Routines for relocs. */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+CONCAT2 (NAME,_get_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_reloc), \
+CONCAT2 (NAME,_bfd_reloc_type_lookup)
+ long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+ long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+ struct symbol_cache_entry **));
+ /* See documentation on reloc types. */
+ reloc_howto_type *
+ (*reloc_type_lookup) PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+ /* Routines used when writing an object file. */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+CONCAT2 (NAME,_set_arch_mach), \
+CONCAT2 (NAME,_set_section_contents)
+ boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+ boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+
+ /* Routines used by the linker. */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+CONCAT2 (NAME,_sizeof_headers), \
+CONCAT2 (NAME,_bfd_get_relocated_section_contents), \
+CONCAT2 (NAME,_bfd_relax_section), \
+CONCAT2 (NAME,_bfd_link_hash_table_create), \
+CONCAT2 (NAME,_bfd_link_add_symbols), \
+CONCAT2 (NAME,_bfd_final_link), \
+CONCAT2 (NAME,_bfd_link_split_section), \
+CONCAT2 (NAME,_bfd_gc_sections), \
+CONCAT2 (NAME,_bfd_merge_sections)
+ int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+ bfd_byte *(*_bfd_get_relocated_section_contents)
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, struct symbol_cache_entry **));
+
+ boolean (*_bfd_relax_section)
+ PARAMS ((bfd *, struct sec *, struct bfd_link_info *, boolean *));
+
+ /* Create a hash table for the linker. Different backends store
+ different information in this table. */
+ struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+ /* Add symbols from this object file into the hash table. */
+ boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Do a link based on the link_order structures attached to each
+ section of the BFD. */
+ boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Should this section be split up into smaller pieces during linking. */
+ boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+ /* Remove sections that are not referenced from the output. */
+ boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Attempt to merge SEC_MERGE sections. */
+ boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Routines to handle dynamic symbols and relocs. */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+CONCAT2 (NAME,_get_dynamic_symtab_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_symtab), \
+CONCAT2 (NAME,_get_dynamic_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_reloc)
+ /* Get the amount of memory required to hold the dynamic symbols. */
+ long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic symbols. */
+ long (*_bfd_canonicalize_dynamic_symtab)
+ PARAMS ((bfd *, struct symbol_cache_entry **));
+ /* Get the amount of memory required to hold the dynamic relocs. */
+ long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic relocs. */
+ long (*_bfd_canonicalize_dynamic_reloc)
+ PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+ /* Opposite endian version of this target. */
+ const struct bfd_target * alternative_target;
+
+ /* Data for use by back-end routines, which isn't
+ generic enough to belong in this structure. */
+ PTR backend_data;
+
+} bfd_target;
+
+boolean
+bfd_set_default_target PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((const char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target *
+bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+const char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gnu/usr.bin/binutils/libbfd/ia64/bfd.h b/gnu/usr.bin/binutils/libbfd/ia64/bfd.h
new file mode 100644
index 0000000..ce0e60f
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/ia64/bfd.h
@@ -0,0 +1,3823 @@
+/* $FreeBSD$ */
+
+/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
+ generated from "bfd-in.h", " ", "init.c", " ", "opncls.c",
+ " ", "libbfd.c", " ", "section.c", " ", "archures.c ", "reloc.c ",
+ "syms.c ", "bfd.c ", "archive.c ", "corefile.c ", "targets.c "
+ and "format.c ".
+ Run "make headers" in your build bfd/ to regenerate. */
+
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FreeBSD does not adhere to the IA-64 psABI. */
+#define ELF_DYNAMIC_INTERPRETER "/usr/libexec/ld-elf.so.1"
+
+#include "ansidecl.h"
+#include "symcat.h"
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This hack is to avoid a problem with some strict ANSI C preprocessors.
+ The problem is, "32_" is not a valid preprocessing token, and we don't
+ want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will
+ cause the inner CONCAT2 macros to be evaluated first, producing
+ still-valid pp-tokens. Then the final concatenation can be done. */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* #define BFD_VERSION 212000000 */
+/* #define BFD_VERSION_DATE 20020309 */
+/* #define BFD_VERSION_STRING "2.12" */
+
+/* The word size used by BFD on the host. This may be 64 with a 32
+ bit target if the host is 64 bit, or if other 64 bit targets have
+ been selected with --enable-targets, or if --enable-64-bit-bfd. */
+#define BFD_ARCH_SIZE 64
+
+/* The word size of the default bfd target. */
+#define BFD_DEFAULT_TARGET_SIZE 64
+
+#if defined(__i386__) || defined(__powerpc__)
+#define BFD_HOST_64BIT_LONG 0
+#else
+#define BFD_HOST_64BIT_LONG 1
+#endif /* 32-bit host */
+#if 0
+#define BFD_HOST_64_BIT
+#define BFD_HOST_U_64_BIT
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* forward declaration */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+#if defined (__GNUG__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, BFD_HOST_64_BIT must be
+ defined above. */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+# define BFD_HOST_64_BIT long
+# define BFD_HOST_U_64_BIT unsigned long
+# else
+# ifdef __GNUC__
+# if __GNUC__ >= 2
+# define BFD_HOST_64_BIT long long
+# define BFD_HOST_U_64_BIT unsigned long long
+# endif /* __GNUC__ >= 2 */
+# endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf (s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf (s, "%08lx", x)
+
+#endif /* not BFD64 */
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef bfd_signed_vma file_ptr;
+typedef bfd_vma ufile_ptr;
+
+extern void bfd_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
+extern void bfd_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/** File formats */
+
+typedef enum bfd_format {
+ bfd_unknown = 0, /* file format is unknown */
+ bfd_object, /* linker/assember/compiler output */
+ bfd_archive, /* object archive file */
+ bfd_core, /* core dump */
+ bfd_type_end} /* marks the end; don't use it! */
+ bfd_format;
+
+/* Values that may appear in the flags field of a BFD. These also
+ appear in the object_flags field of the bfd_target structure, where
+ they indicate the set of flags used by that backend (not all flags
+ are meaningful for all object file formats) (FIXME: at the moment,
+ the object_flags values have mostly just been copied from backend
+ to another, and are not necessarily correct). */
+
+/* No flags. */
+#define BFD_NO_FLAGS 0x00
+
+/* BFD contains relocation entries. */
+#define HAS_RELOC 0x01
+
+/* BFD is directly executable. */
+#define EXEC_P 0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+ COFF header). */
+#define HAS_LINENO 0x04
+
+/* BFD has debugging information. */
+#define HAS_DEBUG 0x08
+
+/* BFD has symbols. */
+#define HAS_SYMS 0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+ header). */
+#define HAS_LOCALS 0x20
+
+/* BFD is a dynamic object. */
+#define DYNAMIC 0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+ like an a.out NMAGIC file) (the linker sets this by default, but
+ clears it for -r or -N). */
+#define WP_TEXT 0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+ linker sets this by default, but clears it for -r or -n or -N). */
+#define D_PAGED 0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+ do something) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+ traditional format. For example, this is used to request that when
+ writing out an a.out object the symbols not be hashed to eliminate
+ duplicates. */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* symbols and relocation */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+ target specific parts are in libcoff.h, libaout.h, etc. */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol. */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym {
+ char *name;
+ file_ptr file_offset; /* look here to find the file */
+} carsym; /* to make these you call a carsymogen */
+
+/* Used in generating armaps (archive tables of contents).
+ Perhaps just a forward definition would do? */
+struct orl { /* output ranlib */
+ char **name; /* symbol name */
+ union {
+ file_ptr pos;
+ bfd *abfd;
+ } u; /* bfd* or file position */
+ int namidx; /* index into string table */
+};
+
+/* Linenumber stuff */
+typedef struct lineno_cache_entry {
+ unsigned int line_number; /* Linenumber from start of function*/
+ union {
+ struct symbol_cache_entry *sym; /* Function name */
+ bfd_vma offset; /* Offset into section */
+ } u;
+} alent;
+
+/* object and core file sections */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ const char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ const char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines. There is no way to free up a hash table. */
+
+/* An element in the hash table. Most uses will actually use a larger
+ structure, and an instance of this will be the first field. */
+
+struct bfd_hash_entry
+{
+ /* Next entry for this hash code. */
+ struct bfd_hash_entry *next;
+ /* String being hashed. */
+ const char *string;
+ /* Hash code. This is the full hash code, not the index into the
+ table. */
+ unsigned long hash;
+};
+
+/* A hash table. */
+
+struct bfd_hash_table
+{
+ /* The hash array. */
+ struct bfd_hash_entry **table;
+ /* The number of slots in the hash table. */
+ unsigned int size;
+ /* A function used to create new elements in the hash table. The
+ first entry is itself a pointer to an element. When this
+ function is first invoked, this pointer will be NULL. However,
+ having the pointer permits a hierarchy of method functions to be
+ built each of which calls the function in the superclass. Thus
+ each function should be written to allocate a new block of memory
+ only if the argument is NULL. */
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+ /* An objalloc for this hash table. This is a struct objalloc *,
+ but we use PTR to avoid requiring the inclusion of objalloc.h. */
+ PTR memory;
+};
+
+/* Initialize a hash table. */
+extern boolean bfd_hash_table_init
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+
+/* Initialize a hash table specifying a size. */
+extern boolean bfd_hash_table_init_n
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int size));
+
+/* Free up a hash table. */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table. If CREATE is true, a new entry
+ will be created for this string if one does not already exist. The
+ COPY argument must be true if this routine should copy the string
+ into newly allocated memory when adding an entry. */
+extern struct bfd_hash_entry *bfd_hash_lookup
+ PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+ boolean copy));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry. */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Grab some space for a hash table entry. */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+ unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+ element. If the function returns false, the traversal stops. The
+ INFO argument is passed to the function. */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+ boolean (*) (struct bfd_hash_entry *,
+ PTR),
+ PTR info));
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_bread PARAMS ((PTR, bfd_size_type, bfd *));
+extern bfd_size_type bfd_bwrite PARAMS ((const PTR, bfd_size_type, bfd *));
+extern int bfd_seek PARAMS ((bfd *, file_ptr, int));
+extern ufile_ptr bfd_tell PARAMS ((bfd *));
+extern int bfd_flush PARAMS ((bfd *));
+extern int bfd_stat PARAMS ((bfd *, struct stat *));
+
+/* Deprecated old routines. */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated
+ PARAMS ((const char *, const char *, int, const char *));
+
+/* Cast from const char * to char * so that caller can assign to
+ a char * without a warning. */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_family_coff(abfd) \
+ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean) (bool)), true)
+
+extern boolean bfd_cache_close PARAMS ((bfd *abfd));
+/* NB: This declaration should match the autogenerated one in libbfd.h. */
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+bfd_vma bfd_getb64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb16 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void bfd_putb64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb16 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl16 PARAMS ((bfd_vma, unsigned char *));
+
+/* Byte swapping routines which take size and endiannes as arguments. */
+
+bfd_vma bfd_get_bits PARAMS ((bfd_byte *, int, boolean));
+void bfd_put_bits PARAMS ((bfd_vma, bfd_byte *, int, boolean));
+
+/* Externally visible ECOFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+ PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+ unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+ PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ bfd *input_bfd, struct ecoff_debug_info *input_debug,
+ const struct ecoff_debug_swap *input_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ boolean relocateable,
+ boolean (*get_extr) (struct symbol_cache_entry *,
+ struct ecoff_extr *),
+ void (*set_index) (struct symbol_cache_entry *,
+ bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+ PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+ PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Return an upper bound on the number of bytes required to store a
+ copy of ABFD's program header table entries. Return -1 if an error
+ occurs; bfd_get_error will return an appropriate code. */
+extern long bfd_get_elf_phdr_upper_bound PARAMS ((bfd *abfd));
+
+/* Copy ABFD's program header table entries to *PHDRS. The entries
+ will be stored as an array of Elf_Internal_Phdr structures, as
+ defined in include/elf/internal.h. To find out how large the
+ buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+ Return the number of program header table entries read, or -1 if an
+ error occurs; bfd_get_error will return an appropriate code. */
+extern int bfd_get_elf_phdrs PARAMS ((bfd *abfd, void *phdrs));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf. */
+extern int bfd_get_arch_size PARAMS ((bfd *));
+
+/* Return true if address "naturally" sign extends, or -1 if not elf. */
+extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+
+extern boolean bfd_m68k_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+ struct sec **));
+
+/* Linux shared library support routines for the linker. */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window {
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+} bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *, unsigned int));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+extern boolean bfd_xcoff_link_generate_rtinit
+ PARAMS ((bfd *, const char *, const char *));
+
+/* Externally visible COFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+ PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+ PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+ PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+extern boolean bfd_m68k_coff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* PE ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_pe_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_pe_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_pe_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support. Called from linker. */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* TI COFF load page support. */
+extern void bfd_ticoff_set_section_load_page
+ PARAMS ((struct sec *, int));
+
+extern int bfd_ticoff_get_section_load_page
+ PARAMS ((struct sec *));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((const char *filename, const char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((const char *filename, const char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((const char *filename, const char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((const char *filename, bfd *templ));
+
+boolean
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+/* Byte swapping macros for user section data. */
+
+#define bfd_put_8(abfd, val, ptr) \
+ ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val)))
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr) \
+ ( (bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \
+ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \
+ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \
+ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \
+ : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr) \
+ ( (bits) == 8 ? bfd_put_8 (abfd, val, ptr) \
+ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \
+ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \
+ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \
+ : (abort (), (void) 0))
+
+
+/* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx16, (val, ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx16, (ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx32, (val, ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx32, (ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx64, (val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx64, (ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr))
+
+/* Refinements on the above, which should eventually go away. Save
+ cluttering the source with (bfd_vma) and (bfd_byte *) casts. */
+
+#define H_PUT_64(abfd, val, where) \
+ bfd_h_put_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_32(abfd, val, where) \
+ bfd_h_put_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_16(abfd, val, where) \
+ bfd_h_put_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_8 bfd_h_put_8
+
+#define H_PUT_S64(abfd, val, where) \
+ bfd_h_put_signed_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S32(abfd, val, where) \
+ bfd_h_put_signed_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S16(abfd, val, where) \
+ bfd_h_put_signed_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S8 bfd_h_put_signed_8
+
+#define H_GET_64(abfd, where) \
+ bfd_h_get_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_32(abfd, where) \
+ bfd_h_get_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_16(abfd, where) \
+ bfd_h_get_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_8 bfd_h_get_8
+
+#define H_GET_S64(abfd, where) \
+ bfd_h_get_signed_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S32(abfd, where) \
+ bfd_h_get_signed_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S16(abfd, where) \
+ bfd_h_get_signed_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S8 bfd_h_get_signed_8
+
+
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+typedef struct sec
+{
+ /* The name of the section; the name isn't a copy, the pointer is
+ the same as that passed to bfd_make_section. */
+
+ const char *name;
+
+ /* A unique sequence number. */
+
+ int id;
+
+ /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */
+
+ int index;
+
+ /* The next section in the list belonging to the BFD, or NULL. */
+
+ struct sec *next;
+
+ /* The field flags contains attributes of the section. Some
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* Tells the OS to allocate space for this section when loading.
+ This is clear for a section containing debug information only. */
+#define SEC_ALLOC 0x001
+
+ /* Tells the OS to load the section from the file when loading.
+ This is clear for a .bss section. */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there is
+ some relocation information too. */
+#define SEC_RELOC 0x004
+
+ /* ELF reserves 4 processor specific bits and 8 operating system
+ specific bits in sh_flags; at present we can get away with just
+ one in communicating between the assembler and BFD, but this
+ isn't a good long-term solution. */
+#define SEC_ARCH_BIT_0 0x008
+
+ /* A signal to the OS that the section contains read only data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+ the symbol to it, and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constructor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker to not output the section
+ even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a COFF shared library section. This flag is
+ only for the linker. If this type of section appears in
+ the input file, the linker must copy it to the output file
+ without changing the vma or size. FIXME: Although this
+ was originally intended to be general, it really is COFF
+ specific (and the flag was renamed to indicate this). It
+ might be cleaner to have some more general mechanism to
+ allow the back end to control what the linker does with
+ sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+ /* The section has GOT references. This flag is only for the
+ linker, and is currently only used by the elf32-hppa back end.
+ It will be set if global offset table references were detected
+ in this section, which indicate to the linker that the section
+ contains PIC code, and must be handled specially when doing a
+ static link. */
+#define SEC_HAS_GOT_REF 0x4000
+
+ /* The section contains common symbols (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* The contents of this section are held in memory pointed to
+ by the contents field. This is checked by bfd_get_section_contents,
+ and the data is retrieved from memory if appropriate. */
+#define SEC_IN_MEMORY 0x20000
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted based on the sum of
+ the symbol and addend values specified by the associated relocation
+ entries. Entries without associated relocation entries will be
+ appended to the end of the section in an unspecified order. */
+#define SEC_SORT_ENTRIES 0x80000
+
+ /* When linking, duplicate sections of the same name should be
+ discarded, rather than being combined into a single section as
+ is usually done. This is similar to how common symbols are
+ handled. See SEC_LINK_DUPLICATES below. */
+#define SEC_LINK_ONCE 0x100000
+
+ /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+ should handle duplicate sections. */
+#define SEC_LINK_DUPLICATES 0x600000
+
+ /* This value for SEC_LINK_DUPLICATES means that duplicate
+ sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if there are any duplicate sections, although
+ it should still only link one copy. */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections are a different size. */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections contain different
+ contents. */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+ /* This section was created by the linker as part of dynamic
+ relocation or other arcane processing. It is skipped when
+ going through the first-pass output, trusting that someone
+ else up the line will take care of it later. */
+#define SEC_LINKER_CREATED 0x800000
+
+ /* This section should not be subject to garbage collection. */
+#define SEC_KEEP 0x1000000
+
+ /* This section contains "short" data, and should be placed
+ "near" the GP. */
+#define SEC_SMALL_DATA 0x2000000
+
+ /* This section contains data which may be shared with other
+ executables or shared objects. */
+#define SEC_SHARED 0x4000000
+
+ /* When a section with this flag is being linked, then if the size of
+ the input section is less than a page, it should not cross a page
+ boundary. If the size of the input section is one page or more, it
+ should be aligned on a page boundary. */
+#define SEC_BLOCK 0x8000000
+
+ /* Conditionally link this section; do not link if there are no
+ references found to any symbol in the section. */
+#define SEC_CLINK 0x10000000
+
+ /* Attempt to merge identical entities in the section.
+ Entity size is given in the entsize field. */
+#define SEC_MERGE 0x20000000
+
+ /* If given with SEC_MERGE, entities to merge are zero terminated
+ strings where entsize specifies character size instead of fixed
+ size entries. */
+#define SEC_STRINGS 0x40000000
+
+ /* This section contains data about section groups. */
+#define SEC_GROUP 0x80000000
+
+ /* End of section flags. */
+
+ /* Some internal packed boolean fields. */
+
+ /* See the vma field. */
+ unsigned int user_set_vma : 1;
+
+ /* Whether relocations have been processed. */
+ unsigned int reloc_done : 1;
+
+ /* A mark flag used by some of the linker backends. */
+ unsigned int linker_mark : 1;
+
+ /* Another mark flag used by some of the linker backends. Set for
+ output sections that have an input section. */
+ unsigned int linker_has_input : 1;
+
+ /* A mark flag used by some linker backends for garbage collection. */
+ unsigned int gc_mark : 1;
+
+ /* Used by the ELF code to mark sections which have been allocated
+ to segments. */
+ unsigned int segment_mark : 1;
+
+ /* End of internal packed boolean fields. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+
+ bfd_vma vma;
+
+ /* The load address of the section - where it would be in a
+ rom image; really only used for writing section header
+ information. */
+
+ bfd_vma lma;
+
+ /* The size of the section in octets, as it will be output.
+ Contains a value even if the section has no contents (e.g., the
+ size of <<.bss>>). This will be filled in after relocation. */
+
+ bfd_size_type _cooked_size;
+
+ /* The original size on disk of the section, in octets. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset in *bytes* into the output section of the first byte in the
+ input section (byte ==> smallest addressable unit on the
+ target). In most cases, if this was going to start at the
+ 100th octet (8-bit quantity) in the output section, this value
+ would be 100. However, if the target byte size is 16 bits
+ (bfd_octets_per_byte is "2"), this value would be 50. */
+
+ bfd_vma output_offset;
+
+ /* The output section through which to map on output. */
+
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent of 2 -
+ e.g., 3 aligns to 2^3 (or 8). */
+
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above */
+
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data. */
+
+ file_ptr filepos;
+
+ /* File position of relocation info. */
+
+ file_ptr rel_filepos;
+
+ /* File position of line data. */
+
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications. */
+
+ PTR userdata;
+
+ /* If the SEC_IN_MEMORY flag is set, this points to the actual
+ contents. */
+ unsigned char *contents;
+
+ /* Attached line number information. */
+
+ alent *lineno;
+
+ /* Number of line number records. */
+
+ unsigned int lineno_count;
+
+ /* Entity size for merging purposes. */
+
+ unsigned int entsize;
+
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+
+ struct bfd_comdat_info *comdat;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out. */
+
+ file_ptr moving_line_filepos;
+
+ /* What the section number is in the target world. */
+
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+
+ bfd *owner;
+
+ /* A symbol which points at this section only */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ struct bfd_link_order *link_order_head;
+ struct bfd_link_order *link_order_tail;
+} asection ;
+
+/* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. New code should use the section_ptr macros rather
+ than referring directly to the const sections. The const sections
+ may eventually vanish. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* the absolute section */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+/* Pointer to the undefined section */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+/* Pointer to the common section */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC) \
+ ( ((SEC) == bfd_abs_section_ptr) \
+ || ((SEC) == bfd_und_section_ptr) \
+ || ((SEC) == bfd_com_section_ptr) \
+ || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+ ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \
+ : (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section)->reloc_done ? (section)->_cooked_size \
+ : (abort (), (bfd_size_type) 1))
+
+/* Macros to handle insertion and deletion of a bfd's sections. These
+ only handle the list pointers, ie. do not adjust section_count,
+ target_index etc. */
+#define bfd_section_list_remove(ABFD, PS) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = *_ps; \
+ *_ps = _s->next; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = _ps; \
+ } \
+ while (0)
+#define bfd_section_list_insert(ABFD, PS, S) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = S; \
+ _s->next = *_ps; \
+ *_ps = _s; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = &_s->next; \
+ } \
+ while (0)
+
+void
+bfd_section_list_clear PARAMS ((bfd *));
+
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, const char *name));
+
+char *
+bfd_get_unique_section_name PARAMS ((bfd *abfd,
+ const char *templat,
+ int *count));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, const char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func) (bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR data, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_get_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec,
+ bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+ BFD_SEND (obfd, _bfd_copy_private_section_data, \
+ (ibfd, isection, obfd, osection))
+void
+_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
+
+enum bfd_architecture
+{
+ bfd_arch_unknown, /* File arch not known */
+ bfd_arch_obscure, /* Arch known, not one of these */
+ bfd_arch_m68k, /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32 8
+#define bfd_mach_mcf5200 9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307 11
+#define bfd_mach_mcf5407 12
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+#define bfd_mach_i960_jx 7
+#define bfd_mach_i960_hx 8
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+#define bfd_mach_sparc 1
+/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
+#define bfd_mach_sparc_sparclet 2
+#define bfd_mach_sparc_sparclite 3
+#define bfd_mach_sparc_v8plus 4
+#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns */
+#define bfd_mach_sparc_sparclite_le 6
+#define bfd_mach_sparc_v9 7
+#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns */
+#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns */
+#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns */
+/* Nonzero if MACH has the v9 instruction set. */
+#define bfd_mach_sparc_v9_p(mach) \
+ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
+ && (mach) != bfd_mach_sparc_sparclite_le)
+ bfd_arch_mips, /* MIPS Rxxxx */
+#define bfd_mach_mips3000 3000
+#define bfd_mach_mips3900 3900
+#define bfd_mach_mips4000 4000
+#define bfd_mach_mips4010 4010
+#define bfd_mach_mips4100 4100
+#define bfd_mach_mips4111 4111
+#define bfd_mach_mips4300 4300
+#define bfd_mach_mips4400 4400
+#define bfd_mach_mips4600 4600
+#define bfd_mach_mips4650 4650
+#define bfd_mach_mips5000 5000
+#define bfd_mach_mips6000 6000
+#define bfd_mach_mips8000 8000
+#define bfd_mach_mips10000 10000
+#define bfd_mach_mips12000 12000
+#define bfd_mach_mips16 16
+#define bfd_mach_mips5 5
+#define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32 32
+#define bfd_mach_mipsisa64 64
+ bfd_arch_i386, /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+#define bfd_mach_x86_64 3
+#define bfd_mach_x86_64_intel_syntax 4
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_i370, /* IBM 360/370 Mainframes */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ bfd_arch_h8300, /* Hitachi H8/300 */
+#define bfd_mach_h8300 1
+#define bfd_mach_h8300h 2
+#define bfd_mach_h8300s 3
+ bfd_arch_pdp11, /* DEC PDP-11 */
+ bfd_arch_powerpc, /* PowerPC */
+#define bfd_mach_ppc 0
+#define bfd_mach_ppc_403 403
+#define bfd_mach_ppc_403gc 4030
+#define bfd_mach_ppc_505 505
+#define bfd_mach_ppc_601 601
+#define bfd_mach_ppc_602 602
+#define bfd_mach_ppc_603 603
+#define bfd_mach_ppc_ec603e 6031
+#define bfd_mach_ppc_604 604
+#define bfd_mach_ppc_620 620
+#define bfd_mach_ppc_630 630
+#define bfd_mach_ppc_750 750
+#define bfd_mach_ppc_860 860
+#define bfd_mach_ppc_a35 35
+#define bfd_mach_ppc_rs64ii 642
+#define bfd_mach_ppc_rs64iii 643
+#define bfd_mach_ppc_7400 7400
+ bfd_arch_rs6000, /* IBM RS/6000 */
+#define bfd_mach_rs6k 0
+#define bfd_mach_rs6k_rs1 6001
+#define bfd_mach_rs6k_rsc 6003
+#define bfd_mach_rs6k_rs2 6002
+ bfd_arch_hppa, /* HP PA RISC */
+ bfd_arch_d10v, /* Mitsubishi D10V */
+#define bfd_mach_d10v 0
+#define bfd_mach_d10v_ts2 2
+#define bfd_mach_d10v_ts3 3
+ bfd_arch_d30v, /* Mitsubishi D30V */
+ bfd_arch_m68hc11, /* Motorola 68HC11 */
+ bfd_arch_m68hc12, /* Motorola 68HC12 */
+ bfd_arch_z8k, /* Zilog Z8000 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+#define bfd_mach_sh 0
+#define bfd_mach_sh2 0x20
+#define bfd_mach_sh_dsp 0x2d
+#define bfd_mach_sh3 0x30
+#define bfd_mach_sh3_dsp 0x3d
+#define bfd_mach_sh3e 0x3e
+#define bfd_mach_sh4 0x40
+ bfd_arch_alpha, /* Dec Alpha */
+#define bfd_mach_alpha_ev4 0x10
+#define bfd_mach_alpha_ev5 0x20
+#define bfd_mach_alpha_ev6 0x30
+ bfd_arch_arm, /* Advanced Risc Machines ARM */
+#define bfd_mach_arm_2 1
+#define bfd_mach_arm_2a 2
+#define bfd_mach_arm_3 3
+#define bfd_mach_arm_3M 4
+#define bfd_mach_arm_4 5
+#define bfd_mach_arm_4T 6
+#define bfd_mach_arm_5 7
+#define bfd_mach_arm_5T 8
+#define bfd_mach_arm_5TE 9
+#define bfd_mach_arm_XScale 10
+ bfd_arch_ns32k, /* National Semiconductors ns32000 */
+ bfd_arch_w65, /* WDC 65816 */
+ bfd_arch_tic30, /* Texas Instruments TMS320C30 */
+ bfd_arch_tic54x, /* Texas Instruments TMS320C54X */
+ bfd_arch_tic80, /* TI TMS320c80 (MVP) */
+ bfd_arch_v850, /* NEC V850 */
+#define bfd_mach_v850 0
+#define bfd_mach_v850e 'E'
+#define bfd_mach_v850ea 'A'
+ bfd_arch_arc, /* ARC Cores */
+#define bfd_mach_arc_5 0
+#define bfd_mach_arc_6 1
+#define bfd_mach_arc_7 2
+#define bfd_mach_arc_8 3
+ bfd_arch_m32r, /* Mitsubishi M32R/D */
+#define bfd_mach_m32r 0 /* backwards compatibility */
+#define bfd_mach_m32rx 'x'
+ bfd_arch_mn10200, /* Matsushita MN10200 */
+ bfd_arch_mn10300, /* Matsushita MN10300 */
+#define bfd_mach_mn10300 300
+#define bfd_mach_am33 330
+ bfd_arch_fr30,
+#define bfd_mach_fr30 0x46523330
+ bfd_arch_mcore,
+ bfd_arch_ia64, /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64 0
+#define bfd_mach_ia64_elf32 1
+ bfd_arch_pj,
+ bfd_arch_avr, /* Atmel AVR microcontrollers */
+#define bfd_mach_avr1 1
+#define bfd_mach_avr2 2
+#define bfd_mach_avr3 3
+#define bfd_mach_avr4 4
+#define bfd_mach_avr5 5
+ bfd_arch_cris, /* Axis CRIS */
+ bfd_arch_s390, /* IBM s390 */
+#define bfd_mach_s390_esa 0
+#define bfd_mach_s390_esame 1
+ bfd_arch_openrisc, /* OpenRISC */
+ bfd_arch_mmix, /* Donald Knuth's educational processor */
+ bfd_arch_xstormy16,
+#define bfd_mach_xstormy16 0
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ unsigned long mach;
+ const char *arch_name;
+ const char *printable_name;
+ unsigned int section_align_power;
+ /* True if this is the default machine for the architecture. */
+ boolean the_default;
+ const struct bfd_arch_info * (*compatible)
+ PARAMS ((const struct bfd_arch_info *a,
+ const struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+ const struct bfd_arch_info *next;
+} bfd_arch_info_type;
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ const bfd *abfd,
+ const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch PARAMS ((enum bfd_architecture
+ arch,
+ unsigned long machine));
+
+const char *
+bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+unsigned int
+bfd_octets_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_mach_octets_per_byte PARAMS ((enum bfd_architecture arch,
+ unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions */
+ bfd_reloc_continue,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_notsupported,
+
+ /* Unused */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ symbols. If this type is returned, the error_message argument
+ to bfd_perform_relocation will be set. */
+ bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+ /* A pointer into the canonical table of pointers */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section */
+ bfd_size_type address;
+
+ /* addend for relocation value */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation */
+ reloc_howto_type *howto;
+
+} arelent;
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+ /* The type field has mainly a documentary use - the back end can
+ do what it wants with it, though normally the back end's
+ external idea of what a reloc number is stored
+ in this field. For example, a PC relative word relocation
+ in a coff environment has the type 023 - because that's
+ what the outside world calls a R_PCRWORD reloc. */
+ unsigned int type;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ power-of-two measure. To get the number of bytes operated
+ on by a type of relocation, use bfd_get_reloc_size. */
+ int size;
+
+ /* The number of bits in the item to be relocated. This is used
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ called rather than the normal function. This allows really
+ strange relocation methods to be accomodated (e.g., i960 callj
+ instructions). */
+ bfd_reloc_status_type (*special_function)
+ PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
+ bfd *, char **));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* Some formats record a relocation addend in the section contents
+ rather than with the relocation. For ELF formats this is the
+ distinction between USE_REL and USE_RELA (though the code checks
+ for USE_REL == 1/0). The value of this field is TRUE if the
+ addend is recorded with the section contents; when performing a
+ partial link (ld -r) the section contents (the data) will be
+ modified. The value of this field is FALSE if addends are
+ recorded with the relocation (in arelent.addend); when performing
+ a partial link the relocation will be modified.
+ All relocations for all ELF USE_RELA targets should set this field
+ to FALSE (values of TRUE should be looked on with suspicion).
+ However, the converse is not true: not all relocations of all ELF
+ USE_REL targets set this field to TRUE. Why this is so is peculiar
+ to each particular target. For relocs that aren't used in partial
+ links (e.g. GOT stuff) it doesn't matter what this is set to. */
+ boolean partial_inplace;
+
+ /* The src_mask selects which parts of the read in data
+ are to be used in the relocation sum. E.g., if this was an 8 bit
+ byte of data which we read and relocated, this would be
+ 0x000000ff. When we have relocs which have an addend, such as
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* The dst_mask selects which parts of the instruction are replaced
+ into the instruction. In most cases src_mask == dst_mask,
+ except in the above special case, where dst_mask would be
+ 0x000000ff, and src_mask would be 0x00000000. */
+ bfd_vma dst_mask;
+
+ /* When some formats create PC relative instructions, they leave
+ the value of the pc of the place being relocated in the offset
+ slot of the instruction, so that a PC relative relocation can
+ be made just by adding in an ordinary offset (e.g., sun3 a.out).
+ Some formats leave the displacement part of an instruction
+ empty (e.g., m88k bcs); this flag signals the fact. */
+ boolean pcrel_offset;
+};
+#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC }
+#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \
+ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \
+ NAME, false, 0, 0, IN)
+
+#define EMPTY_HOWTO(C) \
+ HOWTO ((C), 0, 0, 0, false, 0, complain_overflow_dont, NULL, \
+ NULL, false, 0, 0, false)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *) NULL) \
+ { \
+ if (bfd_is_com_section (symbol->section)) \
+ { \
+ relocation = 0; \
+ } \
+ else \
+ { \
+ relocation = symbol->value; \
+ } \
+ } \
+ }
+unsigned int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain
+{
+ arelent relent;
+ struct relent_chain *next;
+} arelent_chain;
+bfd_reloc_status_type
+bfd_check_overflow PARAMS ((enum complain_overflow how,
+ unsigned int bitsize,
+ unsigned int rightshift,
+ unsigned int addrsize,
+ bfd_vma relocation));
+
+bfd_reloc_status_type
+bfd_perform_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+bfd_reloc_status_type
+bfd_install_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message));
+
+enum bfd_reloc_code_real {
+ _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_26,
+ BFD_RELOC_24,
+ BFD_RELOC_16,
+ BFD_RELOC_14,
+ BFD_RELOC_8,
+
+/* PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_12_PCREL,
+ BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+ BFD_RELOC_32_GOT_PCREL,
+ BFD_RELOC_16_GOT_PCREL,
+ BFD_RELOC_8_GOT_PCREL,
+ BFD_RELOC_32_GOTOFF,
+ BFD_RELOC_16_GOTOFF,
+ BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF,
+ BFD_RELOC_8_GOTOFF,
+ BFD_RELOC_64_PLT_PCREL,
+ BFD_RELOC_32_PLT_PCREL,
+ BFD_RELOC_24_PLT_PCREL,
+ BFD_RELOC_16_PLT_PCREL,
+ BFD_RELOC_8_PLT_PCREL,
+ BFD_RELOC_64_PLTOFF,
+ BFD_RELOC_32_PLTOFF,
+ BFD_RELOC_16_PLTOFF,
+ BFD_RELOC_LO16_PLTOFF,
+ BFD_RELOC_HI16_PLTOFF,
+ BFD_RELOC_HI16_S_PLTOFF,
+ BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+ BFD_RELOC_68K_GLOB_DAT,
+ BFD_RELOC_68K_JMP_SLOT,
+ BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_LO16_BASEREL,
+ BFD_RELOC_HI16_BASEREL,
+ BFD_RELOC_HI16_S_BASEREL,
+ BFD_RELOC_8_BASEREL,
+ BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+ BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+ BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_16_PCREL_S2,
+ BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC. */
+ BFD_RELOC_HI22,
+ BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register. These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+ BFD_RELOC_GPREL16,
+ BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+ BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations. There is probably some overlap with other
+relocation types already defined. */
+ BFD_RELOC_NONE,
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA16,
+ BFD_RELOC_SPARC_UA32,
+ BFD_RELOC_SPARC_UA64,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+ BFD_RELOC_SPARC_10,
+ BFD_RELOC_SPARC_11,
+ BFD_RELOC_SPARC_OLO10,
+ BFD_RELOC_SPARC_HH22,
+ BFD_RELOC_SPARC_HM10,
+ BFD_RELOC_SPARC_LM22,
+ BFD_RELOC_SPARC_PC_HH22,
+ BFD_RELOC_SPARC_PC_HM10,
+ BFD_RELOC_SPARC_PC_LM22,
+ BFD_RELOC_SPARC_WDISP16,
+ BFD_RELOC_SPARC_WDISP19,
+ BFD_RELOC_SPARC_7,
+ BFD_RELOC_SPARC_6,
+ BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+ BFD_RELOC_SPARC_PLT32,
+ BFD_RELOC_SPARC_PLT64,
+ BFD_RELOC_SPARC_HIX22,
+ BFD_RELOC_SPARC_LOX10,
+ BFD_RELOC_SPARC_H44,
+ BFD_RELOC_SPARC_M44,
+ BFD_RELOC_SPARC_L44,
+ BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+ BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol. The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+ BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs. The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+ BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+ BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol. The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references. The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch) */
+ BFD_RELOC_ALPHA_LITERAL,
+ BFD_RELOC_ALPHA_ELF_LITERAL,
+ BFD_RELOC_ALPHA_LITUSE,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+ BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_CODEADDR,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register. */
+ BFD_RELOC_ALPHA_GPREL_HI16,
+ BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+ BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+ BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+ BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+ BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result. If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+ BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+ BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+ BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+ BFD_RELOC_PCREL_LO16,
+
+/* Relocation against a MIPS literal section. */
+ BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+ BFD_RELOC_MIPS_GOT16,
+ BFD_RELOC_MIPS_CALL16,
+ BFD_RELOC_MIPS_GOT_HI16,
+ BFD_RELOC_MIPS_GOT_LO16,
+ BFD_RELOC_MIPS_CALL_HI16,
+ BFD_RELOC_MIPS_CALL_LO16,
+ BFD_RELOC_MIPS_SUB,
+ BFD_RELOC_MIPS_GOT_PAGE,
+ BFD_RELOC_MIPS_GOT_OFST,
+ BFD_RELOC_MIPS_GOT_DISP,
+ BFD_RELOC_MIPS_SHIFT5,
+ BFD_RELOC_MIPS_SHIFT6,
+ BFD_RELOC_MIPS_INSERT_A,
+ BFD_RELOC_MIPS_INSERT_B,
+ BFD_RELOC_MIPS_DELETE,
+ BFD_RELOC_MIPS_HIGHEST,
+ BFD_RELOC_MIPS_HIGHER,
+ BFD_RELOC_MIPS_SCN_DISP,
+ BFD_RELOC_MIPS_REL16,
+ BFD_RELOC_MIPS_RELGOT,
+ BFD_RELOC_MIPS_JALR,
+
+
+/* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ BFD_RELOC_386_GOTOFF,
+ BFD_RELOC_386_GOTPC,
+
+/* x86-64/elf relocations */
+ BFD_RELOC_X86_64_GOT32,
+ BFD_RELOC_X86_64_PLT32,
+ BFD_RELOC_X86_64_COPY,
+ BFD_RELOC_X86_64_GLOB_DAT,
+ BFD_RELOC_X86_64_JUMP_SLOT,
+ BFD_RELOC_X86_64_RELATIVE,
+ BFD_RELOC_X86_64_GOTPCREL,
+ BFD_RELOC_X86_64_32S,
+
+/* ns32k relocations */
+ BFD_RELOC_NS32K_IMM_8,
+ BFD_RELOC_NS32K_IMM_16,
+ BFD_RELOC_NS32K_IMM_32,
+ BFD_RELOC_NS32K_IMM_8_PCREL,
+ BFD_RELOC_NS32K_IMM_16_PCREL,
+ BFD_RELOC_NS32K_IMM_32_PCREL,
+ BFD_RELOC_NS32K_DISP_8,
+ BFD_RELOC_NS32K_DISP_16,
+ BFD_RELOC_NS32K_DISP_32,
+ BFD_RELOC_NS32K_DISP_8_PCREL,
+ BFD_RELOC_NS32K_DISP_16_PCREL,
+ BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* PDP11 relocations */
+ BFD_RELOC_PDP11_DISP_8_PCREL,
+ BFD_RELOC_PDP11_DISP_6_PCREL,
+
+/* Picojava relocs. Not all of these appear in object files. */
+ BFD_RELOC_PJ_CODE_HI16,
+ BFD_RELOC_PJ_CODE_LO16,
+ BFD_RELOC_PJ_CODE_DIR16,
+ BFD_RELOC_PJ_CODE_DIR32,
+ BFD_RELOC_PJ_CODE_REL16,
+ BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+ BFD_RELOC_PPC_B26,
+ BFD_RELOC_PPC_BA26,
+ BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_B16,
+ BFD_RELOC_PPC_B16_BRTAKEN,
+ BFD_RELOC_PPC_B16_BRNTAKEN,
+ BFD_RELOC_PPC_BA16,
+ BFD_RELOC_PPC_BA16_BRTAKEN,
+ BFD_RELOC_PPC_BA16_BRNTAKEN,
+ BFD_RELOC_PPC_COPY,
+ BFD_RELOC_PPC_GLOB_DAT,
+ BFD_RELOC_PPC_JMP_SLOT,
+ BFD_RELOC_PPC_RELATIVE,
+ BFD_RELOC_PPC_LOCAL24PC,
+ BFD_RELOC_PPC_EMB_NADDR32,
+ BFD_RELOC_PPC_EMB_NADDR16,
+ BFD_RELOC_PPC_EMB_NADDR16_LO,
+ BFD_RELOC_PPC_EMB_NADDR16_HI,
+ BFD_RELOC_PPC_EMB_NADDR16_HA,
+ BFD_RELOC_PPC_EMB_SDAI16,
+ BFD_RELOC_PPC_EMB_SDA2I16,
+ BFD_RELOC_PPC_EMB_SDA2REL,
+ BFD_RELOC_PPC_EMB_SDA21,
+ BFD_RELOC_PPC_EMB_MRKREF,
+ BFD_RELOC_PPC_EMB_RELSEC16,
+ BFD_RELOC_PPC_EMB_RELST_LO,
+ BFD_RELOC_PPC_EMB_RELST_HI,
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
+ BFD_RELOC_PPC64_HIGHER,
+ BFD_RELOC_PPC64_HIGHER_S,
+ BFD_RELOC_PPC64_HIGHEST,
+ BFD_RELOC_PPC64_HIGHEST_S,
+ BFD_RELOC_PPC64_TOC16_LO,
+ BFD_RELOC_PPC64_TOC16_HI,
+ BFD_RELOC_PPC64_TOC16_HA,
+ BFD_RELOC_PPC64_TOC,
+ BFD_RELOC_PPC64_PLTGOT16,
+ BFD_RELOC_PPC64_PLTGOT16_LO,
+ BFD_RELOC_PPC64_PLTGOT16_HI,
+ BFD_RELOC_PPC64_PLTGOT16_HA,
+ BFD_RELOC_PPC64_ADDR16_DS,
+ BFD_RELOC_PPC64_ADDR16_LO_DS,
+ BFD_RELOC_PPC64_GOT16_DS,
+ BFD_RELOC_PPC64_GOT16_LO_DS,
+ BFD_RELOC_PPC64_PLT16_LO_DS,
+ BFD_RELOC_PPC64_SECTOFF_DS,
+ BFD_RELOC_PPC64_SECTOFF_LO_DS,
+ BFD_RELOC_PPC64_TOC16_DS,
+ BFD_RELOC_PPC64_TOC16_LO_DS,
+ BFD_RELOC_PPC64_PLTGOT16_DS,
+ BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* IBM 370/390 relocations */
+ BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+ BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. */
+ BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BLX,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_ADRL_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_ADR_IMM,
+ BFD_RELOC_ARM_LDR_IMM,
+ BFD_RELOC_ARM_LITERAL,
+ BFD_RELOC_ARM_IN_POOL,
+ BFD_RELOC_ARM_OFFSET_IMM8,
+ BFD_RELOC_ARM_HWLITERAL,
+ BFD_RELOC_ARM_THUMB_ADD,
+ BFD_RELOC_ARM_THUMB_IMM,
+ BFD_RELOC_ARM_THUMB_SHIFT,
+ BFD_RELOC_ARM_THUMB_OFFSET,
+ BFD_RELOC_ARM_GOT12,
+ BFD_RELOC_ARM_GOT32,
+ BFD_RELOC_ARM_JUMP_SLOT,
+ BFD_RELOC_ARM_COPY,
+ BFD_RELOC_ARM_GLOB_DAT,
+ BFD_RELOC_ARM_PLT32,
+ BFD_RELOC_ARM_RELATIVE,
+ BFD_RELOC_ARM_GOTOFF,
+ BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs. Not all of these appear in object files. */
+ BFD_RELOC_SH_PCDISP8BY2,
+ BFD_RELOC_SH_PCDISP12BY2,
+ BFD_RELOC_SH_IMM4,
+ BFD_RELOC_SH_IMM4BY2,
+ BFD_RELOC_SH_IMM4BY4,
+ BFD_RELOC_SH_IMM8,
+ BFD_RELOC_SH_IMM8BY2,
+ BFD_RELOC_SH_IMM8BY4,
+ BFD_RELOC_SH_PCRELIMM8BY2,
+ BFD_RELOC_SH_PCRELIMM8BY4,
+ BFD_RELOC_SH_SWITCH16,
+ BFD_RELOC_SH_SWITCH32,
+ BFD_RELOC_SH_USES,
+ BFD_RELOC_SH_COUNT,
+ BFD_RELOC_SH_ALIGN,
+ BFD_RELOC_SH_CODE,
+ BFD_RELOC_SH_DATA,
+ BFD_RELOC_SH_LABEL,
+ BFD_RELOC_SH_LOOP_START,
+ BFD_RELOC_SH_LOOP_END,
+ BFD_RELOC_SH_COPY,
+ BFD_RELOC_SH_GLOB_DAT,
+ BFD_RELOC_SH_JMP_SLOT,
+ BFD_RELOC_SH_RELATIVE,
+ BFD_RELOC_SH_GOTPC,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
+be zero and is not stored in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BRANCH9,
+ BFD_RELOC_THUMB_PCREL_BRANCH12,
+ BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* ARC Cores relocs.
+ARC 22 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+ BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch. The lowest two bits must be zero and are not
+stored in the instruction. The high 24 bits are installed in bits 23
+through 0. */
+ BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+ BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+ BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the
+right 3 bitsassumed to be 0. */
+ BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+ BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+ BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+ BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+ BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+ BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+ BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+ BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+ BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+ BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+ BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+ BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+ BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+ BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+ BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+ BFD_RELOC_TIC30_LDP,
+
+/* This is a 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x. */
+ BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+ BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+ BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+ BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+ BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+ BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+ BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+ BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+ BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+ BFD_RELOC_MCORE_PCREL_IMM8BY4,
+ BFD_RELOC_MCORE_PCREL_IMM11BY2,
+ BFD_RELOC_MCORE_PCREL_IMM4BY2,
+ BFD_RELOC_MCORE_PCREL_32,
+ BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+ BFD_RELOC_MCORE_RVA,
+
+/* These are relocations for the GETA instruction. */
+ BFD_RELOC_MMIX_GETA,
+ BFD_RELOC_MMIX_GETA_1,
+ BFD_RELOC_MMIX_GETA_2,
+ BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction. */
+ BFD_RELOC_MMIX_CBRANCH,
+ BFD_RELOC_MMIX_CBRANCH_J,
+ BFD_RELOC_MMIX_CBRANCH_1,
+ BFD_RELOC_MMIX_CBRANCH_2,
+ BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction. */
+ BFD_RELOC_MMIX_PUSHJ,
+ BFD_RELOC_MMIX_PUSHJ_1,
+ BFD_RELOC_MMIX_PUSHJ_2,
+ BFD_RELOC_MMIX_PUSHJ_3,
+
+/* These are relocations for the JMP instruction. */
+ BFD_RELOC_MMIX_JMP,
+ BFD_RELOC_MMIX_JMP_1,
+ BFD_RELOC_MMIX_JMP_2,
+ BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch. */
+ BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction. */
+ BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255. */
+ BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register. */
+ BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation. */
+ BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register. It does not modify contents. */
+ BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits. */
+ BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits. */
+ BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits. */
+ BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits. */
+ BFD_RELOC_AVR_CALL,
+
+/* Direct 12 bit. */
+ BFD_RELOC_390_12,
+
+/* 12 bit GOT offset. */
+ BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime. */
+ BFD_RELOC_390_COPY,
+
+/* Create GOT entry. */
+ BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry. */
+ BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base. */
+ BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT. */
+ BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset. */
+ BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1. */
+ BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1. */
+ BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1. */
+ BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset. */
+ BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry. */
+ BFD_RELOC_390_GOTENT,
+
+/* These two relocations are used by the linker to determine which of
+the entries in a C++ virtual function table are actually used. When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table. The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry. The reloc's symbol should refer to the
+table of the class mentioned in the code. Off of that base, an offset
+describes the entry that is being used. For Rela hosts, this offset
+is stored in the reloc's addend. For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+ BFD_RELOC_VTABLE_INHERIT,
+ BFD_RELOC_VTABLE_ENTRY,
+
+/* Intel IA64 Relocations. */
+ BFD_RELOC_IA64_IMM14,
+ BFD_RELOC_IA64_IMM22,
+ BFD_RELOC_IA64_IMM64,
+ BFD_RELOC_IA64_DIR32MSB,
+ BFD_RELOC_IA64_DIR32LSB,
+ BFD_RELOC_IA64_DIR64MSB,
+ BFD_RELOC_IA64_DIR64LSB,
+ BFD_RELOC_IA64_GPREL22,
+ BFD_RELOC_IA64_GPREL64I,
+ BFD_RELOC_IA64_GPREL32MSB,
+ BFD_RELOC_IA64_GPREL32LSB,
+ BFD_RELOC_IA64_GPREL64MSB,
+ BFD_RELOC_IA64_GPREL64LSB,
+ BFD_RELOC_IA64_LTOFF22,
+ BFD_RELOC_IA64_LTOFF64I,
+ BFD_RELOC_IA64_PLTOFF22,
+ BFD_RELOC_IA64_PLTOFF64I,
+ BFD_RELOC_IA64_PLTOFF64MSB,
+ BFD_RELOC_IA64_PLTOFF64LSB,
+ BFD_RELOC_IA64_FPTR64I,
+ BFD_RELOC_IA64_FPTR32MSB,
+ BFD_RELOC_IA64_FPTR32LSB,
+ BFD_RELOC_IA64_FPTR64MSB,
+ BFD_RELOC_IA64_FPTR64LSB,
+ BFD_RELOC_IA64_PCREL21B,
+ BFD_RELOC_IA64_PCREL21BI,
+ BFD_RELOC_IA64_PCREL21M,
+ BFD_RELOC_IA64_PCREL21F,
+ BFD_RELOC_IA64_PCREL22,
+ BFD_RELOC_IA64_PCREL60B,
+ BFD_RELOC_IA64_PCREL64I,
+ BFD_RELOC_IA64_PCREL32MSB,
+ BFD_RELOC_IA64_PCREL32LSB,
+ BFD_RELOC_IA64_PCREL64MSB,
+ BFD_RELOC_IA64_PCREL64LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR22,
+ BFD_RELOC_IA64_LTOFF_FPTR64I,
+ BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+ BFD_RELOC_IA64_SEGREL32MSB,
+ BFD_RELOC_IA64_SEGREL32LSB,
+ BFD_RELOC_IA64_SEGREL64MSB,
+ BFD_RELOC_IA64_SEGREL64LSB,
+ BFD_RELOC_IA64_SECREL32MSB,
+ BFD_RELOC_IA64_SECREL32LSB,
+ BFD_RELOC_IA64_SECREL64MSB,
+ BFD_RELOC_IA64_SECREL64LSB,
+ BFD_RELOC_IA64_REL32MSB,
+ BFD_RELOC_IA64_REL32LSB,
+ BFD_RELOC_IA64_REL64MSB,
+ BFD_RELOC_IA64_REL64LSB,
+ BFD_RELOC_IA64_LTV32MSB,
+ BFD_RELOC_IA64_LTV32LSB,
+ BFD_RELOC_IA64_LTV64MSB,
+ BFD_RELOC_IA64_LTV64LSB,
+ BFD_RELOC_IA64_IPLTMSB,
+ BFD_RELOC_IA64_IPLTLSB,
+ BFD_RELOC_IA64_COPY,
+ BFD_RELOC_IA64_TPREL22,
+ BFD_RELOC_IA64_TPREL64MSB,
+ BFD_RELOC_IA64_TPREL64LSB,
+ BFD_RELOC_IA64_LTOFF_TP22,
+ BFD_RELOC_IA64_LTOFF22X,
+ BFD_RELOC_IA64_LDXMOV,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits high part of an absolute address. */
+ BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits low part of an absolute address. */
+ BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bits of a value. */
+ BFD_RELOC_M68HC11_3B,
+
+/* These relocs are only used within the CRIS assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_CRIS_BDISP8,
+ BFD_RELOC_CRIS_UNSIGNED_5,
+ BFD_RELOC_CRIS_SIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS. */
+ BFD_RELOC_CRIS_COPY,
+ BFD_RELOC_CRIS_GLOB_DAT,
+ BFD_RELOC_CRIS_JUMP_SLOT,
+ BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT. */
+ BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT. */
+ BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation. */
+ BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations. */
+ BFD_RELOC_860_COPY,
+ BFD_RELOC_860_GLOB_DAT,
+ BFD_RELOC_860_JUMP_SLOT,
+ BFD_RELOC_860_RELATIVE,
+ BFD_RELOC_860_PC26,
+ BFD_RELOC_860_PLT26,
+ BFD_RELOC_860_PC16,
+ BFD_RELOC_860_LOW0,
+ BFD_RELOC_860_SPLIT0,
+ BFD_RELOC_860_LOW1,
+ BFD_RELOC_860_SPLIT1,
+ BFD_RELOC_860_LOW2,
+ BFD_RELOC_860_SPLIT2,
+ BFD_RELOC_860_LOW3,
+ BFD_RELOC_860_LOGOT0,
+ BFD_RELOC_860_SPGOT0,
+ BFD_RELOC_860_LOGOT1,
+ BFD_RELOC_860_SPGOT1,
+ BFD_RELOC_860_LOGOTOFF0,
+ BFD_RELOC_860_SPGOTOFF0,
+ BFD_RELOC_860_LOGOTOFF1,
+ BFD_RELOC_860_SPGOTOFF1,
+ BFD_RELOC_860_LOGOTOFF2,
+ BFD_RELOC_860_LOGOTOFF3,
+ BFD_RELOC_860_LOPC,
+ BFD_RELOC_860_HIGHADJ,
+ BFD_RELOC_860_HAGOT,
+ BFD_RELOC_860_HAGOTOFF,
+ BFD_RELOC_860_HAPC,
+ BFD_RELOC_860_HIGH,
+ BFD_RELOC_860_HIGOT,
+ BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations. */
+ BFD_RELOC_OPENRISC_ABS_26,
+ BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations. */
+ BFD_RELOC_H8_DIR16A8,
+ BFD_RELOC_H8_DIR16R8,
+ BFD_RELOC_H8_DIR24A8,
+ BFD_RELOC_H8_DIR24R8,
+ BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations. */
+ BFD_RELOC_XSTORMY16_REL_12,
+ BFD_RELOC_XSTORMY16_24,
+ BFD_RELOC_XSTORMY16_FPTR16,
+ BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+ /* A pointer to the BFD which owns the symbol. This information
+ is necessary so that a back end can work out what additional
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+
+ struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+ /* The text of the symbol. The name is left alone, and not copied; the
+ application may not alter it. */
+ const char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol: */
+
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ value is the offset into the section of the data. */
+#define BSF_GLOBAL 0x02
+
+ /* The symbol has global scope and is exported. The value is
+ the offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* no real difference */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>> */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning, unless BSF_DEBUGGING_RELOC is also set. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. The name is a
+ warning. The name of the next symbol is the one to warn about;
+ if a reference is made to a symbol with the same name as the next
+ symbol, a warning is issued by the linker. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. This symbol is an indirect
+ pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ /* Symbol is from dynamic linking information. */
+#define BSF_DYNAMIC 0x8000
+
+ /* The symbol denotes a data object. Used in ELF, and perhaps
+ others someday. */
+#define BSF_OBJECT 0x10000
+
+ /* This symbol is a debugging symbol. The value is the offset
+ into the section of the data. BSF_DEBUGGING should be set
+ as well. */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+ flagword flags;
+
+ /* A pointer to the section to which this symbol is
+ relative. This will always be non NULL, there are special
+ sections for undefined and absolute symbols. */
+ struct sec *section;
+
+ /* Back end special data. */
+ union
+ {
+ PTR p;
+ bfd_vma i;
+ } udata;
+
+} asymbol;
+#define bfd_get_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+boolean
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+#define bfd_canonicalize_symtab(abfd, location) \
+ BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+ (abfd, location))
+boolean
+bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((bfd *abfd, PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+asymbol *
+_bfd_generic_make_empty_symbol PARAMS ((bfd *));
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+boolean
+bfd_is_undefined_symclass PARAMS ((int symclass));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+ (ibfd, isymbol, obfd, osymbol))
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ const char *filename;
+
+ /* A pointer to the target jump table. */
+ const struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+ *", and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ PTR iostream;
+
+ /* Is the file descriptor being cached? That is, can it be closed as
+ needed, and re-opened when accessed later? */
+
+ boolean cacheable;
+
+ /* Marks whether there was a default target specified when the
+ BFD was opened. This is used to select which matching algorithm
+ to use to choose the back end. */
+
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs */
+
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here: */
+
+ ufile_ptr where;
+
+ /* and here: (``once'' means at least once) */
+
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time: */
+
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true: */
+
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension.*/
+
+ int ifd;
+
+ /* The format which belongs to the BFD. (object, core, etc.) */
+
+ bfd_format format;
+
+ /* The direction the BFD was opened with*/
+
+ enum bfd_direction {no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3} direction;
+
+ /* Format_specific flags*/
+
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+
+ ufile_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ from happening. */
+ boolean output_has_begun;
+
+ /* A hash table for section names. */
+ struct bfd_hash_table section_htab;
+
+ /* Pointer to linked list of sections. */
+ struct sec *sections;
+
+ /* The place where we add to the section list. */
+ struct sec **section_tail;
+
+ /* The number of sections */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output*/
+ unsigned int symcount;
+
+ /* Symbol table for output BFD (with symcount entries) */
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information*/
+ const struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives:*/
+ PTR arelt_data;
+ struct _bfd *my_archive; /* The containing archive BFD. */
+ struct _bfd *next; /* The next BFD in the archive. */
+ struct _bfd *archive_head; /* The first BFD in the archive. */
+ boolean has_armap;
+
+ /* A chain of BFD structures involved in a link. */
+ struct _bfd *link_next;
+
+ /* A field used by _bfd_generic_link_add_archive_symbols. This will
+ be used only for archive elements. */
+ int archive_pass;
+
+ /* Used by the back end to hold private data. */
+
+ union
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct pe_tdata *pe_obj_data;
+ struct xcoff_tdata *xcoff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct ihex_data_struct *ihex_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct mmo_data_struct *mmo_data;
+ struct sun_core_struct *sun_core_data;
+ struct sco5_core_struct *sco5_core_data;
+ struct trad_core_struct *trad_core_data;
+ struct som_data_struct *som_data;
+ struct hpux_core_struct *hpux_core_data;
+ struct hppabsd_core_struct *hppabsd_core_data;
+ struct sgi_core_struct *sgi_core_data;
+ struct lynx_core_struct *lynx_core_data;
+ struct osf_core_struct *osf_core_data;
+ struct cisco_core_struct *cisco_core_data;
+ struct versados_data_struct *versados_data;
+ struct netbsd_core_struct *netbsd_core_data;
+ PTR any;
+ } tdata;
+
+ /* Used by the application to hold private data*/
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes. This is a
+ struct objalloc *, but we use PTR to avoid requiring the inclusion of
+ objalloc.h. */
+ PTR memory;
+};
+
+typedef enum bfd_error
+{
+ bfd_error_no_error = 0,
+ bfd_error_system_call,
+ bfd_error_invalid_target,
+ bfd_error_wrong_format,
+ bfd_error_wrong_object_format,
+ bfd_error_invalid_operation,
+ bfd_error_no_memory,
+ bfd_error_no_symbols,
+ bfd_error_no_armap,
+ bfd_error_no_more_archived_files,
+ bfd_error_malformed_archive,
+ bfd_error_file_not_recognized,
+ bfd_error_file_ambiguously_recognized,
+ bfd_error_no_contents,
+ bfd_error_nonrepresentable_section,
+ bfd_error_no_debug_section,
+ bfd_error_bad_value,
+ bfd_error_file_truncated,
+ bfd_error_file_too_big,
+ bfd_error_invalid_error_code
+} bfd_error_type;
+
+bfd_error_type
+bfd_get_error PARAMS ((void));
+
+void
+bfd_set_error PARAMS ((bfd_error_type error_tag));
+
+const char *
+bfd_errmsg PARAMS ((bfd_error_type error_tag));
+
+void
+bfd_perror PARAMS ((const char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+bfd_error_handler_type
+bfd_get_error_handler PARAMS ((void));
+
+const char *
+bfd_archive_filename PARAMS ((bfd *));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+void
+bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+
+ );
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+int
+bfd_get_arch_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_sign_extend_vma PARAMS ((bfd *abfd));
+
+boolean
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+bfd_set_gp_size PARAMS ((bfd *abfd, unsigned int i));
+
+bfd_vma
+bfd_scan_vma PARAMS ((const char *string, const char **end, int base));
+
+boolean
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+ BFD_SEND (abfd, _bfd_set_private_flags, \
+ (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_merge_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+ BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+ BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *,
+ boolean, asymbol **));
+
+boolean
+bfd_alt_mach_code PARAMS ((bfd *abfd, int index));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+const char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+ ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ ((*((bfd)->xvec->message)) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+enum bfd_flavour {
+ bfd_target_unknown_flavour,
+ bfd_target_aout_flavour,
+ bfd_target_coff_flavour,
+ bfd_target_ecoff_flavour,
+ bfd_target_xcoff_flavour,
+ bfd_target_elf_flavour,
+ bfd_target_ieee_flavour,
+ bfd_target_nlm_flavour,
+ bfd_target_oasys_flavour,
+ bfd_target_tekhex_flavour,
+ bfd_target_srec_flavour,
+ bfd_target_ihex_flavour,
+ bfd_target_som_flavour,
+ bfd_target_os9k_flavour,
+ bfd_target_versados_flavour,
+ bfd_target_msdos_flavour,
+ bfd_target_ovax_flavour,
+ bfd_target_evax_flavour,
+ bfd_target_mmo_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+/* Forward declaration. */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+ char *name;
+ enum bfd_flavour flavour;
+ enum bfd_endian byteorder;
+ enum bfd_endian header_byteorder;
+ flagword object_flags;
+ flagword section_flags;
+ char symbol_leading_char;
+ char ar_pad_char;
+ unsigned short ar_max_namelen;
+ bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+ boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+ boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Generic entry points. */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+CONCAT2 (NAME,_close_and_cleanup), \
+CONCAT2 (NAME,_bfd_free_cached_info), \
+CONCAT2 (NAME,_new_section_hook), \
+CONCAT2 (NAME,_get_section_contents), \
+CONCAT2 (NAME,_get_section_contents_in_window)
+
+ /* Called when the BFD is being closed to do any necessary cleanup. */
+ boolean (*_close_and_cleanup) PARAMS ((bfd *));
+ /* Ask the BFD to free all cached information. */
+ boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+ /* Called when a new section is created. */
+ boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+ /* Read the contents of a section. */
+ boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type));
+
+ /* Entry points to copy private data. */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+CONCAT2 (NAME,_bfd_copy_private_bfd_data), \
+CONCAT2 (NAME,_bfd_merge_private_bfd_data), \
+CONCAT2 (NAME,_bfd_copy_private_section_data), \
+CONCAT2 (NAME,_bfd_copy_private_symbol_data), \
+CONCAT2 (NAME,_bfd_set_private_flags), \
+CONCAT2 (NAME,_bfd_print_private_bfd_data) \
+ /* Called to copy BFD general private data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to merge BFD general private data from one object file
+ to a common output file when linking. */
+ boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to copy BFD private section data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+ bfd *, sec_ptr));
+ /* Called to copy BFD private symbol data from one symbol
+ to another. */
+ boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+ /* Called to set private backend flags */
+ boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+ /* Called to print private BFD data */
+ boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+ /* Core file entry points. */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+CONCAT2 (NAME,_core_file_failing_command), \
+CONCAT2 (NAME,_core_file_failing_signal), \
+CONCAT2 (NAME,_core_file_matches_executable_p)
+ char * (*_core_file_failing_command) PARAMS ((bfd *));
+ int (*_core_file_failing_signal) PARAMS ((bfd *));
+ boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+ /* Archive entry points. */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+CONCAT2 (NAME,_slurp_armap), \
+CONCAT2 (NAME,_slurp_extended_name_table), \
+CONCAT2 (NAME,_construct_extended_name_table), \
+CONCAT2 (NAME,_truncate_arname), \
+CONCAT2 (NAME,_write_armap), \
+CONCAT2 (NAME,_read_ar_hdr), \
+CONCAT2 (NAME,_openr_next_archived_file), \
+CONCAT2 (NAME,_get_elt_at_index), \
+CONCAT2 (NAME,_generic_stat_arch_elt), \
+CONCAT2 (NAME,_update_armap_timestamp)
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ boolean (*_bfd_construct_extended_name_table)
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, const char *, char *));
+ boolean (*write_armap)
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+ PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *, bfd *));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+ bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+ boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+ /* Entry points used for symbols. */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+CONCAT2 (NAME,_get_symtab_upper_bound), \
+CONCAT2 (NAME,_get_symtab), \
+CONCAT2 (NAME,_make_empty_symbol), \
+CONCAT2 (NAME,_print_symbol), \
+CONCAT2 (NAME,_get_symbol_info), \
+CONCAT2 (NAME,_bfd_is_local_label_name), \
+CONCAT2 (NAME,_get_lineno), \
+CONCAT2 (NAME,_find_nearest_line), \
+CONCAT2 (NAME,_bfd_make_debug_symbol), \
+CONCAT2 (NAME,_read_minisymbols), \
+CONCAT2 (NAME,_minisymbol_to_symbol)
+ long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+ long (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+ struct symbol_cache_entry *
+ (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+ void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ struct symbol_cache_entry *,
+ symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+ boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+ alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+ boolean (*_bfd_find_nearest_line)
+ PARAMS ((bfd *, struct sec *, struct symbol_cache_entry **, bfd_vma,
+ const char **, const char **, unsigned int *));
+ /* Back-door to allow format-aware applications to create debug symbols
+ while using BFD for everything else. Currently used by the assembler
+ when creating COFF files. */
+ asymbol *(*_bfd_make_debug_symbol) PARAMS ((bfd *, void *,
+ unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+ BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+ long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+ unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+ asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+ /* Routines for relocs. */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+CONCAT2 (NAME,_get_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_reloc), \
+CONCAT2 (NAME,_bfd_reloc_type_lookup)
+ long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+ long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+ struct symbol_cache_entry **));
+ /* See documentation on reloc types. */
+ reloc_howto_type *
+ (*reloc_type_lookup) PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+ /* Routines used when writing an object file. */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+CONCAT2 (NAME,_set_arch_mach), \
+CONCAT2 (NAME,_set_section_contents)
+ boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+ boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+
+ /* Routines used by the linker. */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+CONCAT2 (NAME,_sizeof_headers), \
+CONCAT2 (NAME,_bfd_get_relocated_section_contents), \
+CONCAT2 (NAME,_bfd_relax_section), \
+CONCAT2 (NAME,_bfd_link_hash_table_create), \
+CONCAT2 (NAME,_bfd_link_add_symbols), \
+CONCAT2 (NAME,_bfd_final_link), \
+CONCAT2 (NAME,_bfd_link_split_section), \
+CONCAT2 (NAME,_bfd_gc_sections), \
+CONCAT2 (NAME,_bfd_merge_sections)
+ int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+ bfd_byte *(*_bfd_get_relocated_section_contents)
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, struct symbol_cache_entry **));
+
+ boolean (*_bfd_relax_section)
+ PARAMS ((bfd *, struct sec *, struct bfd_link_info *, boolean *));
+
+ /* Create a hash table for the linker. Different backends store
+ different information in this table. */
+ struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+ /* Add symbols from this object file into the hash table. */
+ boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Do a link based on the link_order structures attached to each
+ section of the BFD. */
+ boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Should this section be split up into smaller pieces during linking. */
+ boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+ /* Remove sections that are not referenced from the output. */
+ boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Attempt to merge SEC_MERGE sections. */
+ boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Routines to handle dynamic symbols and relocs. */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+CONCAT2 (NAME,_get_dynamic_symtab_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_symtab), \
+CONCAT2 (NAME,_get_dynamic_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_reloc)
+ /* Get the amount of memory required to hold the dynamic symbols. */
+ long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic symbols. */
+ long (*_bfd_canonicalize_dynamic_symtab)
+ PARAMS ((bfd *, struct symbol_cache_entry **));
+ /* Get the amount of memory required to hold the dynamic relocs. */
+ long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic relocs. */
+ long (*_bfd_canonicalize_dynamic_reloc)
+ PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+ /* Opposite endian version of this target. */
+ const struct bfd_target * alternative_target;
+
+ PTR backend_data;
+
+} bfd_target;
+boolean
+bfd_set_default_target PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((const char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target *
+bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+const char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gnu/usr.bin/binutils/libbfd/powerpc/bfd.h b/gnu/usr.bin/binutils/libbfd/powerpc/bfd.h
new file mode 100644
index 0000000..584882f
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/powerpc/bfd.h
@@ -0,0 +1,3918 @@
+/* $FreeBSD$ */
+
+/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
+ generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+ "section.c", "archures.c", "reloc.c", "syms.c", "bfd.c", "archive.c",
+ "corefile.c", "targets.c" and "format.c".
+ Run "make headers" in your build bfd/ to regenerate. */
+
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+#include "symcat.h"
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This hack is to avoid a problem with some strict ANSI C preprocessors.
+ The problem is, "32_" is not a valid preprocessing token, and we don't
+ want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will
+ cause the inner CONCAT2 macros to be evaluated first, producing
+ still-valid pp-tokens. Then the final concatenation can be done. */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* #define BFD_VERSION 212000000 */
+/* #define BFD_VERSION_DATE 20020309 */
+/* #define BFD_VERSION_STRING "2.12" */
+
+/* The word size used by BFD on the host. This may be 64 with a 32
+ bit target if the host is 64 bit, or if other 64 bit targets have
+ been selected with --enable-targets, or if --enable-64-bit-bfd. */
+#define BFD_ARCH_SIZE 32
+
+/* The word size of the default bfd target. */
+#define BFD_DEFAULT_TARGET_SIZE 32
+
+#if defined(__alpha__) || defined(__sparc64__)
+#define BFD_HOST_64BIT_LONG 1
+#else
+#define BFD_HOST_64BIT_LONG 0
+#endif /* 64-bit host */
+#if 0
+#define BFD_HOST_64_BIT
+#define BFD_HOST_U_64_BIT
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* Forward declaration. */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+/* And even worse if your compiler provides a stdbool.h that conflicts
+ with these definitions... gcc 2.95 and later do. If so, it must
+ be included first. -drow */
+#if defined (__GNUG__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+#define TRUE_FALSE_ALREADY_DEFINED
+#else
+#if defined (__bool_true_false_are_defined)
+/* We have <stdbool.h>. */
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, BFD_HOST_64_BIT must be
+ defined above. */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+# define BFD_HOST_64_BIT long
+# define BFD_HOST_U_64_BIT unsigned long
+# else
+# ifdef __GNUC__
+# if __GNUC__ >= 2
+# define BFD_HOST_64_BIT long long
+# define BFD_HOST_U_64_BIT unsigned long long
+# endif /* __GNUC__ >= 2 */
+# endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf (s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf (s, "%08lx", x)
+
+#endif /* not BFD64 */
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef bfd_signed_vma file_ptr;
+typedef bfd_vma ufile_ptr;
+
+extern void bfd_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
+extern void bfd_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/* File formats. */
+
+typedef enum bfd_format
+{
+ bfd_unknown = 0, /* File format is unknown. */
+ bfd_object, /* Linker/assember/compiler output. */
+ bfd_archive, /* Object archive file. */
+ bfd_core, /* Core dump. */
+ bfd_type_end /* Marks the end; don't use it! */
+}
+bfd_format;
+
+/* Values that may appear in the flags field of a BFD. These also
+ appear in the object_flags field of the bfd_target structure, where
+ they indicate the set of flags used by that backend (not all flags
+ are meaningful for all object file formats) (FIXME: at the moment,
+ the object_flags values have mostly just been copied from backend
+ to another, and are not necessarily correct). */
+
+/* No flags. */
+#define BFD_NO_FLAGS 0x00
+
+/* BFD contains relocation entries. */
+#define HAS_RELOC 0x01
+
+/* BFD is directly executable. */
+#define EXEC_P 0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+ COFF header). */
+#define HAS_LINENO 0x04
+
+/* BFD has debugging information. */
+#define HAS_DEBUG 0x08
+
+/* BFD has symbols. */
+#define HAS_SYMS 0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+ header). */
+#define HAS_LOCALS 0x20
+
+/* BFD is a dynamic object. */
+#define DYNAMIC 0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+ like an a.out NMAGIC file) (the linker sets this by default, but
+ clears it for -r or -N). */
+#define WP_TEXT 0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+ linker sets this by default, but clears it for -r or -n or -N). */
+#define D_PAGED 0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+ do something) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+ traditional format. For example, this is used to request that when
+ writing out an a.out object the symbols not be hashed to eliminate
+ duplicates. */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* Symbols and relocation. */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+ target specific parts are in libcoff.h, libaout.h, etc. */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol. */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym
+{
+ char *name;
+ file_ptr file_offset; /* Look here to find the file. */
+}
+carsym; /* To make these you call a carsymogen. */
+
+/* Used in generating armaps (archive tables of contents).
+ Perhaps just a forward definition would do? */
+struct orl /* Output ranlib. */
+{
+ char **name; /* Symbol name. */
+ union
+ {
+ file_ptr pos;
+ bfd *abfd;
+ } u; /* bfd* or file position. */
+ int namidx; /* Index into string table. */
+};
+
+/* Linenumber stuff. */
+typedef struct lineno_cache_entry
+{
+ unsigned int line_number; /* Linenumber from start of function. */
+ union
+ {
+ struct symbol_cache_entry *sym; /* Function name. */
+ bfd_vma offset; /* Offset into section. */
+ } u;
+}
+alent;
+
+/* Object and core file sections. */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ const char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ const char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines. There is no way to free up a hash table. */
+
+/* An element in the hash table. Most uses will actually use a larger
+ structure, and an instance of this will be the first field. */
+
+struct bfd_hash_entry
+{
+ /* Next entry for this hash code. */
+ struct bfd_hash_entry *next;
+ /* String being hashed. */
+ const char *string;
+ /* Hash code. This is the full hash code, not the index into the
+ table. */
+ unsigned long hash;
+};
+
+/* A hash table. */
+
+struct bfd_hash_table
+{
+ /* The hash array. */
+ struct bfd_hash_entry **table;
+ /* The number of slots in the hash table. */
+ unsigned int size;
+ /* A function used to create new elements in the hash table. The
+ first entry is itself a pointer to an element. When this
+ function is first invoked, this pointer will be NULL. However,
+ having the pointer permits a hierarchy of method functions to be
+ built each of which calls the function in the superclass. Thus
+ each function should be written to allocate a new block of memory
+ only if the argument is NULL. */
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+ /* An objalloc for this hash table. This is a struct objalloc *,
+ but we use PTR to avoid requiring the inclusion of objalloc.h. */
+ PTR memory;
+};
+
+/* Initialize a hash table. */
+extern boolean bfd_hash_table_init
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+
+/* Initialize a hash table specifying a size. */
+extern boolean bfd_hash_table_init_n
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int size));
+
+/* Free up a hash table. */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table. If CREATE is true, a new entry
+ will be created for this string if one does not already exist. The
+ COPY argument must be true if this routine should copy the string
+ into newly allocated memory when adding an entry. */
+extern struct bfd_hash_entry *bfd_hash_lookup
+ PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+ boolean copy));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry. */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Grab some space for a hash table entry. */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+ unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+ element. If the function returns false, the traversal stops. The
+ INFO argument is passed to the function. */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+ boolean (*) (struct bfd_hash_entry *,
+ PTR),
+ PTR info));
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities. */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_bread PARAMS ((PTR, bfd_size_type, bfd *));
+extern bfd_size_type bfd_bwrite PARAMS ((const PTR, bfd_size_type, bfd *));
+extern int bfd_seek PARAMS ((bfd *, file_ptr, int));
+extern ufile_ptr bfd_tell PARAMS ((bfd *));
+extern int bfd_flush PARAMS ((bfd *));
+extern int bfd_stat PARAMS ((bfd *, struct stat *));
+
+/* Deprecated old routines. */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated
+ PARAMS ((const char *, const char *, int, const char *));
+
+/* Cast from const char * to char * so that caller can assign to
+ a char * without a warning. */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_family_coff(abfd) \
+ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean) (bool)), true)
+
+extern boolean bfd_cache_close PARAMS ((bfd *abfd));
+/* NB: This declaration should match the autogenerated one in libbfd.h. */
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+bfd_vma bfd_getb64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb16 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void bfd_putb64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb16 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl16 PARAMS ((bfd_vma, unsigned char *));
+
+/* Byte swapping routines which take size and endiannes as arguments. */
+
+bfd_vma bfd_get_bits PARAMS ((bfd_byte *, int, boolean));
+void bfd_put_bits PARAMS ((bfd_vma, bfd_byte *, int, boolean));
+
+/* Externally visible ECOFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+ PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+ unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+ PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ bfd *input_bfd, struct ecoff_debug_info *input_debug,
+ const struct ecoff_debug_swap *input_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ boolean relocateable,
+ boolean (*get_extr) (struct symbol_cache_entry *,
+ struct ecoff_extr *),
+ void (*set_index) (struct symbol_cache_entry *,
+ bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+ PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+ PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Return an upper bound on the number of bytes required to store a
+ copy of ABFD's program header table entries. Return -1 if an error
+ occurs; bfd_get_error will return an appropriate code. */
+extern long bfd_get_elf_phdr_upper_bound PARAMS ((bfd *abfd));
+
+/* Copy ABFD's program header table entries to *PHDRS. The entries
+ will be stored as an array of Elf_Internal_Phdr structures, as
+ defined in include/elf/internal.h. To find out how large the
+ buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+ Return the number of program header table entries read, or -1 if an
+ error occurs; bfd_get_error will return an appropriate code. */
+extern int bfd_get_elf_phdrs PARAMS ((bfd *abfd, void *phdrs));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf. */
+extern int bfd_get_arch_size PARAMS ((bfd *));
+
+/* Return true if address "naturally" sign extends, or -1 if not elf. */
+extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+
+extern boolean bfd_m68k_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+extern boolean bfd_mips_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+ struct sec **));
+
+/* Linux shared library support routines for the linker. */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window
+{
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+}
+bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *, unsigned int));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+extern boolean bfd_xcoff_link_generate_rtinit
+ PARAMS ((bfd *, const char *, const char *));
+
+/* Externally visible COFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+ PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+ PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+ PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+extern boolean bfd_m68k_coff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* PE ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_pe_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_pe_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_pe_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support. Called from linker. */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* TI COFF load page support. */
+extern void bfd_ticoff_set_section_load_page
+ PARAMS ((struct sec *, int));
+
+extern int bfd_ticoff_get_section_load_page
+ PARAMS ((struct sec *));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((const char *filename, const char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((const char *filename, const char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((const char *filename, const char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((const char *filename, bfd *templ));
+
+boolean
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+/* Byte swapping macros for user section data. */
+
+#define bfd_put_8(abfd, val, ptr) \
+ ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val)))
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr) \
+ ( (bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \
+ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \
+ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \
+ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \
+ : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr) \
+ ( (bits) == 8 ? bfd_put_8 (abfd, val, ptr) \
+ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \
+ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \
+ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \
+ : (abort (), (void) 0))
+
+
+/* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx16, (val, ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx16, (ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx32, (val, ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx32, (ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx64, (val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx64, (ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr))
+
+/* Refinements on the above, which should eventually go away. Save
+ cluttering the source with (bfd_vma) and (bfd_byte *) casts. */
+
+#define H_PUT_64(abfd, val, where) \
+ bfd_h_put_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_32(abfd, val, where) \
+ bfd_h_put_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_16(abfd, val, where) \
+ bfd_h_put_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_8 bfd_h_put_8
+
+#define H_PUT_S64(abfd, val, where) \
+ bfd_h_put_signed_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S32(abfd, val, where) \
+ bfd_h_put_signed_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S16(abfd, val, where) \
+ bfd_h_put_signed_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S8 bfd_h_put_signed_8
+
+#define H_GET_64(abfd, where) \
+ bfd_h_get_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_32(abfd, where) \
+ bfd_h_get_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_16(abfd, where) \
+ bfd_h_get_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_8 bfd_h_get_8
+
+#define H_GET_S64(abfd, where) \
+ bfd_h_get_signed_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S32(abfd, where) \
+ bfd_h_get_signed_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S16(abfd, where) \
+ bfd_h_get_signed_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S8 bfd_h_get_signed_8
+
+
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+typedef struct sec
+{
+ /* The name of the section; the name isn't a copy, the pointer is
+ the same as that passed to bfd_make_section. */
+ const char *name;
+
+ /* A unique sequence number. */
+ int id;
+
+ /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */
+ int index;
+
+ /* The next section in the list belonging to the BFD, or NULL. */
+ struct sec *next;
+
+ /* The field flags contains attributes of the section. Some
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* Tells the OS to allocate space for this section when loading.
+ This is clear for a section containing debug information only. */
+#define SEC_ALLOC 0x001
+
+ /* Tells the OS to load the section from the file when loading.
+ This is clear for a .bss section. */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there is
+ some relocation information too. */
+#define SEC_RELOC 0x004
+
+ /* ELF reserves 4 processor specific bits and 8 operating system
+ specific bits in sh_flags; at present we can get away with just
+ one in communicating between the assembler and BFD, but this
+ isn't a good long-term solution. */
+#define SEC_ARCH_BIT_0 0x008
+
+ /* A signal to the OS that the section contains read only data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+ the symbol to it, and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constructor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker to not output the section
+ even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a COFF shared library section. This flag is
+ only for the linker. If this type of section appears in
+ the input file, the linker must copy it to the output file
+ without changing the vma or size. FIXME: Although this
+ was originally intended to be general, it really is COFF
+ specific (and the flag was renamed to indicate this). It
+ might be cleaner to have some more general mechanism to
+ allow the back end to control what the linker does with
+ sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+ /* The section has GOT references. This flag is only for the
+ linker, and is currently only used by the elf32-hppa back end.
+ It will be set if global offset table references were detected
+ in this section, which indicate to the linker that the section
+ contains PIC code, and must be handled specially when doing a
+ static link. */
+#define SEC_HAS_GOT_REF 0x4000
+
+ /* The section contains common symbols (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* The contents of this section are held in memory pointed to
+ by the contents field. This is checked by bfd_get_section_contents,
+ and the data is retrieved from memory if appropriate. */
+#define SEC_IN_MEMORY 0x20000
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted based on the sum of
+ the symbol and addend values specified by the associated relocation
+ entries. Entries without associated relocation entries will be
+ appended to the end of the section in an unspecified order. */
+#define SEC_SORT_ENTRIES 0x80000
+
+ /* When linking, duplicate sections of the same name should be
+ discarded, rather than being combined into a single section as
+ is usually done. This is similar to how common symbols are
+ handled. See SEC_LINK_DUPLICATES below. */
+#define SEC_LINK_ONCE 0x100000
+
+ /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+ should handle duplicate sections. */
+#define SEC_LINK_DUPLICATES 0x600000
+
+ /* This value for SEC_LINK_DUPLICATES means that duplicate
+ sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if there are any duplicate sections, although
+ it should still only link one copy. */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections are a different size. */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections contain different
+ contents. */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+ /* This section was created by the linker as part of dynamic
+ relocation or other arcane processing. It is skipped when
+ going through the first-pass output, trusting that someone
+ else up the line will take care of it later. */
+#define SEC_LINKER_CREATED 0x800000
+
+ /* This section should not be subject to garbage collection. */
+#define SEC_KEEP 0x1000000
+
+ /* This section contains "short" data, and should be placed
+ "near" the GP. */
+#define SEC_SMALL_DATA 0x2000000
+
+ /* This section contains data which may be shared with other
+ executables or shared objects. */
+#define SEC_SHARED 0x4000000
+
+ /* When a section with this flag is being linked, then if the size of
+ the input section is less than a page, it should not cross a page
+ boundary. If the size of the input section is one page or more, it
+ should be aligned on a page boundary. */
+#define SEC_BLOCK 0x8000000
+
+ /* Conditionally link this section; do not link if there are no
+ references found to any symbol in the section. */
+#define SEC_CLINK 0x10000000
+
+ /* Attempt to merge identical entities in the section.
+ Entity size is given in the entsize field. */
+#define SEC_MERGE 0x20000000
+
+ /* If given with SEC_MERGE, entities to merge are zero terminated
+ strings where entsize specifies character size instead of fixed
+ size entries. */
+#define SEC_STRINGS 0x40000000
+
+ /* This section contains data about section groups. */
+#define SEC_GROUP 0x80000000
+
+ /* End of section flags. */
+
+ /* Some internal packed boolean fields. */
+
+ /* See the vma field. */
+ unsigned int user_set_vma : 1;
+
+ /* Whether relocations have been processed. */
+ unsigned int reloc_done : 1;
+
+ /* A mark flag used by some of the linker backends. */
+ unsigned int linker_mark : 1;
+
+ /* Another mark flag used by some of the linker backends. Set for
+ output sections that have an input section. */
+ unsigned int linker_has_input : 1;
+
+ /* A mark flag used by some linker backends for garbage collection. */
+ unsigned int gc_mark : 1;
+
+ /* Used by the ELF code to mark sections which have been allocated
+ to segments. */
+ unsigned int segment_mark : 1;
+
+ /* End of internal packed boolean fields. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+ bfd_vma vma;
+
+ /* The load address of the section - where it would be in a
+ rom image; really only used for writing section header
+ information. */
+ bfd_vma lma;
+
+ /* The size of the section in octets, as it will be output.
+ Contains a value even if the section has no contents (e.g., the
+ size of <<.bss>>). This will be filled in after relocation. */
+ bfd_size_type _cooked_size;
+
+ /* The original size on disk of the section, in octets. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset in *bytes* into the output section of the first byte in the
+ input section (byte ==> smallest addressable unit on the
+ target). In most cases, if this was going to start at the
+ 100th octet (8-bit quantity) in the output section, this value
+ would be 100. However, if the target byte size is 16 bits
+ (bfd_octets_per_byte is "2"), this value would be 50. */
+ bfd_vma output_offset;
+
+ /* The output section through which to map on output. */
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent of 2 -
+ e.g., 3 aligns to 2^3 (or 8). */
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above. */
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data. */
+ file_ptr filepos;
+
+ /* File position of relocation info. */
+ file_ptr rel_filepos;
+
+ /* File position of line data. */
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications. */
+ PTR userdata;
+
+ /* If the SEC_IN_MEMORY flag is set, this points to the actual
+ contents. */
+ unsigned char *contents;
+
+ /* Attached line number information. */
+ alent *lineno;
+
+ /* Number of line number records. */
+ unsigned int lineno_count;
+
+ /* Entity size for merging purposes. */
+ unsigned int entsize;
+
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct bfd_comdat_info *comdat;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out. */
+ file_ptr moving_line_filepos;
+
+ /* What the section number is in the target world. */
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+ bfd *owner;
+
+ /* A symbol which points at this section only. */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ struct bfd_link_order *link_order_head;
+ struct bfd_link_order *link_order_tail;
+} asection;
+
+/* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. New code should use the section_ptr macros rather
+ than referring directly to the const sections. The const sections
+ may eventually vanish. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* The absolute section. */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+/* Pointer to the undefined section. */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+/* Pointer to the common section. */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section. */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC) \
+ ( ((SEC) == bfd_abs_section_ptr) \
+ || ((SEC) == bfd_und_section_ptr) \
+ || ((SEC) == bfd_com_section_ptr) \
+ || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+ ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \
+ : (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section)->reloc_done ? (section)->_cooked_size \
+ : (abort (), (bfd_size_type) 1))
+
+/* Macros to handle insertion and deletion of a bfd's sections. These
+ only handle the list pointers, ie. do not adjust section_count,
+ target_index etc. */
+#define bfd_section_list_remove(ABFD, PS) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = *_ps; \
+ *_ps = _s->next; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = _ps; \
+ } \
+ while (0)
+#define bfd_section_list_insert(ABFD, PS, S) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = S; \
+ _s->next = *_ps; \
+ *_ps = _s; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = &_s->next; \
+ } \
+ while (0)
+
+void
+bfd_section_list_clear PARAMS ((bfd *));
+
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, const char *name));
+
+char *
+bfd_get_unique_section_name PARAMS ((bfd *abfd,
+ const char *templat,
+ int *count));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, const char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func) (bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR data, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_get_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec,
+ bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+ BFD_SEND (obfd, _bfd_copy_private_section_data, \
+ (ibfd, isection, obfd, osection))
+void
+_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
+
+enum bfd_architecture
+{
+ bfd_arch_unknown, /* File arch not known. */
+ bfd_arch_obscure, /* Arch known, not one of these. */
+ bfd_arch_m68k, /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32 8
+#define bfd_mach_mcf5200 9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307 11
+#define bfd_mach_mcf5407 12
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+#define bfd_mach_i960_jx 7
+#define bfd_mach_i960_hx 8
+
+ bfd_arch_or32, /* OpenRISC 32 */
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+#define bfd_mach_sparc 1
+/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
+#define bfd_mach_sparc_sparclet 2
+#define bfd_mach_sparc_sparclite 3
+#define bfd_mach_sparc_v8plus 4
+#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_sparclite_le 6
+#define bfd_mach_sparc_v9 7
+#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
+#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
+/* Nonzero if MACH has the v9 instruction set. */
+#define bfd_mach_sparc_v9_p(mach) \
+ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
+ && (mach) != bfd_mach_sparc_sparclite_le)
+ bfd_arch_mips, /* MIPS Rxxxx */
+#define bfd_mach_mips3000 3000
+#define bfd_mach_mips3900 3900
+#define bfd_mach_mips4000 4000
+#define bfd_mach_mips4010 4010
+#define bfd_mach_mips4100 4100
+#define bfd_mach_mips4111 4111
+#define bfd_mach_mips4300 4300
+#define bfd_mach_mips4400 4400
+#define bfd_mach_mips4600 4600
+#define bfd_mach_mips4650 4650
+#define bfd_mach_mips5000 5000
+#define bfd_mach_mips6000 6000
+#define bfd_mach_mips8000 8000
+#define bfd_mach_mips10000 10000
+#define bfd_mach_mips12000 12000
+#define bfd_mach_mips16 16
+#define bfd_mach_mips5 5
+#define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32 32
+#define bfd_mach_mipsisa64 64
+ bfd_arch_i386, /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+#define bfd_mach_x86_64 3
+#define bfd_mach_x86_64_intel_syntax 4
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_i370, /* IBM 360/370 Mainframes */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ bfd_arch_h8300, /* Hitachi H8/300 */
+#define bfd_mach_h8300 1
+#define bfd_mach_h8300h 2
+#define bfd_mach_h8300s 3
+ bfd_arch_pdp11, /* DEC PDP-11 */
+ bfd_arch_powerpc, /* PowerPC */
+#define bfd_mach_ppc 0
+#define bfd_mach_ppc64 1
+#define bfd_mach_ppc_403 403
+#define bfd_mach_ppc_403gc 4030
+#define bfd_mach_ppc_505 505
+#define bfd_mach_ppc_601 601
+#define bfd_mach_ppc_602 602
+#define bfd_mach_ppc_603 603
+#define bfd_mach_ppc_ec603e 6031
+#define bfd_mach_ppc_604 604
+#define bfd_mach_ppc_620 620
+#define bfd_mach_ppc_630 630
+#define bfd_mach_ppc_750 750
+#define bfd_mach_ppc_860 860
+#define bfd_mach_ppc_a35 35
+#define bfd_mach_ppc_rs64ii 642
+#define bfd_mach_ppc_rs64iii 643
+#define bfd_mach_ppc_7400 7400
+ bfd_arch_rs6000, /* IBM RS/6000 */
+#define bfd_mach_rs6k 0
+#define bfd_mach_rs6k_rs1 6001
+#define bfd_mach_rs6k_rsc 6003
+#define bfd_mach_rs6k_rs2 6002
+ bfd_arch_hppa, /* HP PA RISC */
+ bfd_arch_d10v, /* Mitsubishi D10V */
+#define bfd_mach_d10v 0
+#define bfd_mach_d10v_ts2 2
+#define bfd_mach_d10v_ts3 3
+ bfd_arch_d30v, /* Mitsubishi D30V */
+ bfd_arch_m68hc11, /* Motorola 68HC11 */
+ bfd_arch_m68hc12, /* Motorola 68HC12 */
+ bfd_arch_z8k, /* Zilog Z8000 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+#define bfd_mach_sh 0
+#define bfd_mach_sh2 0x20
+#define bfd_mach_sh_dsp 0x2d
+#define bfd_mach_sh3 0x30
+#define bfd_mach_sh3_dsp 0x3d
+#define bfd_mach_sh3e 0x3e
+#define bfd_mach_sh4 0x40
+#define bfd_mach_sh5 0x50
+ bfd_arch_alpha, /* Dec Alpha */
+#define bfd_mach_alpha_ev4 0x10
+#define bfd_mach_alpha_ev5 0x20
+#define bfd_mach_alpha_ev6 0x30
+ bfd_arch_arm, /* Advanced Risc Machines ARM. */
+#define bfd_mach_arm_2 1
+#define bfd_mach_arm_2a 2
+#define bfd_mach_arm_3 3
+#define bfd_mach_arm_3M 4
+#define bfd_mach_arm_4 5
+#define bfd_mach_arm_4T 6
+#define bfd_mach_arm_5 7
+#define bfd_mach_arm_5T 8
+#define bfd_mach_arm_5TE 9
+#define bfd_mach_arm_XScale 10
+ bfd_arch_ns32k, /* National Semiconductors ns32000 */
+ bfd_arch_w65, /* WDC 65816 */
+ bfd_arch_tic30, /* Texas Instruments TMS320C30 */
+ bfd_arch_tic54x, /* Texas Instruments TMS320C54X */
+ bfd_arch_tic80, /* TI TMS320c80 (MVP) */
+ bfd_arch_v850, /* NEC V850 */
+#define bfd_mach_v850 0
+#define bfd_mach_v850e 'E'
+#define bfd_mach_v850ea 'A'
+ bfd_arch_arc, /* ARC Cores */
+#define bfd_mach_arc_5 0
+#define bfd_mach_arc_6 1
+#define bfd_mach_arc_7 2
+#define bfd_mach_arc_8 3
+ bfd_arch_m32r, /* Mitsubishi M32R/D */
+#define bfd_mach_m32r 0 /* For backwards compatibility. */
+#define bfd_mach_m32rx 'x'
+ bfd_arch_mn10200, /* Matsushita MN10200 */
+ bfd_arch_mn10300, /* Matsushita MN10300 */
+#define bfd_mach_mn10300 300
+#define bfd_mach_am33 330
+ bfd_arch_fr30,
+#define bfd_mach_fr30 0x46523330
+ bfd_arch_mcore,
+ bfd_arch_ia64, /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64 0
+#define bfd_mach_ia64_elf32 1
+ bfd_arch_pj,
+ bfd_arch_avr, /* Atmel AVR microcontrollers. */
+#define bfd_mach_avr1 1
+#define bfd_mach_avr2 2
+#define bfd_mach_avr3 3
+#define bfd_mach_avr4 4
+#define bfd_mach_avr5 5
+ bfd_arch_cris, /* Axis CRIS */
+ bfd_arch_s390, /* IBM s390 */
+#define bfd_mach_s390_esa 0
+#define bfd_mach_s390_esame 1
+ bfd_arch_openrisc, /* OpenRISC */
+ bfd_arch_mmix, /* Donald Knuth's educational processor. */
+ bfd_arch_xstormy16,
+#define bfd_mach_xstormy16 0
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ unsigned long mach;
+ const char *arch_name;
+ const char *printable_name;
+ unsigned int section_align_power;
+ /* True if this is the default machine for the architecture. */
+ boolean the_default;
+ const struct bfd_arch_info * (*compatible)
+ PARAMS ((const struct bfd_arch_info *a,
+ const struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+ const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ const bfd *abfd,
+ const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch PARAMS ((enum bfd_architecture
+ arch,
+ unsigned long machine));
+
+const char *
+bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+unsigned int
+bfd_octets_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_mach_octets_per_byte PARAMS ((enum bfd_architecture arch,
+ unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected. */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions. */
+ bfd_reloc_continue,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_notsupported,
+
+ /* Unused. */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ symbols. If this type is returned, the error_message argument
+ to bfd_perform_relocation will be set. */
+ bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+ /* A pointer into the canonical table of pointers. */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section. */
+ bfd_size_type address;
+
+ /* addend for relocation value. */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation. */
+ reloc_howto_type *howto;
+
+}
+arelent;
+
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+ /* The type field has mainly a documentary use - the back end can
+ do what it wants with it, though normally the back end's
+ external idea of what a reloc number is stored
+ in this field. For example, a PC relative word relocation
+ in a coff environment has the type 023 - because that's
+ what the outside world calls a R_PCRWORD reloc. */
+ unsigned int type;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ power-of-two measure. To get the number of bytes operated
+ on by a type of relocation, use bfd_get_reloc_size. */
+ int size;
+
+ /* The number of bits in the item to be relocated. This is used
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ called rather than the normal function. This allows really
+ strange relocation methods to be accomodated (e.g., i960 callj
+ instructions). */
+ bfd_reloc_status_type (*special_function)
+ PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
+ bfd *, char **));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* Some formats record a relocation addend in the section contents
+ rather than with the relocation. For ELF formats this is the
+ distinction between USE_REL and USE_RELA (though the code checks
+ for USE_REL == 1/0). The value of this field is TRUE if the
+ addend is recorded with the section contents; when performing a
+ partial link (ld -r) the section contents (the data) will be
+ modified. The value of this field is FALSE if addends are
+ recorded with the relocation (in arelent.addend); when performing
+ a partial link the relocation will be modified.
+ All relocations for all ELF USE_RELA targets should set this field
+ to FALSE (values of TRUE should be looked on with suspicion).
+ However, the converse is not true: not all relocations of all ELF
+ USE_REL targets set this field to TRUE. Why this is so is peculiar
+ to each particular target. For relocs that aren't used in partial
+ links (e.g. GOT stuff) it doesn't matter what this is set to. */
+ boolean partial_inplace;
+
+ /* The src_mask selects which parts of the read in data
+ are to be used in the relocation sum. E.g., if this was an 8 bit
+ byte of data which we read and relocated, this would be
+ 0x000000ff. When we have relocs which have an addend, such as
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* The dst_mask selects which parts of the instruction are replaced
+ into the instruction. In most cases src_mask == dst_mask,
+ except in the above special case, where dst_mask would be
+ 0x000000ff, and src_mask would be 0x00000000. */
+ bfd_vma dst_mask;
+
+ /* When some formats create PC relative instructions, they leave
+ the value of the pc of the place being relocated in the offset
+ slot of the instruction, so that a PC relative relocation can
+ be made just by adding in an ordinary offset (e.g., sun3 a.out).
+ Some formats leave the displacement part of an instruction
+ empty (e.g., m88k bcs); this flag signals the fact. */
+ boolean pcrel_offset;
+};
+
+#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC }
+#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \
+ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \
+ NAME, false, 0, 0, IN)
+
+#define EMPTY_HOWTO(C) \
+ HOWTO ((C), 0, 0, 0, false, 0, complain_overflow_dont, NULL, \
+ NULL, false, 0, 0, false)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *) NULL) \
+ { \
+ if (bfd_is_com_section (symbol->section)) \
+ { \
+ relocation = 0; \
+ } \
+ else \
+ { \
+ relocation = symbol->value; \
+ } \
+ } \
+ }
+
+unsigned int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain
+{
+ arelent relent;
+ struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type
+bfd_check_overflow PARAMS ((enum complain_overflow how,
+ unsigned int bitsize,
+ unsigned int rightshift,
+ unsigned int addrsize,
+ bfd_vma relocation));
+
+bfd_reloc_status_type
+bfd_perform_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+bfd_reloc_status_type
+bfd_install_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message));
+
+enum bfd_reloc_code_real {
+ _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_26,
+ BFD_RELOC_24,
+ BFD_RELOC_16,
+ BFD_RELOC_14,
+ BFD_RELOC_8,
+
+/* PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_12_PCREL,
+ BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+ BFD_RELOC_32_GOT_PCREL,
+ BFD_RELOC_16_GOT_PCREL,
+ BFD_RELOC_8_GOT_PCREL,
+ BFD_RELOC_32_GOTOFF,
+ BFD_RELOC_16_GOTOFF,
+ BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF,
+ BFD_RELOC_8_GOTOFF,
+ BFD_RELOC_64_PLT_PCREL,
+ BFD_RELOC_32_PLT_PCREL,
+ BFD_RELOC_24_PLT_PCREL,
+ BFD_RELOC_16_PLT_PCREL,
+ BFD_RELOC_8_PLT_PCREL,
+ BFD_RELOC_64_PLTOFF,
+ BFD_RELOC_32_PLTOFF,
+ BFD_RELOC_16_PLTOFF,
+ BFD_RELOC_LO16_PLTOFF,
+ BFD_RELOC_HI16_PLTOFF,
+ BFD_RELOC_HI16_S_PLTOFF,
+ BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+ BFD_RELOC_68K_GLOB_DAT,
+ BFD_RELOC_68K_JMP_SLOT,
+ BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_LO16_BASEREL,
+ BFD_RELOC_HI16_BASEREL,
+ BFD_RELOC_HI16_S_BASEREL,
+ BFD_RELOC_8_BASEREL,
+ BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+ BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+ BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_16_PCREL_S2,
+ BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC. */
+ BFD_RELOC_HI22,
+ BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register. These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+ BFD_RELOC_GPREL16,
+ BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+ BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations. There is probably some overlap with other
+relocation types already defined. */
+ BFD_RELOC_NONE,
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA16,
+ BFD_RELOC_SPARC_UA32,
+ BFD_RELOC_SPARC_UA64,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+ BFD_RELOC_SPARC_10,
+ BFD_RELOC_SPARC_11,
+ BFD_RELOC_SPARC_OLO10,
+ BFD_RELOC_SPARC_HH22,
+ BFD_RELOC_SPARC_HM10,
+ BFD_RELOC_SPARC_LM22,
+ BFD_RELOC_SPARC_PC_HH22,
+ BFD_RELOC_SPARC_PC_HM10,
+ BFD_RELOC_SPARC_PC_LM22,
+ BFD_RELOC_SPARC_WDISP16,
+ BFD_RELOC_SPARC_WDISP19,
+ BFD_RELOC_SPARC_7,
+ BFD_RELOC_SPARC_6,
+ BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+ BFD_RELOC_SPARC_PLT32,
+ BFD_RELOC_SPARC_PLT64,
+ BFD_RELOC_SPARC_HIX22,
+ BFD_RELOC_SPARC_LOX10,
+ BFD_RELOC_SPARC_H44,
+ BFD_RELOC_SPARC_M44,
+ BFD_RELOC_SPARC_L44,
+ BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+ BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol. The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+ BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs. The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+ BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+ BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol. The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references. The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch) */
+ BFD_RELOC_ALPHA_LITERAL,
+ BFD_RELOC_ALPHA_ELF_LITERAL,
+ BFD_RELOC_ALPHA_LITUSE,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+ BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_CODEADDR,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register. */
+ BFD_RELOC_ALPHA_GPREL_HI16,
+ BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD. */
+ BFD_RELOC_ALPHA_BRSGP,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+ BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+ BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+ BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+ BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result. If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+ BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+ BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+ BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+ BFD_RELOC_PCREL_LO16,
+
+/* Relocation against a MIPS literal section. */
+ BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+ BFD_RELOC_MIPS_GOT16,
+ BFD_RELOC_MIPS_CALL16,
+ BFD_RELOC_MIPS_GOT_HI16,
+ BFD_RELOC_MIPS_GOT_LO16,
+ BFD_RELOC_MIPS_CALL_HI16,
+ BFD_RELOC_MIPS_CALL_LO16,
+ BFD_RELOC_MIPS_SUB,
+ BFD_RELOC_MIPS_GOT_PAGE,
+ BFD_RELOC_MIPS_GOT_OFST,
+ BFD_RELOC_MIPS_GOT_DISP,
+ BFD_RELOC_MIPS_SHIFT5,
+ BFD_RELOC_MIPS_SHIFT6,
+ BFD_RELOC_MIPS_INSERT_A,
+ BFD_RELOC_MIPS_INSERT_B,
+ BFD_RELOC_MIPS_DELETE,
+ BFD_RELOC_MIPS_HIGHEST,
+ BFD_RELOC_MIPS_HIGHER,
+ BFD_RELOC_MIPS_SCN_DISP,
+ BFD_RELOC_MIPS_REL16,
+ BFD_RELOC_MIPS_RELGOT,
+ BFD_RELOC_MIPS_JALR,
+ BFD_RELOC_SH_GOT_LOW16,
+ BFD_RELOC_SH_GOT_MEDLOW16,
+ BFD_RELOC_SH_GOT_MEDHI16,
+ BFD_RELOC_SH_GOT_HI16,
+ BFD_RELOC_SH_GOTPLT_LOW16,
+ BFD_RELOC_SH_GOTPLT_MEDLOW16,
+ BFD_RELOC_SH_GOTPLT_MEDHI16,
+ BFD_RELOC_SH_GOTPLT_HI16,
+ BFD_RELOC_SH_PLT_LOW16,
+ BFD_RELOC_SH_PLT_MEDLOW16,
+ BFD_RELOC_SH_PLT_MEDHI16,
+ BFD_RELOC_SH_PLT_HI16,
+ BFD_RELOC_SH_GOTOFF_LOW16,
+ BFD_RELOC_SH_GOTOFF_MEDLOW16,
+ BFD_RELOC_SH_GOTOFF_MEDHI16,
+ BFD_RELOC_SH_GOTOFF_HI16,
+ BFD_RELOC_SH_GOTPC_LOW16,
+ BFD_RELOC_SH_GOTPC_MEDLOW16,
+ BFD_RELOC_SH_GOTPC_MEDHI16,
+ BFD_RELOC_SH_GOTPC_HI16,
+ BFD_RELOC_SH_COPY64,
+ BFD_RELOC_SH_GLOB_DAT64,
+ BFD_RELOC_SH_JMP_SLOT64,
+ BFD_RELOC_SH_RELATIVE64,
+ BFD_RELOC_SH_GOT10BY4,
+ BFD_RELOC_SH_GOT10BY8,
+ BFD_RELOC_SH_GOTPLT10BY4,
+ BFD_RELOC_SH_GOTPLT10BY8,
+ BFD_RELOC_SH_GOTPLT32,
+ BFD_RELOC_SH_SHMEDIA_CODE,
+ BFD_RELOC_SH_IMMU5,
+ BFD_RELOC_SH_IMMS6,
+ BFD_RELOC_SH_IMMS6BY32,
+ BFD_RELOC_SH_IMMU6,
+ BFD_RELOC_SH_IMMS10,
+ BFD_RELOC_SH_IMMS10BY2,
+ BFD_RELOC_SH_IMMS10BY4,
+ BFD_RELOC_SH_IMMS10BY8,
+ BFD_RELOC_SH_IMMS16,
+ BFD_RELOC_SH_IMMU16,
+ BFD_RELOC_SH_IMM_LOW16,
+ BFD_RELOC_SH_IMM_LOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDLOW16,
+ BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDHI16,
+ BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+ BFD_RELOC_SH_IMM_HI16,
+ BFD_RELOC_SH_IMM_HI16_PCREL,
+ BFD_RELOC_SH_PT_16,
+
+
+/* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ BFD_RELOC_386_GOTOFF,
+ BFD_RELOC_386_GOTPC,
+
+/* x86-64/elf relocations */
+ BFD_RELOC_X86_64_GOT32,
+ BFD_RELOC_X86_64_PLT32,
+ BFD_RELOC_X86_64_COPY,
+ BFD_RELOC_X86_64_GLOB_DAT,
+ BFD_RELOC_X86_64_JUMP_SLOT,
+ BFD_RELOC_X86_64_RELATIVE,
+ BFD_RELOC_X86_64_GOTPCREL,
+ BFD_RELOC_X86_64_32S,
+
+/* ns32k relocations */
+ BFD_RELOC_NS32K_IMM_8,
+ BFD_RELOC_NS32K_IMM_16,
+ BFD_RELOC_NS32K_IMM_32,
+ BFD_RELOC_NS32K_IMM_8_PCREL,
+ BFD_RELOC_NS32K_IMM_16_PCREL,
+ BFD_RELOC_NS32K_IMM_32_PCREL,
+ BFD_RELOC_NS32K_DISP_8,
+ BFD_RELOC_NS32K_DISP_16,
+ BFD_RELOC_NS32K_DISP_32,
+ BFD_RELOC_NS32K_DISP_8_PCREL,
+ BFD_RELOC_NS32K_DISP_16_PCREL,
+ BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* PDP11 relocations */
+ BFD_RELOC_PDP11_DISP_8_PCREL,
+ BFD_RELOC_PDP11_DISP_6_PCREL,
+
+/* Picojava relocs. Not all of these appear in object files. */
+ BFD_RELOC_PJ_CODE_HI16,
+ BFD_RELOC_PJ_CODE_LO16,
+ BFD_RELOC_PJ_CODE_DIR16,
+ BFD_RELOC_PJ_CODE_DIR32,
+ BFD_RELOC_PJ_CODE_REL16,
+ BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+ BFD_RELOC_PPC_B26,
+ BFD_RELOC_PPC_BA26,
+ BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_B16,
+ BFD_RELOC_PPC_B16_BRTAKEN,
+ BFD_RELOC_PPC_B16_BRNTAKEN,
+ BFD_RELOC_PPC_BA16,
+ BFD_RELOC_PPC_BA16_BRTAKEN,
+ BFD_RELOC_PPC_BA16_BRNTAKEN,
+ BFD_RELOC_PPC_COPY,
+ BFD_RELOC_PPC_GLOB_DAT,
+ BFD_RELOC_PPC_JMP_SLOT,
+ BFD_RELOC_PPC_RELATIVE,
+ BFD_RELOC_PPC_LOCAL24PC,
+ BFD_RELOC_PPC_EMB_NADDR32,
+ BFD_RELOC_PPC_EMB_NADDR16,
+ BFD_RELOC_PPC_EMB_NADDR16_LO,
+ BFD_RELOC_PPC_EMB_NADDR16_HI,
+ BFD_RELOC_PPC_EMB_NADDR16_HA,
+ BFD_RELOC_PPC_EMB_SDAI16,
+ BFD_RELOC_PPC_EMB_SDA2I16,
+ BFD_RELOC_PPC_EMB_SDA2REL,
+ BFD_RELOC_PPC_EMB_SDA21,
+ BFD_RELOC_PPC_EMB_MRKREF,
+ BFD_RELOC_PPC_EMB_RELSEC16,
+ BFD_RELOC_PPC_EMB_RELST_LO,
+ BFD_RELOC_PPC_EMB_RELST_HI,
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
+ BFD_RELOC_PPC64_HIGHER,
+ BFD_RELOC_PPC64_HIGHER_S,
+ BFD_RELOC_PPC64_HIGHEST,
+ BFD_RELOC_PPC64_HIGHEST_S,
+ BFD_RELOC_PPC64_TOC16_LO,
+ BFD_RELOC_PPC64_TOC16_HI,
+ BFD_RELOC_PPC64_TOC16_HA,
+ BFD_RELOC_PPC64_TOC,
+ BFD_RELOC_PPC64_PLTGOT16,
+ BFD_RELOC_PPC64_PLTGOT16_LO,
+ BFD_RELOC_PPC64_PLTGOT16_HI,
+ BFD_RELOC_PPC64_PLTGOT16_HA,
+ BFD_RELOC_PPC64_ADDR16_DS,
+ BFD_RELOC_PPC64_ADDR16_LO_DS,
+ BFD_RELOC_PPC64_GOT16_DS,
+ BFD_RELOC_PPC64_GOT16_LO_DS,
+ BFD_RELOC_PPC64_PLT16_LO_DS,
+ BFD_RELOC_PPC64_SECTOFF_DS,
+ BFD_RELOC_PPC64_SECTOFF_LO_DS,
+ BFD_RELOC_PPC64_TOC16_DS,
+ BFD_RELOC_PPC64_TOC16_LO_DS,
+ BFD_RELOC_PPC64_PLTGOT16_DS,
+ BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* IBM 370/390 relocations */
+ BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+ BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. */
+ BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BLX,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_ADRL_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_ADR_IMM,
+ BFD_RELOC_ARM_LDR_IMM,
+ BFD_RELOC_ARM_LITERAL,
+ BFD_RELOC_ARM_IN_POOL,
+ BFD_RELOC_ARM_OFFSET_IMM8,
+ BFD_RELOC_ARM_HWLITERAL,
+ BFD_RELOC_ARM_THUMB_ADD,
+ BFD_RELOC_ARM_THUMB_IMM,
+ BFD_RELOC_ARM_THUMB_SHIFT,
+ BFD_RELOC_ARM_THUMB_OFFSET,
+ BFD_RELOC_ARM_GOT12,
+ BFD_RELOC_ARM_GOT32,
+ BFD_RELOC_ARM_JUMP_SLOT,
+ BFD_RELOC_ARM_COPY,
+ BFD_RELOC_ARM_GLOB_DAT,
+ BFD_RELOC_ARM_PLT32,
+ BFD_RELOC_ARM_RELATIVE,
+ BFD_RELOC_ARM_GOTOFF,
+ BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs. Not all of these appear in object files. */
+ BFD_RELOC_SH_PCDISP8BY2,
+ BFD_RELOC_SH_PCDISP12BY2,
+ BFD_RELOC_SH_IMM4,
+ BFD_RELOC_SH_IMM4BY2,
+ BFD_RELOC_SH_IMM4BY4,
+ BFD_RELOC_SH_IMM8,
+ BFD_RELOC_SH_IMM8BY2,
+ BFD_RELOC_SH_IMM8BY4,
+ BFD_RELOC_SH_PCRELIMM8BY2,
+ BFD_RELOC_SH_PCRELIMM8BY4,
+ BFD_RELOC_SH_SWITCH16,
+ BFD_RELOC_SH_SWITCH32,
+ BFD_RELOC_SH_USES,
+ BFD_RELOC_SH_COUNT,
+ BFD_RELOC_SH_ALIGN,
+ BFD_RELOC_SH_CODE,
+ BFD_RELOC_SH_DATA,
+ BFD_RELOC_SH_LABEL,
+ BFD_RELOC_SH_LOOP_START,
+ BFD_RELOC_SH_LOOP_END,
+ BFD_RELOC_SH_COPY,
+ BFD_RELOC_SH_GLOB_DAT,
+ BFD_RELOC_SH_JMP_SLOT,
+ BFD_RELOC_SH_RELATIVE,
+ BFD_RELOC_SH_GOTPC,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
+be zero and is not stored in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BRANCH9,
+ BFD_RELOC_THUMB_PCREL_BRANCH12,
+ BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* ARC Cores relocs.
+ARC 22 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+ BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch. The lowest two bits must be zero and are not
+stored in the instruction. The high 24 bits are installed in bits 23
+through 0. */
+ BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+ BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+ BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the
+right 3 bitsassumed to be 0. */
+ BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+ BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+ BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+ BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+ BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+ BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+ BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+ BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+ BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+ BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+ BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+ BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+ BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+ BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+ BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+ BFD_RELOC_TIC30_LDP,
+
+/* This is a 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x. */
+ BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+ BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+ BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+ BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+ BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+ BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+ BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+ BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+ BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+ BFD_RELOC_MCORE_PCREL_IMM8BY4,
+ BFD_RELOC_MCORE_PCREL_IMM11BY2,
+ BFD_RELOC_MCORE_PCREL_IMM4BY2,
+ BFD_RELOC_MCORE_PCREL_32,
+ BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+ BFD_RELOC_MCORE_RVA,
+
+/* These are relocations for the GETA instruction. */
+ BFD_RELOC_MMIX_GETA,
+ BFD_RELOC_MMIX_GETA_1,
+ BFD_RELOC_MMIX_GETA_2,
+ BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction. */
+ BFD_RELOC_MMIX_CBRANCH,
+ BFD_RELOC_MMIX_CBRANCH_J,
+ BFD_RELOC_MMIX_CBRANCH_1,
+ BFD_RELOC_MMIX_CBRANCH_2,
+ BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction. */
+ BFD_RELOC_MMIX_PUSHJ,
+ BFD_RELOC_MMIX_PUSHJ_1,
+ BFD_RELOC_MMIX_PUSHJ_2,
+ BFD_RELOC_MMIX_PUSHJ_3,
+
+/* These are relocations for the JMP instruction. */
+ BFD_RELOC_MMIX_JMP,
+ BFD_RELOC_MMIX_JMP_1,
+ BFD_RELOC_MMIX_JMP_2,
+ BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch. */
+ BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction. */
+ BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255. */
+ BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register. */
+ BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation. */
+ BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register. It does not modify contents. */
+ BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits. */
+ BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits. */
+ BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits. */
+ BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits. */
+ BFD_RELOC_AVR_CALL,
+
+/* Direct 12 bit. */
+ BFD_RELOC_390_12,
+
+/* 12 bit GOT offset. */
+ BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime. */
+ BFD_RELOC_390_COPY,
+
+/* Create GOT entry. */
+ BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry. */
+ BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base. */
+ BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT. */
+ BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset. */
+ BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1. */
+ BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1. */
+ BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1. */
+ BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset. */
+ BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry. */
+ BFD_RELOC_390_GOTENT,
+
+/* These two relocations are used by the linker to determine which of
+the entries in a C++ virtual function table are actually used. When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table. The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry. The reloc's symbol should refer to the
+table of the class mentioned in the code. Off of that base, an offset
+describes the entry that is being used. For Rela hosts, this offset
+is stored in the reloc's addend. For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+ BFD_RELOC_VTABLE_INHERIT,
+ BFD_RELOC_VTABLE_ENTRY,
+
+/* Intel IA64 Relocations. */
+ BFD_RELOC_IA64_IMM14,
+ BFD_RELOC_IA64_IMM22,
+ BFD_RELOC_IA64_IMM64,
+ BFD_RELOC_IA64_DIR32MSB,
+ BFD_RELOC_IA64_DIR32LSB,
+ BFD_RELOC_IA64_DIR64MSB,
+ BFD_RELOC_IA64_DIR64LSB,
+ BFD_RELOC_IA64_GPREL22,
+ BFD_RELOC_IA64_GPREL64I,
+ BFD_RELOC_IA64_GPREL32MSB,
+ BFD_RELOC_IA64_GPREL32LSB,
+ BFD_RELOC_IA64_GPREL64MSB,
+ BFD_RELOC_IA64_GPREL64LSB,
+ BFD_RELOC_IA64_LTOFF22,
+ BFD_RELOC_IA64_LTOFF64I,
+ BFD_RELOC_IA64_PLTOFF22,
+ BFD_RELOC_IA64_PLTOFF64I,
+ BFD_RELOC_IA64_PLTOFF64MSB,
+ BFD_RELOC_IA64_PLTOFF64LSB,
+ BFD_RELOC_IA64_FPTR64I,
+ BFD_RELOC_IA64_FPTR32MSB,
+ BFD_RELOC_IA64_FPTR32LSB,
+ BFD_RELOC_IA64_FPTR64MSB,
+ BFD_RELOC_IA64_FPTR64LSB,
+ BFD_RELOC_IA64_PCREL21B,
+ BFD_RELOC_IA64_PCREL21BI,
+ BFD_RELOC_IA64_PCREL21M,
+ BFD_RELOC_IA64_PCREL21F,
+ BFD_RELOC_IA64_PCREL22,
+ BFD_RELOC_IA64_PCREL60B,
+ BFD_RELOC_IA64_PCREL64I,
+ BFD_RELOC_IA64_PCREL32MSB,
+ BFD_RELOC_IA64_PCREL32LSB,
+ BFD_RELOC_IA64_PCREL64MSB,
+ BFD_RELOC_IA64_PCREL64LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR22,
+ BFD_RELOC_IA64_LTOFF_FPTR64I,
+ BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+ BFD_RELOC_IA64_SEGREL32MSB,
+ BFD_RELOC_IA64_SEGREL32LSB,
+ BFD_RELOC_IA64_SEGREL64MSB,
+ BFD_RELOC_IA64_SEGREL64LSB,
+ BFD_RELOC_IA64_SECREL32MSB,
+ BFD_RELOC_IA64_SECREL32LSB,
+ BFD_RELOC_IA64_SECREL64MSB,
+ BFD_RELOC_IA64_SECREL64LSB,
+ BFD_RELOC_IA64_REL32MSB,
+ BFD_RELOC_IA64_REL32LSB,
+ BFD_RELOC_IA64_REL64MSB,
+ BFD_RELOC_IA64_REL64LSB,
+ BFD_RELOC_IA64_LTV32MSB,
+ BFD_RELOC_IA64_LTV32LSB,
+ BFD_RELOC_IA64_LTV64MSB,
+ BFD_RELOC_IA64_LTV64LSB,
+ BFD_RELOC_IA64_IPLTMSB,
+ BFD_RELOC_IA64_IPLTLSB,
+ BFD_RELOC_IA64_COPY,
+ BFD_RELOC_IA64_TPREL22,
+ BFD_RELOC_IA64_TPREL64MSB,
+ BFD_RELOC_IA64_TPREL64LSB,
+ BFD_RELOC_IA64_LTOFF_TP22,
+ BFD_RELOC_IA64_LTOFF22X,
+ BFD_RELOC_IA64_LDXMOV,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits high part of an absolute address. */
+ BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits low part of an absolute address. */
+ BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bits of a value. */
+ BFD_RELOC_M68HC11_3B,
+
+/* These relocs are only used within the CRIS assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_CRIS_BDISP8,
+ BFD_RELOC_CRIS_UNSIGNED_5,
+ BFD_RELOC_CRIS_SIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS. */
+ BFD_RELOC_CRIS_COPY,
+ BFD_RELOC_CRIS_GLOB_DAT,
+ BFD_RELOC_CRIS_JUMP_SLOT,
+ BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT. */
+ BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT. */
+ BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation. */
+ BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations. */
+ BFD_RELOC_860_COPY,
+ BFD_RELOC_860_GLOB_DAT,
+ BFD_RELOC_860_JUMP_SLOT,
+ BFD_RELOC_860_RELATIVE,
+ BFD_RELOC_860_PC26,
+ BFD_RELOC_860_PLT26,
+ BFD_RELOC_860_PC16,
+ BFD_RELOC_860_LOW0,
+ BFD_RELOC_860_SPLIT0,
+ BFD_RELOC_860_LOW1,
+ BFD_RELOC_860_SPLIT1,
+ BFD_RELOC_860_LOW2,
+ BFD_RELOC_860_SPLIT2,
+ BFD_RELOC_860_LOW3,
+ BFD_RELOC_860_LOGOT0,
+ BFD_RELOC_860_SPGOT0,
+ BFD_RELOC_860_LOGOT1,
+ BFD_RELOC_860_SPGOT1,
+ BFD_RELOC_860_LOGOTOFF0,
+ BFD_RELOC_860_SPGOTOFF0,
+ BFD_RELOC_860_LOGOTOFF1,
+ BFD_RELOC_860_SPGOTOFF1,
+ BFD_RELOC_860_LOGOTOFF2,
+ BFD_RELOC_860_LOGOTOFF3,
+ BFD_RELOC_860_LOPC,
+ BFD_RELOC_860_HIGHADJ,
+ BFD_RELOC_860_HAGOT,
+ BFD_RELOC_860_HAGOTOFF,
+ BFD_RELOC_860_HAPC,
+ BFD_RELOC_860_HIGH,
+ BFD_RELOC_860_HIGOT,
+ BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations. */
+ BFD_RELOC_OPENRISC_ABS_26,
+ BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations. */
+ BFD_RELOC_H8_DIR16A8,
+ BFD_RELOC_H8_DIR16R8,
+ BFD_RELOC_H8_DIR24A8,
+ BFD_RELOC_H8_DIR24R8,
+ BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations. */
+ BFD_RELOC_XSTORMY16_REL_12,
+ BFD_RELOC_XSTORMY16_24,
+ BFD_RELOC_XSTORMY16_FPTR16,
+ BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+ /* A pointer to the BFD which owns the symbol. This information
+ is necessary so that a back end can work out what additional
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+ struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+ /* The text of the symbol. The name is left alone, and not copied; the
+ application may not alter it. */
+ const char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol. */
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ value is the offset into the section of the data. */
+#define BSF_GLOBAL 0x02
+
+ /* The symbol has global scope and is exported. The value is
+ the offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* No real difference. */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>>. */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning, unless BSF_DEBUGGING_RELOC is also set. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. The name is a
+ warning. The name of the next symbol is the one to warn about;
+ if a reference is made to a symbol with the same name as the next
+ symbol, a warning is issued by the linker. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. This symbol is an indirect
+ pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ /* Symbol is from dynamic linking information. */
+#define BSF_DYNAMIC 0x8000
+
+ /* The symbol denotes a data object. Used in ELF, and perhaps
+ others someday. */
+#define BSF_OBJECT 0x10000
+
+ /* This symbol is a debugging symbol. The value is the offset
+ into the section of the data. BSF_DEBUGGING should be set
+ as well. */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+ flagword flags;
+
+ /* A pointer to the section to which this symbol is
+ relative. This will always be non NULL, there are special
+ sections for undefined and absolute symbols. */
+ struct sec *section;
+
+ /* Back end special data. */
+ union
+ {
+ PTR p;
+ bfd_vma i;
+ }
+ udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+boolean
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+ BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+ (abfd, location))
+
+boolean
+bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((bfd *abfd, PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *
+_bfd_generic_make_empty_symbol PARAMS ((bfd *));
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+boolean
+bfd_is_undefined_symclass PARAMS ((int symclass));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+ (ibfd, isymbol, obfd, osymbol))
+
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ const char *filename;
+
+ /* A pointer to the target jump table. */
+ const struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char *",
+ and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ PTR iostream;
+
+ /* Is the file descriptor being cached? That is, can it be closed as
+ needed, and re-opened when accessed later? */
+ boolean cacheable;
+
+ /* Marks whether there was a default target specified when the
+ BFD was opened. This is used to select which matching algorithm
+ to use to choose the back end. */
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs. */
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here... */
+ ufile_ptr where;
+
+ /* ... and here: (``once'' means at least once). */
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time. */
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true. */
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension. */
+ int ifd;
+
+ /* The format which belongs to the BFD. (object, core, etc.) */
+ bfd_format format;
+
+ /* The direction with which the BFD was opened. */
+ enum bfd_direction
+ {
+ no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3
+ }
+ direction;
+
+ /* Format_specific flags. */
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+ ufile_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ from happening. */
+ boolean output_has_begun;
+
+ /* A hash table for section names. */
+ struct bfd_hash_table section_htab;
+
+ /* Pointer to linked list of sections. */
+ struct sec *sections;
+
+ /* The place where we add to the section list. */
+ struct sec **section_tail;
+
+ /* The number of sections. */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output. */
+ unsigned int symcount;
+
+ /* Symbol table for output BFD (with symcount entries). */
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information. */
+ const struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives. */
+ PTR arelt_data;
+ struct _bfd *my_archive; /* The containing archive BFD. */
+ struct _bfd *next; /* The next BFD in the archive. */
+ struct _bfd *archive_head; /* The first BFD in the archive. */
+ boolean has_armap;
+
+ /* A chain of BFD structures involved in a link. */
+ struct _bfd *link_next;
+
+ /* A field used by _bfd_generic_link_add_archive_symbols. This will
+ be used only for archive elements. */
+ int archive_pass;
+
+ /* Used by the back end to hold private data. */
+ union
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct pe_tdata *pe_obj_data;
+ struct xcoff_tdata *xcoff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct ihex_data_struct *ihex_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct mmo_data_struct *mmo_data;
+ struct sun_core_struct *sun_core_data;
+ struct sco5_core_struct *sco5_core_data;
+ struct trad_core_struct *trad_core_data;
+ struct som_data_struct *som_data;
+ struct hpux_core_struct *hpux_core_data;
+ struct hppabsd_core_struct *hppabsd_core_data;
+ struct sgi_core_struct *sgi_core_data;
+ struct lynx_core_struct *lynx_core_data;
+ struct osf_core_struct *osf_core_data;
+ struct cisco_core_struct *cisco_core_data;
+ struct versados_data_struct *versados_data;
+ struct netbsd_core_struct *netbsd_core_data;
+ PTR any;
+ }
+ tdata;
+
+ /* Used by the application to hold private data. */
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes. This is a
+ struct objalloc *, but we use PTR to avoid requiring the inclusion of
+ objalloc.h. */
+ PTR memory;
+};
+
+typedef enum bfd_error
+{
+ bfd_error_no_error = 0,
+ bfd_error_system_call,
+ bfd_error_invalid_target,
+ bfd_error_wrong_format,
+ bfd_error_wrong_object_format,
+ bfd_error_invalid_operation,
+ bfd_error_no_memory,
+ bfd_error_no_symbols,
+ bfd_error_no_armap,
+ bfd_error_no_more_archived_files,
+ bfd_error_malformed_archive,
+ bfd_error_file_not_recognized,
+ bfd_error_file_ambiguously_recognized,
+ bfd_error_no_contents,
+ bfd_error_nonrepresentable_section,
+ bfd_error_no_debug_section,
+ bfd_error_bad_value,
+ bfd_error_file_truncated,
+ bfd_error_file_too_big,
+ bfd_error_invalid_error_code
+}
+bfd_error_type;
+
+bfd_error_type
+bfd_get_error PARAMS ((void));
+
+void
+bfd_set_error PARAMS ((bfd_error_type error_tag));
+
+const char *
+bfd_errmsg PARAMS ((bfd_error_type error_tag));
+
+void
+bfd_perror PARAMS ((const char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+bfd_error_handler_type
+bfd_get_error_handler PARAMS ((void));
+
+const char *
+bfd_archive_filename PARAMS ((bfd *));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+void
+bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count));
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+int
+bfd_get_arch_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_sign_extend_vma PARAMS ((bfd *abfd));
+
+boolean
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+bfd_set_gp_size PARAMS ((bfd *abfd, unsigned int i));
+
+bfd_vma
+bfd_scan_vma PARAMS ((const char *string, const char **end, int base));
+
+boolean
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+ BFD_SEND (abfd, _bfd_set_private_flags, \
+ (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_merge_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+ BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+ BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *,
+ boolean, asymbol **));
+
+boolean
+bfd_alt_mach_code PARAMS ((bfd *abfd, int index));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+const char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+ ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ ((*((bfd)->xvec->message)) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+
+enum bfd_flavour
+{
+ bfd_target_unknown_flavour,
+ bfd_target_aout_flavour,
+ bfd_target_coff_flavour,
+ bfd_target_ecoff_flavour,
+ bfd_target_xcoff_flavour,
+ bfd_target_elf_flavour,
+ bfd_target_ieee_flavour,
+ bfd_target_nlm_flavour,
+ bfd_target_oasys_flavour,
+ bfd_target_tekhex_flavour,
+ bfd_target_srec_flavour,
+ bfd_target_ihex_flavour,
+ bfd_target_som_flavour,
+ bfd_target_os9k_flavour,
+ bfd_target_versados_flavour,
+ bfd_target_msdos_flavour,
+ bfd_target_ovax_flavour,
+ bfd_target_evax_flavour,
+ bfd_target_mmo_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+/* Forward declaration. */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+ /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */
+ char *name;
+
+ /* The "flavour" of a back end is a general indication about
+ the contents of a file. */
+ enum bfd_flavour flavour;
+
+ /* The order of bytes within the data area of a file. */
+ enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file. */
+ enum bfd_endian header_byteorder;
+
+ /* A mask of all the flags which an executable may have set -
+ from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>. */
+ flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+ the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>. */
+ flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+ (if any), perhaps `_'. */
+ char symbol_leading_char;
+
+ /* The pad character for file names within an archive header. */
+ char ar_pad_char;
+
+ /* The maximum number of characters in an archive header. */
+ unsigned short ar_max_namelen;
+
+ /* Entries for byte swapping for data. These are different from the
+ other entry points, since they don't take a BFD asthe first argument.
+ Certain other handlers could do the same. */
+ bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Byte swapping for the headers. */
+ bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Format dependent routines: these are vectors of entry points
+ within the target vector structure, one for each format to check. */
+
+ /* Check the format of a file being read. Return a <<bfd_target *>> or zero. */
+ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Set the format of a file being written. */
+ boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Write cached information into a file being written, at <<bfd_close>>. */
+ boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+
+ /* Generic entry points. */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+CONCAT2 (NAME,_close_and_cleanup), \
+CONCAT2 (NAME,_bfd_free_cached_info), \
+CONCAT2 (NAME,_new_section_hook), \
+CONCAT2 (NAME,_get_section_contents), \
+CONCAT2 (NAME,_get_section_contents_in_window)
+
+ /* Called when the BFD is being closed to do any necessary cleanup. */
+ boolean (*_close_and_cleanup) PARAMS ((bfd *));
+ /* Ask the BFD to free all cached information. */
+ boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+ /* Called when a new section is created. */
+ boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+ /* Read the contents of a section. */
+ boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type));
+
+ /* Entry points to copy private data. */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+CONCAT2 (NAME,_bfd_copy_private_bfd_data), \
+CONCAT2 (NAME,_bfd_merge_private_bfd_data), \
+CONCAT2 (NAME,_bfd_copy_private_section_data), \
+CONCAT2 (NAME,_bfd_copy_private_symbol_data), \
+CONCAT2 (NAME,_bfd_set_private_flags), \
+CONCAT2 (NAME,_bfd_print_private_bfd_data) \
+ /* Called to copy BFD general private data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to merge BFD general private data from one object file
+ to a common output file when linking. */
+ boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to copy BFD private section data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+ bfd *, sec_ptr));
+ /* Called to copy BFD private symbol data from one symbol
+ to another. */
+ boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+ /* Called to set private backend flags. */
+ boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+ /* Called to print private BFD data. */
+ boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+ /* Core file entry points. */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+CONCAT2 (NAME,_core_file_failing_command), \
+CONCAT2 (NAME,_core_file_failing_signal), \
+CONCAT2 (NAME,_core_file_matches_executable_p)
+ char * (*_core_file_failing_command) PARAMS ((bfd *));
+ int (*_core_file_failing_signal) PARAMS ((bfd *));
+ boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+ /* Archive entry points. */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+CONCAT2 (NAME,_slurp_armap), \
+CONCAT2 (NAME,_slurp_extended_name_table), \
+CONCAT2 (NAME,_construct_extended_name_table), \
+CONCAT2 (NAME,_truncate_arname), \
+CONCAT2 (NAME,_write_armap), \
+CONCAT2 (NAME,_read_ar_hdr), \
+CONCAT2 (NAME,_openr_next_archived_file), \
+CONCAT2 (NAME,_get_elt_at_index), \
+CONCAT2 (NAME,_generic_stat_arch_elt), \
+CONCAT2 (NAME,_update_armap_timestamp)
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ boolean (*_bfd_construct_extended_name_table)
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, const char *, char *));
+ boolean (*write_armap)
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+ PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *, bfd *));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+ bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+ boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+ /* Entry points used for symbols. */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+CONCAT2 (NAME,_get_symtab_upper_bound), \
+CONCAT2 (NAME,_get_symtab), \
+CONCAT2 (NAME,_make_empty_symbol), \
+CONCAT2 (NAME,_print_symbol), \
+CONCAT2 (NAME,_get_symbol_info), \
+CONCAT2 (NAME,_bfd_is_local_label_name), \
+CONCAT2 (NAME,_get_lineno), \
+CONCAT2 (NAME,_find_nearest_line), \
+CONCAT2 (NAME,_bfd_make_debug_symbol), \
+CONCAT2 (NAME,_read_minisymbols), \
+CONCAT2 (NAME,_minisymbol_to_symbol)
+ long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+ long (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+ struct symbol_cache_entry *
+ (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+ void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ struct symbol_cache_entry *,
+ symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+ boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+ alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+ boolean (*_bfd_find_nearest_line)
+ PARAMS ((bfd *, struct sec *, struct symbol_cache_entry **, bfd_vma,
+ const char **, const char **, unsigned int *));
+ /* Back-door to allow format-aware applications to create debug symbols
+ while using BFD for everything else. Currently used by the assembler
+ when creating COFF files. */
+ asymbol *(*_bfd_make_debug_symbol) PARAMS ((bfd *, void *,
+ unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+ BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+ long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+ unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+ asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+ /* Routines for relocs. */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+CONCAT2 (NAME,_get_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_reloc), \
+CONCAT2 (NAME,_bfd_reloc_type_lookup)
+ long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+ long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+ struct symbol_cache_entry **));
+ /* See documentation on reloc types. */
+ reloc_howto_type *
+ (*reloc_type_lookup) PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+ /* Routines used when writing an object file. */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+CONCAT2 (NAME,_set_arch_mach), \
+CONCAT2 (NAME,_set_section_contents)
+ boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+ boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+
+ /* Routines used by the linker. */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+CONCAT2 (NAME,_sizeof_headers), \
+CONCAT2 (NAME,_bfd_get_relocated_section_contents), \
+CONCAT2 (NAME,_bfd_relax_section), \
+CONCAT2 (NAME,_bfd_link_hash_table_create), \
+CONCAT2 (NAME,_bfd_link_add_symbols), \
+CONCAT2 (NAME,_bfd_final_link), \
+CONCAT2 (NAME,_bfd_link_split_section), \
+CONCAT2 (NAME,_bfd_gc_sections), \
+CONCAT2 (NAME,_bfd_merge_sections)
+ int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+ bfd_byte *(*_bfd_get_relocated_section_contents)
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, struct symbol_cache_entry **));
+
+ boolean (*_bfd_relax_section)
+ PARAMS ((bfd *, struct sec *, struct bfd_link_info *, boolean *));
+
+ /* Create a hash table for the linker. Different backends store
+ different information in this table. */
+ struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+ /* Add symbols from this object file into the hash table. */
+ boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Do a link based on the link_order structures attached to each
+ section of the BFD. */
+ boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Should this section be split up into smaller pieces during linking. */
+ boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+ /* Remove sections that are not referenced from the output. */
+ boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Attempt to merge SEC_MERGE sections. */
+ boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Routines to handle dynamic symbols and relocs. */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+CONCAT2 (NAME,_get_dynamic_symtab_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_symtab), \
+CONCAT2 (NAME,_get_dynamic_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_reloc)
+ /* Get the amount of memory required to hold the dynamic symbols. */
+ long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic symbols. */
+ long (*_bfd_canonicalize_dynamic_symtab)
+ PARAMS ((bfd *, struct symbol_cache_entry **));
+ /* Get the amount of memory required to hold the dynamic relocs. */
+ long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic relocs. */
+ long (*_bfd_canonicalize_dynamic_reloc)
+ PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+ /* Opposite endian version of this target. */
+ const struct bfd_target * alternative_target;
+
+ /* Data for use by back-end routines, which isn't
+ generic enough to belong in this structure. */
+ PTR backend_data;
+
+} bfd_target;
+
+boolean
+bfd_set_default_target PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((const char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target *
+bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+const char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gnu/usr.bin/binutils/libbfd/sparc64/bfd.h b/gnu/usr.bin/binutils/libbfd/sparc64/bfd.h
new file mode 100644
index 0000000..d2776b5
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/sparc64/bfd.h
@@ -0,0 +1,3918 @@
+/* $FreeBSD$ */
+
+/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
+ generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+ "section.c", "archures.c", "reloc.c", "syms.c", "bfd.c", "archive.c",
+ "corefile.c", "targets.c" and "format.c".
+ Run "make headers" in your build bfd/ to regenerate. */
+
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+#include "symcat.h"
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This hack is to avoid a problem with some strict ANSI C preprocessors.
+ The problem is, "32_" is not a valid preprocessing token, and we don't
+ want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will
+ cause the inner CONCAT2 macros to be evaluated first, producing
+ still-valid pp-tokens. Then the final concatenation can be done. */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* #define BFD_VERSION 212000000 */
+/* #define BFD_VERSION_DATE 20020309 */
+/* #define BFD_VERSION_STRING "2.12" */
+
+/* The word size used by BFD on the host. This may be 64 with a 32
+ bit target if the host is 64 bit, or if other 64 bit targets have
+ been selected with --enable-targets, or if --enable-64-bit-bfd. */
+#define BFD_ARCH_SIZE 64
+
+/* The word size of the default bfd target. */
+#define BFD_DEFAULT_TARGET_SIZE 64
+
+#if defined(__i386__) || defined(__powerpc__)
+#define BFD_HOST_64BIT_LONG 0
+#else
+#define BFD_HOST_64BIT_LONG 1
+#endif /* 32-bit host */
+#if 0
+#define BFD_HOST_64_BIT
+#define BFD_HOST_U_64_BIT
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* Forward declaration. */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+/* And even worse if your compiler provides a stdbool.h that conflicts
+ with these definitions... gcc 2.95 and later do. If so, it must
+ be included first. -drow */
+#if defined (__GNUG__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+#define TRUE_FALSE_ALREADY_DEFINED
+#else
+#if defined (__bool_true_false_are_defined)
+/* We have <stdbool.h>. */
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, BFD_HOST_64_BIT must be
+ defined above. */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+# define BFD_HOST_64_BIT long
+# define BFD_HOST_U_64_BIT unsigned long
+# else
+# ifdef __GNUC__
+# if __GNUC__ >= 2
+# define BFD_HOST_64_BIT long long
+# define BFD_HOST_U_64_BIT unsigned long long
+# endif /* __GNUC__ >= 2 */
+# endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf (s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf (s, "%08lx", x)
+
+#endif /* not BFD64 */
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef bfd_signed_vma file_ptr;
+typedef bfd_vma ufile_ptr;
+
+extern void bfd_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
+extern void bfd_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/* File formats. */
+
+typedef enum bfd_format
+{
+ bfd_unknown = 0, /* File format is unknown. */
+ bfd_object, /* Linker/assember/compiler output. */
+ bfd_archive, /* Object archive file. */
+ bfd_core, /* Core dump. */
+ bfd_type_end /* Marks the end; don't use it! */
+}
+bfd_format;
+
+/* Values that may appear in the flags field of a BFD. These also
+ appear in the object_flags field of the bfd_target structure, where
+ they indicate the set of flags used by that backend (not all flags
+ are meaningful for all object file formats) (FIXME: at the moment,
+ the object_flags values have mostly just been copied from backend
+ to another, and are not necessarily correct). */
+
+/* No flags. */
+#define BFD_NO_FLAGS 0x00
+
+/* BFD contains relocation entries. */
+#define HAS_RELOC 0x01
+
+/* BFD is directly executable. */
+#define EXEC_P 0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+ COFF header). */
+#define HAS_LINENO 0x04
+
+/* BFD has debugging information. */
+#define HAS_DEBUG 0x08
+
+/* BFD has symbols. */
+#define HAS_SYMS 0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+ header). */
+#define HAS_LOCALS 0x20
+
+/* BFD is a dynamic object. */
+#define DYNAMIC 0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+ like an a.out NMAGIC file) (the linker sets this by default, but
+ clears it for -r or -N). */
+#define WP_TEXT 0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+ linker sets this by default, but clears it for -r or -n or -N). */
+#define D_PAGED 0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+ do something) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+ traditional format. For example, this is used to request that when
+ writing out an a.out object the symbols not be hashed to eliminate
+ duplicates. */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* Symbols and relocation. */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+ target specific parts are in libcoff.h, libaout.h, etc. */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol. */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym
+{
+ char *name;
+ file_ptr file_offset; /* Look here to find the file. */
+}
+carsym; /* To make these you call a carsymogen. */
+
+/* Used in generating armaps (archive tables of contents).
+ Perhaps just a forward definition would do? */
+struct orl /* Output ranlib. */
+{
+ char **name; /* Symbol name. */
+ union
+ {
+ file_ptr pos;
+ bfd *abfd;
+ } u; /* bfd* or file position. */
+ int namidx; /* Index into string table. */
+};
+
+/* Linenumber stuff. */
+typedef struct lineno_cache_entry
+{
+ unsigned int line_number; /* Linenumber from start of function. */
+ union
+ {
+ struct symbol_cache_entry *sym; /* Function name. */
+ bfd_vma offset; /* Offset into section. */
+ } u;
+}
+alent;
+
+/* Object and core file sections. */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ const char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ const char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines. There is no way to free up a hash table. */
+
+/* An element in the hash table. Most uses will actually use a larger
+ structure, and an instance of this will be the first field. */
+
+struct bfd_hash_entry
+{
+ /* Next entry for this hash code. */
+ struct bfd_hash_entry *next;
+ /* String being hashed. */
+ const char *string;
+ /* Hash code. This is the full hash code, not the index into the
+ table. */
+ unsigned long hash;
+};
+
+/* A hash table. */
+
+struct bfd_hash_table
+{
+ /* The hash array. */
+ struct bfd_hash_entry **table;
+ /* The number of slots in the hash table. */
+ unsigned int size;
+ /* A function used to create new elements in the hash table. The
+ first entry is itself a pointer to an element. When this
+ function is first invoked, this pointer will be NULL. However,
+ having the pointer permits a hierarchy of method functions to be
+ built each of which calls the function in the superclass. Thus
+ each function should be written to allocate a new block of memory
+ only if the argument is NULL. */
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+ /* An objalloc for this hash table. This is a struct objalloc *,
+ but we use PTR to avoid requiring the inclusion of objalloc.h. */
+ PTR memory;
+};
+
+/* Initialize a hash table. */
+extern boolean bfd_hash_table_init
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+
+/* Initialize a hash table specifying a size. */
+extern boolean bfd_hash_table_init_n
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int size));
+
+/* Free up a hash table. */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table. If CREATE is true, a new entry
+ will be created for this string if one does not already exist. The
+ COPY argument must be true if this routine should copy the string
+ into newly allocated memory when adding an entry. */
+extern struct bfd_hash_entry *bfd_hash_lookup
+ PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+ boolean copy));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry. */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Grab some space for a hash table entry. */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+ unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+ element. If the function returns false, the traversal stops. The
+ INFO argument is passed to the function. */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+ boolean (*) (struct bfd_hash_entry *,
+ PTR),
+ PTR info));
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities. */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_bread PARAMS ((PTR, bfd_size_type, bfd *));
+extern bfd_size_type bfd_bwrite PARAMS ((const PTR, bfd_size_type, bfd *));
+extern int bfd_seek PARAMS ((bfd *, file_ptr, int));
+extern ufile_ptr bfd_tell PARAMS ((bfd *));
+extern int bfd_flush PARAMS ((bfd *));
+extern int bfd_stat PARAMS ((bfd *, struct stat *));
+
+/* Deprecated old routines. */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated
+ PARAMS ((const char *, const char *, int, const char *));
+
+/* Cast from const char * to char * so that caller can assign to
+ a char * without a warning. */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_family_coff(abfd) \
+ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean) (bool)), true)
+
+extern boolean bfd_cache_close PARAMS ((bfd *abfd));
+/* NB: This declaration should match the autogenerated one in libbfd.h. */
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+bfd_vma bfd_getb64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb16 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void bfd_putb64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb16 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl16 PARAMS ((bfd_vma, unsigned char *));
+
+/* Byte swapping routines which take size and endiannes as arguments. */
+
+bfd_vma bfd_get_bits PARAMS ((bfd_byte *, int, boolean));
+void bfd_put_bits PARAMS ((bfd_vma, bfd_byte *, int, boolean));
+
+/* Externally visible ECOFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+ PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+ unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+ PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ bfd *input_bfd, struct ecoff_debug_info *input_debug,
+ const struct ecoff_debug_swap *input_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ boolean relocateable,
+ boolean (*get_extr) (struct symbol_cache_entry *,
+ struct ecoff_extr *),
+ void (*set_index) (struct symbol_cache_entry *,
+ bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+ PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+ PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Return an upper bound on the number of bytes required to store a
+ copy of ABFD's program header table entries. Return -1 if an error
+ occurs; bfd_get_error will return an appropriate code. */
+extern long bfd_get_elf_phdr_upper_bound PARAMS ((bfd *abfd));
+
+/* Copy ABFD's program header table entries to *PHDRS. The entries
+ will be stored as an array of Elf_Internal_Phdr structures, as
+ defined in include/elf/internal.h. To find out how large the
+ buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+ Return the number of program header table entries read, or -1 if an
+ error occurs; bfd_get_error will return an appropriate code. */
+extern int bfd_get_elf_phdrs PARAMS ((bfd *abfd, void *phdrs));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf. */
+extern int bfd_get_arch_size PARAMS ((bfd *));
+
+/* Return true if address "naturally" sign extends, or -1 if not elf. */
+extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+
+extern boolean bfd_m68k_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+extern boolean bfd_mips_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+ struct sec **));
+
+/* Linux shared library support routines for the linker. */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window
+{
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+}
+bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *, unsigned int));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+extern boolean bfd_xcoff_link_generate_rtinit
+ PARAMS ((bfd *, const char *, const char *));
+
+/* Externally visible COFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+ PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+ PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+ PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+extern boolean bfd_m68k_coff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* PE ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_pe_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_pe_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_pe_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support. Called from linker. */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* TI COFF load page support. */
+extern void bfd_ticoff_set_section_load_page
+ PARAMS ((struct sec *, int));
+
+extern int bfd_ticoff_get_section_load_page
+ PARAMS ((struct sec *));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((const char *filename, const char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((const char *filename, const char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((const char *filename, const char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((const char *filename, bfd *templ));
+
+boolean
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+/* Byte swapping macros for user section data. */
+
+#define bfd_put_8(abfd, val, ptr) \
+ ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val)))
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr) \
+ ( (bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \
+ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \
+ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \
+ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \
+ : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr) \
+ ( (bits) == 8 ? bfd_put_8 (abfd, val, ptr) \
+ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \
+ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \
+ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \
+ : (abort (), (void) 0))
+
+
+/* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx16, (val, ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx16, (ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx32, (val, ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx32, (ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx64, (val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx64, (ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr))
+
+/* Refinements on the above, which should eventually go away. Save
+ cluttering the source with (bfd_vma) and (bfd_byte *) casts. */
+
+#define H_PUT_64(abfd, val, where) \
+ bfd_h_put_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_32(abfd, val, where) \
+ bfd_h_put_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_16(abfd, val, where) \
+ bfd_h_put_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_8 bfd_h_put_8
+
+#define H_PUT_S64(abfd, val, where) \
+ bfd_h_put_signed_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S32(abfd, val, where) \
+ bfd_h_put_signed_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S16(abfd, val, where) \
+ bfd_h_put_signed_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S8 bfd_h_put_signed_8
+
+#define H_GET_64(abfd, where) \
+ bfd_h_get_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_32(abfd, where) \
+ bfd_h_get_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_16(abfd, where) \
+ bfd_h_get_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_8 bfd_h_get_8
+
+#define H_GET_S64(abfd, where) \
+ bfd_h_get_signed_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S32(abfd, where) \
+ bfd_h_get_signed_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S16(abfd, where) \
+ bfd_h_get_signed_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S8 bfd_h_get_signed_8
+
+
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+typedef struct sec
+{
+ /* The name of the section; the name isn't a copy, the pointer is
+ the same as that passed to bfd_make_section. */
+ const char *name;
+
+ /* A unique sequence number. */
+ int id;
+
+ /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */
+ int index;
+
+ /* The next section in the list belonging to the BFD, or NULL. */
+ struct sec *next;
+
+ /* The field flags contains attributes of the section. Some
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* Tells the OS to allocate space for this section when loading.
+ This is clear for a section containing debug information only. */
+#define SEC_ALLOC 0x001
+
+ /* Tells the OS to load the section from the file when loading.
+ This is clear for a .bss section. */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there is
+ some relocation information too. */
+#define SEC_RELOC 0x004
+
+ /* ELF reserves 4 processor specific bits and 8 operating system
+ specific bits in sh_flags; at present we can get away with just
+ one in communicating between the assembler and BFD, but this
+ isn't a good long-term solution. */
+#define SEC_ARCH_BIT_0 0x008
+
+ /* A signal to the OS that the section contains read only data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+ the symbol to it, and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constructor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker to not output the section
+ even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a COFF shared library section. This flag is
+ only for the linker. If this type of section appears in
+ the input file, the linker must copy it to the output file
+ without changing the vma or size. FIXME: Although this
+ was originally intended to be general, it really is COFF
+ specific (and the flag was renamed to indicate this). It
+ might be cleaner to have some more general mechanism to
+ allow the back end to control what the linker does with
+ sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+ /* The section has GOT references. This flag is only for the
+ linker, and is currently only used by the elf32-hppa back end.
+ It will be set if global offset table references were detected
+ in this section, which indicate to the linker that the section
+ contains PIC code, and must be handled specially when doing a
+ static link. */
+#define SEC_HAS_GOT_REF 0x4000
+
+ /* The section contains common symbols (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* The contents of this section are held in memory pointed to
+ by the contents field. This is checked by bfd_get_section_contents,
+ and the data is retrieved from memory if appropriate. */
+#define SEC_IN_MEMORY 0x20000
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted based on the sum of
+ the symbol and addend values specified by the associated relocation
+ entries. Entries without associated relocation entries will be
+ appended to the end of the section in an unspecified order. */
+#define SEC_SORT_ENTRIES 0x80000
+
+ /* When linking, duplicate sections of the same name should be
+ discarded, rather than being combined into a single section as
+ is usually done. This is similar to how common symbols are
+ handled. See SEC_LINK_DUPLICATES below. */
+#define SEC_LINK_ONCE 0x100000
+
+ /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+ should handle duplicate sections. */
+#define SEC_LINK_DUPLICATES 0x600000
+
+ /* This value for SEC_LINK_DUPLICATES means that duplicate
+ sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if there are any duplicate sections, although
+ it should still only link one copy. */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections are a different size. */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections contain different
+ contents. */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+ /* This section was created by the linker as part of dynamic
+ relocation or other arcane processing. It is skipped when
+ going through the first-pass output, trusting that someone
+ else up the line will take care of it later. */
+#define SEC_LINKER_CREATED 0x800000
+
+ /* This section should not be subject to garbage collection. */
+#define SEC_KEEP 0x1000000
+
+ /* This section contains "short" data, and should be placed
+ "near" the GP. */
+#define SEC_SMALL_DATA 0x2000000
+
+ /* This section contains data which may be shared with other
+ executables or shared objects. */
+#define SEC_SHARED 0x4000000
+
+ /* When a section with this flag is being linked, then if the size of
+ the input section is less than a page, it should not cross a page
+ boundary. If the size of the input section is one page or more, it
+ should be aligned on a page boundary. */
+#define SEC_BLOCK 0x8000000
+
+ /* Conditionally link this section; do not link if there are no
+ references found to any symbol in the section. */
+#define SEC_CLINK 0x10000000
+
+ /* Attempt to merge identical entities in the section.
+ Entity size is given in the entsize field. */
+#define SEC_MERGE 0x20000000
+
+ /* If given with SEC_MERGE, entities to merge are zero terminated
+ strings where entsize specifies character size instead of fixed
+ size entries. */
+#define SEC_STRINGS 0x40000000
+
+ /* This section contains data about section groups. */
+#define SEC_GROUP 0x80000000
+
+ /* End of section flags. */
+
+ /* Some internal packed boolean fields. */
+
+ /* See the vma field. */
+ unsigned int user_set_vma : 1;
+
+ /* Whether relocations have been processed. */
+ unsigned int reloc_done : 1;
+
+ /* A mark flag used by some of the linker backends. */
+ unsigned int linker_mark : 1;
+
+ /* Another mark flag used by some of the linker backends. Set for
+ output sections that have an input section. */
+ unsigned int linker_has_input : 1;
+
+ /* A mark flag used by some linker backends for garbage collection. */
+ unsigned int gc_mark : 1;
+
+ /* Used by the ELF code to mark sections which have been allocated
+ to segments. */
+ unsigned int segment_mark : 1;
+
+ /* End of internal packed boolean fields. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+ bfd_vma vma;
+
+ /* The load address of the section - where it would be in a
+ rom image; really only used for writing section header
+ information. */
+ bfd_vma lma;
+
+ /* The size of the section in octets, as it will be output.
+ Contains a value even if the section has no contents (e.g., the
+ size of <<.bss>>). This will be filled in after relocation. */
+ bfd_size_type _cooked_size;
+
+ /* The original size on disk of the section, in octets. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset in *bytes* into the output section of the first byte in the
+ input section (byte ==> smallest addressable unit on the
+ target). In most cases, if this was going to start at the
+ 100th octet (8-bit quantity) in the output section, this value
+ would be 100. However, if the target byte size is 16 bits
+ (bfd_octets_per_byte is "2"), this value would be 50. */
+ bfd_vma output_offset;
+
+ /* The output section through which to map on output. */
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent of 2 -
+ e.g., 3 aligns to 2^3 (or 8). */
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above. */
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data. */
+ file_ptr filepos;
+
+ /* File position of relocation info. */
+ file_ptr rel_filepos;
+
+ /* File position of line data. */
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications. */
+ PTR userdata;
+
+ /* If the SEC_IN_MEMORY flag is set, this points to the actual
+ contents. */
+ unsigned char *contents;
+
+ /* Attached line number information. */
+ alent *lineno;
+
+ /* Number of line number records. */
+ unsigned int lineno_count;
+
+ /* Entity size for merging purposes. */
+ unsigned int entsize;
+
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct bfd_comdat_info *comdat;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out. */
+ file_ptr moving_line_filepos;
+
+ /* What the section number is in the target world. */
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+ bfd *owner;
+
+ /* A symbol which points at this section only. */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ struct bfd_link_order *link_order_head;
+ struct bfd_link_order *link_order_tail;
+} asection;
+
+/* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. New code should use the section_ptr macros rather
+ than referring directly to the const sections. The const sections
+ may eventually vanish. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* The absolute section. */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+/* Pointer to the undefined section. */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+/* Pointer to the common section. */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section. */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC) \
+ ( ((SEC) == bfd_abs_section_ptr) \
+ || ((SEC) == bfd_und_section_ptr) \
+ || ((SEC) == bfd_com_section_ptr) \
+ || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+ ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \
+ : (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section)->reloc_done ? (section)->_cooked_size \
+ : (abort (), (bfd_size_type) 1))
+
+/* Macros to handle insertion and deletion of a bfd's sections. These
+ only handle the list pointers, ie. do not adjust section_count,
+ target_index etc. */
+#define bfd_section_list_remove(ABFD, PS) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = *_ps; \
+ *_ps = _s->next; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = _ps; \
+ } \
+ while (0)
+#define bfd_section_list_insert(ABFD, PS, S) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = S; \
+ _s->next = *_ps; \
+ *_ps = _s; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = &_s->next; \
+ } \
+ while (0)
+
+void
+bfd_section_list_clear PARAMS ((bfd *));
+
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, const char *name));
+
+char *
+bfd_get_unique_section_name PARAMS ((bfd *abfd,
+ const char *templat,
+ int *count));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, const char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func) (bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR data, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_get_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec,
+ bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+ BFD_SEND (obfd, _bfd_copy_private_section_data, \
+ (ibfd, isection, obfd, osection))
+void
+_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
+
+enum bfd_architecture
+{
+ bfd_arch_unknown, /* File arch not known. */
+ bfd_arch_obscure, /* Arch known, not one of these. */
+ bfd_arch_m68k, /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32 8
+#define bfd_mach_mcf5200 9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307 11
+#define bfd_mach_mcf5407 12
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+#define bfd_mach_i960_jx 7
+#define bfd_mach_i960_hx 8
+
+ bfd_arch_or32, /* OpenRISC 32 */
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+#define bfd_mach_sparc 1
+/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
+#define bfd_mach_sparc_sparclet 2
+#define bfd_mach_sparc_sparclite 3
+#define bfd_mach_sparc_v8plus 4
+#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_sparclite_le 6
+#define bfd_mach_sparc_v9 7
+#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
+#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
+/* Nonzero if MACH has the v9 instruction set. */
+#define bfd_mach_sparc_v9_p(mach) \
+ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
+ && (mach) != bfd_mach_sparc_sparclite_le)
+ bfd_arch_mips, /* MIPS Rxxxx */
+#define bfd_mach_mips3000 3000
+#define bfd_mach_mips3900 3900
+#define bfd_mach_mips4000 4000
+#define bfd_mach_mips4010 4010
+#define bfd_mach_mips4100 4100
+#define bfd_mach_mips4111 4111
+#define bfd_mach_mips4300 4300
+#define bfd_mach_mips4400 4400
+#define bfd_mach_mips4600 4600
+#define bfd_mach_mips4650 4650
+#define bfd_mach_mips5000 5000
+#define bfd_mach_mips6000 6000
+#define bfd_mach_mips8000 8000
+#define bfd_mach_mips10000 10000
+#define bfd_mach_mips12000 12000
+#define bfd_mach_mips16 16
+#define bfd_mach_mips5 5
+#define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32 32
+#define bfd_mach_mipsisa64 64
+ bfd_arch_i386, /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+#define bfd_mach_x86_64 3
+#define bfd_mach_x86_64_intel_syntax 4
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_i370, /* IBM 360/370 Mainframes */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ bfd_arch_h8300, /* Hitachi H8/300 */
+#define bfd_mach_h8300 1
+#define bfd_mach_h8300h 2
+#define bfd_mach_h8300s 3
+ bfd_arch_pdp11, /* DEC PDP-11 */
+ bfd_arch_powerpc, /* PowerPC */
+#define bfd_mach_ppc 0
+#define bfd_mach_ppc64 1
+#define bfd_mach_ppc_403 403
+#define bfd_mach_ppc_403gc 4030
+#define bfd_mach_ppc_505 505
+#define bfd_mach_ppc_601 601
+#define bfd_mach_ppc_602 602
+#define bfd_mach_ppc_603 603
+#define bfd_mach_ppc_ec603e 6031
+#define bfd_mach_ppc_604 604
+#define bfd_mach_ppc_620 620
+#define bfd_mach_ppc_630 630
+#define bfd_mach_ppc_750 750
+#define bfd_mach_ppc_860 860
+#define bfd_mach_ppc_a35 35
+#define bfd_mach_ppc_rs64ii 642
+#define bfd_mach_ppc_rs64iii 643
+#define bfd_mach_ppc_7400 7400
+ bfd_arch_rs6000, /* IBM RS/6000 */
+#define bfd_mach_rs6k 0
+#define bfd_mach_rs6k_rs1 6001
+#define bfd_mach_rs6k_rsc 6003
+#define bfd_mach_rs6k_rs2 6002
+ bfd_arch_hppa, /* HP PA RISC */
+ bfd_arch_d10v, /* Mitsubishi D10V */
+#define bfd_mach_d10v 0
+#define bfd_mach_d10v_ts2 2
+#define bfd_mach_d10v_ts3 3
+ bfd_arch_d30v, /* Mitsubishi D30V */
+ bfd_arch_m68hc11, /* Motorola 68HC11 */
+ bfd_arch_m68hc12, /* Motorola 68HC12 */
+ bfd_arch_z8k, /* Zilog Z8000 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+#define bfd_mach_sh 0
+#define bfd_mach_sh2 0x20
+#define bfd_mach_sh_dsp 0x2d
+#define bfd_mach_sh3 0x30
+#define bfd_mach_sh3_dsp 0x3d
+#define bfd_mach_sh3e 0x3e
+#define bfd_mach_sh4 0x40
+#define bfd_mach_sh5 0x50
+ bfd_arch_alpha, /* Dec Alpha */
+#define bfd_mach_alpha_ev4 0x10
+#define bfd_mach_alpha_ev5 0x20
+#define bfd_mach_alpha_ev6 0x30
+ bfd_arch_arm, /* Advanced Risc Machines ARM. */
+#define bfd_mach_arm_2 1
+#define bfd_mach_arm_2a 2
+#define bfd_mach_arm_3 3
+#define bfd_mach_arm_3M 4
+#define bfd_mach_arm_4 5
+#define bfd_mach_arm_4T 6
+#define bfd_mach_arm_5 7
+#define bfd_mach_arm_5T 8
+#define bfd_mach_arm_5TE 9
+#define bfd_mach_arm_XScale 10
+ bfd_arch_ns32k, /* National Semiconductors ns32000 */
+ bfd_arch_w65, /* WDC 65816 */
+ bfd_arch_tic30, /* Texas Instruments TMS320C30 */
+ bfd_arch_tic54x, /* Texas Instruments TMS320C54X */
+ bfd_arch_tic80, /* TI TMS320c80 (MVP) */
+ bfd_arch_v850, /* NEC V850 */
+#define bfd_mach_v850 0
+#define bfd_mach_v850e 'E'
+#define bfd_mach_v850ea 'A'
+ bfd_arch_arc, /* ARC Cores */
+#define bfd_mach_arc_5 0
+#define bfd_mach_arc_6 1
+#define bfd_mach_arc_7 2
+#define bfd_mach_arc_8 3
+ bfd_arch_m32r, /* Mitsubishi M32R/D */
+#define bfd_mach_m32r 0 /* For backwards compatibility. */
+#define bfd_mach_m32rx 'x'
+ bfd_arch_mn10200, /* Matsushita MN10200 */
+ bfd_arch_mn10300, /* Matsushita MN10300 */
+#define bfd_mach_mn10300 300
+#define bfd_mach_am33 330
+ bfd_arch_fr30,
+#define bfd_mach_fr30 0x46523330
+ bfd_arch_mcore,
+ bfd_arch_ia64, /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64 0
+#define bfd_mach_ia64_elf32 1
+ bfd_arch_pj,
+ bfd_arch_avr, /* Atmel AVR microcontrollers. */
+#define bfd_mach_avr1 1
+#define bfd_mach_avr2 2
+#define bfd_mach_avr3 3
+#define bfd_mach_avr4 4
+#define bfd_mach_avr5 5
+ bfd_arch_cris, /* Axis CRIS */
+ bfd_arch_s390, /* IBM s390 */
+#define bfd_mach_s390_esa 0
+#define bfd_mach_s390_esame 1
+ bfd_arch_openrisc, /* OpenRISC */
+ bfd_arch_mmix, /* Donald Knuth's educational processor. */
+ bfd_arch_xstormy16,
+#define bfd_mach_xstormy16 0
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ unsigned long mach;
+ const char *arch_name;
+ const char *printable_name;
+ unsigned int section_align_power;
+ /* True if this is the default machine for the architecture. */
+ boolean the_default;
+ const struct bfd_arch_info * (*compatible)
+ PARAMS ((const struct bfd_arch_info *a,
+ const struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+ const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ const bfd *abfd,
+ const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch PARAMS ((enum bfd_architecture
+ arch,
+ unsigned long machine));
+
+const char *
+bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+unsigned int
+bfd_octets_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_mach_octets_per_byte PARAMS ((enum bfd_architecture arch,
+ unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected. */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions. */
+ bfd_reloc_continue,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_notsupported,
+
+ /* Unused. */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ symbols. If this type is returned, the error_message argument
+ to bfd_perform_relocation will be set. */
+ bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+ /* A pointer into the canonical table of pointers. */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section. */
+ bfd_size_type address;
+
+ /* addend for relocation value. */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation. */
+ reloc_howto_type *howto;
+
+}
+arelent;
+
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+ /* The type field has mainly a documentary use - the back end can
+ do what it wants with it, though normally the back end's
+ external idea of what a reloc number is stored
+ in this field. For example, a PC relative word relocation
+ in a coff environment has the type 023 - because that's
+ what the outside world calls a R_PCRWORD reloc. */
+ unsigned int type;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ power-of-two measure. To get the number of bytes operated
+ on by a type of relocation, use bfd_get_reloc_size. */
+ int size;
+
+ /* The number of bits in the item to be relocated. This is used
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ called rather than the normal function. This allows really
+ strange relocation methods to be accomodated (e.g., i960 callj
+ instructions). */
+ bfd_reloc_status_type (*special_function)
+ PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
+ bfd *, char **));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* Some formats record a relocation addend in the section contents
+ rather than with the relocation. For ELF formats this is the
+ distinction between USE_REL and USE_RELA (though the code checks
+ for USE_REL == 1/0). The value of this field is TRUE if the
+ addend is recorded with the section contents; when performing a
+ partial link (ld -r) the section contents (the data) will be
+ modified. The value of this field is FALSE if addends are
+ recorded with the relocation (in arelent.addend); when performing
+ a partial link the relocation will be modified.
+ All relocations for all ELF USE_RELA targets should set this field
+ to FALSE (values of TRUE should be looked on with suspicion).
+ However, the converse is not true: not all relocations of all ELF
+ USE_REL targets set this field to TRUE. Why this is so is peculiar
+ to each particular target. For relocs that aren't used in partial
+ links (e.g. GOT stuff) it doesn't matter what this is set to. */
+ boolean partial_inplace;
+
+ /* The src_mask selects which parts of the read in data
+ are to be used in the relocation sum. E.g., if this was an 8 bit
+ byte of data which we read and relocated, this would be
+ 0x000000ff. When we have relocs which have an addend, such as
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* The dst_mask selects which parts of the instruction are replaced
+ into the instruction. In most cases src_mask == dst_mask,
+ except in the above special case, where dst_mask would be
+ 0x000000ff, and src_mask would be 0x00000000. */
+ bfd_vma dst_mask;
+
+ /* When some formats create PC relative instructions, they leave
+ the value of the pc of the place being relocated in the offset
+ slot of the instruction, so that a PC relative relocation can
+ be made just by adding in an ordinary offset (e.g., sun3 a.out).
+ Some formats leave the displacement part of an instruction
+ empty (e.g., m88k bcs); this flag signals the fact. */
+ boolean pcrel_offset;
+};
+
+#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC }
+#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \
+ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \
+ NAME, false, 0, 0, IN)
+
+#define EMPTY_HOWTO(C) \
+ HOWTO ((C), 0, 0, 0, false, 0, complain_overflow_dont, NULL, \
+ NULL, false, 0, 0, false)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *) NULL) \
+ { \
+ if (bfd_is_com_section (symbol->section)) \
+ { \
+ relocation = 0; \
+ } \
+ else \
+ { \
+ relocation = symbol->value; \
+ } \
+ } \
+ }
+
+unsigned int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain
+{
+ arelent relent;
+ struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type
+bfd_check_overflow PARAMS ((enum complain_overflow how,
+ unsigned int bitsize,
+ unsigned int rightshift,
+ unsigned int addrsize,
+ bfd_vma relocation));
+
+bfd_reloc_status_type
+bfd_perform_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+bfd_reloc_status_type
+bfd_install_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message));
+
+enum bfd_reloc_code_real {
+ _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_26,
+ BFD_RELOC_24,
+ BFD_RELOC_16,
+ BFD_RELOC_14,
+ BFD_RELOC_8,
+
+/* PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_12_PCREL,
+ BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+ BFD_RELOC_32_GOT_PCREL,
+ BFD_RELOC_16_GOT_PCREL,
+ BFD_RELOC_8_GOT_PCREL,
+ BFD_RELOC_32_GOTOFF,
+ BFD_RELOC_16_GOTOFF,
+ BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF,
+ BFD_RELOC_8_GOTOFF,
+ BFD_RELOC_64_PLT_PCREL,
+ BFD_RELOC_32_PLT_PCREL,
+ BFD_RELOC_24_PLT_PCREL,
+ BFD_RELOC_16_PLT_PCREL,
+ BFD_RELOC_8_PLT_PCREL,
+ BFD_RELOC_64_PLTOFF,
+ BFD_RELOC_32_PLTOFF,
+ BFD_RELOC_16_PLTOFF,
+ BFD_RELOC_LO16_PLTOFF,
+ BFD_RELOC_HI16_PLTOFF,
+ BFD_RELOC_HI16_S_PLTOFF,
+ BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+ BFD_RELOC_68K_GLOB_DAT,
+ BFD_RELOC_68K_JMP_SLOT,
+ BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_LO16_BASEREL,
+ BFD_RELOC_HI16_BASEREL,
+ BFD_RELOC_HI16_S_BASEREL,
+ BFD_RELOC_8_BASEREL,
+ BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+ BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+ BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_16_PCREL_S2,
+ BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC. */
+ BFD_RELOC_HI22,
+ BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register. These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+ BFD_RELOC_GPREL16,
+ BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+ BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations. There is probably some overlap with other
+relocation types already defined. */
+ BFD_RELOC_NONE,
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA16,
+ BFD_RELOC_SPARC_UA32,
+ BFD_RELOC_SPARC_UA64,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+ BFD_RELOC_SPARC_10,
+ BFD_RELOC_SPARC_11,
+ BFD_RELOC_SPARC_OLO10,
+ BFD_RELOC_SPARC_HH22,
+ BFD_RELOC_SPARC_HM10,
+ BFD_RELOC_SPARC_LM22,
+ BFD_RELOC_SPARC_PC_HH22,
+ BFD_RELOC_SPARC_PC_HM10,
+ BFD_RELOC_SPARC_PC_LM22,
+ BFD_RELOC_SPARC_WDISP16,
+ BFD_RELOC_SPARC_WDISP19,
+ BFD_RELOC_SPARC_7,
+ BFD_RELOC_SPARC_6,
+ BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+ BFD_RELOC_SPARC_PLT32,
+ BFD_RELOC_SPARC_PLT64,
+ BFD_RELOC_SPARC_HIX22,
+ BFD_RELOC_SPARC_LOX10,
+ BFD_RELOC_SPARC_H44,
+ BFD_RELOC_SPARC_M44,
+ BFD_RELOC_SPARC_L44,
+ BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+ BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol. The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+ BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs. The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+ BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+ BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol. The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references. The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch) */
+ BFD_RELOC_ALPHA_LITERAL,
+ BFD_RELOC_ALPHA_ELF_LITERAL,
+ BFD_RELOC_ALPHA_LITUSE,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+ BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_CODEADDR,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register. */
+ BFD_RELOC_ALPHA_GPREL_HI16,
+ BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD. */
+ BFD_RELOC_ALPHA_BRSGP,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+ BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+ BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+ BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+ BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result. If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+ BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+ BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+ BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+ BFD_RELOC_PCREL_LO16,
+
+/* Relocation against a MIPS literal section. */
+ BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+ BFD_RELOC_MIPS_GOT16,
+ BFD_RELOC_MIPS_CALL16,
+ BFD_RELOC_MIPS_GOT_HI16,
+ BFD_RELOC_MIPS_GOT_LO16,
+ BFD_RELOC_MIPS_CALL_HI16,
+ BFD_RELOC_MIPS_CALL_LO16,
+ BFD_RELOC_MIPS_SUB,
+ BFD_RELOC_MIPS_GOT_PAGE,
+ BFD_RELOC_MIPS_GOT_OFST,
+ BFD_RELOC_MIPS_GOT_DISP,
+ BFD_RELOC_MIPS_SHIFT5,
+ BFD_RELOC_MIPS_SHIFT6,
+ BFD_RELOC_MIPS_INSERT_A,
+ BFD_RELOC_MIPS_INSERT_B,
+ BFD_RELOC_MIPS_DELETE,
+ BFD_RELOC_MIPS_HIGHEST,
+ BFD_RELOC_MIPS_HIGHER,
+ BFD_RELOC_MIPS_SCN_DISP,
+ BFD_RELOC_MIPS_REL16,
+ BFD_RELOC_MIPS_RELGOT,
+ BFD_RELOC_MIPS_JALR,
+ BFD_RELOC_SH_GOT_LOW16,
+ BFD_RELOC_SH_GOT_MEDLOW16,
+ BFD_RELOC_SH_GOT_MEDHI16,
+ BFD_RELOC_SH_GOT_HI16,
+ BFD_RELOC_SH_GOTPLT_LOW16,
+ BFD_RELOC_SH_GOTPLT_MEDLOW16,
+ BFD_RELOC_SH_GOTPLT_MEDHI16,
+ BFD_RELOC_SH_GOTPLT_HI16,
+ BFD_RELOC_SH_PLT_LOW16,
+ BFD_RELOC_SH_PLT_MEDLOW16,
+ BFD_RELOC_SH_PLT_MEDHI16,
+ BFD_RELOC_SH_PLT_HI16,
+ BFD_RELOC_SH_GOTOFF_LOW16,
+ BFD_RELOC_SH_GOTOFF_MEDLOW16,
+ BFD_RELOC_SH_GOTOFF_MEDHI16,
+ BFD_RELOC_SH_GOTOFF_HI16,
+ BFD_RELOC_SH_GOTPC_LOW16,
+ BFD_RELOC_SH_GOTPC_MEDLOW16,
+ BFD_RELOC_SH_GOTPC_MEDHI16,
+ BFD_RELOC_SH_GOTPC_HI16,
+ BFD_RELOC_SH_COPY64,
+ BFD_RELOC_SH_GLOB_DAT64,
+ BFD_RELOC_SH_JMP_SLOT64,
+ BFD_RELOC_SH_RELATIVE64,
+ BFD_RELOC_SH_GOT10BY4,
+ BFD_RELOC_SH_GOT10BY8,
+ BFD_RELOC_SH_GOTPLT10BY4,
+ BFD_RELOC_SH_GOTPLT10BY8,
+ BFD_RELOC_SH_GOTPLT32,
+ BFD_RELOC_SH_SHMEDIA_CODE,
+ BFD_RELOC_SH_IMMU5,
+ BFD_RELOC_SH_IMMS6,
+ BFD_RELOC_SH_IMMS6BY32,
+ BFD_RELOC_SH_IMMU6,
+ BFD_RELOC_SH_IMMS10,
+ BFD_RELOC_SH_IMMS10BY2,
+ BFD_RELOC_SH_IMMS10BY4,
+ BFD_RELOC_SH_IMMS10BY8,
+ BFD_RELOC_SH_IMMS16,
+ BFD_RELOC_SH_IMMU16,
+ BFD_RELOC_SH_IMM_LOW16,
+ BFD_RELOC_SH_IMM_LOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDLOW16,
+ BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDHI16,
+ BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+ BFD_RELOC_SH_IMM_HI16,
+ BFD_RELOC_SH_IMM_HI16_PCREL,
+ BFD_RELOC_SH_PT_16,
+
+
+/* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ BFD_RELOC_386_GOTOFF,
+ BFD_RELOC_386_GOTPC,
+
+/* x86-64/elf relocations */
+ BFD_RELOC_X86_64_GOT32,
+ BFD_RELOC_X86_64_PLT32,
+ BFD_RELOC_X86_64_COPY,
+ BFD_RELOC_X86_64_GLOB_DAT,
+ BFD_RELOC_X86_64_JUMP_SLOT,
+ BFD_RELOC_X86_64_RELATIVE,
+ BFD_RELOC_X86_64_GOTPCREL,
+ BFD_RELOC_X86_64_32S,
+
+/* ns32k relocations */
+ BFD_RELOC_NS32K_IMM_8,
+ BFD_RELOC_NS32K_IMM_16,
+ BFD_RELOC_NS32K_IMM_32,
+ BFD_RELOC_NS32K_IMM_8_PCREL,
+ BFD_RELOC_NS32K_IMM_16_PCREL,
+ BFD_RELOC_NS32K_IMM_32_PCREL,
+ BFD_RELOC_NS32K_DISP_8,
+ BFD_RELOC_NS32K_DISP_16,
+ BFD_RELOC_NS32K_DISP_32,
+ BFD_RELOC_NS32K_DISP_8_PCREL,
+ BFD_RELOC_NS32K_DISP_16_PCREL,
+ BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* PDP11 relocations */
+ BFD_RELOC_PDP11_DISP_8_PCREL,
+ BFD_RELOC_PDP11_DISP_6_PCREL,
+
+/* Picojava relocs. Not all of these appear in object files. */
+ BFD_RELOC_PJ_CODE_HI16,
+ BFD_RELOC_PJ_CODE_LO16,
+ BFD_RELOC_PJ_CODE_DIR16,
+ BFD_RELOC_PJ_CODE_DIR32,
+ BFD_RELOC_PJ_CODE_REL16,
+ BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+ BFD_RELOC_PPC_B26,
+ BFD_RELOC_PPC_BA26,
+ BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_B16,
+ BFD_RELOC_PPC_B16_BRTAKEN,
+ BFD_RELOC_PPC_B16_BRNTAKEN,
+ BFD_RELOC_PPC_BA16,
+ BFD_RELOC_PPC_BA16_BRTAKEN,
+ BFD_RELOC_PPC_BA16_BRNTAKEN,
+ BFD_RELOC_PPC_COPY,
+ BFD_RELOC_PPC_GLOB_DAT,
+ BFD_RELOC_PPC_JMP_SLOT,
+ BFD_RELOC_PPC_RELATIVE,
+ BFD_RELOC_PPC_LOCAL24PC,
+ BFD_RELOC_PPC_EMB_NADDR32,
+ BFD_RELOC_PPC_EMB_NADDR16,
+ BFD_RELOC_PPC_EMB_NADDR16_LO,
+ BFD_RELOC_PPC_EMB_NADDR16_HI,
+ BFD_RELOC_PPC_EMB_NADDR16_HA,
+ BFD_RELOC_PPC_EMB_SDAI16,
+ BFD_RELOC_PPC_EMB_SDA2I16,
+ BFD_RELOC_PPC_EMB_SDA2REL,
+ BFD_RELOC_PPC_EMB_SDA21,
+ BFD_RELOC_PPC_EMB_MRKREF,
+ BFD_RELOC_PPC_EMB_RELSEC16,
+ BFD_RELOC_PPC_EMB_RELST_LO,
+ BFD_RELOC_PPC_EMB_RELST_HI,
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
+ BFD_RELOC_PPC64_HIGHER,
+ BFD_RELOC_PPC64_HIGHER_S,
+ BFD_RELOC_PPC64_HIGHEST,
+ BFD_RELOC_PPC64_HIGHEST_S,
+ BFD_RELOC_PPC64_TOC16_LO,
+ BFD_RELOC_PPC64_TOC16_HI,
+ BFD_RELOC_PPC64_TOC16_HA,
+ BFD_RELOC_PPC64_TOC,
+ BFD_RELOC_PPC64_PLTGOT16,
+ BFD_RELOC_PPC64_PLTGOT16_LO,
+ BFD_RELOC_PPC64_PLTGOT16_HI,
+ BFD_RELOC_PPC64_PLTGOT16_HA,
+ BFD_RELOC_PPC64_ADDR16_DS,
+ BFD_RELOC_PPC64_ADDR16_LO_DS,
+ BFD_RELOC_PPC64_GOT16_DS,
+ BFD_RELOC_PPC64_GOT16_LO_DS,
+ BFD_RELOC_PPC64_PLT16_LO_DS,
+ BFD_RELOC_PPC64_SECTOFF_DS,
+ BFD_RELOC_PPC64_SECTOFF_LO_DS,
+ BFD_RELOC_PPC64_TOC16_DS,
+ BFD_RELOC_PPC64_TOC16_LO_DS,
+ BFD_RELOC_PPC64_PLTGOT16_DS,
+ BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* IBM 370/390 relocations */
+ BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+ BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. */
+ BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BLX,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_ADRL_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_ADR_IMM,
+ BFD_RELOC_ARM_LDR_IMM,
+ BFD_RELOC_ARM_LITERAL,
+ BFD_RELOC_ARM_IN_POOL,
+ BFD_RELOC_ARM_OFFSET_IMM8,
+ BFD_RELOC_ARM_HWLITERAL,
+ BFD_RELOC_ARM_THUMB_ADD,
+ BFD_RELOC_ARM_THUMB_IMM,
+ BFD_RELOC_ARM_THUMB_SHIFT,
+ BFD_RELOC_ARM_THUMB_OFFSET,
+ BFD_RELOC_ARM_GOT12,
+ BFD_RELOC_ARM_GOT32,
+ BFD_RELOC_ARM_JUMP_SLOT,
+ BFD_RELOC_ARM_COPY,
+ BFD_RELOC_ARM_GLOB_DAT,
+ BFD_RELOC_ARM_PLT32,
+ BFD_RELOC_ARM_RELATIVE,
+ BFD_RELOC_ARM_GOTOFF,
+ BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs. Not all of these appear in object files. */
+ BFD_RELOC_SH_PCDISP8BY2,
+ BFD_RELOC_SH_PCDISP12BY2,
+ BFD_RELOC_SH_IMM4,
+ BFD_RELOC_SH_IMM4BY2,
+ BFD_RELOC_SH_IMM4BY4,
+ BFD_RELOC_SH_IMM8,
+ BFD_RELOC_SH_IMM8BY2,
+ BFD_RELOC_SH_IMM8BY4,
+ BFD_RELOC_SH_PCRELIMM8BY2,
+ BFD_RELOC_SH_PCRELIMM8BY4,
+ BFD_RELOC_SH_SWITCH16,
+ BFD_RELOC_SH_SWITCH32,
+ BFD_RELOC_SH_USES,
+ BFD_RELOC_SH_COUNT,
+ BFD_RELOC_SH_ALIGN,
+ BFD_RELOC_SH_CODE,
+ BFD_RELOC_SH_DATA,
+ BFD_RELOC_SH_LABEL,
+ BFD_RELOC_SH_LOOP_START,
+ BFD_RELOC_SH_LOOP_END,
+ BFD_RELOC_SH_COPY,
+ BFD_RELOC_SH_GLOB_DAT,
+ BFD_RELOC_SH_JMP_SLOT,
+ BFD_RELOC_SH_RELATIVE,
+ BFD_RELOC_SH_GOTPC,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
+be zero and is not stored in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BRANCH9,
+ BFD_RELOC_THUMB_PCREL_BRANCH12,
+ BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* ARC Cores relocs.
+ARC 22 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+ BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch. The lowest two bits must be zero and are not
+stored in the instruction. The high 24 bits are installed in bits 23
+through 0. */
+ BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+ BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+ BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the
+right 3 bitsassumed to be 0. */
+ BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+ BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+ BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+ BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+ BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+ BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+ BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+ BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+ BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+ BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+ BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+ BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+ BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+ BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+ BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+ BFD_RELOC_TIC30_LDP,
+
+/* This is a 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x. */
+ BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+ BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+ BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+ BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+ BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+ BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+ BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+ BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+ BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+ BFD_RELOC_MCORE_PCREL_IMM8BY4,
+ BFD_RELOC_MCORE_PCREL_IMM11BY2,
+ BFD_RELOC_MCORE_PCREL_IMM4BY2,
+ BFD_RELOC_MCORE_PCREL_32,
+ BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+ BFD_RELOC_MCORE_RVA,
+
+/* These are relocations for the GETA instruction. */
+ BFD_RELOC_MMIX_GETA,
+ BFD_RELOC_MMIX_GETA_1,
+ BFD_RELOC_MMIX_GETA_2,
+ BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction. */
+ BFD_RELOC_MMIX_CBRANCH,
+ BFD_RELOC_MMIX_CBRANCH_J,
+ BFD_RELOC_MMIX_CBRANCH_1,
+ BFD_RELOC_MMIX_CBRANCH_2,
+ BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction. */
+ BFD_RELOC_MMIX_PUSHJ,
+ BFD_RELOC_MMIX_PUSHJ_1,
+ BFD_RELOC_MMIX_PUSHJ_2,
+ BFD_RELOC_MMIX_PUSHJ_3,
+
+/* These are relocations for the JMP instruction. */
+ BFD_RELOC_MMIX_JMP,
+ BFD_RELOC_MMIX_JMP_1,
+ BFD_RELOC_MMIX_JMP_2,
+ BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch. */
+ BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction. */
+ BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255. */
+ BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register. */
+ BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation. */
+ BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register. It does not modify contents. */
+ BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits. */
+ BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits. */
+ BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits. */
+ BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits. */
+ BFD_RELOC_AVR_CALL,
+
+/* Direct 12 bit. */
+ BFD_RELOC_390_12,
+
+/* 12 bit GOT offset. */
+ BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime. */
+ BFD_RELOC_390_COPY,
+
+/* Create GOT entry. */
+ BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry. */
+ BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base. */
+ BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT. */
+ BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset. */
+ BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1. */
+ BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1. */
+ BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1. */
+ BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset. */
+ BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry. */
+ BFD_RELOC_390_GOTENT,
+
+/* These two relocations are used by the linker to determine which of
+the entries in a C++ virtual function table are actually used. When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table. The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry. The reloc's symbol should refer to the
+table of the class mentioned in the code. Off of that base, an offset
+describes the entry that is being used. For Rela hosts, this offset
+is stored in the reloc's addend. For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+ BFD_RELOC_VTABLE_INHERIT,
+ BFD_RELOC_VTABLE_ENTRY,
+
+/* Intel IA64 Relocations. */
+ BFD_RELOC_IA64_IMM14,
+ BFD_RELOC_IA64_IMM22,
+ BFD_RELOC_IA64_IMM64,
+ BFD_RELOC_IA64_DIR32MSB,
+ BFD_RELOC_IA64_DIR32LSB,
+ BFD_RELOC_IA64_DIR64MSB,
+ BFD_RELOC_IA64_DIR64LSB,
+ BFD_RELOC_IA64_GPREL22,
+ BFD_RELOC_IA64_GPREL64I,
+ BFD_RELOC_IA64_GPREL32MSB,
+ BFD_RELOC_IA64_GPREL32LSB,
+ BFD_RELOC_IA64_GPREL64MSB,
+ BFD_RELOC_IA64_GPREL64LSB,
+ BFD_RELOC_IA64_LTOFF22,
+ BFD_RELOC_IA64_LTOFF64I,
+ BFD_RELOC_IA64_PLTOFF22,
+ BFD_RELOC_IA64_PLTOFF64I,
+ BFD_RELOC_IA64_PLTOFF64MSB,
+ BFD_RELOC_IA64_PLTOFF64LSB,
+ BFD_RELOC_IA64_FPTR64I,
+ BFD_RELOC_IA64_FPTR32MSB,
+ BFD_RELOC_IA64_FPTR32LSB,
+ BFD_RELOC_IA64_FPTR64MSB,
+ BFD_RELOC_IA64_FPTR64LSB,
+ BFD_RELOC_IA64_PCREL21B,
+ BFD_RELOC_IA64_PCREL21BI,
+ BFD_RELOC_IA64_PCREL21M,
+ BFD_RELOC_IA64_PCREL21F,
+ BFD_RELOC_IA64_PCREL22,
+ BFD_RELOC_IA64_PCREL60B,
+ BFD_RELOC_IA64_PCREL64I,
+ BFD_RELOC_IA64_PCREL32MSB,
+ BFD_RELOC_IA64_PCREL32LSB,
+ BFD_RELOC_IA64_PCREL64MSB,
+ BFD_RELOC_IA64_PCREL64LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR22,
+ BFD_RELOC_IA64_LTOFF_FPTR64I,
+ BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+ BFD_RELOC_IA64_SEGREL32MSB,
+ BFD_RELOC_IA64_SEGREL32LSB,
+ BFD_RELOC_IA64_SEGREL64MSB,
+ BFD_RELOC_IA64_SEGREL64LSB,
+ BFD_RELOC_IA64_SECREL32MSB,
+ BFD_RELOC_IA64_SECREL32LSB,
+ BFD_RELOC_IA64_SECREL64MSB,
+ BFD_RELOC_IA64_SECREL64LSB,
+ BFD_RELOC_IA64_REL32MSB,
+ BFD_RELOC_IA64_REL32LSB,
+ BFD_RELOC_IA64_REL64MSB,
+ BFD_RELOC_IA64_REL64LSB,
+ BFD_RELOC_IA64_LTV32MSB,
+ BFD_RELOC_IA64_LTV32LSB,
+ BFD_RELOC_IA64_LTV64MSB,
+ BFD_RELOC_IA64_LTV64LSB,
+ BFD_RELOC_IA64_IPLTMSB,
+ BFD_RELOC_IA64_IPLTLSB,
+ BFD_RELOC_IA64_COPY,
+ BFD_RELOC_IA64_TPREL22,
+ BFD_RELOC_IA64_TPREL64MSB,
+ BFD_RELOC_IA64_TPREL64LSB,
+ BFD_RELOC_IA64_LTOFF_TP22,
+ BFD_RELOC_IA64_LTOFF22X,
+ BFD_RELOC_IA64_LDXMOV,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits high part of an absolute address. */
+ BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits low part of an absolute address. */
+ BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bits of a value. */
+ BFD_RELOC_M68HC11_3B,
+
+/* These relocs are only used within the CRIS assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_CRIS_BDISP8,
+ BFD_RELOC_CRIS_UNSIGNED_5,
+ BFD_RELOC_CRIS_SIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS. */
+ BFD_RELOC_CRIS_COPY,
+ BFD_RELOC_CRIS_GLOB_DAT,
+ BFD_RELOC_CRIS_JUMP_SLOT,
+ BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT. */
+ BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT. */
+ BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation. */
+ BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations. */
+ BFD_RELOC_860_COPY,
+ BFD_RELOC_860_GLOB_DAT,
+ BFD_RELOC_860_JUMP_SLOT,
+ BFD_RELOC_860_RELATIVE,
+ BFD_RELOC_860_PC26,
+ BFD_RELOC_860_PLT26,
+ BFD_RELOC_860_PC16,
+ BFD_RELOC_860_LOW0,
+ BFD_RELOC_860_SPLIT0,
+ BFD_RELOC_860_LOW1,
+ BFD_RELOC_860_SPLIT1,
+ BFD_RELOC_860_LOW2,
+ BFD_RELOC_860_SPLIT2,
+ BFD_RELOC_860_LOW3,
+ BFD_RELOC_860_LOGOT0,
+ BFD_RELOC_860_SPGOT0,
+ BFD_RELOC_860_LOGOT1,
+ BFD_RELOC_860_SPGOT1,
+ BFD_RELOC_860_LOGOTOFF0,
+ BFD_RELOC_860_SPGOTOFF0,
+ BFD_RELOC_860_LOGOTOFF1,
+ BFD_RELOC_860_SPGOTOFF1,
+ BFD_RELOC_860_LOGOTOFF2,
+ BFD_RELOC_860_LOGOTOFF3,
+ BFD_RELOC_860_LOPC,
+ BFD_RELOC_860_HIGHADJ,
+ BFD_RELOC_860_HAGOT,
+ BFD_RELOC_860_HAGOTOFF,
+ BFD_RELOC_860_HAPC,
+ BFD_RELOC_860_HIGH,
+ BFD_RELOC_860_HIGOT,
+ BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations. */
+ BFD_RELOC_OPENRISC_ABS_26,
+ BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations. */
+ BFD_RELOC_H8_DIR16A8,
+ BFD_RELOC_H8_DIR16R8,
+ BFD_RELOC_H8_DIR24A8,
+ BFD_RELOC_H8_DIR24R8,
+ BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations. */
+ BFD_RELOC_XSTORMY16_REL_12,
+ BFD_RELOC_XSTORMY16_24,
+ BFD_RELOC_XSTORMY16_FPTR16,
+ BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+ /* A pointer to the BFD which owns the symbol. This information
+ is necessary so that a back end can work out what additional
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+ struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+ /* The text of the symbol. The name is left alone, and not copied; the
+ application may not alter it. */
+ const char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol. */
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ value is the offset into the section of the data. */
+#define BSF_GLOBAL 0x02
+
+ /* The symbol has global scope and is exported. The value is
+ the offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* No real difference. */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>>. */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning, unless BSF_DEBUGGING_RELOC is also set. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. The name is a
+ warning. The name of the next symbol is the one to warn about;
+ if a reference is made to a symbol with the same name as the next
+ symbol, a warning is issued by the linker. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. This symbol is an indirect
+ pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ /* Symbol is from dynamic linking information. */
+#define BSF_DYNAMIC 0x8000
+
+ /* The symbol denotes a data object. Used in ELF, and perhaps
+ others someday. */
+#define BSF_OBJECT 0x10000
+
+ /* This symbol is a debugging symbol. The value is the offset
+ into the section of the data. BSF_DEBUGGING should be set
+ as well. */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+ flagword flags;
+
+ /* A pointer to the section to which this symbol is
+ relative. This will always be non NULL, there are special
+ sections for undefined and absolute symbols. */
+ struct sec *section;
+
+ /* Back end special data. */
+ union
+ {
+ PTR p;
+ bfd_vma i;
+ }
+ udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+boolean
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+ BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+ (abfd, location))
+
+boolean
+bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((bfd *abfd, PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *
+_bfd_generic_make_empty_symbol PARAMS ((bfd *));
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+boolean
+bfd_is_undefined_symclass PARAMS ((int symclass));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+ (ibfd, isymbol, obfd, osymbol))
+
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ const char *filename;
+
+ /* A pointer to the target jump table. */
+ const struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char *",
+ and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ PTR iostream;
+
+ /* Is the file descriptor being cached? That is, can it be closed as
+ needed, and re-opened when accessed later? */
+ boolean cacheable;
+
+ /* Marks whether there was a default target specified when the
+ BFD was opened. This is used to select which matching algorithm
+ to use to choose the back end. */
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs. */
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here... */
+ ufile_ptr where;
+
+ /* ... and here: (``once'' means at least once). */
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time. */
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true. */
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension. */
+ int ifd;
+
+ /* The format which belongs to the BFD. (object, core, etc.) */
+ bfd_format format;
+
+ /* The direction with which the BFD was opened. */
+ enum bfd_direction
+ {
+ no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3
+ }
+ direction;
+
+ /* Format_specific flags. */
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+ ufile_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ from happening. */
+ boolean output_has_begun;
+
+ /* A hash table for section names. */
+ struct bfd_hash_table section_htab;
+
+ /* Pointer to linked list of sections. */
+ struct sec *sections;
+
+ /* The place where we add to the section list. */
+ struct sec **section_tail;
+
+ /* The number of sections. */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output. */
+ unsigned int symcount;
+
+ /* Symbol table for output BFD (with symcount entries). */
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information. */
+ const struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives. */
+ PTR arelt_data;
+ struct _bfd *my_archive; /* The containing archive BFD. */
+ struct _bfd *next; /* The next BFD in the archive. */
+ struct _bfd *archive_head; /* The first BFD in the archive. */
+ boolean has_armap;
+
+ /* A chain of BFD structures involved in a link. */
+ struct _bfd *link_next;
+
+ /* A field used by _bfd_generic_link_add_archive_symbols. This will
+ be used only for archive elements. */
+ int archive_pass;
+
+ /* Used by the back end to hold private data. */
+ union
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct pe_tdata *pe_obj_data;
+ struct xcoff_tdata *xcoff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct ihex_data_struct *ihex_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct mmo_data_struct *mmo_data;
+ struct sun_core_struct *sun_core_data;
+ struct sco5_core_struct *sco5_core_data;
+ struct trad_core_struct *trad_core_data;
+ struct som_data_struct *som_data;
+ struct hpux_core_struct *hpux_core_data;
+ struct hppabsd_core_struct *hppabsd_core_data;
+ struct sgi_core_struct *sgi_core_data;
+ struct lynx_core_struct *lynx_core_data;
+ struct osf_core_struct *osf_core_data;
+ struct cisco_core_struct *cisco_core_data;
+ struct versados_data_struct *versados_data;
+ struct netbsd_core_struct *netbsd_core_data;
+ PTR any;
+ }
+ tdata;
+
+ /* Used by the application to hold private data. */
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes. This is a
+ struct objalloc *, but we use PTR to avoid requiring the inclusion of
+ objalloc.h. */
+ PTR memory;
+};
+
+typedef enum bfd_error
+{
+ bfd_error_no_error = 0,
+ bfd_error_system_call,
+ bfd_error_invalid_target,
+ bfd_error_wrong_format,
+ bfd_error_wrong_object_format,
+ bfd_error_invalid_operation,
+ bfd_error_no_memory,
+ bfd_error_no_symbols,
+ bfd_error_no_armap,
+ bfd_error_no_more_archived_files,
+ bfd_error_malformed_archive,
+ bfd_error_file_not_recognized,
+ bfd_error_file_ambiguously_recognized,
+ bfd_error_no_contents,
+ bfd_error_nonrepresentable_section,
+ bfd_error_no_debug_section,
+ bfd_error_bad_value,
+ bfd_error_file_truncated,
+ bfd_error_file_too_big,
+ bfd_error_invalid_error_code
+}
+bfd_error_type;
+
+bfd_error_type
+bfd_get_error PARAMS ((void));
+
+void
+bfd_set_error PARAMS ((bfd_error_type error_tag));
+
+const char *
+bfd_errmsg PARAMS ((bfd_error_type error_tag));
+
+void
+bfd_perror PARAMS ((const char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+bfd_error_handler_type
+bfd_get_error_handler PARAMS ((void));
+
+const char *
+bfd_archive_filename PARAMS ((bfd *));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+void
+bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count));
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+int
+bfd_get_arch_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_sign_extend_vma PARAMS ((bfd *abfd));
+
+boolean
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+bfd_set_gp_size PARAMS ((bfd *abfd, unsigned int i));
+
+bfd_vma
+bfd_scan_vma PARAMS ((const char *string, const char **end, int base));
+
+boolean
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+ BFD_SEND (abfd, _bfd_set_private_flags, \
+ (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_merge_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+ BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+ BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *,
+ boolean, asymbol **));
+
+boolean
+bfd_alt_mach_code PARAMS ((bfd *abfd, int index));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+const char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+ ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ ((*((bfd)->xvec->message)) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+
+enum bfd_flavour
+{
+ bfd_target_unknown_flavour,
+ bfd_target_aout_flavour,
+ bfd_target_coff_flavour,
+ bfd_target_ecoff_flavour,
+ bfd_target_xcoff_flavour,
+ bfd_target_elf_flavour,
+ bfd_target_ieee_flavour,
+ bfd_target_nlm_flavour,
+ bfd_target_oasys_flavour,
+ bfd_target_tekhex_flavour,
+ bfd_target_srec_flavour,
+ bfd_target_ihex_flavour,
+ bfd_target_som_flavour,
+ bfd_target_os9k_flavour,
+ bfd_target_versados_flavour,
+ bfd_target_msdos_flavour,
+ bfd_target_ovax_flavour,
+ bfd_target_evax_flavour,
+ bfd_target_mmo_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+/* Forward declaration. */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+ /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */
+ char *name;
+
+ /* The "flavour" of a back end is a general indication about
+ the contents of a file. */
+ enum bfd_flavour flavour;
+
+ /* The order of bytes within the data area of a file. */
+ enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file. */
+ enum bfd_endian header_byteorder;
+
+ /* A mask of all the flags which an executable may have set -
+ from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>. */
+ flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+ the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>. */
+ flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+ (if any), perhaps `_'. */
+ char symbol_leading_char;
+
+ /* The pad character for file names within an archive header. */
+ char ar_pad_char;
+
+ /* The maximum number of characters in an archive header. */
+ unsigned short ar_max_namelen;
+
+ /* Entries for byte swapping for data. These are different from the
+ other entry points, since they don't take a BFD asthe first argument.
+ Certain other handlers could do the same. */
+ bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Byte swapping for the headers. */
+ bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Format dependent routines: these are vectors of entry points
+ within the target vector structure, one for each format to check. */
+
+ /* Check the format of a file being read. Return a <<bfd_target *>> or zero. */
+ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Set the format of a file being written. */
+ boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Write cached information into a file being written, at <<bfd_close>>. */
+ boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+
+ /* Generic entry points. */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+CONCAT2 (NAME,_close_and_cleanup), \
+CONCAT2 (NAME,_bfd_free_cached_info), \
+CONCAT2 (NAME,_new_section_hook), \
+CONCAT2 (NAME,_get_section_contents), \
+CONCAT2 (NAME,_get_section_contents_in_window)
+
+ /* Called when the BFD is being closed to do any necessary cleanup. */
+ boolean (*_close_and_cleanup) PARAMS ((bfd *));
+ /* Ask the BFD to free all cached information. */
+ boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+ /* Called when a new section is created. */
+ boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+ /* Read the contents of a section. */
+ boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type));
+
+ /* Entry points to copy private data. */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+CONCAT2 (NAME,_bfd_copy_private_bfd_data), \
+CONCAT2 (NAME,_bfd_merge_private_bfd_data), \
+CONCAT2 (NAME,_bfd_copy_private_section_data), \
+CONCAT2 (NAME,_bfd_copy_private_symbol_data), \
+CONCAT2 (NAME,_bfd_set_private_flags), \
+CONCAT2 (NAME,_bfd_print_private_bfd_data) \
+ /* Called to copy BFD general private data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to merge BFD general private data from one object file
+ to a common output file when linking. */
+ boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to copy BFD private section data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+ bfd *, sec_ptr));
+ /* Called to copy BFD private symbol data from one symbol
+ to another. */
+ boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+ /* Called to set private backend flags. */
+ boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+ /* Called to print private BFD data. */
+ boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+ /* Core file entry points. */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+CONCAT2 (NAME,_core_file_failing_command), \
+CONCAT2 (NAME,_core_file_failing_signal), \
+CONCAT2 (NAME,_core_file_matches_executable_p)
+ char * (*_core_file_failing_command) PARAMS ((bfd *));
+ int (*_core_file_failing_signal) PARAMS ((bfd *));
+ boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+ /* Archive entry points. */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+CONCAT2 (NAME,_slurp_armap), \
+CONCAT2 (NAME,_slurp_extended_name_table), \
+CONCAT2 (NAME,_construct_extended_name_table), \
+CONCAT2 (NAME,_truncate_arname), \
+CONCAT2 (NAME,_write_armap), \
+CONCAT2 (NAME,_read_ar_hdr), \
+CONCAT2 (NAME,_openr_next_archived_file), \
+CONCAT2 (NAME,_get_elt_at_index), \
+CONCAT2 (NAME,_generic_stat_arch_elt), \
+CONCAT2 (NAME,_update_armap_timestamp)
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ boolean (*_bfd_construct_extended_name_table)
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, const char *, char *));
+ boolean (*write_armap)
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+ PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *, bfd *));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+ bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+ boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+ /* Entry points used for symbols. */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+CONCAT2 (NAME,_get_symtab_upper_bound), \
+CONCAT2 (NAME,_get_symtab), \
+CONCAT2 (NAME,_make_empty_symbol), \
+CONCAT2 (NAME,_print_symbol), \
+CONCAT2 (NAME,_get_symbol_info), \
+CONCAT2 (NAME,_bfd_is_local_label_name), \
+CONCAT2 (NAME,_get_lineno), \
+CONCAT2 (NAME,_find_nearest_line), \
+CONCAT2 (NAME,_bfd_make_debug_symbol), \
+CONCAT2 (NAME,_read_minisymbols), \
+CONCAT2 (NAME,_minisymbol_to_symbol)
+ long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+ long (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+ struct symbol_cache_entry *
+ (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+ void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ struct symbol_cache_entry *,
+ symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+ boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+ alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+ boolean (*_bfd_find_nearest_line)
+ PARAMS ((bfd *, struct sec *, struct symbol_cache_entry **, bfd_vma,
+ const char **, const char **, unsigned int *));
+ /* Back-door to allow format-aware applications to create debug symbols
+ while using BFD for everything else. Currently used by the assembler
+ when creating COFF files. */
+ asymbol *(*_bfd_make_debug_symbol) PARAMS ((bfd *, void *,
+ unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+ BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+ long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+ unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+ asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+ /* Routines for relocs. */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+CONCAT2 (NAME,_get_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_reloc), \
+CONCAT2 (NAME,_bfd_reloc_type_lookup)
+ long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+ long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+ struct symbol_cache_entry **));
+ /* See documentation on reloc types. */
+ reloc_howto_type *
+ (*reloc_type_lookup) PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+ /* Routines used when writing an object file. */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+CONCAT2 (NAME,_set_arch_mach), \
+CONCAT2 (NAME,_set_section_contents)
+ boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+ boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+
+ /* Routines used by the linker. */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+CONCAT2 (NAME,_sizeof_headers), \
+CONCAT2 (NAME,_bfd_get_relocated_section_contents), \
+CONCAT2 (NAME,_bfd_relax_section), \
+CONCAT2 (NAME,_bfd_link_hash_table_create), \
+CONCAT2 (NAME,_bfd_link_add_symbols), \
+CONCAT2 (NAME,_bfd_final_link), \
+CONCAT2 (NAME,_bfd_link_split_section), \
+CONCAT2 (NAME,_bfd_gc_sections), \
+CONCAT2 (NAME,_bfd_merge_sections)
+ int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+ bfd_byte *(*_bfd_get_relocated_section_contents)
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, struct symbol_cache_entry **));
+
+ boolean (*_bfd_relax_section)
+ PARAMS ((bfd *, struct sec *, struct bfd_link_info *, boolean *));
+
+ /* Create a hash table for the linker. Different backends store
+ different information in this table. */
+ struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+ /* Add symbols from this object file into the hash table. */
+ boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Do a link based on the link_order structures attached to each
+ section of the BFD. */
+ boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Should this section be split up into smaller pieces during linking. */
+ boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+ /* Remove sections that are not referenced from the output. */
+ boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Attempt to merge SEC_MERGE sections. */
+ boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Routines to handle dynamic symbols and relocs. */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+CONCAT2 (NAME,_get_dynamic_symtab_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_symtab), \
+CONCAT2 (NAME,_get_dynamic_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_reloc)
+ /* Get the amount of memory required to hold the dynamic symbols. */
+ long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic symbols. */
+ long (*_bfd_canonicalize_dynamic_symtab)
+ PARAMS ((bfd *, struct symbol_cache_entry **));
+ /* Get the amount of memory required to hold the dynamic relocs. */
+ long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic relocs. */
+ long (*_bfd_canonicalize_dynamic_reloc)
+ PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+ /* Opposite endian version of this target. */
+ const struct bfd_target * alternative_target;
+
+ /* Data for use by back-end routines, which isn't
+ generic enough to belong in this structure. */
+ PTR backend_data;
+
+} bfd_target;
+
+boolean
+bfd_set_default_target PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((const char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target *
+bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+const char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gnu/usr.bin/binutils/libbfd/x86-64/bfd.h b/gnu/usr.bin/binutils/libbfd/x86-64/bfd.h
new file mode 100644
index 0000000..d2776b5
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbfd/x86-64/bfd.h
@@ -0,0 +1,3918 @@
+/* $FreeBSD$ */
+
+/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically
+ generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c",
+ "section.c", "archures.c", "reloc.c", "syms.c", "bfd.c", "archive.c",
+ "corefile.c", "targets.c" and "format.c".
+ Run "make headers" in your build bfd/ to regenerate. */
+
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+#include "symcat.h"
+#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
+#ifndef SABER
+/* This hack is to avoid a problem with some strict ANSI C preprocessors.
+ The problem is, "32_" is not a valid preprocessing token, and we don't
+ want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will
+ cause the inner CONCAT2 macros to be evaluated first, producing
+ still-valid pp-tokens. Then the final concatenation can be done. */
+#undef CONCAT4
+#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d))
+#endif
+#endif
+
+/* #define BFD_VERSION 212000000 */
+/* #define BFD_VERSION_DATE 20020309 */
+/* #define BFD_VERSION_STRING "2.12" */
+
+/* The word size used by BFD on the host. This may be 64 with a 32
+ bit target if the host is 64 bit, or if other 64 bit targets have
+ been selected with --enable-targets, or if --enable-64-bit-bfd. */
+#define BFD_ARCH_SIZE 64
+
+/* The word size of the default bfd target. */
+#define BFD_DEFAULT_TARGET_SIZE 64
+
+#if defined(__i386__) || defined(__powerpc__)
+#define BFD_HOST_64BIT_LONG 0
+#else
+#define BFD_HOST_64BIT_LONG 1
+#endif /* 32-bit host */
+#if 0
+#define BFD_HOST_64_BIT
+#define BFD_HOST_U_64_BIT
+#endif
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* Forward declaration. */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+/* And even worse if your compiler provides a stdbool.h that conflicts
+ with these definitions... gcc 2.95 and later do. If so, it must
+ be included first. -drow */
+#if defined (__GNUG__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6))
+#define TRUE_FALSE_ALREADY_DEFINED
+#else
+#if defined (__bool_true_false_are_defined)
+/* We have <stdbool.h>. */
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, BFD_HOST_64_BIT must be
+ defined above. */
+
+#ifndef BFD_HOST_64_BIT
+# if BFD_HOST_64BIT_LONG
+# define BFD_HOST_64_BIT long
+# define BFD_HOST_U_64_BIT unsigned long
+# else
+# ifdef __GNUC__
+# if __GNUC__ >= 2
+# define BFD_HOST_64_BIT long long
+# define BFD_HOST_U_64_BIT unsigned long long
+# endif /* __GNUC__ >= 2 */
+# endif /* ! defined (__GNUC__) */
+# endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+ #error No 64 bit integer type available
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+typedef BFD_HOST_U_64_BIT bfd_vma;
+typedef BFD_HOST_64_BIT bfd_signed_vma;
+typedef BFD_HOST_U_64_BIT bfd_size_type;
+typedef BFD_HOST_U_64_BIT symvalue;
+
+#ifndef fprintf_vma
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf (s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf (s, "%08lx", x)
+
+#endif /* not BFD64 */
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef bfd_signed_vma file_ptr;
+typedef bfd_vma ufile_ptr;
+
+extern void bfd_sprintf_vma PARAMS ((bfd *, char *, bfd_vma));
+extern void bfd_fprintf_vma PARAMS ((bfd *, PTR, bfd_vma));
+
+#define printf_vma(x) fprintf_vma(stdout,x)
+#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/* File formats. */
+
+typedef enum bfd_format
+{
+ bfd_unknown = 0, /* File format is unknown. */
+ bfd_object, /* Linker/assember/compiler output. */
+ bfd_archive, /* Object archive file. */
+ bfd_core, /* Core dump. */
+ bfd_type_end /* Marks the end; don't use it! */
+}
+bfd_format;
+
+/* Values that may appear in the flags field of a BFD. These also
+ appear in the object_flags field of the bfd_target structure, where
+ they indicate the set of flags used by that backend (not all flags
+ are meaningful for all object file formats) (FIXME: at the moment,
+ the object_flags values have mostly just been copied from backend
+ to another, and are not necessarily correct). */
+
+/* No flags. */
+#define BFD_NO_FLAGS 0x00
+
+/* BFD contains relocation entries. */
+#define HAS_RELOC 0x01
+
+/* BFD is directly executable. */
+#define EXEC_P 0x02
+
+/* BFD has line number information (basically used for F_LNNO in a
+ COFF header). */
+#define HAS_LINENO 0x04
+
+/* BFD has debugging information. */
+#define HAS_DEBUG 0x08
+
+/* BFD has symbols. */
+#define HAS_SYMS 0x10
+
+/* BFD has local symbols (basically used for F_LSYMS in a COFF
+ header). */
+#define HAS_LOCALS 0x20
+
+/* BFD is a dynamic object. */
+#define DYNAMIC 0x40
+
+/* Text section is write protected (if D_PAGED is not set, this is
+ like an a.out NMAGIC file) (the linker sets this by default, but
+ clears it for -r or -N). */
+#define WP_TEXT 0x80
+
+/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the
+ linker sets this by default, but clears it for -r or -n or -N). */
+#define D_PAGED 0x100
+
+/* BFD is relaxable (this means that bfd_relax_section may be able to
+ do something) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#define BFD_IS_RELAXABLE 0x200
+
+/* This may be set before writing out a BFD to request using a
+ traditional format. For example, this is used to request that when
+ writing out an a.out object the symbols not be hashed to eliminate
+ duplicates. */
+#define BFD_TRADITIONAL_FORMAT 0x400
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* Symbols and relocation. */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* General purpose part of a symbol X;
+ target specific parts are in libcoff.h, libaout.h, etc. */
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* A canonical archive symbol. */
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym
+{
+ char *name;
+ file_ptr file_offset; /* Look here to find the file. */
+}
+carsym; /* To make these you call a carsymogen. */
+
+/* Used in generating armaps (archive tables of contents).
+ Perhaps just a forward definition would do? */
+struct orl /* Output ranlib. */
+{
+ char **name; /* Symbol name. */
+ union
+ {
+ file_ptr pos;
+ bfd *abfd;
+ } u; /* bfd* or file position. */
+ int namidx; /* Index into string table. */
+};
+
+/* Linenumber stuff. */
+typedef struct lineno_cache_entry
+{
+ unsigned int line_number; /* Linenumber from start of function. */
+ union
+ {
+ struct symbol_cache_entry *sym; /* Function name. */
+ bfd_vma offset; /* Offset into section. */
+ } u;
+}
+alent;
+
+/* Object and core file sections. */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_lma(bfd, ptr) ((ptr)->lma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ const char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ const char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* Hash table routines. There is no way to free up a hash table. */
+
+/* An element in the hash table. Most uses will actually use a larger
+ structure, and an instance of this will be the first field. */
+
+struct bfd_hash_entry
+{
+ /* Next entry for this hash code. */
+ struct bfd_hash_entry *next;
+ /* String being hashed. */
+ const char *string;
+ /* Hash code. This is the full hash code, not the index into the
+ table. */
+ unsigned long hash;
+};
+
+/* A hash table. */
+
+struct bfd_hash_table
+{
+ /* The hash array. */
+ struct bfd_hash_entry **table;
+ /* The number of slots in the hash table. */
+ unsigned int size;
+ /* A function used to create new elements in the hash table. The
+ first entry is itself a pointer to an element. When this
+ function is first invoked, this pointer will be NULL. However,
+ having the pointer permits a hierarchy of method functions to be
+ built each of which calls the function in the superclass. Thus
+ each function should be written to allocate a new block of memory
+ only if the argument is NULL. */
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+ /* An objalloc for this hash table. This is a struct objalloc *,
+ but we use PTR to avoid requiring the inclusion of objalloc.h. */
+ PTR memory;
+};
+
+/* Initialize a hash table. */
+extern boolean bfd_hash_table_init
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+
+/* Initialize a hash table specifying a size. */
+extern boolean bfd_hash_table_init_n
+ PARAMS ((struct bfd_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *),
+ unsigned int size));
+
+/* Free up a hash table. */
+extern void bfd_hash_table_free PARAMS ((struct bfd_hash_table *));
+
+/* Look up a string in a hash table. If CREATE is true, a new entry
+ will be created for this string if one does not already exist. The
+ COPY argument must be true if this routine should copy the string
+ into newly allocated memory when adding an entry. */
+extern struct bfd_hash_entry *bfd_hash_lookup
+ PARAMS ((struct bfd_hash_table *, const char *, boolean create,
+ boolean copy));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* Base method for creating a hash table entry. */
+extern struct bfd_hash_entry *bfd_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Grab some space for a hash table entry. */
+extern PTR bfd_hash_allocate PARAMS ((struct bfd_hash_table *,
+ unsigned int));
+
+/* Traverse a hash table in a random order, calling a function on each
+ element. If the function returns false, the traversal stops. The
+ INFO argument is passed to the function. */
+extern void bfd_hash_traverse PARAMS ((struct bfd_hash_table *,
+ boolean (*) (struct bfd_hash_entry *,
+ PTR),
+ PTR info));
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities. */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_bread PARAMS ((PTR, bfd_size_type, bfd *));
+extern bfd_size_type bfd_bwrite PARAMS ((const PTR, bfd_size_type, bfd *));
+extern int bfd_seek PARAMS ((bfd *, file_ptr, int));
+extern ufile_ptr bfd_tell PARAMS ((bfd *));
+extern int bfd_flush PARAMS ((bfd *));
+extern int bfd_stat PARAMS ((bfd *, struct stat *));
+
+/* Deprecated old routines. */
+#if __GNUC__
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#else
+#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \
+ bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \
+ (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\
+ bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD)))
+#endif
+extern void warn_deprecated
+ PARAMS ((const char *, const char *, int, const char *));
+
+/* Cast from const char * to char * so that caller can assign to
+ a char * without a warning. */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_cacheable(abfd) ((abfd)->cacheable)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour)
+#define bfd_family_coff(abfd) \
+ (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \
+ bfd_get_flavour (abfd) == bfd_target_xcoff_flavour)
+#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean) (bool)), true)
+
+extern boolean bfd_cache_close PARAMS ((bfd *abfd));
+/* NB: This declaration should match the autogenerated one in libbfd.h. */
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+bfd_vma bfd_getb64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_64 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_64 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_32 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_32 PARAMS ((const unsigned char *));
+bfd_vma bfd_getb16 PARAMS ((const unsigned char *));
+bfd_vma bfd_getl16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getb_signed_16 PARAMS ((const unsigned char *));
+bfd_signed_vma bfd_getl_signed_16 PARAMS ((const unsigned char *));
+void bfd_putb64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb16 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl16 PARAMS ((bfd_vma, unsigned char *));
+
+/* Byte swapping routines which take size and endiannes as arguments. */
+
+bfd_vma bfd_get_bits PARAMS ((bfd_byte *, int, boolean));
+void bfd_put_bits PARAMS ((bfd_vma, bfd_byte *, int, boolean));
+
+/* Externally visible ECOFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_debug_info;
+struct ecoff_debug_swap;
+struct ecoff_extr;
+struct symbol_cache_entry;
+struct bfd_link_info;
+struct bfd_link_hash_entry;
+struct bfd_elf_version_tree;
+#endif
+extern bfd_vma bfd_ecoff_get_gp_value PARAMS ((bfd * abfd));
+extern boolean bfd_ecoff_set_gp_value PARAMS ((bfd *abfd, bfd_vma gp_value));
+extern boolean bfd_ecoff_set_regmasks
+ PARAMS ((bfd *abfd, unsigned long gprmask, unsigned long fprmask,
+ unsigned long *cprmask));
+extern PTR bfd_ecoff_debug_init
+ PARAMS ((bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern void bfd_ecoff_debug_free
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap,
+ bfd *input_bfd, struct ecoff_debug_info *input_debug,
+ const struct ecoff_debug_swap *input_swap,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_accumulate_other
+ PARAMS ((PTR handle, bfd *output_bfd, struct ecoff_debug_info *output_debug,
+ const struct ecoff_debug_swap *output_swap, bfd *input_bfd,
+ struct bfd_link_info *));
+extern boolean bfd_ecoff_debug_externals
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ boolean relocateable,
+ boolean (*get_extr) (struct symbol_cache_entry *,
+ struct ecoff_extr *),
+ void (*set_index) (struct symbol_cache_entry *,
+ bfd_size_type)));
+extern boolean bfd_ecoff_debug_one_external
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ const char *name, struct ecoff_extr *esym));
+extern bfd_size_type bfd_ecoff_debug_size
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+extern boolean bfd_ecoff_write_debug
+ PARAMS ((bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap, file_ptr where));
+extern boolean bfd_ecoff_write_accumulated_debug
+ PARAMS ((PTR handle, bfd *abfd, struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap,
+ struct bfd_link_info *info, file_ptr where));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf_get_bfd_needed_list
+ PARAMS ((bfd *, struct bfd_link_needed_list **));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, const char *,
+ const char * const *, struct bfd_link_info *, struct sec **,
+ struct bfd_elf_version_tree *));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern void bfd_elf_set_dt_needed_soname PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf64_discard_info
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Return an upper bound on the number of bytes required to store a
+ copy of ABFD's program header table entries. Return -1 if an error
+ occurs; bfd_get_error will return an appropriate code. */
+extern long bfd_get_elf_phdr_upper_bound PARAMS ((bfd *abfd));
+
+/* Copy ABFD's program header table entries to *PHDRS. The entries
+ will be stored as an array of Elf_Internal_Phdr structures, as
+ defined in include/elf/internal.h. To find out how large the
+ buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+ Return the number of program header table entries read, or -1 if an
+ error occurs; bfd_get_error will return an appropriate code. */
+extern int bfd_get_elf_phdrs PARAMS ((bfd *abfd, void *phdrs));
+
+/* Return the arch_size field of an elf bfd, or -1 if not elf. */
+extern int bfd_get_arch_size PARAMS ((bfd *));
+
+/* Return true if address "naturally" sign extends, or -1 if not elf. */
+extern int bfd_get_sign_extend_vma PARAMS ((bfd *));
+
+extern boolean bfd_m68k_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+extern boolean bfd_mips_elf32_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sunos_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_sunos_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec **, struct sec **,
+ struct sec **));
+
+/* Linux shared library support routines for the linker. */
+
+extern boolean bfd_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_sparclinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window
+{
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+}
+bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *, unsigned int));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+extern boolean bfd_xcoff_link_generate_rtinit
+ PARAMS ((bfd *, const char *, const char *));
+
+/* Externally visible COFF routines. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct internal_syment;
+union internal_auxent;
+#endif
+
+extern boolean bfd_coff_get_syment
+ PARAMS ((bfd *, struct symbol_cache_entry *, struct internal_syment *));
+
+extern boolean bfd_coff_get_auxent
+ PARAMS ((bfd *, struct symbol_cache_entry *, int, union internal_auxent *));
+
+extern boolean bfd_coff_set_symbol_class
+ PARAMS ((bfd *, struct symbol_cache_entry *, unsigned int));
+
+extern boolean bfd_m68k_coff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* PE ARM Interworking support. Called from linker. */
+extern boolean bfd_arm_pe_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_arm_pe_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_arm_pe_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* ELF ARM Interworking support. Called from linker. */
+extern boolean bfd_elf32_arm_allocate_interworking_sections
+ PARAMS ((struct bfd_link_info *));
+
+extern boolean bfd_elf32_arm_process_before_allocation
+ PARAMS ((bfd *, struct bfd_link_info *, int));
+
+extern boolean bfd_elf32_arm_get_bfd_for_interworking
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* TI COFF load page support. */
+extern void bfd_ticoff_set_section_load_page
+ PARAMS ((struct sec *, int));
+
+extern int bfd_ticoff_get_section_load_page
+ PARAMS ((struct sec *));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((const char *filename, const char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((const char *filename, const char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS ((const char *, const char *, PTR));
+
+bfd *
+bfd_openw PARAMS ((const char *filename, const char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd *
+bfd_create PARAMS ((const char *filename, bfd *templ));
+
+boolean
+bfd_make_writable PARAMS ((bfd *abfd));
+
+boolean
+bfd_make_readable PARAMS ((bfd *abfd));
+
+
+/* Byte swapping macros for user section data. */
+
+#define bfd_put_8(abfd, val, ptr) \
+ ((void) (*((unsigned char *) (ptr)) = (unsigned char) (val)))
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *) (ptr) & 0xff)
+#define bfd_get_signed_8(abfd, ptr) \
+ (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+#define bfd_get(bits, abfd, ptr) \
+ ( (bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \
+ : (bits) == 16 ? bfd_get_16 (abfd, ptr) \
+ : (bits) == 32 ? bfd_get_32 (abfd, ptr) \
+ : (bits) == 64 ? bfd_get_64 (abfd, ptr) \
+ : (abort (), (bfd_vma) - 1))
+
+#define bfd_put(bits, abfd, val, ptr) \
+ ( (bits) == 8 ? bfd_put_8 (abfd, val, ptr) \
+ : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \
+ : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \
+ : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \
+ : (abort (), (void) 0))
+
+
+/* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx16, (val, ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx16, (ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx32, (val, ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx32, (ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND (abfd, bfd_h_putx64, (val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx64, (ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr))
+
+/* Refinements on the above, which should eventually go away. Save
+ cluttering the source with (bfd_vma) and (bfd_byte *) casts. */
+
+#define H_PUT_64(abfd, val, where) \
+ bfd_h_put_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_32(abfd, val, where) \
+ bfd_h_put_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_16(abfd, val, where) \
+ bfd_h_put_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_8 bfd_h_put_8
+
+#define H_PUT_S64(abfd, val, where) \
+ bfd_h_put_signed_64 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S32(abfd, val, where) \
+ bfd_h_put_signed_32 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S16(abfd, val, where) \
+ bfd_h_put_signed_16 ((abfd), (bfd_vma) (val), (bfd_byte *) (where))
+
+#define H_PUT_S8 bfd_h_put_signed_8
+
+#define H_GET_64(abfd, where) \
+ bfd_h_get_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_32(abfd, where) \
+ bfd_h_get_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_16(abfd, where) \
+ bfd_h_get_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_8 bfd_h_get_8
+
+#define H_GET_S64(abfd, where) \
+ bfd_h_get_signed_64 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S32(abfd, where) \
+ bfd_h_get_signed_32 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S16(abfd, where) \
+ bfd_h_get_signed_16 ((abfd), (bfd_byte *) (where))
+
+#define H_GET_S8 bfd_h_get_signed_8
+
+
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct bfd_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+typedef struct sec
+{
+ /* The name of the section; the name isn't a copy, the pointer is
+ the same as that passed to bfd_make_section. */
+ const char *name;
+
+ /* A unique sequence number. */
+ int id;
+
+ /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */
+ int index;
+
+ /* The next section in the list belonging to the BFD, or NULL. */
+ struct sec *next;
+
+ /* The field flags contains attributes of the section. Some
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* Tells the OS to allocate space for this section when loading.
+ This is clear for a section containing debug information only. */
+#define SEC_ALLOC 0x001
+
+ /* Tells the OS to load the section from the file when loading.
+ This is clear for a .bss section. */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there is
+ some relocation information too. */
+#define SEC_RELOC 0x004
+
+ /* ELF reserves 4 processor specific bits and 8 operating system
+ specific bits in sh_flags; at present we can get away with just
+ one in communicating between the assembler and BFD, but this
+ isn't a good long-term solution. */
+#define SEC_ARCH_BIT_0 0x008
+
+ /* A signal to the OS that the section contains read only data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (e.g., <<__CTOR_LIST__>>), attaches
+ the symbol to it, and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constructor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker to not output the section
+ even if it has information which would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a COFF shared library section. This flag is
+ only for the linker. If this type of section appears in
+ the input file, the linker must copy it to the output file
+ without changing the vma or size. FIXME: Although this
+ was originally intended to be general, it really is COFF
+ specific (and the flag was renamed to indicate this). It
+ might be cleaner to have some more general mechanism to
+ allow the back end to control what the linker does with
+ sections. */
+#define SEC_COFF_SHARED_LIBRARY 0x800
+
+ /* The section has GOT references. This flag is only for the
+ linker, and is currently only used by the elf32-hppa back end.
+ It will be set if global offset table references were detected
+ in this section, which indicate to the linker that the section
+ contains PIC code, and must be handled specially when doing a
+ static link. */
+#define SEC_HAS_GOT_REF 0x4000
+
+ /* The section contains common symbols (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* The contents of this section are held in memory pointed to
+ by the contents field. This is checked by bfd_get_section_contents,
+ and the data is retrieved from memory if appropriate. */
+#define SEC_IN_MEMORY 0x20000
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted based on the sum of
+ the symbol and addend values specified by the associated relocation
+ entries. Entries without associated relocation entries will be
+ appended to the end of the section in an unspecified order. */
+#define SEC_SORT_ENTRIES 0x80000
+
+ /* When linking, duplicate sections of the same name should be
+ discarded, rather than being combined into a single section as
+ is usually done. This is similar to how common symbols are
+ handled. See SEC_LINK_DUPLICATES below. */
+#define SEC_LINK_ONCE 0x100000
+
+ /* If SEC_LINK_ONCE is set, this bitfield describes how the linker
+ should handle duplicate sections. */
+#define SEC_LINK_DUPLICATES 0x600000
+
+ /* This value for SEC_LINK_DUPLICATES means that duplicate
+ sections with the same name should simply be discarded. */
+#define SEC_LINK_DUPLICATES_DISCARD 0x0
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if there are any duplicate sections, although
+ it should still only link one copy. */
+#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections are a different size. */
+#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000
+
+ /* This value for SEC_LINK_DUPLICATES means that the linker
+ should warn if any duplicate sections contain different
+ contents. */
+#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000
+
+ /* This section was created by the linker as part of dynamic
+ relocation or other arcane processing. It is skipped when
+ going through the first-pass output, trusting that someone
+ else up the line will take care of it later. */
+#define SEC_LINKER_CREATED 0x800000
+
+ /* This section should not be subject to garbage collection. */
+#define SEC_KEEP 0x1000000
+
+ /* This section contains "short" data, and should be placed
+ "near" the GP. */
+#define SEC_SMALL_DATA 0x2000000
+
+ /* This section contains data which may be shared with other
+ executables or shared objects. */
+#define SEC_SHARED 0x4000000
+
+ /* When a section with this flag is being linked, then if the size of
+ the input section is less than a page, it should not cross a page
+ boundary. If the size of the input section is one page or more, it
+ should be aligned on a page boundary. */
+#define SEC_BLOCK 0x8000000
+
+ /* Conditionally link this section; do not link if there are no
+ references found to any symbol in the section. */
+#define SEC_CLINK 0x10000000
+
+ /* Attempt to merge identical entities in the section.
+ Entity size is given in the entsize field. */
+#define SEC_MERGE 0x20000000
+
+ /* If given with SEC_MERGE, entities to merge are zero terminated
+ strings where entsize specifies character size instead of fixed
+ size entries. */
+#define SEC_STRINGS 0x40000000
+
+ /* This section contains data about section groups. */
+#define SEC_GROUP 0x80000000
+
+ /* End of section flags. */
+
+ /* Some internal packed boolean fields. */
+
+ /* See the vma field. */
+ unsigned int user_set_vma : 1;
+
+ /* Whether relocations have been processed. */
+ unsigned int reloc_done : 1;
+
+ /* A mark flag used by some of the linker backends. */
+ unsigned int linker_mark : 1;
+
+ /* Another mark flag used by some of the linker backends. Set for
+ output sections that have an input section. */
+ unsigned int linker_has_input : 1;
+
+ /* A mark flag used by some linker backends for garbage collection. */
+ unsigned int gc_mark : 1;
+
+ /* Used by the ELF code to mark sections which have been allocated
+ to segments. */
+ unsigned int segment_mark : 1;
+
+ /* End of internal packed boolean fields. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+ bfd_vma vma;
+
+ /* The load address of the section - where it would be in a
+ rom image; really only used for writing section header
+ information. */
+ bfd_vma lma;
+
+ /* The size of the section in octets, as it will be output.
+ Contains a value even if the section has no contents (e.g., the
+ size of <<.bss>>). This will be filled in after relocation. */
+ bfd_size_type _cooked_size;
+
+ /* The original size on disk of the section, in octets. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset in *bytes* into the output section of the first byte in the
+ input section (byte ==> smallest addressable unit on the
+ target). In most cases, if this was going to start at the
+ 100th octet (8-bit quantity) in the output section, this value
+ would be 100. However, if the target byte size is 16 bits
+ (bfd_octets_per_byte is "2"), this value would be 50. */
+ bfd_vma output_offset;
+
+ /* The output section through which to map on output. */
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent of 2 -
+ e.g., 3 aligns to 2^3 (or 8). */
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above. */
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data. */
+ file_ptr filepos;
+
+ /* File position of relocation info. */
+ file_ptr rel_filepos;
+
+ /* File position of line data. */
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications. */
+ PTR userdata;
+
+ /* If the SEC_IN_MEMORY flag is set, this points to the actual
+ contents. */
+ unsigned char *contents;
+
+ /* Attached line number information. */
+ alent *lineno;
+
+ /* Number of line number records. */
+ unsigned int lineno_count;
+
+ /* Entity size for merging purposes. */
+ unsigned int entsize;
+
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct bfd_comdat_info *comdat;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out. */
+ file_ptr moving_line_filepos;
+
+ /* What the section number is in the target world. */
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+ bfd *owner;
+
+ /* A symbol which points at this section only. */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ struct bfd_link_order *link_order_head;
+ struct bfd_link_order *link_order_tail;
+} asection;
+
+/* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. New code should use the section_ptr macros rather
+ than referring directly to the const sections. The const sections
+ may eventually vanish. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+/* The absolute section. */
+extern const asection bfd_abs_section;
+#define bfd_abs_section_ptr ((asection *) &bfd_abs_section)
+#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr)
+/* Pointer to the undefined section. */
+extern const asection bfd_und_section;
+#define bfd_und_section_ptr ((asection *) &bfd_und_section)
+#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr)
+/* Pointer to the common section. */
+extern const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+/* Pointer to the indirect section. */
+extern const asection bfd_ind_section;
+#define bfd_ind_section_ptr ((asection *) &bfd_ind_section)
+#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr)
+
+#define bfd_is_const_section(SEC) \
+ ( ((SEC) == bfd_abs_section_ptr) \
+ || ((SEC) == bfd_und_section_ptr) \
+ || ((SEC) == bfd_com_section_ptr) \
+ || ((SEC) == bfd_ind_section_ptr))
+
+extern const struct symbol_cache_entry * const bfd_abs_symbol;
+extern const struct symbol_cache_entry * const bfd_com_symbol;
+extern const struct symbol_cache_entry * const bfd_und_symbol;
+extern const struct symbol_cache_entry * const bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+ ((section)->reloc_done ? (abort (), (bfd_size_type) 1) \
+ : (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section)->reloc_done ? (section)->_cooked_size \
+ : (abort (), (bfd_size_type) 1))
+
+/* Macros to handle insertion and deletion of a bfd's sections. These
+ only handle the list pointers, ie. do not adjust section_count,
+ target_index etc. */
+#define bfd_section_list_remove(ABFD, PS) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = *_ps; \
+ *_ps = _s->next; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = _ps; \
+ } \
+ while (0)
+#define bfd_section_list_insert(ABFD, PS, S) \
+ do \
+ { \
+ asection **_ps = PS; \
+ asection *_s = S; \
+ _s->next = *_ps; \
+ *_ps = _s; \
+ if (_s->next == NULL) \
+ (ABFD)->section_tail = &_s->next; \
+ } \
+ while (0)
+
+void
+bfd_section_list_clear PARAMS ((bfd *));
+
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, const char *name));
+
+char *
+bfd_get_unique_section_name PARAMS ((bfd *abfd,
+ const char *templat,
+ int *count));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *abfd, const char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, const char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func) (bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR data, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_get_section_contents PARAMS ((bfd *abfd, asection *section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_copy_private_section_data PARAMS ((bfd *ibfd, asection *isec,
+ bfd *obfd, asection *osec));
+
+#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+ BFD_SEND (obfd, _bfd_copy_private_section_data, \
+ (ibfd, isection, obfd, osection))
+void
+_bfd_strip_section_from_output PARAMS ((struct bfd_link_info *info, asection *section));
+
+enum bfd_architecture
+{
+ bfd_arch_unknown, /* File arch not known. */
+ bfd_arch_obscure, /* Arch known, not one of these. */
+ bfd_arch_m68k, /* Motorola 68xxx */
+#define bfd_mach_m68000 1
+#define bfd_mach_m68008 2
+#define bfd_mach_m68010 3
+#define bfd_mach_m68020 4
+#define bfd_mach_m68030 5
+#define bfd_mach_m68040 6
+#define bfd_mach_m68060 7
+#define bfd_mach_cpu32 8
+#define bfd_mach_mcf5200 9
+#define bfd_mach_mcf5206e 10
+#define bfd_mach_mcf5307 11
+#define bfd_mach_mcf5407 12
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+#define bfd_mach_i960_jx 7
+#define bfd_mach_i960_hx 8
+
+ bfd_arch_or32, /* OpenRISC 32 */
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+#define bfd_mach_sparc 1
+/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
+#define bfd_mach_sparc_sparclet 2
+#define bfd_mach_sparc_sparclite 3
+#define bfd_mach_sparc_v8plus 4
+#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_sparclite_le 6
+#define bfd_mach_sparc_v9 7
+#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
+#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
+#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
+/* Nonzero if MACH has the v9 instruction set. */
+#define bfd_mach_sparc_v9_p(mach) \
+ ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
+ && (mach) != bfd_mach_sparc_sparclite_le)
+ bfd_arch_mips, /* MIPS Rxxxx */
+#define bfd_mach_mips3000 3000
+#define bfd_mach_mips3900 3900
+#define bfd_mach_mips4000 4000
+#define bfd_mach_mips4010 4010
+#define bfd_mach_mips4100 4100
+#define bfd_mach_mips4111 4111
+#define bfd_mach_mips4300 4300
+#define bfd_mach_mips4400 4400
+#define bfd_mach_mips4600 4600
+#define bfd_mach_mips4650 4650
+#define bfd_mach_mips5000 5000
+#define bfd_mach_mips6000 6000
+#define bfd_mach_mips8000 8000
+#define bfd_mach_mips10000 10000
+#define bfd_mach_mips12000 12000
+#define bfd_mach_mips16 16
+#define bfd_mach_mips5 5
+#define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */
+#define bfd_mach_mipsisa32 32
+#define bfd_mach_mipsisa64 64
+ bfd_arch_i386, /* Intel 386 */
+#define bfd_mach_i386_i386 0
+#define bfd_mach_i386_i8086 1
+#define bfd_mach_i386_i386_intel_syntax 2
+#define bfd_mach_x86_64 3
+#define bfd_mach_x86_64_intel_syntax 4
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_i370, /* IBM 360/370 Mainframes */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ bfd_arch_h8300, /* Hitachi H8/300 */
+#define bfd_mach_h8300 1
+#define bfd_mach_h8300h 2
+#define bfd_mach_h8300s 3
+ bfd_arch_pdp11, /* DEC PDP-11 */
+ bfd_arch_powerpc, /* PowerPC */
+#define bfd_mach_ppc 0
+#define bfd_mach_ppc64 1
+#define bfd_mach_ppc_403 403
+#define bfd_mach_ppc_403gc 4030
+#define bfd_mach_ppc_505 505
+#define bfd_mach_ppc_601 601
+#define bfd_mach_ppc_602 602
+#define bfd_mach_ppc_603 603
+#define bfd_mach_ppc_ec603e 6031
+#define bfd_mach_ppc_604 604
+#define bfd_mach_ppc_620 620
+#define bfd_mach_ppc_630 630
+#define bfd_mach_ppc_750 750
+#define bfd_mach_ppc_860 860
+#define bfd_mach_ppc_a35 35
+#define bfd_mach_ppc_rs64ii 642
+#define bfd_mach_ppc_rs64iii 643
+#define bfd_mach_ppc_7400 7400
+ bfd_arch_rs6000, /* IBM RS/6000 */
+#define bfd_mach_rs6k 0
+#define bfd_mach_rs6k_rs1 6001
+#define bfd_mach_rs6k_rsc 6003
+#define bfd_mach_rs6k_rs2 6002
+ bfd_arch_hppa, /* HP PA RISC */
+ bfd_arch_d10v, /* Mitsubishi D10V */
+#define bfd_mach_d10v 0
+#define bfd_mach_d10v_ts2 2
+#define bfd_mach_d10v_ts3 3
+ bfd_arch_d30v, /* Mitsubishi D30V */
+ bfd_arch_m68hc11, /* Motorola 68HC11 */
+ bfd_arch_m68hc12, /* Motorola 68HC12 */
+ bfd_arch_z8k, /* Zilog Z8000 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+#define bfd_mach_sh 0
+#define bfd_mach_sh2 0x20
+#define bfd_mach_sh_dsp 0x2d
+#define bfd_mach_sh3 0x30
+#define bfd_mach_sh3_dsp 0x3d
+#define bfd_mach_sh3e 0x3e
+#define bfd_mach_sh4 0x40
+#define bfd_mach_sh5 0x50
+ bfd_arch_alpha, /* Dec Alpha */
+#define bfd_mach_alpha_ev4 0x10
+#define bfd_mach_alpha_ev5 0x20
+#define bfd_mach_alpha_ev6 0x30
+ bfd_arch_arm, /* Advanced Risc Machines ARM. */
+#define bfd_mach_arm_2 1
+#define bfd_mach_arm_2a 2
+#define bfd_mach_arm_3 3
+#define bfd_mach_arm_3M 4
+#define bfd_mach_arm_4 5
+#define bfd_mach_arm_4T 6
+#define bfd_mach_arm_5 7
+#define bfd_mach_arm_5T 8
+#define bfd_mach_arm_5TE 9
+#define bfd_mach_arm_XScale 10
+ bfd_arch_ns32k, /* National Semiconductors ns32000 */
+ bfd_arch_w65, /* WDC 65816 */
+ bfd_arch_tic30, /* Texas Instruments TMS320C30 */
+ bfd_arch_tic54x, /* Texas Instruments TMS320C54X */
+ bfd_arch_tic80, /* TI TMS320c80 (MVP) */
+ bfd_arch_v850, /* NEC V850 */
+#define bfd_mach_v850 0
+#define bfd_mach_v850e 'E'
+#define bfd_mach_v850ea 'A'
+ bfd_arch_arc, /* ARC Cores */
+#define bfd_mach_arc_5 0
+#define bfd_mach_arc_6 1
+#define bfd_mach_arc_7 2
+#define bfd_mach_arc_8 3
+ bfd_arch_m32r, /* Mitsubishi M32R/D */
+#define bfd_mach_m32r 0 /* For backwards compatibility. */
+#define bfd_mach_m32rx 'x'
+ bfd_arch_mn10200, /* Matsushita MN10200 */
+ bfd_arch_mn10300, /* Matsushita MN10300 */
+#define bfd_mach_mn10300 300
+#define bfd_mach_am33 330
+ bfd_arch_fr30,
+#define bfd_mach_fr30 0x46523330
+ bfd_arch_mcore,
+ bfd_arch_ia64, /* HP/Intel ia64 */
+#define bfd_mach_ia64_elf64 0
+#define bfd_mach_ia64_elf32 1
+ bfd_arch_pj,
+ bfd_arch_avr, /* Atmel AVR microcontrollers. */
+#define bfd_mach_avr1 1
+#define bfd_mach_avr2 2
+#define bfd_mach_avr3 3
+#define bfd_mach_avr4 4
+#define bfd_mach_avr5 5
+ bfd_arch_cris, /* Axis CRIS */
+ bfd_arch_s390, /* IBM s390 */
+#define bfd_mach_s390_esa 0
+#define bfd_mach_s390_esame 1
+ bfd_arch_openrisc, /* OpenRISC */
+ bfd_arch_mmix, /* Donald Knuth's educational processor. */
+ bfd_arch_xstormy16,
+#define bfd_mach_xstormy16 0
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ unsigned long mach;
+ const char *arch_name;
+ const char *printable_name;
+ unsigned int section_align_power;
+ /* True if this is the default machine for the architecture. */
+ boolean the_default;
+ const struct bfd_arch_info * (*compatible)
+ PARAMS ((const struct bfd_arch_info *a,
+ const struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+ const struct bfd_arch_info *next;
+}
+bfd_arch_info_type;
+
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const char **
+bfd_arch_list PARAMS ((void));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ const bfd *abfd,
+ const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch PARAMS ((enum bfd_architecture
+ arch,
+ unsigned long machine));
+
+const char *
+bfd_printable_arch_mach PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+unsigned int
+bfd_octets_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_mach_octets_per_byte PARAMS ((enum bfd_architecture arch,
+ unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected. */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions. */
+ bfd_reloc_continue,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_notsupported,
+
+ /* Unused. */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ symbols. If this type is returned, the error_message argument
+ to bfd_perform_relocation will be set. */
+ bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+ /* A pointer into the canonical table of pointers. */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section. */
+ bfd_size_type address;
+
+ /* addend for relocation value. */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation. */
+ reloc_howto_type *howto;
+
+}
+arelent;
+
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+ /* The type field has mainly a documentary use - the back end can
+ do what it wants with it, though normally the back end's
+ external idea of what a reloc number is stored
+ in this field. For example, a PC relative word relocation
+ in a coff environment has the type 023 - because that's
+ what the outside world calls a R_PCRWORD reloc. */
+ unsigned int type;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ power-of-two measure. To get the number of bytes operated
+ on by a type of relocation, use bfd_get_reloc_size. */
+ int size;
+
+ /* The number of bits in the item to be relocated. This is used
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ called rather than the normal function. This allows really
+ strange relocation methods to be accomodated (e.g., i960 callj
+ instructions). */
+ bfd_reloc_status_type (*special_function)
+ PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
+ bfd *, char **));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* Some formats record a relocation addend in the section contents
+ rather than with the relocation. For ELF formats this is the
+ distinction between USE_REL and USE_RELA (though the code checks
+ for USE_REL == 1/0). The value of this field is TRUE if the
+ addend is recorded with the section contents; when performing a
+ partial link (ld -r) the section contents (the data) will be
+ modified. The value of this field is FALSE if addends are
+ recorded with the relocation (in arelent.addend); when performing
+ a partial link the relocation will be modified.
+ All relocations for all ELF USE_RELA targets should set this field
+ to FALSE (values of TRUE should be looked on with suspicion).
+ However, the converse is not true: not all relocations of all ELF
+ USE_REL targets set this field to TRUE. Why this is so is peculiar
+ to each particular target. For relocs that aren't used in partial
+ links (e.g. GOT stuff) it doesn't matter what this is set to. */
+ boolean partial_inplace;
+
+ /* The src_mask selects which parts of the read in data
+ are to be used in the relocation sum. E.g., if this was an 8 bit
+ byte of data which we read and relocated, this would be
+ 0x000000ff. When we have relocs which have an addend, such as
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* The dst_mask selects which parts of the instruction are replaced
+ into the instruction. In most cases src_mask == dst_mask,
+ except in the above special case, where dst_mask would be
+ 0x000000ff, and src_mask would be 0x00000000. */
+ bfd_vma dst_mask;
+
+ /* When some formats create PC relative instructions, they leave
+ the value of the pc of the place being relocated in the offset
+ slot of the instruction, so that a PC relative relocation can
+ be made just by adding in an ordinary offset (e.g., sun3 a.out).
+ Some formats leave the displacement part of an instruction
+ empty (e.g., m88k bcs); this flag signals the fact. */
+ boolean pcrel_offset;
+};
+
+#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+ { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC }
+#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \
+ HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \
+ NAME, false, 0, 0, IN)
+
+#define EMPTY_HOWTO(C) \
+ HOWTO ((C), 0, 0, 0, false, 0, complain_overflow_dont, NULL, \
+ NULL, false, 0, 0, false)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *) NULL) \
+ { \
+ if (bfd_is_com_section (symbol->section)) \
+ { \
+ relocation = 0; \
+ } \
+ else \
+ { \
+ relocation = symbol->value; \
+ } \
+ } \
+ }
+
+unsigned int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain
+{
+ arelent relent;
+ struct relent_chain *next;
+}
+arelent_chain;
+
+bfd_reloc_status_type
+bfd_check_overflow PARAMS ((enum complain_overflow how,
+ unsigned int bitsize,
+ unsigned int rightshift,
+ unsigned int addrsize,
+ bfd_vma relocation));
+
+bfd_reloc_status_type
+bfd_perform_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+bfd_reloc_status_type
+bfd_install_relocation PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message));
+
+enum bfd_reloc_code_real {
+ _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_26,
+ BFD_RELOC_24,
+ BFD_RELOC_16,
+ BFD_RELOC_14,
+ BFD_RELOC_8,
+
+/* PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_12_PCREL,
+ BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+ BFD_RELOC_32_GOT_PCREL,
+ BFD_RELOC_16_GOT_PCREL,
+ BFD_RELOC_8_GOT_PCREL,
+ BFD_RELOC_32_GOTOFF,
+ BFD_RELOC_16_GOTOFF,
+ BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF,
+ BFD_RELOC_8_GOTOFF,
+ BFD_RELOC_64_PLT_PCREL,
+ BFD_RELOC_32_PLT_PCREL,
+ BFD_RELOC_24_PLT_PCREL,
+ BFD_RELOC_16_PLT_PCREL,
+ BFD_RELOC_8_PLT_PCREL,
+ BFD_RELOC_64_PLTOFF,
+ BFD_RELOC_32_PLTOFF,
+ BFD_RELOC_16_PLTOFF,
+ BFD_RELOC_LO16_PLTOFF,
+ BFD_RELOC_HI16_PLTOFF,
+ BFD_RELOC_HI16_S_PLTOFF,
+ BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+ BFD_RELOC_68K_GLOB_DAT,
+ BFD_RELOC_68K_JMP_SLOT,
+ BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_LO16_BASEREL,
+ BFD_RELOC_HI16_BASEREL,
+ BFD_RELOC_HI16_S_BASEREL,
+ BFD_RELOC_8_BASEREL,
+ BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+ BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+ BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_16_PCREL_S2,
+ BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC. */
+ BFD_RELOC_HI22,
+ BFD_RELOC_LO10,
+
+/* For systems that allocate a Global Pointer register, these are
+displacements off that register. These relocation types are
+handled specially, because the value the register will have is
+decided relatively late. */
+ BFD_RELOC_GPREL16,
+ BFD_RELOC_GPREL32,
+
+/* Reloc types used for i960/b.out. */
+ BFD_RELOC_I960_CALLJ,
+
+/* SPARC ELF relocations. There is probably some overlap with other
+relocation types already defined. */
+ BFD_RELOC_NONE,
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA16,
+ BFD_RELOC_SPARC_UA32,
+ BFD_RELOC_SPARC_UA64,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+/* SPARC64 relocations */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+ BFD_RELOC_SPARC_10,
+ BFD_RELOC_SPARC_11,
+ BFD_RELOC_SPARC_OLO10,
+ BFD_RELOC_SPARC_HH22,
+ BFD_RELOC_SPARC_HM10,
+ BFD_RELOC_SPARC_LM22,
+ BFD_RELOC_SPARC_PC_HH22,
+ BFD_RELOC_SPARC_PC_HM10,
+ BFD_RELOC_SPARC_PC_LM22,
+ BFD_RELOC_SPARC_WDISP16,
+ BFD_RELOC_SPARC_WDISP19,
+ BFD_RELOC_SPARC_7,
+ BFD_RELOC_SPARC_6,
+ BFD_RELOC_SPARC_5,
+#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL
+ BFD_RELOC_SPARC_PLT32,
+ BFD_RELOC_SPARC_PLT64,
+ BFD_RELOC_SPARC_HIX22,
+ BFD_RELOC_SPARC_LOX10,
+ BFD_RELOC_SPARC_H44,
+ BFD_RELOC_SPARC_M44,
+ BFD_RELOC_SPARC_L44,
+ BFD_RELOC_SPARC_REGISTER,
+
+/* SPARC little endian relocation */
+ BFD_RELOC_SPARC_REV32,
+
+/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or
+"addend" in some special way.
+For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when
+writing; when reading, it will be the absolute section symbol. The
+addend is the displacement in bytes of the "lda" instruction from
+the "ldah" instruction (which is at the address of this reloc). */
+ BFD_RELOC_ALPHA_GPDISP_HI16,
+
+/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as
+with GPDISP_HI16 relocs. The addend is ignored when writing the
+relocations out, and is filled in with the file's GP value on
+reading, for convenience. */
+ BFD_RELOC_ALPHA_GPDISP_LO16,
+
+/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16
+relocation except that there is no accompanying GPDISP_LO16
+relocation. */
+ BFD_RELOC_ALPHA_GPDISP,
+
+/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference;
+the assembler turns it into a LDQ instruction to load the address of
+the symbol, and then fills in a register in the real instruction.
+
+The LITERAL reloc, at the LDQ instruction, refers to the .lita
+section symbol. The addend is ignored when writing, but is filled
+in with the file's GP value on reading, for convenience, as with the
+GPDISP_LO16 reloc.
+
+The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16.
+It should refer to the symbol to be referenced, as with 16_GOTOFF,
+but it generates output not based on the position within the .got
+section, but relative to the GP value chosen for the file during the
+final link stage.
+
+The LITUSE reloc, on the instruction using the loaded address, gives
+information to the linker that it might be able to use to optimize
+away some literal section references. The symbol is ignored (read
+as the absolute section symbol), and the "addend" indicates the type
+of instruction using the register:
+1 - "memory" fmt insn
+2 - byte-manipulation (byte offset reg)
+3 - jsr (target of branch) */
+ BFD_RELOC_ALPHA_LITERAL,
+ BFD_RELOC_ALPHA_ELF_LITERAL,
+ BFD_RELOC_ALPHA_LITUSE,
+
+/* The HINT relocation indicates a value that should be filled into the
+"hint" field of a jmp/jsr/ret instruction, for possible branch-
+prediction logic which may be provided on some processors. */
+ BFD_RELOC_ALPHA_HINT,
+
+/* The LINKAGE relocation outputs a linkage pair in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_LINKAGE,
+
+/* The CODEADDR relocation outputs a STO_CA in the object file,
+which is filled by the linker. */
+ BFD_RELOC_ALPHA_CODEADDR,
+
+/* The GPREL_HI/LO relocations together form a 32-bit offset from the
+GP register. */
+ BFD_RELOC_ALPHA_GPREL_HI16,
+ BFD_RELOC_ALPHA_GPREL_LO16,
+
+/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must
+share a common GP, and the target address is adjusted for
+STO_ALPHA_STD_GPLOAD. */
+ BFD_RELOC_ALPHA_BRSGP,
+
+/* Bits 27..2 of the relocation address shifted right 2 bits;
+simple reloc otherwise. */
+ BFD_RELOC_MIPS_JMP,
+
+/* The MIPS16 jump instruction. */
+ BFD_RELOC_MIPS16_JMP,
+
+/* MIPS16 GP relative reloc. */
+ BFD_RELOC_MIPS16_GPREL,
+
+/* High 16 bits of 32-bit value; simple reloc. */
+ BFD_RELOC_HI16,
+
+/* High 16 bits of 32-bit value but the low 16 bits will be sign
+extended and added to form the final result. If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+ BFD_RELOC_HI16_S,
+
+/* Low 16 bits. */
+ BFD_RELOC_LO16,
+
+/* Like BFD_RELOC_HI16_S, but PC relative. */
+ BFD_RELOC_PCREL_HI16_S,
+
+/* Like BFD_RELOC_LO16, but PC relative. */
+ BFD_RELOC_PCREL_LO16,
+
+/* Relocation against a MIPS literal section. */
+ BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+ BFD_RELOC_MIPS_GOT16,
+ BFD_RELOC_MIPS_CALL16,
+ BFD_RELOC_MIPS_GOT_HI16,
+ BFD_RELOC_MIPS_GOT_LO16,
+ BFD_RELOC_MIPS_CALL_HI16,
+ BFD_RELOC_MIPS_CALL_LO16,
+ BFD_RELOC_MIPS_SUB,
+ BFD_RELOC_MIPS_GOT_PAGE,
+ BFD_RELOC_MIPS_GOT_OFST,
+ BFD_RELOC_MIPS_GOT_DISP,
+ BFD_RELOC_MIPS_SHIFT5,
+ BFD_RELOC_MIPS_SHIFT6,
+ BFD_RELOC_MIPS_INSERT_A,
+ BFD_RELOC_MIPS_INSERT_B,
+ BFD_RELOC_MIPS_DELETE,
+ BFD_RELOC_MIPS_HIGHEST,
+ BFD_RELOC_MIPS_HIGHER,
+ BFD_RELOC_MIPS_SCN_DISP,
+ BFD_RELOC_MIPS_REL16,
+ BFD_RELOC_MIPS_RELGOT,
+ BFD_RELOC_MIPS_JALR,
+ BFD_RELOC_SH_GOT_LOW16,
+ BFD_RELOC_SH_GOT_MEDLOW16,
+ BFD_RELOC_SH_GOT_MEDHI16,
+ BFD_RELOC_SH_GOT_HI16,
+ BFD_RELOC_SH_GOTPLT_LOW16,
+ BFD_RELOC_SH_GOTPLT_MEDLOW16,
+ BFD_RELOC_SH_GOTPLT_MEDHI16,
+ BFD_RELOC_SH_GOTPLT_HI16,
+ BFD_RELOC_SH_PLT_LOW16,
+ BFD_RELOC_SH_PLT_MEDLOW16,
+ BFD_RELOC_SH_PLT_MEDHI16,
+ BFD_RELOC_SH_PLT_HI16,
+ BFD_RELOC_SH_GOTOFF_LOW16,
+ BFD_RELOC_SH_GOTOFF_MEDLOW16,
+ BFD_RELOC_SH_GOTOFF_MEDHI16,
+ BFD_RELOC_SH_GOTOFF_HI16,
+ BFD_RELOC_SH_GOTPC_LOW16,
+ BFD_RELOC_SH_GOTPC_MEDLOW16,
+ BFD_RELOC_SH_GOTPC_MEDHI16,
+ BFD_RELOC_SH_GOTPC_HI16,
+ BFD_RELOC_SH_COPY64,
+ BFD_RELOC_SH_GLOB_DAT64,
+ BFD_RELOC_SH_JMP_SLOT64,
+ BFD_RELOC_SH_RELATIVE64,
+ BFD_RELOC_SH_GOT10BY4,
+ BFD_RELOC_SH_GOT10BY8,
+ BFD_RELOC_SH_GOTPLT10BY4,
+ BFD_RELOC_SH_GOTPLT10BY8,
+ BFD_RELOC_SH_GOTPLT32,
+ BFD_RELOC_SH_SHMEDIA_CODE,
+ BFD_RELOC_SH_IMMU5,
+ BFD_RELOC_SH_IMMS6,
+ BFD_RELOC_SH_IMMS6BY32,
+ BFD_RELOC_SH_IMMU6,
+ BFD_RELOC_SH_IMMS10,
+ BFD_RELOC_SH_IMMS10BY2,
+ BFD_RELOC_SH_IMMS10BY4,
+ BFD_RELOC_SH_IMMS10BY8,
+ BFD_RELOC_SH_IMMS16,
+ BFD_RELOC_SH_IMMU16,
+ BFD_RELOC_SH_IMM_LOW16,
+ BFD_RELOC_SH_IMM_LOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDLOW16,
+ BFD_RELOC_SH_IMM_MEDLOW16_PCREL,
+ BFD_RELOC_SH_IMM_MEDHI16,
+ BFD_RELOC_SH_IMM_MEDHI16_PCREL,
+ BFD_RELOC_SH_IMM_HI16,
+ BFD_RELOC_SH_IMM_HI16_PCREL,
+ BFD_RELOC_SH_PT_16,
+
+
+/* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ BFD_RELOC_386_GOTOFF,
+ BFD_RELOC_386_GOTPC,
+
+/* x86-64/elf relocations */
+ BFD_RELOC_X86_64_GOT32,
+ BFD_RELOC_X86_64_PLT32,
+ BFD_RELOC_X86_64_COPY,
+ BFD_RELOC_X86_64_GLOB_DAT,
+ BFD_RELOC_X86_64_JUMP_SLOT,
+ BFD_RELOC_X86_64_RELATIVE,
+ BFD_RELOC_X86_64_GOTPCREL,
+ BFD_RELOC_X86_64_32S,
+
+/* ns32k relocations */
+ BFD_RELOC_NS32K_IMM_8,
+ BFD_RELOC_NS32K_IMM_16,
+ BFD_RELOC_NS32K_IMM_32,
+ BFD_RELOC_NS32K_IMM_8_PCREL,
+ BFD_RELOC_NS32K_IMM_16_PCREL,
+ BFD_RELOC_NS32K_IMM_32_PCREL,
+ BFD_RELOC_NS32K_DISP_8,
+ BFD_RELOC_NS32K_DISP_16,
+ BFD_RELOC_NS32K_DISP_32,
+ BFD_RELOC_NS32K_DISP_8_PCREL,
+ BFD_RELOC_NS32K_DISP_16_PCREL,
+ BFD_RELOC_NS32K_DISP_32_PCREL,
+
+/* PDP11 relocations */
+ BFD_RELOC_PDP11_DISP_8_PCREL,
+ BFD_RELOC_PDP11_DISP_6_PCREL,
+
+/* Picojava relocs. Not all of these appear in object files. */
+ BFD_RELOC_PJ_CODE_HI16,
+ BFD_RELOC_PJ_CODE_LO16,
+ BFD_RELOC_PJ_CODE_DIR16,
+ BFD_RELOC_PJ_CODE_DIR32,
+ BFD_RELOC_PJ_CODE_REL16,
+ BFD_RELOC_PJ_CODE_REL32,
+
+/* Power(rs6000) and PowerPC relocations. */
+ BFD_RELOC_PPC_B26,
+ BFD_RELOC_PPC_BA26,
+ BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_B16,
+ BFD_RELOC_PPC_B16_BRTAKEN,
+ BFD_RELOC_PPC_B16_BRNTAKEN,
+ BFD_RELOC_PPC_BA16,
+ BFD_RELOC_PPC_BA16_BRTAKEN,
+ BFD_RELOC_PPC_BA16_BRNTAKEN,
+ BFD_RELOC_PPC_COPY,
+ BFD_RELOC_PPC_GLOB_DAT,
+ BFD_RELOC_PPC_JMP_SLOT,
+ BFD_RELOC_PPC_RELATIVE,
+ BFD_RELOC_PPC_LOCAL24PC,
+ BFD_RELOC_PPC_EMB_NADDR32,
+ BFD_RELOC_PPC_EMB_NADDR16,
+ BFD_RELOC_PPC_EMB_NADDR16_LO,
+ BFD_RELOC_PPC_EMB_NADDR16_HI,
+ BFD_RELOC_PPC_EMB_NADDR16_HA,
+ BFD_RELOC_PPC_EMB_SDAI16,
+ BFD_RELOC_PPC_EMB_SDA2I16,
+ BFD_RELOC_PPC_EMB_SDA2REL,
+ BFD_RELOC_PPC_EMB_SDA21,
+ BFD_RELOC_PPC_EMB_MRKREF,
+ BFD_RELOC_PPC_EMB_RELSEC16,
+ BFD_RELOC_PPC_EMB_RELST_LO,
+ BFD_RELOC_PPC_EMB_RELST_HI,
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
+ BFD_RELOC_PPC64_HIGHER,
+ BFD_RELOC_PPC64_HIGHER_S,
+ BFD_RELOC_PPC64_HIGHEST,
+ BFD_RELOC_PPC64_HIGHEST_S,
+ BFD_RELOC_PPC64_TOC16_LO,
+ BFD_RELOC_PPC64_TOC16_HI,
+ BFD_RELOC_PPC64_TOC16_HA,
+ BFD_RELOC_PPC64_TOC,
+ BFD_RELOC_PPC64_PLTGOT16,
+ BFD_RELOC_PPC64_PLTGOT16_LO,
+ BFD_RELOC_PPC64_PLTGOT16_HI,
+ BFD_RELOC_PPC64_PLTGOT16_HA,
+ BFD_RELOC_PPC64_ADDR16_DS,
+ BFD_RELOC_PPC64_ADDR16_LO_DS,
+ BFD_RELOC_PPC64_GOT16_DS,
+ BFD_RELOC_PPC64_GOT16_LO_DS,
+ BFD_RELOC_PPC64_PLT16_LO_DS,
+ BFD_RELOC_PPC64_SECTOFF_DS,
+ BFD_RELOC_PPC64_SECTOFF_LO_DS,
+ BFD_RELOC_PPC64_TOC16_DS,
+ BFD_RELOC_PPC64_TOC16_LO_DS,
+ BFD_RELOC_PPC64_PLTGOT16_DS,
+ BFD_RELOC_PPC64_PLTGOT16_LO_DS,
+
+/* IBM 370/390 relocations */
+ BFD_RELOC_I370_D12,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+ BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. */
+ BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* ARM 26 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_ARM_PCREL_BLX,
+
+/* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is
+not stored in the instruction. The 2nd lowest bit comes from a 1 bit
+field in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BLX,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_ADRL_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_ADR_IMM,
+ BFD_RELOC_ARM_LDR_IMM,
+ BFD_RELOC_ARM_LITERAL,
+ BFD_RELOC_ARM_IN_POOL,
+ BFD_RELOC_ARM_OFFSET_IMM8,
+ BFD_RELOC_ARM_HWLITERAL,
+ BFD_RELOC_ARM_THUMB_ADD,
+ BFD_RELOC_ARM_THUMB_IMM,
+ BFD_RELOC_ARM_THUMB_SHIFT,
+ BFD_RELOC_ARM_THUMB_OFFSET,
+ BFD_RELOC_ARM_GOT12,
+ BFD_RELOC_ARM_GOT32,
+ BFD_RELOC_ARM_JUMP_SLOT,
+ BFD_RELOC_ARM_COPY,
+ BFD_RELOC_ARM_GLOB_DAT,
+ BFD_RELOC_ARM_PLT32,
+ BFD_RELOC_ARM_RELATIVE,
+ BFD_RELOC_ARM_GOTOFF,
+ BFD_RELOC_ARM_GOTPC,
+
+/* Hitachi SH relocs. Not all of these appear in object files. */
+ BFD_RELOC_SH_PCDISP8BY2,
+ BFD_RELOC_SH_PCDISP12BY2,
+ BFD_RELOC_SH_IMM4,
+ BFD_RELOC_SH_IMM4BY2,
+ BFD_RELOC_SH_IMM4BY4,
+ BFD_RELOC_SH_IMM8,
+ BFD_RELOC_SH_IMM8BY2,
+ BFD_RELOC_SH_IMM8BY4,
+ BFD_RELOC_SH_PCRELIMM8BY2,
+ BFD_RELOC_SH_PCRELIMM8BY4,
+ BFD_RELOC_SH_SWITCH16,
+ BFD_RELOC_SH_SWITCH32,
+ BFD_RELOC_SH_USES,
+ BFD_RELOC_SH_COUNT,
+ BFD_RELOC_SH_ALIGN,
+ BFD_RELOC_SH_CODE,
+ BFD_RELOC_SH_DATA,
+ BFD_RELOC_SH_LABEL,
+ BFD_RELOC_SH_LOOP_START,
+ BFD_RELOC_SH_LOOP_END,
+ BFD_RELOC_SH_COPY,
+ BFD_RELOC_SH_GLOB_DAT,
+ BFD_RELOC_SH_JMP_SLOT,
+ BFD_RELOC_SH_RELATIVE,
+ BFD_RELOC_SH_GOTPC,
+
+/* Thumb 23-, 12- and 9-bit pc-relative branches. The lowest bit must
+be zero and is not stored in the instruction. */
+ BFD_RELOC_THUMB_PCREL_BRANCH9,
+ BFD_RELOC_THUMB_PCREL_BRANCH12,
+ BFD_RELOC_THUMB_PCREL_BRANCH23,
+
+/* ARC Cores relocs.
+ARC 22 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. The high 20 bits are installed in bits 26
+through 7 of the instruction. */
+ BFD_RELOC_ARC_B22_PCREL,
+
+/* ARC 26 bit absolute branch. The lowest two bits must be zero and are not
+stored in the instruction. The high 24 bits are installed in bits 23
+through 0. */
+ BFD_RELOC_ARC_B26,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_10_PCREL_R,
+
+/* Mitsubishi D10V relocs.
+This is a 10-bit reloc with the right 2 bits
+assumed to be 0. This is the same as the previous reloc
+except it is in the left container, i.e.,
+shifted left 15 bits. */
+ BFD_RELOC_D10V_10_PCREL_L,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18,
+
+/* This is an 18-bit reloc with the right 2 bits
+assumed to be 0. */
+ BFD_RELOC_D10V_18_PCREL,
+
+/* Mitsubishi D30V relocs.
+This is a 6-bit absolute reloc. */
+ BFD_RELOC_D30V_6,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_9_PCREL,
+
+/* This is a 6-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_9_PCREL_R,
+
+/* This is a 12-bit absolute reloc with the
+right 3 bitsassumed to be 0. */
+ BFD_RELOC_D30V_15,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_15_PCREL,
+
+/* This is a 12-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_15_PCREL_R,
+
+/* This is an 18-bit absolute reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. */
+ BFD_RELOC_D30V_21_PCREL,
+
+/* This is an 18-bit pc-relative reloc with
+the right 3 bits assumed to be 0. Same
+as the previous reloc but on the right side
+of the container. */
+ BFD_RELOC_D30V_21_PCREL_R,
+
+/* This is a 32-bit absolute reloc. */
+ BFD_RELOC_D30V_32,
+
+/* This is a 32-bit pc-relative reloc. */
+ BFD_RELOC_D30V_32_PCREL,
+
+/* Mitsubishi M32R relocs.
+This is a 24 bit absolute address. */
+ BFD_RELOC_M32R_24,
+
+/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_10_PCREL,
+
+/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_18_PCREL,
+
+/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */
+ BFD_RELOC_M32R_26_PCREL,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as unsigned. */
+ BFD_RELOC_M32R_HI16_ULO,
+
+/* This is a 16-bit reloc containing the high 16 bits of an address
+used when the lower 16 bits are treated as signed. */
+ BFD_RELOC_M32R_HI16_SLO,
+
+/* This is a 16-bit reloc containing the lower 16 bits of an address. */
+ BFD_RELOC_M32R_LO16,
+
+/* This is a 16-bit reloc containing the small data area offset for use in
+add3, load, and store instructions. */
+ BFD_RELOC_M32R_SDA16,
+
+/* This is a 9-bit reloc */
+ BFD_RELOC_V850_9_PCREL,
+
+/* This is a 22-bit reloc */
+ BFD_RELOC_V850_22_PCREL,
+
+/* This is a 16 bit offset from the short data area pointer. */
+ BFD_RELOC_V850_SDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+short data area pointer. */
+ BFD_RELOC_V850_SDA_15_16_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer. */
+ BFD_RELOC_V850_ZDA_16_16_OFFSET,
+
+/* This is a 16 bit offset (of which only 15 bits are used) from the
+zero data area pointer. */
+ BFD_RELOC_V850_ZDA_15_16_OFFSET,
+
+/* This is an 8 bit offset (of which only 6 bits are used) from the
+tiny data area pointer. */
+ BFD_RELOC_V850_TDA_6_8_OFFSET,
+
+/* This is an 8bit offset (of which only 7 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_7_8_OFFSET,
+
+/* This is a 7 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_7_7_OFFSET,
+
+/* This is a 16 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_16_16_OFFSET,
+
+/* This is a 5 bit offset (of which only 4 bits are used) from the tiny
+data area pointer. */
+ BFD_RELOC_V850_TDA_4_5_OFFSET,
+
+/* This is a 4 bit offset from the tiny data area pointer. */
+ BFD_RELOC_V850_TDA_4_4_OFFSET,
+
+/* This is a 16 bit offset from the short data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET,
+
+/* This is a 16 bit offset from the zero data area pointer, with the
+bits placed non-contigously in the instruction. */
+ BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET,
+
+/* This is a 6 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_6_7_OFFSET,
+
+/* This is a 16 bit offset from the call table base pointer. */
+ BFD_RELOC_V850_CALLT_16_16_OFFSET,
+
+
+/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_32_PCREL,
+
+/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the
+instruction. */
+ BFD_RELOC_MN10300_16_PCREL,
+
+/* This is a 8bit DP reloc for the tms320c30, where the most
+significant 8 bits of a 24 bit word are placed into the least
+significant 8 bits of the opcode. */
+ BFD_RELOC_TIC30_LDP,
+
+/* This is a 7bit reloc for the tms320c54x, where the least
+significant 7 bits of a 16 bit word are placed into the least
+significant 7 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTLS7,
+
+/* This is a 9bit DP reloc for the tms320c54x, where the most
+significant 9 bits of a 16 bit word are placed into the least
+significant 9 bits of the opcode. */
+ BFD_RELOC_TIC54X_PARTMS9,
+
+/* This is an extended address 23-bit reloc for the tms320c54x. */
+ BFD_RELOC_TIC54X_23,
+
+/* This is a 16-bit reloc for the tms320c54x, where the least
+significant 16 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_16_OF_23,
+
+/* This is a reloc for the tms320c54x, where the most
+significant 7 bits of a 23-bit extended address are placed into
+the opcode. */
+ BFD_RELOC_TIC54X_MS7_OF_23,
+
+/* This is a 48 bit reloc for the FR30 that stores 32 bits. */
+ BFD_RELOC_FR30_48,
+
+/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into
+two sections. */
+ BFD_RELOC_FR30_20,
+
+/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in
+4 bits. */
+ BFD_RELOC_FR30_6_IN_4,
+
+/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset
+into 8 bits. */
+ BFD_RELOC_FR30_8_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset
+into 8 bits. */
+ BFD_RELOC_FR30_9_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset
+into 8 bits. */
+ BFD_RELOC_FR30_10_IN_8,
+
+/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative
+short offset into 8 bits. */
+ BFD_RELOC_FR30_9_PCREL,
+
+/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative
+short offset into 11 bits. */
+ BFD_RELOC_FR30_12_PCREL,
+
+/* Motorola Mcore relocations. */
+ BFD_RELOC_MCORE_PCREL_IMM8BY4,
+ BFD_RELOC_MCORE_PCREL_IMM11BY2,
+ BFD_RELOC_MCORE_PCREL_IMM4BY2,
+ BFD_RELOC_MCORE_PCREL_32,
+ BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2,
+ BFD_RELOC_MCORE_RVA,
+
+/* These are relocations for the GETA instruction. */
+ BFD_RELOC_MMIX_GETA,
+ BFD_RELOC_MMIX_GETA_1,
+ BFD_RELOC_MMIX_GETA_2,
+ BFD_RELOC_MMIX_GETA_3,
+
+/* These are relocations for a conditional branch instruction. */
+ BFD_RELOC_MMIX_CBRANCH,
+ BFD_RELOC_MMIX_CBRANCH_J,
+ BFD_RELOC_MMIX_CBRANCH_1,
+ BFD_RELOC_MMIX_CBRANCH_2,
+ BFD_RELOC_MMIX_CBRANCH_3,
+
+/* These are relocations for the PUSHJ instruction. */
+ BFD_RELOC_MMIX_PUSHJ,
+ BFD_RELOC_MMIX_PUSHJ_1,
+ BFD_RELOC_MMIX_PUSHJ_2,
+ BFD_RELOC_MMIX_PUSHJ_3,
+
+/* These are relocations for the JMP instruction. */
+ BFD_RELOC_MMIX_JMP,
+ BFD_RELOC_MMIX_JMP_1,
+ BFD_RELOC_MMIX_JMP_2,
+ BFD_RELOC_MMIX_JMP_3,
+
+/* This is a relocation for a relative address as in a GETA instruction or
+a branch. */
+ BFD_RELOC_MMIX_ADDR19,
+
+/* This is a relocation for a relative address as in a JMP instruction. */
+ BFD_RELOC_MMIX_ADDR27,
+
+/* This is a relocation for an instruction field that may be a general
+register or a value 0..255. */
+ BFD_RELOC_MMIX_REG_OR_BYTE,
+
+/* This is a relocation for an instruction field that may be a general
+register. */
+ BFD_RELOC_MMIX_REG,
+
+/* This is a relocation for two instruction fields holding a register and
+an offset, the equivalent of the relocation. */
+ BFD_RELOC_MMIX_BASE_PLUS_OFFSET,
+
+/* This relocation is an assertion that the expression is not allocated as
+a global register. It does not modify contents. */
+ BFD_RELOC_MMIX_LOCAL,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative
+short offset into 7 bits. */
+ BFD_RELOC_AVR_7_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative
+short offset into 12 bits. */
+ BFD_RELOC_AVR_13_PCREL,
+
+/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually
+program memory address) into 16 bits. */
+ BFD_RELOC_AVR_16_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of data memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of program memory address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually data memory address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of data memory address) into 8 bit immediate value of
+SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(most high 8 bit of program memory address) into 8 bit immediate value
+of LDI or SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually
+command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit
+of command address) into 8 bit immediate value of LDI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(usually command address) into 8 bit immediate value of SUBI insn. */
+ BFD_RELOC_AVR_LO8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 8 bit of 16 bit command address) into 8 bit immediate value
+of SUBI insn. */
+ BFD_RELOC_AVR_HI8_LDI_PM_NEG,
+
+/* This is a 16 bit reloc for the AVR that stores negated 8 bit value
+(high 6 bit of 22 bit command address) into 8 bit immediate
+value of SUBI insn. */
+ BFD_RELOC_AVR_HH8_LDI_PM_NEG,
+
+/* This is a 32 bit reloc for the AVR that stores 23 bit value
+into 22 bits. */
+ BFD_RELOC_AVR_CALL,
+
+/* Direct 12 bit. */
+ BFD_RELOC_390_12,
+
+/* 12 bit GOT offset. */
+ BFD_RELOC_390_GOT12,
+
+/* 32 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT32,
+
+/* Copy symbol at runtime. */
+ BFD_RELOC_390_COPY,
+
+/* Create GOT entry. */
+ BFD_RELOC_390_GLOB_DAT,
+
+/* Create PLT entry. */
+ BFD_RELOC_390_JMP_SLOT,
+
+/* Adjust by program base. */
+ BFD_RELOC_390_RELATIVE,
+
+/* 32 bit PC relative offset to GOT. */
+ BFD_RELOC_390_GOTPC,
+
+/* 16 bit GOT offset. */
+ BFD_RELOC_390_GOT16,
+
+/* PC relative 16 bit shifted by 1. */
+ BFD_RELOC_390_PC16DBL,
+
+/* 16 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT16DBL,
+
+/* PC relative 32 bit shifted by 1. */
+ BFD_RELOC_390_PC32DBL,
+
+/* 32 bit PC rel. PLT shifted by 1. */
+ BFD_RELOC_390_PLT32DBL,
+
+/* 32 bit PC rel. GOT shifted by 1. */
+ BFD_RELOC_390_GOTPCDBL,
+
+/* 64 bit GOT offset. */
+ BFD_RELOC_390_GOT64,
+
+/* 64 bit PC relative PLT address. */
+ BFD_RELOC_390_PLT64,
+
+/* 32 bit rel. offset to GOT entry. */
+ BFD_RELOC_390_GOTENT,
+
+/* These two relocations are used by the linker to determine which of
+the entries in a C++ virtual function table are actually used. When
+the --gc-sections option is given, the linker will zero out the entries
+that are not used, so that the code for those functions need not be
+included in the output.
+
+VTABLE_INHERIT is a zero-space relocation used to describe to the
+linker the inheritence tree of a C++ virtual function table. The
+relocation's symbol should be the parent class' vtable, and the
+relocation should be located at the child vtable.
+
+VTABLE_ENTRY is a zero-space relocation that describes the use of a
+virtual function table entry. The reloc's symbol should refer to the
+table of the class mentioned in the code. Off of that base, an offset
+describes the entry that is being used. For Rela hosts, this offset
+is stored in the reloc's addend. For Rel hosts, we are forced to put
+this offset in the reloc's section offset. */
+ BFD_RELOC_VTABLE_INHERIT,
+ BFD_RELOC_VTABLE_ENTRY,
+
+/* Intel IA64 Relocations. */
+ BFD_RELOC_IA64_IMM14,
+ BFD_RELOC_IA64_IMM22,
+ BFD_RELOC_IA64_IMM64,
+ BFD_RELOC_IA64_DIR32MSB,
+ BFD_RELOC_IA64_DIR32LSB,
+ BFD_RELOC_IA64_DIR64MSB,
+ BFD_RELOC_IA64_DIR64LSB,
+ BFD_RELOC_IA64_GPREL22,
+ BFD_RELOC_IA64_GPREL64I,
+ BFD_RELOC_IA64_GPREL32MSB,
+ BFD_RELOC_IA64_GPREL32LSB,
+ BFD_RELOC_IA64_GPREL64MSB,
+ BFD_RELOC_IA64_GPREL64LSB,
+ BFD_RELOC_IA64_LTOFF22,
+ BFD_RELOC_IA64_LTOFF64I,
+ BFD_RELOC_IA64_PLTOFF22,
+ BFD_RELOC_IA64_PLTOFF64I,
+ BFD_RELOC_IA64_PLTOFF64MSB,
+ BFD_RELOC_IA64_PLTOFF64LSB,
+ BFD_RELOC_IA64_FPTR64I,
+ BFD_RELOC_IA64_FPTR32MSB,
+ BFD_RELOC_IA64_FPTR32LSB,
+ BFD_RELOC_IA64_FPTR64MSB,
+ BFD_RELOC_IA64_FPTR64LSB,
+ BFD_RELOC_IA64_PCREL21B,
+ BFD_RELOC_IA64_PCREL21BI,
+ BFD_RELOC_IA64_PCREL21M,
+ BFD_RELOC_IA64_PCREL21F,
+ BFD_RELOC_IA64_PCREL22,
+ BFD_RELOC_IA64_PCREL60B,
+ BFD_RELOC_IA64_PCREL64I,
+ BFD_RELOC_IA64_PCREL32MSB,
+ BFD_RELOC_IA64_PCREL32LSB,
+ BFD_RELOC_IA64_PCREL64MSB,
+ BFD_RELOC_IA64_PCREL64LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR22,
+ BFD_RELOC_IA64_LTOFF_FPTR64I,
+ BFD_RELOC_IA64_LTOFF_FPTR32MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR32LSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64MSB,
+ BFD_RELOC_IA64_LTOFF_FPTR64LSB,
+ BFD_RELOC_IA64_SEGREL32MSB,
+ BFD_RELOC_IA64_SEGREL32LSB,
+ BFD_RELOC_IA64_SEGREL64MSB,
+ BFD_RELOC_IA64_SEGREL64LSB,
+ BFD_RELOC_IA64_SECREL32MSB,
+ BFD_RELOC_IA64_SECREL32LSB,
+ BFD_RELOC_IA64_SECREL64MSB,
+ BFD_RELOC_IA64_SECREL64LSB,
+ BFD_RELOC_IA64_REL32MSB,
+ BFD_RELOC_IA64_REL32LSB,
+ BFD_RELOC_IA64_REL64MSB,
+ BFD_RELOC_IA64_REL64LSB,
+ BFD_RELOC_IA64_LTV32MSB,
+ BFD_RELOC_IA64_LTV32LSB,
+ BFD_RELOC_IA64_LTV64MSB,
+ BFD_RELOC_IA64_LTV64LSB,
+ BFD_RELOC_IA64_IPLTMSB,
+ BFD_RELOC_IA64_IPLTLSB,
+ BFD_RELOC_IA64_COPY,
+ BFD_RELOC_IA64_TPREL22,
+ BFD_RELOC_IA64_TPREL64MSB,
+ BFD_RELOC_IA64_TPREL64LSB,
+ BFD_RELOC_IA64_LTOFF_TP22,
+ BFD_RELOC_IA64_LTOFF22X,
+ BFD_RELOC_IA64_LDXMOV,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits high part of an absolute address. */
+ BFD_RELOC_M68HC11_HI8,
+
+/* Motorola 68HC11 reloc.
+This is the 8 bits low part of an absolute address. */
+ BFD_RELOC_M68HC11_LO8,
+
+/* Motorola 68HC11 reloc.
+This is the 3 bits of a value. */
+ BFD_RELOC_M68HC11_3B,
+
+/* These relocs are only used within the CRIS assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_CRIS_BDISP8,
+ BFD_RELOC_CRIS_UNSIGNED_5,
+ BFD_RELOC_CRIS_SIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_6,
+ BFD_RELOC_CRIS_UNSIGNED_4,
+
+/* Relocs used in ELF shared libraries for CRIS. */
+ BFD_RELOC_CRIS_COPY,
+ BFD_RELOC_CRIS_GLOB_DAT,
+ BFD_RELOC_CRIS_JUMP_SLOT,
+ BFD_RELOC_CRIS_RELATIVE,
+
+/* 32-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_32_GOT,
+
+/* 16-bit offset to symbol-entry within GOT. */
+ BFD_RELOC_CRIS_16_GOT,
+
+/* 32-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_32_GOTPLT,
+
+/* 16-bit offset to symbol-entry within GOT, with PLT handling. */
+ BFD_RELOC_CRIS_16_GOTPLT,
+
+/* 32-bit offset to symbol, relative to GOT. */
+ BFD_RELOC_CRIS_32_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to GOT. */
+ BFD_RELOC_CRIS_32_PLT_GOTREL,
+
+/* 32-bit offset to symbol with PLT entry, relative to this relocation. */
+ BFD_RELOC_CRIS_32_PLT_PCREL,
+
+/* Intel i860 Relocations. */
+ BFD_RELOC_860_COPY,
+ BFD_RELOC_860_GLOB_DAT,
+ BFD_RELOC_860_JUMP_SLOT,
+ BFD_RELOC_860_RELATIVE,
+ BFD_RELOC_860_PC26,
+ BFD_RELOC_860_PLT26,
+ BFD_RELOC_860_PC16,
+ BFD_RELOC_860_LOW0,
+ BFD_RELOC_860_SPLIT0,
+ BFD_RELOC_860_LOW1,
+ BFD_RELOC_860_SPLIT1,
+ BFD_RELOC_860_LOW2,
+ BFD_RELOC_860_SPLIT2,
+ BFD_RELOC_860_LOW3,
+ BFD_RELOC_860_LOGOT0,
+ BFD_RELOC_860_SPGOT0,
+ BFD_RELOC_860_LOGOT1,
+ BFD_RELOC_860_SPGOT1,
+ BFD_RELOC_860_LOGOTOFF0,
+ BFD_RELOC_860_SPGOTOFF0,
+ BFD_RELOC_860_LOGOTOFF1,
+ BFD_RELOC_860_SPGOTOFF1,
+ BFD_RELOC_860_LOGOTOFF2,
+ BFD_RELOC_860_LOGOTOFF3,
+ BFD_RELOC_860_LOPC,
+ BFD_RELOC_860_HIGHADJ,
+ BFD_RELOC_860_HAGOT,
+ BFD_RELOC_860_HAGOTOFF,
+ BFD_RELOC_860_HAPC,
+ BFD_RELOC_860_HIGH,
+ BFD_RELOC_860_HIGOT,
+ BFD_RELOC_860_HIGOTOFF,
+
+/* OpenRISC Relocations. */
+ BFD_RELOC_OPENRISC_ABS_26,
+ BFD_RELOC_OPENRISC_REL_26,
+
+/* H8 elf Relocations. */
+ BFD_RELOC_H8_DIR16A8,
+ BFD_RELOC_H8_DIR16R8,
+ BFD_RELOC_H8_DIR24A8,
+ BFD_RELOC_H8_DIR24R8,
+ BFD_RELOC_H8_DIR32A16,
+
+/* Sony Xstormy16 Relocations. */
+ BFD_RELOC_XSTORMY16_REL_12,
+ BFD_RELOC_XSTORMY16_24,
+ BFD_RELOC_XSTORMY16_FPTR16,
+ BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+ /* A pointer to the BFD which owns the symbol. This information
+ is necessary so that a back end can work out what additional
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+ struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+ /* The text of the symbol. The name is left alone, and not copied; the
+ application may not alter it. */
+ const char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol. */
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ value is the offset into the section of the data. */
+#define BSF_GLOBAL 0x02
+
+ /* The symbol has global scope and is exported. The value is
+ the offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* No real difference. */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>>. */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning, unless BSF_DEBUGGING_RELOC is also set. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. The name is a
+ warning. The name of the next symbol is the one to warn about;
+ if a reference is made to a symbol with the same name as the next
+ symbol, a warning is issued by the linker. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. This symbol is an indirect
+ pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ /* Symbol is from dynamic linking information. */
+#define BSF_DYNAMIC 0x8000
+
+ /* The symbol denotes a data object. Used in ELF, and perhaps
+ others someday. */
+#define BSF_OBJECT 0x10000
+
+ /* This symbol is a debugging symbol. The value is the offset
+ into the section of the data. BSF_DEBUGGING should be set
+ as well. */
+#define BSF_DEBUGGING_RELOC 0x20000
+
+ flagword flags;
+
+ /* A pointer to the section to which this symbol is
+ relative. This will always be non NULL, there are special
+ sections for undefined and absolute symbols. */
+ struct sec *section;
+
+ /* Back end special data. */
+ union
+ {
+ PTR p;
+ bfd_vma i;
+ }
+ udata;
+}
+asymbol;
+
+#define bfd_get_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
+
+boolean
+bfd_is_local_label PARAMS ((bfd *abfd, asymbol *sym));
+
+boolean
+bfd_is_local_label_name PARAMS ((bfd *abfd, const char *name));
+
+#define bfd_is_local_label_name(abfd, name) \
+ BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name))
+
+#define bfd_canonicalize_symtab(abfd, location) \
+ BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+ (abfd, location))
+
+boolean
+bfd_set_symtab PARAMS ((bfd *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((bfd *abfd, PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+
+asymbol *
+_bfd_generic_make_empty_symbol PARAMS ((bfd *));
+
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+boolean
+bfd_is_undefined_symclass PARAMS ((int symclass));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+ BFD_SEND (obfd, _bfd_copy_private_symbol_data, \
+ (ibfd, isymbol, obfd, osymbol))
+
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ const char *filename;
+
+ /* A pointer to the target jump table. */
+ const struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char *",
+ and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ PTR iostream;
+
+ /* Is the file descriptor being cached? That is, can it be closed as
+ needed, and re-opened when accessed later? */
+ boolean cacheable;
+
+ /* Marks whether there was a default target specified when the
+ BFD was opened. This is used to select which matching algorithm
+ to use to choose the back end. */
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs. */
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here... */
+ ufile_ptr where;
+
+ /* ... and here: (``once'' means at least once). */
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time. */
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true. */
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension. */
+ int ifd;
+
+ /* The format which belongs to the BFD. (object, core, etc.) */
+ bfd_format format;
+
+ /* The direction with which the BFD was opened. */
+ enum bfd_direction
+ {
+ no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3
+ }
+ direction;
+
+ /* Format_specific flags. */
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+ ufile_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ from happening. */
+ boolean output_has_begun;
+
+ /* A hash table for section names. */
+ struct bfd_hash_table section_htab;
+
+ /* Pointer to linked list of sections. */
+ struct sec *sections;
+
+ /* The place where we add to the section list. */
+ struct sec **section_tail;
+
+ /* The number of sections. */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output. */
+ unsigned int symcount;
+
+ /* Symbol table for output BFD (with symcount entries). */
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information. */
+ const struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives. */
+ PTR arelt_data;
+ struct _bfd *my_archive; /* The containing archive BFD. */
+ struct _bfd *next; /* The next BFD in the archive. */
+ struct _bfd *archive_head; /* The first BFD in the archive. */
+ boolean has_armap;
+
+ /* A chain of BFD structures involved in a link. */
+ struct _bfd *link_next;
+
+ /* A field used by _bfd_generic_link_add_archive_symbols. This will
+ be used only for archive elements. */
+ int archive_pass;
+
+ /* Used by the back end to hold private data. */
+ union
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct pe_tdata *pe_obj_data;
+ struct xcoff_tdata *xcoff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct ihex_data_struct *ihex_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct mmo_data_struct *mmo_data;
+ struct sun_core_struct *sun_core_data;
+ struct sco5_core_struct *sco5_core_data;
+ struct trad_core_struct *trad_core_data;
+ struct som_data_struct *som_data;
+ struct hpux_core_struct *hpux_core_data;
+ struct hppabsd_core_struct *hppabsd_core_data;
+ struct sgi_core_struct *sgi_core_data;
+ struct lynx_core_struct *lynx_core_data;
+ struct osf_core_struct *osf_core_data;
+ struct cisco_core_struct *cisco_core_data;
+ struct versados_data_struct *versados_data;
+ struct netbsd_core_struct *netbsd_core_data;
+ PTR any;
+ }
+ tdata;
+
+ /* Used by the application to hold private data. */
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes. This is a
+ struct objalloc *, but we use PTR to avoid requiring the inclusion of
+ objalloc.h. */
+ PTR memory;
+};
+
+typedef enum bfd_error
+{
+ bfd_error_no_error = 0,
+ bfd_error_system_call,
+ bfd_error_invalid_target,
+ bfd_error_wrong_format,
+ bfd_error_wrong_object_format,
+ bfd_error_invalid_operation,
+ bfd_error_no_memory,
+ bfd_error_no_symbols,
+ bfd_error_no_armap,
+ bfd_error_no_more_archived_files,
+ bfd_error_malformed_archive,
+ bfd_error_file_not_recognized,
+ bfd_error_file_ambiguously_recognized,
+ bfd_error_no_contents,
+ bfd_error_nonrepresentable_section,
+ bfd_error_no_debug_section,
+ bfd_error_bad_value,
+ bfd_error_file_truncated,
+ bfd_error_file_too_big,
+ bfd_error_invalid_error_code
+}
+bfd_error_type;
+
+bfd_error_type
+bfd_get_error PARAMS ((void));
+
+void
+bfd_set_error PARAMS ((bfd_error_type error_tag));
+
+const char *
+bfd_errmsg PARAMS ((bfd_error_type error_tag));
+
+void
+bfd_perror PARAMS ((const char *message));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+bfd_error_handler_type
+bfd_get_error_handler PARAMS ((void));
+
+const char *
+bfd_archive_filename PARAMS ((bfd *));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+void
+bfd_set_reloc PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count));
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+int
+bfd_get_arch_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_sign_extend_vma PARAMS ((bfd *abfd));
+
+boolean
+bfd_set_start_address PARAMS ((bfd *abfd, bfd_vma vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+bfd_set_gp_size PARAMS ((bfd *abfd, unsigned int i));
+
+bfd_vma
+bfd_scan_vma PARAMS ((const char *string, const char **end, int base));
+
+boolean
+bfd_copy_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_copy_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_copy_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (obfd, _bfd_merge_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+ BFD_SEND (abfd, _bfd_set_private_flags, \
+ (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_relax_section(abfd, section, link_info, again) \
+ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
+
+#define bfd_gc_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info))
+
+#define bfd_merge_sections(abfd, link_info) \
+ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info))
+
+#define bfd_link_hash_table_create(abfd) \
+ BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
+
+#define bfd_link_add_symbols(abfd, info) \
+ BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info))
+
+#define bfd_final_link(abfd, info) \
+ BFD_SEND (abfd, _bfd_final_link, (abfd, info))
+
+#define bfd_free_cached_info(abfd) \
+ BFD_SEND (abfd, _bfd_free_cached_info, (abfd))
+
+#define bfd_get_dynamic_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd))
+
+#define bfd_print_private_bfd_data(abfd, file)\
+ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols))
+
+#define bfd_get_dynamic_reloc_upper_bound(abfd) \
+ BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd))
+
+#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
+ BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *,
+ boolean, asymbol **));
+
+boolean
+bfd_alt_mach_code PARAMS ((bfd *abfd, int index));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+const char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+ ((*((bfd)->xvec->message)) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND
+#define BFD_SEND(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ ((*((bfd)->xvec->message)) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist)
+
+#ifdef DEBUG_BFD_SEND
+#undef BFD_SEND_FMT
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \
+ (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \
+ (bfd_assert (__FILE__,__LINE__), NULL))
+#endif
+
+enum bfd_flavour
+{
+ bfd_target_unknown_flavour,
+ bfd_target_aout_flavour,
+ bfd_target_coff_flavour,
+ bfd_target_ecoff_flavour,
+ bfd_target_xcoff_flavour,
+ bfd_target_elf_flavour,
+ bfd_target_ieee_flavour,
+ bfd_target_nlm_flavour,
+ bfd_target_oasys_flavour,
+ bfd_target_tekhex_flavour,
+ bfd_target_srec_flavour,
+ bfd_target_ihex_flavour,
+ bfd_target_som_flavour,
+ bfd_target_os9k_flavour,
+ bfd_target_versados_flavour,
+ bfd_target_msdos_flavour,
+ bfd_target_ovax_flavour,
+ bfd_target_evax_flavour,
+ bfd_target_mmo_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+/* Forward declaration. */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+ /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */
+ char *name;
+
+ /* The "flavour" of a back end is a general indication about
+ the contents of a file. */
+ enum bfd_flavour flavour;
+
+ /* The order of bytes within the data area of a file. */
+ enum bfd_endian byteorder;
+
+ /* The order of bytes within the header parts of a file. */
+ enum bfd_endian header_byteorder;
+
+ /* A mask of all the flags which an executable may have set -
+ from the set <<BFD_NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>. */
+ flagword object_flags;
+
+ /* A mask of all the flags which a section may have set - from
+ the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>. */
+ flagword section_flags;
+
+ /* The character normally found at the front of a symbol.
+ (if any), perhaps `_'. */
+ char symbol_leading_char;
+
+ /* The pad character for file names within an archive header. */
+ char ar_pad_char;
+
+ /* The maximum number of characters in an archive header. */
+ unsigned short ar_max_namelen;
+
+ /* Entries for byte swapping for data. These are different from the
+ other entry points, since they don't take a BFD asthe first argument.
+ Certain other handlers could do the same. */
+ bfd_vma (*bfd_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Byte swapping for the headers. */
+ bfd_vma (*bfd_h_getx64) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx32) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx16) PARAMS ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+ /* Format dependent routines: these are vectors of entry points
+ within the target vector structure, one for each format to check. */
+
+ /* Check the format of a file being read. Return a <<bfd_target *>> or zero. */
+ const struct bfd_target *(*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Set the format of a file being written. */
+ boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+
+ /* Write cached information into a file being written, at <<bfd_close>>. */
+ boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+
+ /* Generic entry points. */
+#define BFD_JUMP_TABLE_GENERIC(NAME) \
+CONCAT2 (NAME,_close_and_cleanup), \
+CONCAT2 (NAME,_bfd_free_cached_info), \
+CONCAT2 (NAME,_new_section_hook), \
+CONCAT2 (NAME,_get_section_contents), \
+CONCAT2 (NAME,_get_section_contents_in_window)
+
+ /* Called when the BFD is being closed to do any necessary cleanup. */
+ boolean (*_close_and_cleanup) PARAMS ((bfd *));
+ /* Ask the BFD to free all cached information. */
+ boolean (*_bfd_free_cached_info) PARAMS ((bfd *));
+ /* Called when a new section is created. */
+ boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+ /* Read the contents of a section. */
+ boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type));
+
+ /* Entry points to copy private data. */
+#define BFD_JUMP_TABLE_COPY(NAME) \
+CONCAT2 (NAME,_bfd_copy_private_bfd_data), \
+CONCAT2 (NAME,_bfd_merge_private_bfd_data), \
+CONCAT2 (NAME,_bfd_copy_private_section_data), \
+CONCAT2 (NAME,_bfd_copy_private_symbol_data), \
+CONCAT2 (NAME,_bfd_set_private_flags), \
+CONCAT2 (NAME,_bfd_print_private_bfd_data) \
+ /* Called to copy BFD general private data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to merge BFD general private data from one object file
+ to a common output file when linking. */
+ boolean (*_bfd_merge_private_bfd_data) PARAMS ((bfd *, bfd *));
+ /* Called to copy BFD private section data from one object file
+ to another. */
+ boolean (*_bfd_copy_private_section_data) PARAMS ((bfd *, sec_ptr,
+ bfd *, sec_ptr));
+ /* Called to copy BFD private symbol data from one symbol
+ to another. */
+ boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+ /* Called to set private backend flags. */
+ boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+ /* Called to print private BFD data. */
+ boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, PTR));
+
+ /* Core file entry points. */
+#define BFD_JUMP_TABLE_CORE(NAME) \
+CONCAT2 (NAME,_core_file_failing_command), \
+CONCAT2 (NAME,_core_file_failing_signal), \
+CONCAT2 (NAME,_core_file_matches_executable_p)
+ char * (*_core_file_failing_command) PARAMS ((bfd *));
+ int (*_core_file_failing_signal) PARAMS ((bfd *));
+ boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+ /* Archive entry points. */
+#define BFD_JUMP_TABLE_ARCHIVE(NAME) \
+CONCAT2 (NAME,_slurp_armap), \
+CONCAT2 (NAME,_slurp_extended_name_table), \
+CONCAT2 (NAME,_construct_extended_name_table), \
+CONCAT2 (NAME,_truncate_arname), \
+CONCAT2 (NAME,_write_armap), \
+CONCAT2 (NAME,_read_ar_hdr), \
+CONCAT2 (NAME,_openr_next_archived_file), \
+CONCAT2 (NAME,_get_elt_at_index), \
+CONCAT2 (NAME,_generic_stat_arch_elt), \
+CONCAT2 (NAME,_update_armap_timestamp)
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ boolean (*_bfd_construct_extended_name_table)
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, const char *, char *));
+ boolean (*write_armap)
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+ PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *, bfd *));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+ bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+ boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+ /* Entry points used for symbols. */
+#define BFD_JUMP_TABLE_SYMBOLS(NAME) \
+CONCAT2 (NAME,_get_symtab_upper_bound), \
+CONCAT2 (NAME,_get_symtab), \
+CONCAT2 (NAME,_make_empty_symbol), \
+CONCAT2 (NAME,_print_symbol), \
+CONCAT2 (NAME,_get_symbol_info), \
+CONCAT2 (NAME,_bfd_is_local_label_name), \
+CONCAT2 (NAME,_get_lineno), \
+CONCAT2 (NAME,_find_nearest_line), \
+CONCAT2 (NAME,_bfd_make_debug_symbol), \
+CONCAT2 (NAME,_read_minisymbols), \
+CONCAT2 (NAME,_minisymbol_to_symbol)
+ long (*_bfd_get_symtab_upper_bound) PARAMS ((bfd *));
+ long (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+ struct symbol_cache_entry *
+ (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+ void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ struct symbol_cache_entry *,
+ symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+ boolean (*_bfd_is_local_label_name) PARAMS ((bfd *, const char *));
+
+ alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+ boolean (*_bfd_find_nearest_line)
+ PARAMS ((bfd *, struct sec *, struct symbol_cache_entry **, bfd_vma,
+ const char **, const char **, unsigned int *));
+ /* Back-door to allow format-aware applications to create debug symbols
+ while using BFD for everything else. Currently used by the assembler
+ when creating COFF files. */
+ asymbol *(*_bfd_make_debug_symbol) PARAMS ((bfd *, void *,
+ unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+ BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+ long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+ unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+ asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+ /* Routines for relocs. */
+#define BFD_JUMP_TABLE_RELOCS(NAME) \
+CONCAT2 (NAME,_get_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_reloc), \
+CONCAT2 (NAME,_bfd_reloc_type_lookup)
+ long (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+ long (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+ struct symbol_cache_entry **));
+ /* See documentation on reloc types. */
+ reloc_howto_type *
+ (*reloc_type_lookup) PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+ /* Routines used when writing an object file. */
+#define BFD_JUMP_TABLE_WRITE(NAME) \
+CONCAT2 (NAME,_set_arch_mach), \
+CONCAT2 (NAME,_set_section_contents)
+ boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+ boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+
+ /* Routines used by the linker. */
+#define BFD_JUMP_TABLE_LINK(NAME) \
+CONCAT2 (NAME,_sizeof_headers), \
+CONCAT2 (NAME,_bfd_get_relocated_section_contents), \
+CONCAT2 (NAME,_bfd_relax_section), \
+CONCAT2 (NAME,_bfd_link_hash_table_create), \
+CONCAT2 (NAME,_bfd_link_add_symbols), \
+CONCAT2 (NAME,_bfd_final_link), \
+CONCAT2 (NAME,_bfd_link_split_section), \
+CONCAT2 (NAME,_bfd_gc_sections), \
+CONCAT2 (NAME,_bfd_merge_sections)
+ int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+ bfd_byte *(*_bfd_get_relocated_section_contents)
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, struct symbol_cache_entry **));
+
+ boolean (*_bfd_relax_section)
+ PARAMS ((bfd *, struct sec *, struct bfd_link_info *, boolean *));
+
+ /* Create a hash table for the linker. Different backends store
+ different information in this table. */
+ struct bfd_link_hash_table *(*_bfd_link_hash_table_create) PARAMS ((bfd *));
+
+ /* Add symbols from this object file into the hash table. */
+ boolean (*_bfd_link_add_symbols) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Do a link based on the link_order structures attached to each
+ section of the BFD. */
+ boolean (*_bfd_final_link) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Should this section be split up into smaller pieces during linking. */
+ boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+ /* Remove sections that are not referenced from the output. */
+ boolean (*_bfd_gc_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Attempt to merge SEC_MERGE sections. */
+ boolean (*_bfd_merge_sections) PARAMS ((bfd *, struct bfd_link_info *));
+
+ /* Routines to handle dynamic symbols and relocs. */
+#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
+CONCAT2 (NAME,_get_dynamic_symtab_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_symtab), \
+CONCAT2 (NAME,_get_dynamic_reloc_upper_bound), \
+CONCAT2 (NAME,_canonicalize_dynamic_reloc)
+ /* Get the amount of memory required to hold the dynamic symbols. */
+ long (*_bfd_get_dynamic_symtab_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic symbols. */
+ long (*_bfd_canonicalize_dynamic_symtab)
+ PARAMS ((bfd *, struct symbol_cache_entry **));
+ /* Get the amount of memory required to hold the dynamic relocs. */
+ long (*_bfd_get_dynamic_reloc_upper_bound) PARAMS ((bfd *));
+ /* Read in the dynamic relocs. */
+ long (*_bfd_canonicalize_dynamic_reloc)
+ PARAMS ((bfd *, arelent **, struct symbol_cache_entry **));
+
+ /* Opposite endian version of this target. */
+ const struct bfd_target * alternative_target;
+
+ /* Data for use by back-end routines, which isn't
+ generic enough to belong in this structure. */
+ PTR backend_data;
+
+} bfd_target;
+
+boolean
+bfd_set_default_target PARAMS ((const char *name));
+
+const bfd_target *
+bfd_find_target PARAMS ((const char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+const bfd_target *
+bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching));
+
+boolean
+bfd_set_format PARAMS ((bfd *abfd, bfd_format format));
+
+const char *
+bfd_format_string PARAMS ((bfd_format format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/gnu/usr.bin/binutils/libbinutils/Makefile b/gnu/usr.bin/binutils/libbinutils/Makefile
new file mode 100644
index 0000000..d9cd774
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbinutils/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils
+
+LIB= binutils
+SRCS+= arlex.l arparse.y arsup.c bucomm.c debug.c filemode.c \
+ ieee.c rdcoff.c rddbg.c rename.c stabs.c unwind-ia64.c \
+ wrstabs.c version.c
+WARNS= 0
+CFLAGS+= -DTARGET=\"${TARGET_ARCH}-unknown-freebsd\"
+CFLAGS+= -DBFD_VERSION_STRING=\"${VERSION}\"
+CFLAGS+= -I${SRCDIR}/binutils
+CFLAGS+= -I${SRCDIR}/bfd
+INTERNALLIB= true
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/binutils/libbinutils/config.h b/gnu/usr.bin/binutils/libbinutils/config.h
new file mode 100644
index 0000000..98d0fee
--- /dev/null
+++ b/gnu/usr.bin/binutils/libbinutils/config.h
@@ -0,0 +1,207 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* 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 to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if lex declares yytext as a char * by default, not a char[]. */
+#define YYTEXT_POINTER 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getc_unlocked function. */
+/* #undef HAVE_GETC_UNLOCKED */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setmode function. */
+#define HAVE_SETMODE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the utimes function. */
+#define HAVE_UTIMES 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Name of package */
+#define PACKAGE "binutils"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
+/* Does the platform use an executable suffix? */
+/* #undef HAVE_EXECUTABLE_SUFFIX */
+
+/* Suffix used for executables, if any. */
+#define EXECUTABLE_SUFFIX ""
+
+/* Is fopen64 available? */
+/* #undef HAVE_FOPEN64 */
+
+/* Enable LFS */
+/* #undef _LARGEFILE64_SOURCE */
+
+/* Is the type time_t defined in <time.h>? */
+#define HAVE_TIME_T_IN_TIME_H 1
+
+/* Is the type time_t defined in <sys/types.h>? */
+#define HAVE_TIME_T_IN_TYPES_H 1
+
+/* Does <utime.h> define struct utimbuf? */
+#define HAVE_GOOD_UTIME_H 1
+
+/* Define if fprintf is not declared in system header files. */
+/* #undef NEED_DECLARATION_FPRINTF */
+
+/* Define if strstr is not declared in system header files. */
+/* #undef NEED_DECLARATION_STRSTR */
+
+/* Define if sbrk is not declared in system header files. */
+/* #undef NEED_DECLARATION_SBRK */
+
+/* Define if getenv is not declared in system header files. */
+/* #undef NEED_DECLARATION_GETENV */
+
+/* Define if environ is not declared in system header files. */
+#define NEED_DECLARATION_ENVIRON 1
+
+/* Use b modifier when opening binary files? */
+/* #undef USE_BINARY_FOPEN */
+
+/* Configured target name. */
+/* #define TARGET "alpha-unknown-freebsd5.0" */
+
diff --git a/gnu/usr.bin/binutils/libiberty/Makefile b/gnu/usr.bin/binutils/libiberty/Makefile
new file mode 100644
index 0000000..f34be9e
--- /dev/null
+++ b/gnu/usr.bin/binutils/libiberty/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/libiberty
+
+LIB= iberty
+SRCS= argv.c choose-temp.c concat.c cp-demangle.c cplus-dem.c \
+ dyn-string.c getopt.c getopt1.c getpwd.c getruntime.c \
+ hex.c floatformat.c hashtab.c lbasename.c make-temp-file.c \
+ objalloc.c obstack.c safe-ctype.c xatexit.c xexit.c xmalloc.c \
+ xstrdup.c xstrerror.c
+.if defined(BOOTSTRAPPING)
+SRCS+= basename.c
+.endif
+WARNS= 1
+CFLAGS+= -DHAVE_CONFIG_H
+INTERNALLIB= true
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/binutils/libiberty/config.h b/gnu/usr.bin/binutils/libiberty/config.h
new file mode 100644
index 0000000..deac895
--- /dev/null
+++ b/gnu/usr.bin/binutils/libiberty/config.h
@@ -0,0 +1,257 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader 2.13. */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have <vfork.h>. */
+/* #undef HAVE_VFORK_H */
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define vfork as fork if vfork does not work. */
+/* #undef vfork */
+
+/* Define if you have the _doprnt function. */
+/* #undef HAVE__DOPRNT */
+
+/* Define if you have the asprintf function. */
+#define HAVE_ASPRINTF 1
+
+/* Define if you have the atexit function. */
+#define HAVE_ATEXIT 1
+
+/* Define if you have the basename function. */
+#define HAVE_BASENAME 1
+
+/* Define if you have the bcmp function. */
+#define HAVE_BCMP 1
+
+/* Define if you have the bcopy function. */
+#define HAVE_BCOPY 1
+
+/* Define if you have the bsearch function. */
+#define HAVE_BSEARCH 1
+
+/* Define if you have the bzero function. */
+#define HAVE_BZERO 1
+
+/* Define if you have the calloc function. */
+#define HAVE_CALLOC 1
+
+/* Define if you have the clock function. */
+#define HAVE_CLOCK 1
+
+/* Define if you have the ffs function. */
+#define HAVE_FFS 1
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getrusage function. */
+#define HAVE_GETRUSAGE 1
+
+/* Define if you have the gettimeofday function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the index function. */
+#define HAVE_INDEX 1
+
+/* Define if you have the insque function. */
+/* #undef HAVE_INSQUE */
+
+/* Define if you have the memchr function. */
+#define HAVE_MEMCHR 1
+
+/* Define if you have the memcmp function. */
+#define HAVE_MEMCMP 1
+
+/* Define if you have the memcpy function. */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the memset function. */
+#define HAVE_MEMSET 1
+
+/* Define if you have the mkstemps function. */
+#define HAVE_MKSTEMPS 1
+
+/* Define if you have the on_exit function. */
+/* #undef HAVE_ON_EXIT */
+
+/* Define if you have the psignal function. */
+#define HAVE_PSIGNAL 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the random function. */
+#define HAVE_RANDOM 1
+
+/* Define if you have the rename function. */
+#define HAVE_RENAME 1
+
+/* Define if you have the rindex function. */
+#define HAVE_RINDEX 1
+
+/* Define if you have the sbrk function. */
+#define HAVE_SBRK 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the sigsetmask function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strncasecmp function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define if you have the strrchr function. */
+#define HAVE_STRRCHR 1
+
+/* Define if you have the strsignal function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtod function. */
+#define HAVE_STRTOD 1
+
+/* Define if you have the strtol function. */
+#define HAVE_STRTOL 1
+
+/* Define if you have the strtoul function. */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the sysconf function. */
+#define HAVE_SYSCONF 1
+
+/* Define if you have the times function. */
+#define HAVE_TIMES 1
+
+/* Define if you have the tmpnam function. */
+#define HAVE_TMPNAM 1
+
+/* Define if you have the vasprintf function. */
+#define HAVE_VASPRINTF 1
+
+/* Define if you have the vfprintf function. */
+#define HAVE_VFPRINTF 1
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
+/* Define if you have the vsprintf function. */
+#define HAVE_VSPRINTF 1
+
+/* Define if you have the waitpid function. */
+#define HAVE_WAITPID 1
+
+/* Define if you have the <alloca.h> header file. */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if errno must be declared even when <errno.h> is included. */
+/* #undef NEED_DECLARATION_ERRNO */
+
+/* Define if you have the `uintptr_t' type. */
+#define HAVE_UINTPTR_T 1
+
+/* Define if you have the sys_errlist variable. */
+#define HAVE_SYS_ERRLIST 1
+
+/* Define if you have the sys_nerr variable. */
+#define HAVE_SYS_NERR 1
+
+/* Define if you have the sys_siglist variable. */
+#define HAVE_SYS_SIGLIST 1
+
+/* 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 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 */
+#define STACK_DIRECTION -1
+
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile b/gnu/usr.bin/binutils/libopcodes/Makefile
new file mode 100644
index 0000000..053245f
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/opcodes
+
+LIB= opcodes
+SRCS+= dis-buf.c disassemble.c
+CFLAGS+= -I${SRCDIR}/opcodes -I${SRCDIR}/bfd
+INTERNALLIB= true
+
+# If set, BINUTILSDISTDIR is the path to a directory containing the full GNU
+# binutils release. FreeBSD only distributes the bits that are required to
+# build native architectures. BINUTILSDISTDIR is needed to build cross tools.
+.if defined(BINUTILSDISTDIR) && exists(${BINUTILSDISTDIR})
+.PATH: ${BINUTILSDISTDIR}/bfd ${BINUTILSDISTDIR}/opcodes
+CFLAGS+= -I${BINUTILSDISTDIR}/opcodes -I${BINUTILSDISTDIR}/bfd
+CFLAGS+= -I${BINUTILSDISTDIR}/include
+.endif
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.alpha b/gnu/usr.bin/binutils/libopcodes/Makefile.alpha
new file mode 100644
index 0000000..03d911d
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.alpha
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+SRCS+= alpha-dis.c alpha-opc.c
+CFLAGS+= -DARCH_alpha
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.amd64 b/gnu/usr.bin/binutils/libopcodes/Makefile.amd64
new file mode 100644
index 0000000..5b1ce3a
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.amd64
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+SRCS+= i386-dis.c
+CFLAGS+= -DARCH_i386
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.i386 b/gnu/usr.bin/binutils/libopcodes/Makefile.i386
new file mode 100644
index 0000000..5b1ce3a
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.i386
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+SRCS+= i386-dis.c
+CFLAGS+= -DARCH_i386
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.ia64 b/gnu/usr.bin/binutils/libopcodes/Makefile.ia64
new file mode 100644
index 0000000..98198cd
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.ia64
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+SRCS+= ia64-dis.c ia64-opc.c
+CFLAGS+= -DARCH_ia64
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.m68k b/gnu/usr.bin/binutils/libopcodes/Makefile.m68k
new file mode 100644
index 0000000..927e2a1
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.m68k
@@ -0,0 +1,6 @@
+#
+# $FreeBSD$
+#
+
+SRCS+= m68k-dis.c m68k-opc.c
+CFLAGS+= -DARCH_m68k
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.powerpc b/gnu/usr.bin/binutils/libopcodes/Makefile.powerpc
new file mode 100644
index 0000000..cc010ec
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.powerpc
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+SRCS+= ppc-dis.c ppc-opc.c
+CFLAGS+= -DARCH_powerpc -DARCH_rs6000
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.sparc b/gnu/usr.bin/binutils/libopcodes/Makefile.sparc
new file mode 100644
index 0000000..190b766
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.sparc
@@ -0,0 +1,6 @@
+#
+# $FreeBSD$
+#
+
+SRCS+= sparc-dis.c sparc-opc.c
+CFLAGS+= -DARCH_sparc
diff --git a/gnu/usr.bin/binutils/libopcodes/Makefile.sparc64 b/gnu/usr.bin/binutils/libopcodes/Makefile.sparc64
new file mode 100644
index 0000000..e795ad4
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/Makefile.sparc64
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+SRCS+= sparc-dis.c sparc-opc.c
+CFLAGS+= -DARCH_sparc
diff --git a/gnu/usr.bin/binutils/libopcodes/config.h b/gnu/usr.bin/binutils/libopcodes/config.h
new file mode 100644
index 0000000..bce0fce
--- /dev/null
+++ b/gnu/usr.bin/binutils/libopcodes/config.h
@@ -0,0 +1,135 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* 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 to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you have the __argz_count function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define if you have the __argz_next function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define if you have the __argz_stringify function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <values.h> header file. */
+/* #undef HAVE_VALUES_H */
+
+/* Name of package */
+#define PACKAGE "opcodes"
+
+/* Version number of package */
+/* #define VERSION "2.12" */
+
+/* Define if you have the stpcpy function */
+/* #undef HAVE_STPCPY */
+
+/* Define if your locale.h file contains LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if NLS is requested */
+/* #define ENABLE_NLS 1 */
+
+/* Define as 1 if you have gettext and don't want to use GNU gettext. */
+/* #undef HAVE_GETTEXT */
+
diff --git a/gnu/usr.bin/binutils/nm/Makefile b/gnu/usr.bin/binutils/nm/Makefile
new file mode 100644
index 0000000..76acc7c
--- /dev/null
+++ b/gnu/usr.bin/binutils/nm/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= nm
+SRCS= nm.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/objcopy/Makefile b/gnu/usr.bin/binutils/objcopy/Makefile
new file mode 100644
index 0000000..dfa04f5
--- /dev/null
+++ b/gnu/usr.bin/binutils/objcopy/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= objcopy
+SRCS= objcopy.c not-strip.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/objdump/Makefile b/gnu/usr.bin/binutils/objdump/Makefile
new file mode 100644
index 0000000..4a1d6a3
--- /dev/null
+++ b/gnu/usr.bin/binutils/objdump/Makefile
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= objdump
+SRCS= objdump.c prdbg.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+CFLAGS+= -DBFD_VERSION_STRING=\"${VERSION}\"
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libopcodes/libopcodes.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/ranlib/Makefile b/gnu/usr.bin/binutils/ranlib/Makefile
new file mode 100644
index 0000000..960b130
--- /dev/null
+++ b/gnu/usr.bin/binutils/ranlib/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= ranlib
+SRCS= ar.o is-ranlib.o
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+CFLAGS+= -I${SRCDIR}/bfd
+NOSHARED?= yes
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/readelf/Makefile b/gnu/usr.bin/binutils/readelf/Makefile
new file mode 100644
index 0000000..9601246
--- /dev/null
+++ b/gnu/usr.bin/binutils/readelf/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+# No a.out vs. ELF version so don't install in /usr/libexec/elf
+BINDIR=/usr/bin
+
+PROG= readelf
+SRCS= ${PROG}.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils -I${SRCDIR}/binutils
+
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/size/Makefile b/gnu/usr.bin/binutils/size/Makefile
new file mode 100644
index 0000000..a0ef3171
--- /dev/null
+++ b/gnu/usr.bin/binutils/size/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= size
+SRCS= size.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/strings/Makefile b/gnu/usr.bin/binutils/strings/Makefile
new file mode 100644
index 0000000..346e59f
--- /dev/null
+++ b/gnu/usr.bin/binutils/strings/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= strings
+SRCS= strings.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/strip/Makefile b/gnu/usr.bin/binutils/strip/Makefile
new file mode 100644
index 0000000..4dc10c2
--- /dev/null
+++ b/gnu/usr.bin/binutils/strip/Makefile
@@ -0,0 +1,32 @@
+# $FreeBSD$
+
+.include "../Makefile.inc0"
+
+.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
+
+PROG= strip
+SRCS= objcopy.c is-strip.c
+WARNS= 2
+CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
+CFLAGS+= -I${SRCDIR}/binutils
+DPADD= ${RELTOP}/libbinutils/libbinutils.a
+DPADD+= ${RELTOP}/libbfd/libbfd.a
+DPADD+= ${RELTOP}/libiberty/libiberty.a
+LDADD= ${DPADD}
+CLEANFILES+= maybe_stripped
+
+all: maybe_stripped
+
+maybe_stripped: strip
+ cp strip maybe_stripped
+.if defined(STRIP)
+.if ${STRIP:M-s} != ""
+ -strip maybe_stripped
+.endif
+.endif
+
+realinstall:
+ ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ maybe_stripped ${DESTDIR}${BINDIR}/strip
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/update.sh b/gnu/usr.bin/binutils/update.sh
new file mode 100755
index 0000000..976cf3e
--- /dev/null
+++ b/gnu/usr.bin/binutils/update.sh
@@ -0,0 +1,47 @@
+#! /bin/sh
+#
+# $FreeBSD$
+#
+# This script installs the main files generated by the binutils
+# "configure" scripts and makefiles. It can be used for upgrading to
+# a new version of binutils.
+#
+# Don't forget to change the VERSION definition in the top level
+# "Makefile.inc0".
+
+gnudir=$(pwd)
+contribdir="${gnudir}/../../../contrib/binutils"
+platform="`uname -m`"
+
+rm -rf build
+mkdir build
+
+echo "binutils elf configuration for $platform"
+
+(cd build
+ ${contribdir}/configure $platform-unknown-freebsd || exit
+ (cd gas
+ echo "Updating as"
+ make config.h || exit
+ cp config.h ${gnudir}/as/$platform/config.h || exit
+ )
+ (cd ld
+ echo "Updating ld"
+ make config.h ldemul-list.h || exit
+ cp config.h ${gnudir}/ld || exit
+ cp ldemul-list.h ${gnudir}/ld/$platform || exit
+ )
+ (cd bfd
+ echo "Updating libbfd"
+ make bfd.h config.h || exit
+ cp bfd.h ${gnudir}/libbfd/$platform || exit
+ cp config.h ${gnudir}/libbfd/$platform || exit
+ )
+ (cd binutils
+ echo "Updating libbinutils"
+ make config.h || exit
+ cp config.h ${gnudir}/libbinutils/config.h || exit
+ )
+ )
+
+rm -rf build
diff --git a/gnu/usr.bin/cc/Makefile b/gnu/usr.bin/cc/Makefile
new file mode 100644
index 0000000..23499e1
--- /dev/null
+++ b/gnu/usr.bin/cc/Makefile
@@ -0,0 +1,31 @@
+# $FreeBSD$
+
+# The order of some of these are rather important. Some depend on previous
+# subdirs.
+
+SUBDIR= cc_tools cc_int cc cc1 cpp0 include protoize tradcpp0 doc
+
+.if !defined(NO_CPP)
+SUBDIR+= cpp
+.endif
+
+.if !defined(NO_CXX)
+SUBDIR+= cc1plus c++ c++filt
+.if !defined(NO_COLLECT2)
+#SUBDIR+= collect2
+.endif
+.endif
+
+.if !defined(NO_OBJC)
+SUBDIR+= cc1obj
+.endif
+
+.if !defined(NO_FORTRAN)
+SUBDIR+= f77 f771 f77doc
+.endif
+
+.if !defined(NO_GCOV)
+SUBDIR+= gcov
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/cc/Makefile.fe b/gnu/usr.bin/cc/Makefile.fe
new file mode 100644
index 0000000..c4a02f8
--- /dev/null
+++ b/gnu/usr.bin/cc/Makefile.fe
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+# Front-end-only bits
+
+version!= sed -n /version_string/p ${GCCDIR}/version.c | sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/'
diff --git a/gnu/usr.bin/cc/Makefile.inc b/gnu/usr.bin/cc/Makefile.inc
new file mode 100644
index 0000000..b130243
--- /dev/null
+++ b/gnu/usr.bin/cc/Makefile.inc
@@ -0,0 +1,49 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+# Sometimes this is .include'd several times...
+.if !defined(__CC_MAKEFILE_INC__)
+__CC_MAKEFILE_INC__= ${MFILE}
+
+GCCDIR= ${.CURDIR}/../../../../contrib/gcc
+
+.include "Makefile.tgt"
+
+# Machine description.
+MD_FILE= ${GCCDIR}/config/${GCC_CPU}/${GCC_CPU}.md
+target= ${TARGET_ARCH}-undermydesk-freebsd
+
+CFLAGS+= -DIN_GCC -DHAVE_CONFIG_H
+CFLAGS+= -DPREFIX=\"${TOOLS_PREFIX}/usr\"
+#CFLAGS+= -DWANT_COMPILER_INVARIANTS
+
+# If building 64-bit longs for the i386, "_LARGE_LONG" should also be defined
+# to get the proper sizes in limits.h
+.if defined(LONG_TYPE_SIZE)
+CFLAGS+= -DLONG_TYPE_SIZE=${LONG_TYPE_SIZE}
+.endif
+
+.if ${TARGET_ARCH} != ${MACHINE_ARCH}
+CFLAGS+= -DCROSS_COMPILE
+.endif
+
+.if defined(WANT_FORCE_OPTIMIZATION_DOWNGRADE)
+CFLAGS+= -DFORCE_OPTIMIZATION_DOWNGRADE=${WANT_FORCE_OPTIMIZATION_DOWNGRADE}
+.endif
+
+.if exists(${.OBJDIR}/../cc_tools)
+CFLAGS+= -I${.OBJDIR}/../cc_tools
+.endif
+CFLAGS+= -I${.CURDIR}/../cc_tools
+# This must go after the -I for cc_tools to resolve ambiguities for hash.h
+# correctly.
+CFLAGS+= -I${GCCDIR} -I${GCCDIR}/config
+
+.if exists(${.OBJDIR}/../cc_int)
+LIBCC_INT= ${.OBJDIR}/../cc_int/libcc_int.a
+.else
+LIBCC_INT= ${.CURDIR}/../cc_int/libcc_int.a
+.endif
+
+.endif # !__CC_MAKEFILE_INC__
diff --git a/gnu/usr.bin/cc/Makefile.tgt b/gnu/usr.bin/cc/Makefile.tgt
new file mode 100644
index 0000000..7bffcd8
--- /dev/null
+++ b/gnu/usr.bin/cc/Makefile.tgt
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+TARGET_ARCH?= ${MACHINE_ARCH}
+
+.if ${TARGET_ARCH} == "alpha"
+GCC_CPU= alpha
+.elif ${TARGET_ARCH} == "arm"
+GCC_CPU= arm
+.elif ${TARGET_ARCH} == "i386" || ${TARGET_ARCH} == "x86-64"
+GCC_CPU= i386
+.elif ${TARGET_ARCH} == "ia64"
+GCC_CPU= ia64
+.elif ${TARGET_ARCH} == "powerpc"
+GCC_CPU= rs6000
+.elif ${TARGET_ARCH} == "sparc64"
+GCC_CPU= sparc
+TARGET_CPU_DEFAULT= TARGET_CPU_ultrasparc
+.endif
diff --git a/gnu/usr.bin/cc/c++/Makefile b/gnu/usr.bin/cc/c++/Makefile
new file mode 100644
index 0000000..c1a57b2
--- /dev/null
+++ b/gnu/usr.bin/cc/c++/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+.include "../Makefile.fe"
+
+.PATH: ${GCCDIR}/cp ${GCCDIR}
+
+PROG= c++
+SRCS= gcc.c g++spec.c
+LINKS= ${BINDIR}/c++ ${BINDIR}/g++
+LINKS+= ${BINDIR}/c++ ${BINDIR}/CC
+NOMAN= 1
+
+CFLAGS+= -DDEFAULT_TARGET_VERSION=\"$(version)\"
+CFLAGS+= -DDEFAULT_TARGET_MACHINE=\"$(target)\"
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/c++filt/Makefile b/gnu/usr.bin/cc/c++filt/Makefile
new file mode 100644
index 0000000..6c42e2a
--- /dev/null
+++ b/gnu/usr.bin/cc/c++filt/Makefile
@@ -0,0 +1,24 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}
+
+PROG= c++filt
+SRCS= cp-demangle.c cplus-dem+%DIKED.c
+BINDIR= /usr/libexec/${OBJFORMAT}
+NOMAN= 1
+
+CFLAGS+= -DMAIN -DIN_GCC -DVERSION=\"$(version)\"
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+cplus-dem+%DIKED.c: cplus-dem.c
+ sed -e 's/^xmalloc[ ]/_DONT_xmalloc /g' \
+ -e 's/^xrealloc[ ]/_DONT_xrealloc /g' \
+ ${.ALLSRC} > ${.TARGET}
+
+CLEANFILES= cplus-dem+%DIKED.c
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/cc/Makefile b/gnu/usr.bin/cc/cc/Makefile
new file mode 100644
index 0000000..3dbc859
--- /dev/null
+++ b/gnu/usr.bin/cc/cc/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+.include "../Makefile.fe"
+
+.PATH: ${GCCDIR}
+
+PROG= cc
+MAN= gcc.1
+SRCS= gcc.c gccspec.c
+NOSHARED?=yes
+
+LINKS= ${BINDIR}/cc ${BINDIR}/gcc
+MLINKS= gcc.1 cc.1 gcc.1 c++.1 gcc.1 g++.1 gcc.1 CC.1
+
+CFLAGS+= -DDEFAULT_TARGET_VERSION=\"$(version)\"
+CFLAGS+= -DDEFAULT_TARGET_MACHINE=\"$(target)\"
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/cc1/Makefile b/gnu/usr.bin/cc/cc1/Makefile
new file mode 100644
index 0000000..09a89b5
--- /dev/null
+++ b/gnu/usr.bin/cc/cc1/Makefile
@@ -0,0 +1,34 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}
+
+PROG= cc1
+SRCS= main.c c-parse+%DIKED.c c-lang.c c-decl.c
+BINDIR= /usr/libexec
+NOMAN= 1
+NOSHARED?=yes
+
+CFLAGS+= -I.
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+#-----------------------------------------------------------------------
+# C parser
+c-parse+%DIKED.c: c-parse.c
+ sed -e "s/malloc/xmalloc/g" \
+ -e "s/realloc/xrealloc/g" \
+ ${.ALLSRC} > ${.TARGET}
+
+c-parse.y: c-parse.in
+ sed -e "/^ifobjc$$/,/^end ifobjc$$/d" \
+ -e "/^ifc$$/d" \
+ -e "/^end ifc$$/d" \
+ ${.ALLSRC} > ${.TARGET}
+
+CLEANFILES= c-parse+%DIKED.c c-parse.c c-parse.y
+CLEANFILES+= y.tab.h # we don't use it, but the system YACC rules are naive
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/cc1obj/Makefile b/gnu/usr.bin/cc/cc1obj/Makefile
new file mode 100644
index 0000000..d4ecd8c
--- /dev/null
+++ b/gnu/usr.bin/cc/cc1obj/Makefile
@@ -0,0 +1,36 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}/objc ${GCCDIR}
+
+PROG= cc1obj
+SRCS= objc-parse+DIKED.c objc-act.c objc-lang.c main.c c-decl.c
+BINDIR= /usr/libexec
+NOMAN= 1
+NOSHARED?=yes
+
+CFLAGS+= -I${GCCDIR}/objc -I.
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+#-----------------------------------------------------------------------
+# objc parser
+objc-parse+DIKED.c: objc-parse.c
+ sed -e "s/malloc/xmalloc/g" \
+ -e "s/realloc/xrealloc/g" \
+ ${.ALLSRC} > ${.TARGET}
+
+objc-parse.y: c-parse.in
+ sed -e "/^ifc$$/,/^end ifc$$/d" \
+ -e "/^ifobjc$$/d" \
+ -e "/^end ifobjc$$/d" \
+ ${.ALLSRC} > ${.TARGET}
+
+CLEANFILES= objc-parse+DIKED.c objc-parse.c objc-parse.y
+CLEANFILES+= y.tab.h # we don't use it, but the system YACC rules are naive
+
+#-----------------------------------------------------------------------
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/cc1plus/Makefile b/gnu/usr.bin/cc/cc1plus/Makefile
new file mode 100644
index 0000000..0833f61
--- /dev/null
+++ b/gnu/usr.bin/cc/cc1plus/Makefile
@@ -0,0 +1,37 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}/cp ${GCCDIR}
+
+PROG= cc1plus
+SRCS= parse+%DIKED.c parse.h
+SRCS+= main.c cp-lang.c \
+ call.c class.c cvt.c decl.c decl2.c error.c except.c expr.c friend.c \
+ init.c lex.c mangle.c method.c pt.c ptree.c repo.c rtti.c search.c \
+ semantics.c spew.c tree.c typeck.c typeck2.c dump.c optimize.c
+
+BINDIR= /usr/libexec
+NOMAN= 1
+NOSHARED?=yes
+
+CFLAGS+= -I${GCCDIR}/cp -I.
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+#-----------------------------------------------------------------------
+# C++ parser
+
+parse+%DIKED.c y.tab.h: parse.c
+ sed -e "s/malloc/xmalloc/g" \
+ -e "s/realloc/xrealloc/g" \
+ ${.ALLSRC:M*c} > ${.TARGET}
+
+parse.h: y.tab.h
+ cp -pf y.tab.h ${.TARGET}
+ grep '^#define[ ]*YYEMPTY' ${.TARGET:S/h$/c/} >>${.TARGET}
+
+CLEANFILES= parse+%DIKED.c parse.c parse.h y.tab.h
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/cc_drv/Makefile b/gnu/usr.bin/cc/cc_drv/Makefile
new file mode 100644
index 0000000..332b37a
--- /dev/null
+++ b/gnu/usr.bin/cc/cc_drv/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ../cc_tools ${GCCDIR}
+
+LIB= cc_drv
+NOPROFILE= YES
+NOPIC= YES
+
+SRCS= multilib.h choose-temp.c obstack.c prefix.c pexecute.c version.c
+
+CFLAGS+= -DIN_GCC
+
+install:
+ @true
+
+${OUT_OBJ}.o ${OUT_OBJ}.so: ${OUT_FILE}
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/cc/cc_int/Makefile b/gnu/usr.bin/cc/cc_int/Makefile
new file mode 100644
index 0000000..831b876
--- /dev/null
+++ b/gnu/usr.bin/cc/cc_int/Makefile
@@ -0,0 +1,85 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ../cc_tools ${GCCDIR}/config/${GCC_CPU} ${GCCDIR} ${GCCDIR}/../libiberty
+
+LIB= cc_int
+INTERNALLIB= YES
+
+# dbxout.c dwarfout.c emit-rtl.c explow.c expmed.c expr.c \
+# alias.c bitmap.c dwarf2out.c dyn-string.c \
+SRCS= c-common.c c-format.c \
+ c-pragma.c c-semantics.c \
+ \
+ caller-save.c calls.c combine.c convert.c cse.c \
+ dbxout.c dwarfout.c dwarf2out.c dwarf2asm.c emit-rtl.c explow.c expmed.c expr.c \
+ final.c flow.c fold-const.c function.c getpwd.c global.c graph.c \
+ hash.c haifa-sched.c \
+ integrate.c jump.c lcm.c local-alloc.c loop.c optabs.c \
+ print-rtl.c print-tree.c real.c recog.c reg-stack.c regclass.c \
+ reload.c reload1.c reorg.c rtl.c rtlanal.c \
+ sbitmap.c sdbout.c stmt.c stor-layout.c \
+ toplev.c tree.c unroll.c varasm.c version.c xcoffout.c \
+ alias.c bitmap.c dyn-string.c \
+ gcse.c genrtl.c profile.c regmove.c varray.c \
+ attribs.c cselib.c debug.c rtl-error.c tree-dump.c tree-inline.c \
+ ${GCC_CPU}.c
+
+SRCS+= bb-reorder.c conflict.c ggc-common.c \
+ ggc-page.c ifcvt.c lists.c predict.c regrename.c resource.c sibcall.c \
+ simplify-rtx.c ssa.c timevar.c ssa-dce.c ssa-ccp.c df.c fibheap.c
+
+# insn-* gunk -- headers are built in cc_tools, as they are used by the
+# "build-tools"
+.for F in attrtab emit extract opinit output peep recog
+SRCS+= insn-$F.c
+CLEANFILES+= insn-$F.c
+insn-$F.c: ${.OBJDIR}/../cc_tools/gen$F ${MD_FILE}
+ ${.OBJDIR}/../cc_tools/gen$F ${MD_FILE} > insn-$F.c
+.endfor
+
+# shared between the drivers
+SRCS+= multilib.h choose-temp.c obstack.c prefix.c pexecute.c version.c mbchar.c concat.c make-temp-file.c underscore.c
+# C_AND_OBJC_OBJS
+#SRCS+= attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \
+# c-convert.o c-aux-info.o c-common.o c-format.o c-semantics.o \
+# c-objc-common.o
+
+# XXX: shared by cc1, cc1obj & cpp0
+# cc1plus seems to be able to tolerate these here,
+# BUT only if the right .o's are specified in cc1plus/Makefile
+SRCS+= c-lex.c c-typeck.c \
+ c-errors.o c-pragma.o c-convert.o c-aux-info.o c-common.o c-format.o c-semantics.o c-objc-common.o
+
+# libbackend
+SRCS+= builtins.c diagnostic.c doloop.c dominance.c except.c gcse.c params.c sched-deps.c sched-vis.c sched-rgn.c sched-ebb.c \
+ stringpool.c c-lex.c langhooks.c hashtable.c \
+ hooks.c \
+ cfg.c cfganal.c cfgbuild.c cfgcleanup.c cfglayout.c cfgloop.c cfgrtl.c
+
+# libcpp
+SRCS+= cppdefault.c cpperror.c cppexp.c cppfiles.c cppinit.c cpphash.c \
+ cpplex.c cpplib.c cppmacro.c mkdeps.c line-map.c
+
+# stuff that makes libiberty now required (2.95) and shouldn't be...
+SRCS+= obstack.c splay-tree.c hashtab.c partition.c lbasename.c md5.c hex.c getopt.c getopt1.c
+CFLAGS+= -DHAVE_CONFIG_H
+
+CFLAGS+= -DTARGET_NAME=\"${target}\" -DIN_GCC
+.if defined(TARGET_CPU_DEFAULT)
+CFLAGS+= -DTARGET_CPU_DEFAULT=${TARGET_CPU_DEFAULT}
+.endif
+
+.if ${OBJFORMAT} == aout
+UNDERSCORES= 1
+.else
+UNDERSCORES= 0
+.endif
+SRCS+= underscore.c
+CLEANFILES+= underscore.c
+underscore.c: Makefile
+ echo '/*WARNING: This file is automatically generated!*/' >${.TARGET}
+ echo "int prepends_underscore = ${UNDERSCORES};" >>${.TARGET}
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/cc/cc_tools/Makefile b/gnu/usr.bin/cc/cc_tools/Makefile
new file mode 100644
index 0000000..22bb6f9
--- /dev/null
+++ b/gnu/usr.bin/cc/cc_tools/Makefile
@@ -0,0 +1,240 @@
+# $FreeBSD$
+
+#
+# This could probably be merged with ../cc_int/Makefile, but bsd.lib.mk
+# is such a !@#!*#% nightmare because of how it reprograms the dependencies,
+# suffix rules, SRCS, etc. It's easiest to cheat by using bsd.prog.mk and
+# SRCS to get dependencies.
+#
+
+# ../Makefile.inc will put an absolute path to our objdir in CFLAGS.
+# Prevent mkdep from using it, so that we don't have to give rules for
+# aliases of generated headers.
+
+CFLAGS+= -I.
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR} ${GCCDIR}/cp ${GCCDIR}/../libiberty
+
+CFLAGS+= -static -DGENERATOR_FILE
+
+#-----------------------------------------------------------------------
+# insn-* gunk
+
+.for F in attr codes config flags
+insn-$F.h: gen$F ${MD_FILE}
+ ./gen$F ${MD_FILE} > insn-$F.h
+GENSRCS+= insn-$F.h
+.endfor
+
+GENSRCS+= gen-time-stamp
+gen-time-stamp: genattrtab genemit genextract genopinit genoutput genpeep genrecog
+ touch ${.TARGET}
+
+.for F in attr codes config emit extract flags opinit output peep recog
+build-tools: gen$F
+
+gen$F: gen$F.o rtl.o obstack.o print-rtl.o bitmap.o errors.o gensupport.o ggc-none.o hashtab.o read-rtl.o
+ ${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${.ALLSRC}
+
+GENSRCS+= gen$F.c
+CLEANFILES+= gen$F
+.endfor
+
+.for F in attrtab
+build-tools: gen$F
+
+gen$F: gen$F.o rtl.o print-rtl.o obstack.o bitmap.o errors.o gensupport.o ggc-none.o hashtab.o read-rtl.o
+ ${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${.ALLSRC}
+
+GENSRCS+= gen$F.c
+CLEANFILES+= gen$F
+.endfor
+
+SRCS+= bitmap.c errors.c gensupport.c ggc-none.c hashtab.c obstack.c print-rtl.c regclass.c rtl.c rtlanal.c read-rtl.c
+
+.for F in check genrtl preds
+build-tools: gen$F
+
+gen$F: gen$F.o
+ ${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${.ALLSRC}
+
+GENSRCS+= gen$F.c
+CLEANFILES+= gen$F
+.endfor
+
+.ORDER: genrtl.c genrtl.h
+genrtl.c genrtl.h: gengenrtl
+ ./gengenrtl > genrtl.c
+ ./gengenrtl -h > genrtl.h
+
+GENSRCS+= genrtl.c genrtl.h
+
+#-----------------------------------------------------------------------
+# Common parser stuff.
+
+tree-check.h: gencheck
+ ./gencheck > ${.TARGET}
+GENSRCS+= tree-check.h
+
+#-----------------------------------------------------------------------
+# Predicates stuff.
+
+tm-preds.h: genpreds
+ ./genpreds > ${.TARGET}
+GENSRCS+= tm-preds.h
+
+#-----------------------------------------------------------------------
+# the host/target compiler config.
+
+COMMONHDRS= config.h hconfig.h multilib.h options.h specs.h tconfig.h \
+ tm_p.h configargs.h safe-ctype.h
+GENSRCS+= ${COMMONHDRS} gencheck.h
+
+MFILE?= ${.CURDIR}/Makefile
+${COMMONHDRS}: ${MFILE}
+
+configargs.h:
+ echo 'static const char configuration_arguments[] =' > ${.TARGET}
+ echo ' "FreeBSD/${TARGET_ARCH} system compiler";' >> ${.TARGET}
+ echo 'static const char thread_model[] = "posix";' >> ${.TARGET}
+
+hconfig.h:
+ echo '#include "auto-host.h"' > ${.TARGET}
+ echo '#include <tconfig.h>' >> ${.TARGET}
+
+gencheck.h:
+ echo '#include "cp/cp-tree.def"' > ${.TARGET}
+ echo '#include "objc/objc-tree.def"' >> ${.TARGET}
+
+multilib.h:
+ echo 'static const char *const multilib_raw[] = { \
+ "aout maout;", "elf !maout;", NULL };' > ${.TARGET}
+ echo 'static const char *const multilib_matches_raw[] = { \
+ "maout maout;", "melf melf;", NULL };' >> ${.TARGET}
+ echo 'static const char *multilib_extra = "";' >> ${.TARGET}
+ echo 'static const char *const multilib_exclusions_raw[] = { \
+ NULL };' >> ${.TARGET}
+
+options.h:
+ echo '#include "cp/lang-options.h"' > ${.TARGET}
+ echo '#include "f/lang-options.h"' >> ${.TARGET}
+ echo '#include "objc/lang-options.h"' >> ${.TARGET}
+
+specs.h:
+ echo '#include "cp/lang-specs.h"' > ${.TARGET}
+ echo '#include "f/lang-specs.h"' >> ${.TARGET}
+ echo '#include "objc/lang-specs.h"' >> ${.TARGET}
+
+config.h:
+ echo '#include <hconfig.h>' > ${.TARGET}
+ echo '#ifndef GENERATOR_FILE' >> ${.TARGET}
+ echo '#include "insn-codes.h"' >> ${.TARGET}
+ echo '#include "insn-flags.h"' >> ${.TARGET}
+ echo '#endif' >> ${.TARGET}
+
+tconfig.h:
+ echo 'struct rtx_def;' > ${.TARGET}
+ echo 'typedef struct rtx_def *rtx;' >> ${.TARGET}
+ echo 'struct rtvec_def;' >> ${.TARGET}
+ echo 'typedef struct rtvec_def *rtvec;' >> ${.TARGET}
+ echo 'union tree_node;' >> ${.TARGET}
+ echo 'typedef union tree_node *tree;' >> ${.TARGET}
+ echo '' >> ${.TARGET}
+.if ${TARGET_ARCH} == "ia64"
+ echo '#define TARGET_CPU_DEFAULT (MASK_GNU_AS|MASK_GNU_LD)' >>${.TARGET}
+.endif
+ echo '#include "ansidecl.h"' >> ${.TARGET}
+ echo '#include "${GCC_CPU}/${GCC_CPU}.h"' >> ${.TARGET}
+.if ${TARGET_ARCH} == "i386"
+ echo '#include "${GCC_CPU}/att.h"' >> ${.TARGET}
+.endif
+.if ${TARGET_ARCH} != "alpha"
+ echo '#include "dbxelf.h"' >> ${.TARGET}
+ echo '#include "elfos.h"' >> ${.TARGET}
+.endif
+ echo '#include <freebsd-native.h>' >> ${.TARGET}
+ echo '#include "freebsd-spec.h"' >> ${.TARGET}
+ echo '#include "freebsd.h"' >> ${.TARGET}
+.if ${TARGET_ARCH} == "alpha"
+ echo '#include "${GCC_CPU}/elf.h"' >> ${.TARGET}
+.endif
+.if ${TARGET_ARCH} != "i386"
+.if exists(${GCCDIR}/config/${GCC_CPU}/sysv4.h)
+ echo '#include "${GCC_CPU}/sysv4.h"' >> ${.TARGET}
+.endif
+.endif
+ echo '#include "${GCC_CPU}/freebsd.h"' >> ${.TARGET}
+.if ${TARGET_ARCH} == "x86-64"
+ echo '#include "${GCC_CPU}/freebsd64.h"' >> ${.TARGET}
+.endif
+ echo '#include "defaults.h"' >> ${.TARGET}
+ echo '#ifndef POSIX' >> ${.TARGET}
+ echo '# define POSIX' >> ${.TARGET}
+ echo '#endif' >> ${.TARGET}
+.if ${TARGET_ARCH} != "ia64"
+ echo '#define CONFIG_SJLJ_EXCEPTIONS 0' >> ${.TARGET}
+.endif
+
+tm_p.h:
+ echo '#include "${GCC_CPU}/${GCC_CPU}-protos.h"' >> ${.TARGET}
+ echo '#include "tm-preds.h"' >> ${.TARGET}
+
+safe-ctype.h: Makefile
+ echo '#include <ctype.h>' > ${.TARGET}
+.for Z in TOUPPER TOLOWER ISDIGIT ISXDIGIT ISUPPER ISLOWER ISALPHA ISALNUM \
+ ISSPACE ISPUNCT ISGRAPH ISBLANK ISPRINT ISCNTRL
+ echo '#define ${Z} ${Z:L}' >> ${.TARGET}
+.endfor
+ echo "#define ISIDST(x) \
+ ((x) == '_' || isalpha(x))" >> ${.TARGET}
+ echo "#define ISIDNUM(x) \
+ (isdigit(x) || ISIDST(x))" >> ${.TARGET}
+ echo "#define IS_VSPACE(x) \
+ ((x) == '\n' || (x) == '\r')" >> ${.TARGET}
+ echo "#define IS_NVSPACE(x) \
+ (!IS_VSPACE(x) && (isspace(x) || (x) == '\0'))" >> ${.TARGET}
+ echo "#define IS_SPACE_OR_NUL(x) \
+ (isspace(x) || (x) == '\0')" >> ${.TARGET}
+
+#-----------------------------------------------------------------------
+# General things.
+
+SRCS+= ${GENSRCS}
+CLEANFILES+= ${GENSRCS}
+
+all: ${SRCS}
+
+.include <bsd.prog.mk>
+
+#-----------------------------------------------------------------------
+# Fixups.
+
+# Set OBJS the same as bsd.prog.mk would do if we defined PROG. We can't
+# define PROG because we have multiple programs.
+#
+OBJS+= ${SRCS:N*.h:R:S/$/.o/g}
+
+.if !exists(${DEPENDFILE})
+# Fudge pre-dependfile dependencies of objects in much the same way as
+# bsd.prog.mk would do if we defined PROG. There are complications to
+# avoid circular dependencies. First, only make most objects depend on
+# all headers. Filter out the objects that would cause problems (i.e.,
+# objects that will be used to create programs that will generate headers).
+#
+${OBJS:Nbitmap.o:Nerrors.o:Ngenattr.o:Ngencheck.o:Ngencodes.o:Ngenconfig.o:Ngenflags.o:Ngengenrtl.o:Ngenpreds.o:Ngensupport.o:Nggc-none.o:Nhashtab.o:Nobstack.o:Nprint-rtl.o:Nread-rtl.o:Nrtl.o}: ${SRCS:M*.h}
+
+# Force these to be made absolustly first w/-j
+${OBJS}: ${COMMONHDRS}
+
+# Next, make each of the problematic objects depend on only most headers.
+# Filter out the headers that would cause problems (and a few more when it
+# is inconvenient to filter precisely).
+#
+bitmap.o genattr.o gencodes.o genconfig.o genflags.o gensupport.o obstack.o print-rtl.o \
+ read-rtl.o rtl.o: ${SRCS:M*.h:Ninsn-*.h}
+gencheck.o: gencheck.h ${SRCS:M*.h:Ngenrtl.h:Ntree-check.h:Ninsn-*.h}
+gengenrtl.o: ${SRCS:M*.h:Ngenrtl.h:Ninsn-*.h}
+genpreds.o: ${COMMONHDRS}
+.endif
diff --git a/gnu/usr.bin/cc/cc_tools/auto-host.h b/gnu/usr.bin/cc/cc_tools/auto-host.h
new file mode 100644
index 0000000..bd8af40
--- /dev/null
+++ b/gnu/usr.bin/cc/cc_tools/auto-host.h
@@ -0,0 +1,596 @@
+/* $FreeBSD$ */
+
+#include <sys/param.h>
+
+/* auto-host.h. Generated automatically by configure. */
+/* config.in. Generated automatically from configure.in by autoheader 2.13. */
+
+/* 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 to the type of elements in the array set by `getgroups'.
+ Usually this is either `int' or `gid_t'. */
+#define GETGROUPS_T gid_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have the ANSI # stringizing operator in cpp. */
+#define HAVE_STRINGIZE 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if you have <vfork.h>. */
+/* #undef HAVE_VFORK_H */
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define vfork as fork if vfork does not work. */
+/* #undef vfork */
+
+/* Define if your assembler supports specifying the maximum number
+ of bytes to skip when using the GAS .p2align command. */
+#define HAVE_GAS_MAX_SKIP_P2ALIGN 1
+
+/* Define if your assembler supports .balign and .p2align. */
+#define HAVE_GAS_BALIGN_AND_P2ALIGN 1
+
+/* Define if your assembler uses the old HImode fild and fist notation. */
+#define HAVE_GAS_FILDS_FISTS 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef ssize_t */
+
+/* Define if cpp should also search $prefix/include. */
+/* #define PREFIX_INCLUDE_DIR "NONE/include" */
+
+/* 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 atoll function. */
+#if __FreeBSD_version >= 500027
+/* FreeBSD didn't always have atoll(3). */
+#define HAVE_ATOLL 1
+#endif
+
+/* Define if you have the atoq function. */
+/* #undef HAVE_ATOQ */
+
+/* Define if you have the clock function. */
+#define HAVE_CLOCK 1
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the dup2 function. */
+#define HAVE_DUP2 1
+
+/* Define if you have the feof_unlocked function. */
+/* #undef HAVE_FEOF_UNLOCKED */
+
+/* Define if you have the fgets_unlocked function. */
+/* #undef HAVE_FGETS_UNLOCKED */
+
+/* Define if you have the fprintf_unlocked function. */
+/* #undef HAVE_FPRINTF_UNLOCKED */
+
+/* Define if you have the fputc_unlocked function. */
+/* #undef HAVE_FPUTC_UNLOCKED */
+
+/* Define if you have the fputs_unlocked function. */
+/* #undef HAVE_FPUTS_UNLOCKED */
+
+/* Define if you have the fwrite_unlocked function. */
+/* #undef HAVE_FWRITE_UNLOCKED */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getegid function. */
+#define HAVE_GETEGID 1
+
+/* Define if you have the geteuid function. */
+#define HAVE_GETEUID 1
+
+/* Define if you have the getgid function. */
+#define HAVE_GETGID 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getrlimit function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define if you have the getrusage function. */
+#define HAVE_GETRUSAGE 1
+
+/* Define if you have the getuid function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the kill function. */
+#define HAVE_KILL 1
+
+/* Define if you have the lstat function. */
+#define HAVE_LSTAT 1
+
+/* Define if you have the mempcpy function. */
+/* #undef HAVE_MEMPCPY */
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the nl_langinfo function. */
+#define HAVE_NL_LANGINFO 1
+
+/* Define if you have the putc_unlocked function. */
+/* #undef HAVE_PUTC_UNLOCKED */
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setrlimit function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strsignal function. */
+#define HAVE_STRSIGNAL 1
+
+/* Define if you have the strtoul function. */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the sysconf function. */
+#define HAVE_SYSCONF 1
+
+/* Define if you have the times function. */
+#define HAVE_TIMES 1
+
+/* Define if you have the tsearch function. */
+#define HAVE_TSEARCH 1
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <direct.h> header file. */
+/* #undef HAVE_DIRECT_H */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <langinfo.h> header file. */
+#define HAVE_LANGINFO_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/times.h> header file. */
+#define HAVE_SYS_TIMES_H 1
+
+/* Define if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to enable the use of a default linker. */
+/* #undef DEFAULT_LINKER */
+
+/* Define to enable the use of a default assembler. */
+/* #undef DEFAULT_ASSEMBLER */
+
+#ifdef WANT_COMPILER_INVARIANTS
+//#warning WANT_COMPILER_INVARIANTS turned on
+
+/* Define if you want more run-time sanity checks. This one gets a grab
+ bag of miscellaneous but relatively cheap checks. */
+#define ENABLE_CHECKING 1
+
+/* Define if you want all operations on trees (the basic data
+ structure of the front ends) to be checked for dynamic type safety
+ at runtime. This is moderately expensive. */
+#define ENABLE_TREE_CHECKING 1
+
+/* Define if you want all operations on RTL (the basic data structure
+ of the optimizer and back end) to be checked for dynamic type safety
+ at runtime. This is quite expensive. */
+#define ENABLE_RTL_CHECKING 1
+
+/* Define if you want the garbage collector to do object poisoning and
+ other memory allocation checks. This is quite expensive. */
+#define ENABLE_GC_CHECKING 1
+
+/* Define if you want the garbage collector to operate in maximally
+ paranoid mode, validating the entire heap and collecting garbage at
+ every opportunity. This is extremely expensive. */
+#define ENABLE_GC_ALWAYS_COLLECT 1
+
+#endif /* WANT_COMPILER_INVARIANTS */
+
+/* Define if you want the C and C++ compilers to support multibyte
+ character sets for source code. */
+/* #undef MULTIBYTE_CHARS */
+
+/* Define if your compiler understands volatile. */
+#define HAVE_VOLATILE 1
+
+/* Define if your compiler supports the `long double' type. */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define if your compiler supports the `long long' type. */
+#define HAVE_LONG_LONG 1
+
+/* Define if your compiler supports the `__int64' type. */
+/* #undef HAVE___INT64 */
+
+/* Define if the `_Bool' type is built-in. */
+/* #undef HAVE__BOOL */
+
+/* The number of bytes in type short */
+#define SIZEOF_SHORT 2
+
+/* The number of bytes in type int */
+#define SIZEOF_INT 4
+
+/* The number of bytes in type long */
+/* #define SIZEOF_LONG 4 */
+#if defined(__i386__) || defined(__powerpc__) || defined(__strongarm__)
+#define SIZEOF_LONG SIZEOF_INT
+#elif defined(__alpha__) || defined(__sparc64__) || defined(__ia64__)
+#define SIZEOF_LONG SIZEOF_LONG_LONG
+#else
+#error "I don't know what arch this is."
+#endif
+
+/* The number of bytes in type long long */
+#define SIZEOF_LONG_LONG 8
+
+/* The number of bytes in type __int64 */
+/* #undef SIZEOF___INT64 */
+
+/* Define if the host execution character set is EBCDIC. */
+/* #undef HOST_EBCDIC */
+
+/* Always define this when using the GNU C Library */
+/* #undef _GNU_SOURCE */
+
+/* Define if you have a working <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define if you can safely include both <string.h> and <strings.h>. */
+#define STRING_WITH_STRINGS 1
+
+/* Define as the number of bits in a byte, if `limits.h' doesn't. */
+/* #undef CHAR_BIT */
+
+/* Define if the host machine stores words of multi-word integers in
+ big-endian order. */
+/* #undef HOST_WORDS_BIG_ENDIAN */
+
+/* Define to the floating point format of the host machine, if not IEEE. */
+/* #undef HOST_FLOAT_FORMAT */
+
+/* Define to 1 if the host machine stores floating point numbers in
+ memory with the word containing the sign bit at the lowest address,
+ or to 0 if it does it the other way around.
+
+ This macro should not be defined if the ordering is the same as for
+ multi-word integers. */
+/* #undef HOST_FLOAT_WORDS_BIG_ENDIAN */
+
+/* Define if you have a working <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if printf supports %p. */
+#define HAVE_PRINTF_PTR 1
+
+/* Define if mmap can get us zeroed pages from /dev/zero. */
+#define HAVE_MMAP_DEV_ZERO 1
+
+/* Define if mmap can get us zeroed pages using MAP_ANON(YMOUS). */
+#define HAVE_MMAP_ANON 1
+
+/* Define if read-only mmap of a plain file works. */
+#define HAVE_MMAP_FILE 1
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define as const if the declaration of iconv() needs const. */
+/* #undef ICONV_CONST */
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_GETENV 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_ATOL 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_SBRK 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_ABORT 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_ATOF 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_GETCWD 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_GETWD 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_STRSIGNAL 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_PUTC_UNLOCKED 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_FPUTS_UNLOCKED 0
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_FWRITE_UNLOCKED 0
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_FPRINTF_UNLOCKED 0
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_STRSTR 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_ERRNO 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_MALLOC 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_REALLOC 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_CALLOC 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_FREE 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_BASENAME 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_GETOPT 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_CLOCK 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_GETRLIMIT 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_SETRLIMIT 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_GETRUSAGE 1
+
+/* Define to 1 if we found this declaration otherwise define to 0. */
+#define HAVE_DECL_TIMES 1
+
+/* Define if <sys/times.h> defines struct tms. */
+#define HAVE_STRUCT_TMS 1
+
+/* Define if <time.h> defines clock_t. */
+#define HAVE_CLOCK_T 1
+
+/* Define if host mkdir takes a single argument. */
+/* #undef MKDIR_TAKES_ONE_ARG */
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define as const if the declaration of iconv() needs const. */
+/* #undef ICONV_CONST */
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if translation of program messages to the user's native language
+ is requested. */
+/* #define ENABLE_NLS 1 */
+
+/* Define if you have the <libintl.h> header file. */
+/* #undef HAVE_LIBINTL_H */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to use the libintl included with this package instead of any
+ version in the system libraries. */
+/* #define USE_INCLUDED_LIBINTL 1 */
+
+/* Define to 1 if installation paths should be looked up in Windows32
+ Registry. Ignored on non windows32 hosts. */
+/* #undef ENABLE_WIN32_REGISTRY */
+
+/* Define to be the last portion of registry key on windows hosts. */
+/* #undef WIN32_REGISTRY_KEY */
+
+/* Define if your assembler supports .subsection and .subsection -1 starts
+ emitting at the beginning of your section. */
+#define HAVE_GAS_SUBSECTION_ORDERING 1
+
+/* Define if your assembler supports .weak. */
+#define HAVE_GAS_WEAK 1
+
+/* Define if your assembler supports .hidden. */
+#define HAVE_GAS_HIDDEN 1
+
+/* Define if your assembler supports .uleb128. */
+#define HAVE_AS_LEB128 1
+
+/* Define if your assembler mis-optimizes .eh_frame data. */
+/* #undef USE_AS_TRADITIONAL_FORMAT */
+
+/* Define if your assembler supports marking sections with SHF_MERGE flag. */
+/* XXX:DEO new; caused Peter IA-64 trouble until he adjusted
+ sys/boot/efi/libefi/arch/ia64/ldscript.ia64. */
+#define HAVE_GAS_SHF_MERGE 1
+
+/* XXX HAVE_GAS_SHF_MERGE is target-dependent so it shouldn't be put in
+ this target-independent config file. Defining it breaks aout support
+ on i386's. */
+#undef HAVE_GAS_SHF_MERGE
+
+/* Define if your assembler supports explicit relocations. */
+/* #undef HAVE_AS_EXPLICIT_RELOCS */
+
+/* Define if your assembler supports .register. */
+/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
+
+/* Define if your assembler supports -relax option. */
+/* #undef HAVE_AS_RELAX_OPTION */
+
+/* Define if your assembler and linker support unaligned PC relative relocs. */
+/* #undef HAVE_AS_SPARC_UA_PCREL */
+
+/* Define if the assembler supports 64bit sparc. */
+/* #undef AS_SPARC64_FLAG */
+
+/* Define if your assembler supports offsetable %lo(). */
+/* #undef HAVE_AS_OFFSETABLE_LO10 */
+
+/* Define true if the assembler supports '.long foo@GOTOFF'. */
+/* DEO:XXX match TARGET_ELF definition in i386/freebsd.h. */
+#define HAVE_AS_GOTOFF_IN_DATA ((target_flags & MASK_AOUT) == 0)
+
+/* Define if your assembler supports dwarf2 .file/.loc directives,
+ and preserves file table indices exactly as given. */
+/* #undef HAVE_AS_DWARF2_DEBUG_LINE */
+
+/* Define if your assembler supports the --gdwarf2 option. */
+#define HAVE_AS_GDWARF2_DEBUG_FLAG 1
+
+/* Define if your assembler supports the --gstabs option. */
+#define HAVE_AS_GSTABS_DEBUG_FLAG 1
+
+/* Define if your linker supports --eh-frame-hdr option. */
+#define HAVE_LD_EH_FRAME_HDR 1
+
+/* Define 0/1 to force the choice for exception handling model. */
+/* #undef CONFIG_SJLJ_EXCEPTIONS */
+
+
+/* Bison unconditionally undefines `const' if neither `__STDC__' nor
+ __cplusplus are defined. That's a problem since we use `const' in
+ the GCC headers, and the resulting bison code is therefore type
+ unsafe. Thus, we must match the bison behavior here. */
+
+#ifndef __STDC__
+#ifndef __cplusplus
+/* #undef const */
+#define const
+#endif
+#endif
diff --git a/gnu/usr.bin/cc/cc_tools/freebsd-native.h b/gnu/usr.bin/cc/cc_tools/freebsd-native.h
new file mode 100644
index 0000000..a102a89
--- /dev/null
+++ b/gnu/usr.bin/cc/cc_tools/freebsd-native.h
@@ -0,0 +1,72 @@
+/* $FreeBSD$ */
+
+/* FREEBSD_NATIVE is defined when gcc is integrated into the FreeBSD
+ source tree so it can be configured appropriately without using
+ the GNU configure/build mechanism. */
+
+#define FREEBSD_NATIVE 1
+
+/* Fake out gcc/config/freebsd<version>.h. */
+#define FBSD_MAJOR 5
+
+#undef SYSTEM_INCLUDE_DIR /* We don't need one for now. */
+#undef TOOL_INCLUDE_DIR /* We don't need one for now. */
+#undef LOCAL_INCLUDE_DIR /* We don't wish to support one. */
+
+/* Look for the include files in the system-defined places. */
+#define GPLUSPLUS_INCLUDE_DIR PREFIX"/include/g++"
+#define GPLUSPLUS_BACKWARD_INCLUDE_DIR PREFIX"/include/g++/backward"
+#define GCC_INCLUDE_DIR PREFIX"/include"
+#ifdef CROSS_COMPILE
+#define CROSS_INCLUDE_DIR PREFIX"/include"
+#else
+#define STANDARD_INCLUDE_DIR PREFIX"/include"
+#endif
+
+/* Under FreeBSD, the normal location of the compiler back ends is the
+ /usr/libexec directory.
+
+ ``cc --print-search-dirs'' gives:
+ install: STANDARD_EXEC_PREFIX/(null)
+ programs: /usr/libexec/<OBJFORMAT>/:STANDARD_EXEC_PREFIX:MD_EXEC_PREFIX
+ libraries: MD_EXEC_PREFIX:MD_STARTFILE_PREFIX:STANDARD_STARTFILE_PREFIX
+*/
+#undef TOOLDIR_BASE_PREFIX /* Old?? This is not documented. */
+#undef STANDARD_BINDIR_PREFIX /* We don't need one for now. */
+#define STANDARD_EXEC_PREFIX PREFIX"/libexec/"
+#undef MD_EXEC_PREFIX /* We don't want one. */
+#define FBSD_DATA_PREFIX PREFIX"/libdata/gcc/"
+
+/* Under FreeBSD, the normal location of the various *crt*.o files is the
+ /usr/lib directory. */
+
+#define STANDARD_STARTFILE_PREFIX PREFIX"/lib/"
+#ifdef CROSS_COMPILE
+#define CROSS_STARTFILE_PREFIX PREFIX"/lib/"
+#endif
+#undef MD_STARTFILE_PREFIX /* We don't need one for now. */
+
+/* For the native system compiler, we actually build libgcc in a profiled
+ version. So we should use it with -pg. */
+#define LIBGCC_SPEC "%{!pg: -lgcc} %{pg: -lgcc_p}"
+#define LIBSTDCXX_PROFILE "-lstdc++_p"
+#define MATH_LIBRARY_PROFILE "-lm_p"
+#define FORTRAN_LIBRARY_PROFILE "-lg2c_p"
+
+/* FreeBSD is 4.4BSD derived */
+#define bsd4_4
+
+/* Dike out [stupid, IMHO] libiberty functions. */
+#define xmalloc_set_program_name(dummy)
+#define xmalloc malloc
+#define xcalloc calloc
+#define xrealloc realloc
+#define xstrdup strdup
+#define xstrerror strerror
+
+/* And now they want to replace ctype.h.... grr... [stupid, IMHO] */
+#define xxxISDIGIT isdigit
+#define xxxISGRAPH isgraph
+#define xxxISLOWER islower
+#define xxxISSPACE isspace
+#define xxxTOUPPER toupper
diff --git a/gnu/usr.bin/cc/cccp/Makefile b/gnu/usr.bin/cc/cccp/Makefile
new file mode 100644
index 0000000..eb0bc72
--- /dev/null
+++ b/gnu/usr.bin/cc/cccp/Makefile
@@ -0,0 +1,36 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}
+
+PROG= cpp0
+SRCS= cppmain.c c-parse+%DIKED.c c-lang.c c-decl.c
+
+BINDIR= /usr/libexec
+NOMAN= 1
+NOSHARED?=yes
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+#-----------------------------------------------------------------------
+# C parser
+
+c-parse+%DIKED.c: c-parse.c
+ sed -e "s/malloc/xmalloc/g" \
+ -e "s/realloc/xrealloc/g" \
+ ${.ALLSRC} > ${.TARGET}
+
+c-parse.y: c-parse.in
+ sed -e "/^ifobjc$$/,/^end ifobjc$$/d" \
+ -e "/^ifc$$/d" \
+ -e "/^end ifc$$/d" \
+ ${.ALLSRC} > ${.TARGET}
+
+CLEANFILES= c-parse+%DIKED.c c-parse.c c-parse.y
+CLEANFILES+= y.tab.h # we don't use it, but the system YACC rules are naive
+
+#-----------------------------------------------------------------------
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/collect2/Makefile b/gnu/usr.bin/cc/collect2/Makefile
new file mode 100644
index 0000000..7fe6877
--- /dev/null
+++ b/gnu/usr.bin/cc/collect2/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR} ${GCCDIR}/../libiberty
+
+PROG= collect2
+SRCS= collect2.c cp-demangle.c cplus-dem.c tlink.c
+NOMAN=
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/cpp/Makefile b/gnu/usr.bin/cc/cpp/Makefile
new file mode 100644
index 0000000..56fdc06
--- /dev/null
+++ b/gnu/usr.bin/cc/cpp/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+.include "../Makefile.fe"
+
+.PATH: ${GCCDIR}
+
+PROG= cpp
+SRCS= gcc.c cppspec.c
+
+CFLAGS+= -DDEFAULT_TARGET_VERSION=\"$(version)\"
+CFLAGS+= -DDEFAULT_TARGET_MACHINE=\"$(target)\"
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+CLEANFILES= cpp.1
+
+cpp.1: cccp.1
+ ln -sf ${.ALLSRC} ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/cpp0/Makefile b/gnu/usr.bin/cc/cpp0/Makefile
new file mode 100644
index 0000000..eb0bc72
--- /dev/null
+++ b/gnu/usr.bin/cc/cpp0/Makefile
@@ -0,0 +1,36 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}
+
+PROG= cpp0
+SRCS= cppmain.c c-parse+%DIKED.c c-lang.c c-decl.c
+
+BINDIR= /usr/libexec
+NOMAN= 1
+NOSHARED?=yes
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+#-----------------------------------------------------------------------
+# C parser
+
+c-parse+%DIKED.c: c-parse.c
+ sed -e "s/malloc/xmalloc/g" \
+ -e "s/realloc/xrealloc/g" \
+ ${.ALLSRC} > ${.TARGET}
+
+c-parse.y: c-parse.in
+ sed -e "/^ifobjc$$/,/^end ifobjc$$/d" \
+ -e "/^ifc$$/d" \
+ -e "/^end ifc$$/d" \
+ ${.ALLSRC} > ${.TARGET}
+
+CLEANFILES= c-parse+%DIKED.c c-parse.c c-parse.y
+CLEANFILES+= y.tab.h # we don't use it, but the system YACC rules are naive
+
+#-----------------------------------------------------------------------
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/doc/Makefile b/gnu/usr.bin/cc/doc/Makefile
new file mode 100644
index 0000000..bc2cd1c
--- /dev/null
+++ b/gnu/usr.bin/cc/doc/Makefile
@@ -0,0 +1,32 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}/doc
+
+INFO= gcc cpp gccint cppinternals
+
+INFOSECTION= "Gcc Documentation"
+INFOENTRY_gcc= "* gcc: (gcc). The GNU C compiler."
+INFOENTRY_cpp= "* cpp: (cpp). The GNU C pre-processor."
+INFOENTRY_gccint= "* gccint: (gccint). The GNU compiler family internal documentation."
+INFOENTRY_cppinternals= "* cppinternals: (cppinternals). The GNU compiler preprocessor internal documentation."
+
+gcc.info: gcc.texi include/gcc-common.texi frontends.texi standards.texi \
+ invoke.texi extend.texi md.texi objc.texi gcov.texi trouble.texi \
+ bugreport.texi service.texi contribute.texi vms.texi \
+ include/funding.texi gnu.texi include/gpl.texi include/fdl.texi \
+ contrib.texi cppenv.texi cppopts.texi
+
+gccint.info: gccint.texi include/gcc-common.texi contribute.texi \
+ makefile.texi configterms.texi portability.texi interface.texi \
+ passes.texi c-tree.texi rtl.texi md.texi tm.texi hostconfig.texi \
+ fragments.texi configfiles.texi collect2.texi headerdirs.texi \
+ include/funding.texi gnu.texi include/gpl.texi include/fdl.texi \
+ contrib.texi languages.texi sourcebuild.texi
+
+cpp.info: cpp.texi include/fdl.texi cppenv.texi cppopts.texi
+
+MAKEINFOFLAGS+= -I ${GCCDIR}/doc -I ${GCCDIR}/doc/include
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/cc/f77/Makefile b/gnu/usr.bin/cc/f77/Makefile
new file mode 100644
index 0000000..4902ba5
--- /dev/null
+++ b/gnu/usr.bin/cc/f77/Makefile
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+.include "../Makefile.fe"
+
+.PATH: ${GCCDIR}/f ${GCCDIR}
+
+PROG= f77
+SRCS= gcc.c g77spec.c version.c
+
+CFLAGS+= -DDEFAULT_TARGET_VERSION=\"$(version)\"
+CFLAGS+= -DDEFAULT_TARGET_MACHINE=\"$(target)\"
+CFLAGS+= -DFORTRAN_INIT=\"-lg2c\" -DFORTRAN_INIT_PROFILE=\"-lg2c_p\"
+
+DPADD= ${LIBCC_INT}
+LDADD= ${LIBCC_INT}
+
+CLEANFILES= f77.1
+
+f77.1: g77.1
+ ln -sf ${.ALLSRC} ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/f771/Makefile b/gnu/usr.bin/cc/f771/Makefile
new file mode 100644
index 0000000..f37ce94
--- /dev/null
+++ b/gnu/usr.bin/cc/f771/Makefile
@@ -0,0 +1,46 @@
+# $FreeBSD$
+
+.include "${.CURDIR}/../Makefile.inc"
+
+.PATH: ${GCCDIR}/f ${GCCDIR}
+
+PROG= f771
+SRCS= bad.c bit.c bld.c com.c data.c equiv.c expr.c global.c implic.c info.c \
+ intrin.c lab.c lex.c malloc.c name.c parse.c src.c st.c sta.c \
+ stb.c stc.c std.c ste.c storag.c stp.c str.c sts.c stt.c stu.c stv.c \
+ stw.c symbol.c target.c top.c type.c version.c where.c main.c
+BINDIR= /usr/libexec
+NOMAN=
+
+CFLAGS+= -I${GCCDIR}/f -I.
+
+DPADD= ${LIBCC_INT}
+LDADD= ${LIBCC_INT}
+
+build-tools: fini
+fini: fini.o
+ ${CC} -static ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${.ALLSRC}
+
+CLEANFILES= fini fini.o
+
+#-----------------------------------------------------------------------
+# str-* gunk
+
+.for i in 1t 2t fo io nq op ot
+.ORDER: str-$i.h str-$i.j
+str-$i.j str-$i.h: str-$i.fin fini
+ ./fini ${GCCDIR}/f/str-$i.fin str-$i.j str-$i.h
+
+FINIHDRS+= str-$i.j str-$i.h
+.endfor
+
+CLEANFILES+= ${FINIHDRS}
+
+.include <bsd.prog.mk>
+
+#-----------------------------------------------------------------------
+# Fixups.
+
+.if !exists(${DEPENDFILE})
+${OBJS:Nproj.o} ${DEPENDFILE}: ${FINIHDRS}
+.endif
diff --git a/gnu/usr.bin/cc/f77doc/Makefile b/gnu/usr.bin/cc/f77doc/Makefile
new file mode 100644
index 0000000..1dd59de
--- /dev/null
+++ b/gnu/usr.bin/cc/f77doc/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}/f
+
+INFO= g77
+
+MAKEINFOFLAGS+= -I ${GCCDIR}/f -I ${GCCDIR}/doc/include
+
+g77.info: g77.texi intdoc.texi ffe.texi invoke.texi news.texi bugs.texi \
+ ../doc/include/gpl.texi ../doc/include/fdl.texi ../doc/include/funding.texi
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/cc/gcov/Makefile b/gnu/usr.bin/cc/gcov/Makefile
new file mode 100644
index 0000000..6ecc59f
--- /dev/null
+++ b/gnu/usr.bin/cc/gcov/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR} ${GCCDIR}/doc ${GCCDIR}/../libiberty
+
+PROG= gcov
+SRCS= gcov.c version.c
+NOMAN= #true
+
+DPADD= ${LIBCC_INT}
+LDADD= ${LIBCC_INT}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/include/Makefile b/gnu/usr.bin/cc/include/Makefile
new file mode 100644
index 0000000..71fde69
--- /dev/null
+++ b/gnu/usr.bin/cc/include/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}/config/${GCC_CPU}
+
+.if ${TARGET_ARCH} == "i386" || ${TARGET_ARCH} == "x86-64"
+INCS= mmintrin.h xmmintrin.h
+.elif ${TARGET_ARCH} == "ia64"
+INCS= ia64intrin.h
+.endif
+
+.include <bsd.init.mk>
+.include <bsd.incs.mk>
+.include <bsd.obj.mk>
diff --git a/gnu/usr.bin/cc/protoize/Makefile b/gnu/usr.bin/cc/protoize/Makefile
new file mode 100644
index 0000000..500dd03
--- /dev/null
+++ b/gnu/usr.bin/cc/protoize/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${.CURDIR}/../cc_tools ${GCCDIR}
+
+PROG= protoize
+NOMAN=
+
+# things are rather hard-coded, we work around that here
+CFLAGS+= -DDEFAULT_TARGET_VERSION=\"\"
+CFLAGS+= -DDEFAULT_TARGET_MACHINE=\"../libdata/gcc\"
+
+DPADD= ${LIBCC_INT}
+LDADD= ${LIBCC_INT}
+
+CLEANFILES= config.h
+config.h: auto-host.h freebsd-native.h
+ cat ${.ALLSRC} >${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/tradcpp0/Makefile b/gnu/usr.bin/cc/tradcpp0/Makefile
new file mode 100644
index 0000000..3ec8968
--- /dev/null
+++ b/gnu/usr.bin/cc/tradcpp0/Makefile
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+.include "../Makefile.inc"
+
+.PATH: ${GCCDIR}
+
+PROG= tradcpp0
+SRCS= tradcpp.c tradcif+%DIKED.c
+BINDIR= /usr/libexec
+NOMAN= 1
+
+DPADD+= ${LIBCC_INT}
+LDADD+= ${LIBCC_INT}
+
+tradcif+%DIKED.c: tradcif.c
+ sed -e "s/malloc/xmalloc/g" \
+ -e "s/realloc/xrealloc/g" \
+ ${.ALLSRC} >${.TARGET}
+
+CLEANFILES= tradcif+%DIKED.c tradcif.c
+CLEANFILES+= y.tab.h # we don't use it, but the system YACC rules are naive
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cpio/Makefile b/gnu/usr.bin/cpio/Makefile
new file mode 100644
index 0000000..279b60e
--- /dev/null
+++ b/gnu/usr.bin/cpio/Makefile
@@ -0,0 +1,23 @@
+# Note that this files is under a "BSD" copyright (c) by David O'Brien 1997,
+# even though it may live in src/gnu/...
+
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../contrib/cpio
+
+SUBDIR= doc
+
+PROG= cpio
+
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../../contrib/cpio
+CFLAGS+= -DRETSIGTYPE=void -DHAVE_SYS_MTIO_H=1 -DSTDC_HEADERS=1 \
+ -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_FCNTL_H=1 -DHAVE_UTIME_H=1 \
+ -DHAVE_STRERROR=1 -DHAVE_VPRINTF=1 -DDIRENT=1 -DHAVE_LCHOWN \
+ -DHAVE_SYS_PARAM_H=1
+
+SRCS = copyin.c copyout.c copypass.c defer.c dirname.c dstring.c error.c \
+ filemode.c getopt.c getopt1.c global.c idcache.c main.c makepath.c \
+ rtapelib.c stripslash.c tar.c userspec.c util.c version.c \
+ xmalloc.c xstrdup.c
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cpio/doc/Makefile b/gnu/usr.bin/cpio/doc/Makefile
new file mode 100644
index 0000000..5ccf5da
--- /dev/null
+++ b/gnu/usr.bin/cpio/doc/Makefile
@@ -0,0 +1,15 @@
+# Note that this files is under a "BSD" copyright (c) by David O'Brien 1997,
+# even though it may live in src/gnu/...
+
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../../contrib/cpio
+
+INFO = cpio
+
+INFOSECTION= "Cpio Documentation"
+INFOENTRY_cpio="* CPIO: (cpio). Making tape (or disk) archives."
+
+SRCDIR= ${.CURDIR}/../../../../contrib/cpio
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/cvs/Makefile b/gnu/usr.bin/cvs/Makefile
new file mode 100644
index 0000000..e8ed2e5
--- /dev/null
+++ b/gnu/usr.bin/cvs/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+MAINTAINER= peter@FreeBSD.org
+
+SUBDIR = lib libdiff cvs contrib cvsbug doc
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/cvs/Makefile.inc b/gnu/usr.bin/cvs/Makefile.inc
new file mode 100644
index 0000000..e1889d6
--- /dev/null
+++ b/gnu/usr.bin/cvs/Makefile.inc
@@ -0,0 +1,25 @@
+.if !defined(CVSDIR)
+
+CVSDIR= $(.CURDIR)/../../../../contrib/cvs
+
+.if exists(${.OBJDIR}/../lib)
+LIBCVSDIR= ${.OBJDIR}/../lib
+.else
+LIBCVSDIR= ${.CURDIR}/../lib
+.endif
+
+LIBCVS= ${LIBCVSDIR}/libcvs.a
+
+.if exists(${.OBJDIR}/../libdiff)
+LIBDIFFDIR= ${.OBJDIR}/../libdiff
+.else
+LIBDIFFDIR= ${.CURDIR}/../libdiff
+.endif
+
+LIBDIFF= ${LIBDIFFDIR}/libdiff.a
+
+.if exists(${.CURDIR}/../../Makefile.inc)
+.include "${.CURDIR}/../../Makefile.inc"
+.endif
+
+.endif
diff --git a/gnu/usr.bin/cvs/contrib/Makefile b/gnu/usr.bin/cvs/contrib/Makefile
new file mode 100644
index 0000000..8cce7cd
--- /dev/null
+++ b/gnu/usr.bin/cvs/contrib/Makefile
@@ -0,0 +1,33 @@
+# $FreeBSD$
+
+MAINTAINER= peter@FreeBSD.org
+
+.include "../Makefile.inc"
+
+.PATH: ${CVSDIR}/contrib
+.PATH: ${CVSDIR}/man
+
+SCRIPTS= clmerge cln_hist commit_prep cvs2vendor cvs_acls cvscheck \
+ log log_accum mfpipe rcs-to-cvs rcs2log rcslock sccs2rcs \
+ easy-import
+
+FILES= README cvscheck.man cvshelp.man descend.man intro.doc
+
+EXAMPDIR= ${SHAREDIR}/examples/cvs
+FILESDIR= ${EXAMPDIR}/contrib
+SCRIPTSDIR= ${FILESDIR}
+PERLPATH= /usr/bin/perl
+CLEANFILES+= $(SCRIPTS)
+
+.SUFFIXES: .sh .pl .in
+
+.sh:
+ cp $< $@
+
+.pl:
+ sed -e 's,xPERL_PATHx,$(PERLPATH),' $< > $@
+
+.in:
+ sed -e 's,@CSH@,/bin/csh,' -e 's,@PERL@,$(PERLPATH),' $< > $@
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cvs/contrib/easy-import.pl b/gnu/usr.bin/cvs/contrib/easy-import.pl
new file mode 100644
index 0000000..d266957
--- /dev/null
+++ b/gnu/usr.bin/cvs/contrib/easy-import.pl
@@ -0,0 +1,403 @@
+#! xPERL_PATHx
+#
+# Support for importing a source collection into CVS.
+# Tries to prevent the user from the most common pitfalls (like creating
+# new top-level repositories or second-level areas accidentally), and
+# cares to do some of the `dirty' work like maintaining the modules
+# database accordingly.
+#
+# Written by Jörg Wunsch, 95/03/07, and placed in the public domain.
+#
+# $FreeBSD$
+
+require "complete.pl";
+require "getopts.pl";
+
+
+sub scan_opts
+{
+ local($status);
+
+ $status = &Getopts("nv");
+
+ $dont_do_it = "-n" if $opt_n;
+ if($opt_v) {
+ print STDERR '$FreeBSD$' . "\n"; # 'emacs kludge
+ exit 0;
+ }
+ die "usage: $0 [-v] [-n] [moduledir]\n" .
+ " -n: don't do any commit, show only\n" .
+ " -v: show program version\n"
+ unless $status && $#ARGV <= 0;
+
+ if($#ARGV == 0) {
+ $moduledir = $ARGV[0];
+ shift;
+ }
+}
+
+sub lsdir
+{
+ # find all subdirectories under @_
+ # ignore all CVS entries, dot entries, and non-directories
+
+ local($base) = @_;
+ local(@ls, @rv, $fname);
+
+ opendir(DIR, $base) || die "Cannot find dir $base.\n";
+
+ @ls = readdir(DIR);
+ closedir(DIR);
+
+ @rv = ();
+
+ foreach $fname (@ls) {
+ next if $fname =~ /^CVS/ || $fname eq "Attic"
+ || $fname =~ /^\./ || ! -d "$base/$fname";
+ @rv = (@rv, $fname);
+ }
+
+ return sort(@rv);
+}
+
+
+sub contains
+{
+ # look if the first parameter is contained in the list following it
+ local($item, @list) = @_;
+ local($found, $i);
+
+ $found = 0;
+ foreach $i (@list) {
+ return 1 if $i eq $item;
+ }
+ return 0;
+}
+
+
+
+sub term_init
+{
+ # first, get some terminal attributes
+
+ # try bold mode first
+ $so = `tput md`; $se = `tput me`;
+
+ # if no bold mode available, use standout mode
+ if ($so eq "") {
+ $so = `tput so`; $se = `tput se`;
+ }
+
+ # try if we can underscore
+ $us = `tput us`; $ue = `tput ue`;
+ # if we don't have it available, or same as bold/standout, disable it
+ if ($us eq "" || $us eq $so) {
+ $us = $ue = "";
+ }
+
+ # look how many columns we've got
+ if($ENV{'COLUMNS'} ne "") {
+ $columns = $ENV{'COLUMNS'};
+ } elsif(-t STDIN) { # if we operate on a terminal...
+ local($word, $tmp);
+
+ open(STTY, "stty -a|");
+ $_ = <STTY>; # try getting the tty win structure value
+ close(STTY);
+ chop;
+ $columns = 0;
+ foreach $word (split) {
+ $columns = $tmp if $word eq "columns;"; # the number preceding
+ $tmp = $word;
+ }
+ } else {
+ $columns = 80;
+ }
+ # sanity
+ $columns = 80 unless $columns >= 5;
+}
+
+
+sub list
+{
+ # pretty-print a list
+ # imports: global variable $columns
+ local(@items) = @_;
+ local($longest,$i,$item,$cols,$width);
+
+ # find the longest item
+ $longest = 0;
+ foreach $item (@items) {
+ $i = length($item);
+ $longest = $i if $longest < $i;
+ }
+ $width = $longest + 1;
+ $cols = int($columns / $width);
+
+ $i = 0;
+ foreach $item (@items) {
+ print $item;
+ if(++$i == $cols) {
+ $i = 0; print "\n";
+ } else {
+ print ' ' x ($width - length($item));
+ }
+ }
+ print "\n" unless $i == 0;
+}
+
+sub cvs_init
+{
+ # get the CVS repository(s)
+
+ die "You need to have the \$CVSROOT variable set.\n"
+ unless $ENV{'CVSROOT'} ne "";
+
+ # get the list of available repositories
+ $cvsroot = $ENV{'CVSROOT'};
+ $cvsroot = (split(/:/, $cvsroot, 2))[1] if $cvsroot =~ /:/;
+ @reps = &lsdir($cvsroot);
+}
+
+
+sub lsmodules
+{
+ # list all known CVS modules
+ local(%rv, $mname, $mpath, $_);
+
+ %rv = ();
+
+ open(CVS, "cvs co -c|");
+ while($_ = <CVS>) {
+ chop;
+ ($mname,$mpath) = split;
+ next if $mname eq "";
+ $rv{$mname} = $mpath;
+ }
+ close(CVS);
+
+ return %rv;
+}
+
+
+sub checktag
+{
+ # check a given string for tag rules
+ local($s, $name) = @_;
+ local($regexp);
+
+ if($name eq "vendor") { $regexp = '^[A-Z][A-Z0-9_]*$'; }
+ elsif($name eq "release") { $regexp = '^[a-z][a-z0-9_]*$'; }
+ else {
+ print STDERR "Internal error: unknown tag name $name\n";
+ exit(2);
+ }
+
+ if($s !~ /$regexp/) {
+ print "\a${us}Valid $name tags must match the regexp " .
+ "$regexp.${ue}\n";
+ return 0;
+ }
+ if($s =~ /^RELENG/) {
+ print "\a${us}Tags must not start with the word \"RELENG\".${ue}\n";
+ return 0;
+ }
+
+ return 1;
+}
+
+
+&scan_opts;
+&term_init;
+&cvs_init;
+
+if(! $moduledir) {
+ @dirs = &lsdir(".");
+ print "${so}Import from which directory?${se}\n";
+ @dirs = (@dirs, ".");
+ &list(@dirs);
+ $moduledir = &Complete("Which? [.]: ", @dirs);
+ $moduledir = "." unless $moduledir ne "";
+}
+
+chdir $moduledir || die "Cannot chdir to $moduledir\n";
+
+print "${so}Available repositories:${se}\n";
+&list(@reps);
+
+# the following kludge prevents the Complete package from starting
+# over with the string just selected; Complete should better provide
+# some reinitialize method
+$Complete'return = ""; $Complete'r = 0;
+
+$selected =
+ &Complete("Enter repository (<TAB>=complete, ^D=show): ",
+ @reps);
+
+die "\aYou cannot create new repositories with this script.\n"
+ unless &contains($selected, @reps);
+
+$rep = $selected;
+
+print "\n${so}Selected repository:${se} ${us}$rep${ue}\n";
+
+
+@areas = &lsdir("$cvsroot/$rep");
+
+print "${so}Existent areas in this repository:${se}\n";
+&list(@areas);
+
+$Complete'return = ""; $Complete'r = 0;
+
+$selected =
+ &Complete("Enter area name (<TAB>=complete, ^D=show): ",
+ @areas);
+
+print "\a${us}Warning: this will create a new area.${ue}\n"
+ unless &contains($selected, @areas);
+
+$area = "$rep/$selected";
+
+print "\n${so}[Working on:${se} ${us}$area${ue}${so}]${se}\n";
+
+%cvsmods = &lsmodules();
+
+for(;;) {
+ $| = 1;
+ print "${so}Gimme the module name:${se} ";
+ $| = 0;
+ $modname = <>;
+ chop $modname;
+ if ($modname eq "") {
+ print "\a${us}You cannot use an empty module name.${ue}\n";
+ next;
+ }
+ last if !$cvsmods{$modname};
+ print "\a${us}This module name does already exist; do you intend to\n" .
+ "perform a vendor-branch import to the existing sources?${ue}: ";
+ $rep = <>;
+ if ($rep =~ /\s*[yY]/) {
+ ($area,$modpath) = split(/\//,$cvsmods{$modname},2);
+ $branchimport = 1;
+ last;
+ }
+ print "${us}Choose another name.${ue}\n";
+}
+
+
+if(!$branchimport) {
+ for(;;) {
+ $| = 1;
+ print "${so}Enter the module path:${se} $area/";
+ $| = 0;
+ $modpath = <>;
+ chop $modpath;
+ if ($modpath eq "") {
+ print "\a${us}You cannot use an empty module path.${ue}\n";
+ next;
+ }
+ last if ! -d "$cvsroot/$area/$modpath";
+ print "\a${us}This module path does already exist; " .
+ "choose another one.${ue}\n";
+ }
+
+
+ @newdirs = ();
+ $dir1 = "$cvsroot/$area";
+ $dir2 = "$area";
+
+ @newdirs = (@newdirs, "$dir2") if ! -d $dir1;
+
+ foreach $ele (split(/\//, $modpath)) {
+ $dir1 = "$dir1/$ele";
+ $dir2 = "$dir2/$ele";
+ @newdirs = (@newdirs, "$dir2") if ! -d $dir1;
+ }
+
+ print "${so}You're going to create the following new directories:${se}\n";
+
+ &list(@newdirs);
+}
+
+for(;;) {
+ $| = 1;
+ print "${so}Enter a \`vendor\' tag (e. g. the authors ID):${se} ";
+ $| = 0;
+ $vtag = <>;
+ chop $vtag;
+ last if &checktag($vtag, "vendor");
+}
+
+for(;;) {
+ $| = 1;
+ print "${so}Enter a \`release\' tag (e. g. the version #):${se} ";
+ $| = 0;
+ $rtag = <>;
+ chop $rtag;
+ last if &checktag($rtag, "release");
+}
+
+
+$| = 1;
+print "${so}This is your last chance to interrupt, " .
+ "hit <return> to go on:${se} ";
+$| = 0;
+<>;
+
+if (!$branchimport) {
+ $mod = "";
+ foreach $tmp (sort(keys(%cvsmods))) {
+ if($tmp gt $modname) {
+ $mod = $tmp;
+ last;
+ }
+ }
+ if($mod eq "") {
+ # we are going to append our module
+ $cmd = "\$\na\n";
+ } else {
+ # we can insert it
+ $cmd = "/^${mod}[ \t]/\ni\n";
+ }
+
+ print "${so}Checking out the modules database...${se}\n";
+ system("cvs co modules") && die "${us}failed.\n${ue}";
+
+ print "${so}Inserting new module...${se}\n";
+ open(ED, "|ed modules/modules") || die "${us}Cannot start ed${ue}\n";
+ print(ED "${cmd}${modname} " . ' ' x (15 - length($modname)) .
+ "$area/${modpath}\n.\nw\nq\n");
+ close(ED);
+
+ print "${so}Commiting new modules database...${se}\n";
+ system("cvs $dont_do_it commit -m \" " .
+ "${modname} --> $area/${modpath}\" modules")
+ && die "Commit failed\n";
+
+ # we always release "modules" to prevent duplicate
+ system("cvs -Q release -d modules");
+}
+
+print "${so}Importing source. Enter a commit message in the editor.${se}\n";
+
+system("cvs $dont_do_it import $area/$modpath $vtag $rtag");
+
+print "${so}You are done now. Go to a different directory, perform a${se}\n".
+ "${us}cvs co ${modname}${ue} ${so}command, and see if your new module" .
+ " builds ok.${se}\n";
+
+print "\nPlease don't forget to edit the parent Makefile to add what you\n".
+ "just imported.\n";
+
+if($dont_do_it) {
+print <<END
+
+
+${so}Since you did not allow to commit anything, you'll have${se}
+${so}to remove the edited modules' database yourself.${se}
+${so}To do this, perform a${se}
+${us}cd ${moduledir}; cvs -Q release -d modules${ue}
+${so}command.${se}
+END
+;
+}
diff --git a/gnu/usr.bin/cvs/cvs/Makefile b/gnu/usr.bin/cvs/cvs/Makefile
new file mode 100644
index 0000000..8f09c8b
--- /dev/null
+++ b/gnu/usr.bin/cvs/cvs/Makefile
@@ -0,0 +1,72 @@
+# $FreeBSD$
+
+MAINTAINER= peter@FreeBSD.org
+
+.include "${.CURDIR}/../Makefile.inc"
+
+.PATH: ${CVSDIR}/src
+.PATH: ${CVSDIR}/lib
+.PATH: ${CVSDIR}/man
+.PATH: ${CVSDIR}
+
+PROG= cvs
+MAN= cvs.1 cvs.5
+
+SRCS= add.c admin.c annotate.c buffer.c checkin.c checkout.c classify.c client.c \
+ commit.c create_adm.c cvsrc.c diff.c edit.c entries.c error.c \
+ expand_path.c fileattr.c filesubr.c find_names.c \
+ hardlink.c hash.c history.c \
+ ignore.c import.c lock.c log.c login.c logmsg.c main.c mkmodules.c \
+ modules.c myndbm.c no_diff.c parseinfo.c patch.c prepend_args.c \
+ rcs.c rcscmds.c \
+ recurse.c release.c remove.c repos.c root.c run.c scramble.c \
+ server.c status.c subr.c tag.c update.c vers_ts.c version.c watch.c \
+ wrapper.c zlib.c
+
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../lib -DHAVE_CONFIG_H \
+ -I${CVSDIR}/src -I${CVSDIR}/lib -I${CVSDIR}/diff
+
+DPADD+= ${LIBCVS} ${LIBDIFF} ${LIBGNUREGEX} ${LIBMD} ${LIBCRYPT} ${LIBZ}
+LDADD+= ${LIBCVS} ${LIBDIFF} -lgnuregex -lmd -lcrypt -lz
+
+.if defined(MAKE_KERBEROS4) && !defined(NO_OPENSSL) && !defined(NOCRYPT)
+CFLAGS+=-DHAVE_KERBEROS -DHAVE_KRB_GET_ERR_TEXT
+LDADD+= -lkrb -lcrypto -lcom_err
+DPADD+= ${LIBKRB} ${LIBCRYPTO} ${LIBCOM_ERR}
+DISTRIBUTION= krb4
+# XXX do we want to mess with this? It's probably not really worth it for
+# the public freebsd stuff, but others might want it. It's an optional
+# feature anyway, the -x switch is needed to activate it.
+CFLAGS+= -DENCRYPTION
+.endif
+
+CLEANFILES+= version.c
+VERSION!= sed < ${CVSDIR}/configure \
+ -e '/^VERSION=/!d' -e 's/.*=\(.*\)/\1/' -e q
+
+version.c: version.c.in
+ sed -e "s,@VERSION@,${VERSION}-FreeBSD,g" ${.ALLSRC} > ${.TARGET}
+
+#
+# Regression test support
+#
+CLEANDIRS+=cvs-sanity
+.ifmake regress
+USERID!=id -u
+regress:
+ mkdir -p ${.OBJDIR}/cvs-sanity/tmp ${.OBJDIR}/cvs-sanity/work
+.if ${USERID} == "0"
+ chown -R nobody ${.OBJDIR}/cvs-sanity
+ (TESTDIR=`sh -c 'cd ${.OBJDIR}/cvs-sanity/tmp && /bin/pwd'`;\
+ export TESTDIR;\
+ cd ${.OBJDIR}/cvs-sanity/work;\
+ su -m nobody -c "sh ${CVSDIR}/src/sanity.sh ${.OBJDIR}/cvs")
+.else
+ (TESTDIR=`sh -c 'cd ${.OBJDIR}/cvs-sanity/tmp && /bin/pwd'`;\
+ export TESTDIR;\
+ cd ${.OBJDIR}/cvs-sanity/work;\
+ sh ${CVSDIR}/src/sanity.sh ${.OBJDIR}/cvs)
+.endif
+.endif
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cvs/cvs/options.h b/gnu/usr.bin/cvs/cvs/options.h
new file mode 100644
index 0000000..41e1f94
--- /dev/null
+++ b/gnu/usr.bin/cvs/cvs/options.h
@@ -0,0 +1,201 @@
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 1992, Brian Berliner and Jeff Polk
+ * Copyright (c) 1989-1992, Brian Berliner
+ *
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS source distribution.
+ *
+ * This file holds (most of) the configuration tweaks that can be made to
+ * customize CVS for your site. CVS comes configured for a typical SunOS 4.x
+ * environment. The comments for each configurable item are intended to be
+ * self-explanatory. All #defines are tested first to see if an over-riding
+ * option was specified on the "make" command line.
+ *
+ * If special libraries are needed, you will have to edit the Makefile.in file
+ * or the configure script directly. Sorry.
+ */
+
+/* By default, CVS stores its modules and other such items in flat
+ text files (MY_NDBM enables this). Turning off MY_NDBM causes CVS
+ to look for a system-supplied ndbm database library and use it
+ instead. That may speed things up, but the default setting
+ generally works fine too. */
+
+#ifndef MY_NDBM
+#define MY_NDBM
+#endif
+
+/*
+ * The "patch" program to run when using the CVS server and accepting
+ * patches across the network. Specify a full pathname if your site
+ * wants to use a particular patch.
+ */
+#ifndef PATCH_PROGRAM
+#define PATCH_PROGRAM "patch"
+#endif
+
+/* Directory used for storing temporary files, if not overridden by
+ environment variables or the -T global option. There should be little
+ need to change this (-T is a better mechanism if you need to use a
+ different directory for temporary files). */
+#ifndef TMPDIR_DFLT
+#define TMPDIR_DFLT "/tmp"
+#endif
+
+/*
+ * The default editor to use, if one does not specify the "-e" option
+ * to cvs, or does not have an EDITOR environment variable. I set
+ * this to just "vi", and use the shell to find where "vi" actually
+ * is. This allows sites with /usr/bin/vi or /usr/ucb/vi to work
+ * equally well (assuming that your PATH is reasonable).
+ */
+#ifndef EDITOR_DFLT
+#define EDITOR_DFLT "vi"
+#endif
+
+/*
+ * The default umask to use when creating or otherwise setting file or
+ * directory permissions in the repository. Must be a value in the
+ * range of 0 through 0777. For example, a value of 002 allows group
+ * rwx access and world rx access; a value of 007 allows group rwx
+ * access but no world access. This value is overridden by the value
+ * of the CVSUMASK environment variable, which is interpreted as an
+ * octal number.
+ */
+#ifndef UMASK_DFLT
+#define UMASK_DFLT 002
+#endif
+
+/*
+ * The cvs admin command is restricted to the members of the group
+ * CVS_ADMIN_GROUP. If this group does not exist, all users are
+ * allowed to run cvs admin. To disable the cvs admin for all users,
+ * create an empty group CVS_ADMIN_GROUP. To disable access control
+ * for cvs admin, comment out the define below.
+ */
+#ifndef CVS_ADMIN_GROUP
+#define CVS_ADMIN_GROUP "cvsadmin"
+#endif
+
+/*
+ * The Repository file holds the path to the directory within the
+ * source repository that contains the RCS ,v files for each CVS
+ * working directory. This path is either a full-path or a path
+ * relative to CVSROOT.
+ *
+ * The big advantage that I can see to having a relative path is that
+ * one can change the physical location of the master source
+ * repository, change the contents of CVS/Root files in your
+ * checked-out code, and CVS will work without problems.
+ *
+ * Therefore, RELATIVE_REPOS is now the default. In the future, this
+ * is likely to disappear entirely as a compile-time (or other) option,
+ * so if you have other software which relies on absolute pathnames,
+ * update them.
+ */
+#define RELATIVE_REPOS 1
+
+/*
+ * When committing or importing files, you must enter a log message.
+ * Normally, you can do this either via the -m flag on the command
+ * line or an editor will be started for you. If you like to use
+ * logging templates (the rcsinfo file within the $CVSROOT/CVSROOT
+ * directory), you might want to force people to use the editor even
+ * if they specify a message with -m. Enabling FORCE_USE_EDITOR will
+ * cause the -m message to be appended to the temp file when the
+ * editor is started.
+ */
+#ifndef FORCE_USE_EDITOR
+/* #define FORCE_USE_EDITOR */
+#endif
+
+/*
+ * When locking the repository, some sites like to remove locks and
+ * assume the program that created them went away if the lock has
+ * existed for a long time. This used to be the default for previous
+ * versions of CVS. CVS now attempts to be much more robust, so lock
+ * files should not be left around by mistake. The new behaviour will
+ * never remove old locks (they must now be removed by hand).
+ * Enabling CVS_FUDGELOCKS will cause CVS to remove locks that are
+ * older than CVSLCKAGE seconds.
+ *
+ * Use of this option is NOT recommended.
+ */
+#ifndef CVS_FUDGELOCKS
+/* #define CVS_FUDGELOCKS */
+#endif
+
+/*
+ * When committing a permanent change, CVS and RCS make a log entry of
+ * who committed the change. If you are committing the change logged
+ * in as "root" (not under "su" or other root-priv giving program),
+ * CVS/RCS cannot determine who is actually making the change.
+ *
+ * As such, by default, CVS disallows changes to be committed by users
+ * logged in as "root". You can disable this option by commenting out
+ * the lines below.
+ */
+#ifndef CVS_BADROOT
+#define CVS_BADROOT
+#endif
+
+/* Define this to enable the SETXID support. The way to use this is
+ to create a group with no users in it (except perhaps cvs
+ administrators), set the cvs executable to setgid that group, chown
+ all the repository files to that group, and change all directory
+ permissions in the repository to 770. The last person to modify a
+ file will own it, but as long as directory permissions are set
+ right that won't matter. You'll need a system which inherits file
+ groups from the parent directory (WARNING: using the wrong kind of
+ system (I think Solaris 2.4 is the wrong kind, for example) will
+ create a security hole! You will receive no warning other than the
+ fact that files in the working directory are owned by the group
+ which cvs is setgid to).
+
+ One security hole which has been reported is that setgid is not
+ turned off when the editor is invoked--most editors provide a way
+ to execute a shell, or the user can specify an editor (this one is
+ large enough to drive a truck through). Don't assume that the
+ holes described here are the only ones; I don't know how carefully
+ SETXID has been inspected for security holes. */
+#ifndef SETXID_SUPPORT
+/* #define SETXID_SUPPORT */
+#endif
+
+/*
+ * Should we build the password-authenticating client? Whether to
+ * include the password-authenticating _server_, on the other hand, is
+ * set in config.h.
+ */
+#ifdef CLIENT_SUPPORT
+#define AUTH_CLIENT_SUPPORT 1
+#endif
+
+/*
+ * If you are working with a large remote repository and a 'cvs
+ * checkout' is swamping your network and memory, define these to
+ * enable flow control. You will end up with even less probability of
+ * a consistent checkout (see Concurrency in cvs.texinfo), but CVS
+ * doesn't try to guarantee that anyway. The master server process
+ * will monitor how far it is getting behind, if it reaches the high
+ * water mark, it will signal the child process to stop generating
+ * data when convenient (ie: no locks are held, currently at the
+ * beginning of a new directory). Once the buffer has drained
+ * sufficiently to reach the low water mark, it will be signalled to
+ * start again. You may override the default hi/low watermarks here
+ * too.
+ */
+#define SERVER_FLOWCONTROL
+#define SERVER_HI_WATER (2 * 1024 * 1024)
+#define SERVER_LO_WATER (1 * 1024 * 1024)
+
+/* End of CVS configuration section */
+
+/*
+ * Externs that are included in libc, but are used frequently enough
+ * to warrant defining here.
+ */
+#ifndef STDC_HEADERS
+extern void exit ();
+#endif
diff --git a/gnu/usr.bin/cvs/cvs/prepend_args.c b/gnu/usr.bin/cvs/cvs/prepend_args.c
new file mode 100644
index 0000000..12322ce
--- /dev/null
+++ b/gnu/usr.bin/cvs/cvs/prepend_args.c
@@ -0,0 +1,86 @@
+/* prepend_args.c - utilility programs for manpiulating argv[]
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "cvs.h"
+#include "prepend_args.h"
+
+
+/* Find the white-space-separated options specified by OPTIONS, and
+ using BUF to store copies of these options, set ARGV[0], ARGV[1],
+ etc. to the option copies. Return the number N of options found.
+ Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0]
+ etc. Backslash can be used to escape whitespace (and backslashes). */
+static int
+prepend_args (options, buf, argv)
+ char const *options;
+ char *buf;
+ char **argv;
+{
+ char const *o = options;
+ char *b = buf;
+ int n = 0;
+
+ for (;;)
+ {
+ while (isspace ((unsigned char) *o))
+ o++;
+ if (!*o)
+ return n;
+ if (argv)
+ argv[n] = b;
+ n++;
+
+ do
+ if ((*b++ = *o++) == '\\' && *o)
+ b[-1] = *o++;
+ while (*o && ! isspace ((unsigned char) *o));
+
+ *b++ = '\0';
+ }
+}
+
+/* Prepend the whitespace-separated options in OPTIONS to the argument
+ vector of a main program with argument count *PARGC and argument
+ vector *PARGV. */
+void
+prepend_default_options (options, pargc, pargv)
+ char const *options;
+ int *pargc;
+ char ***pargv;
+{
+ if (options)
+ {
+ char *buf = xmalloc (strlen (options) + 1);
+ int prepended = prepend_args (options, buf, (char **) NULL);
+ int argc = *pargc;
+ char * const *argv = *pargv;
+ char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
+ *pargc = prepended + argc;
+ *pargv = pp;
+ *pp++ = *argv++;
+ pp += prepend_args (options, buf, pp);
+ while ((*pp++ = *argv++))
+ continue;
+ }
+}
diff --git a/gnu/usr.bin/cvs/cvs/prepend_args.h b/gnu/usr.bin/cvs/cvs/prepend_args.h
new file mode 100644
index 0000000..6708442
--- /dev/null
+++ b/gnu/usr.bin/cvs/cvs/prepend_args.h
@@ -0,0 +1,26 @@
+/* prepend_args.h - utilility programs for manpiulating argv[]
+ Copyright (C) 1999 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+/* This code, taken from GNU Grep, originally used the "PARAM" macro, as the
+ current GNU coding standards requires. Older GNU code used the "PROTO"
+ macro, before the GNU coding standards replaced it. We use the older
+ form here to keep from having to include another file in cvs/src/main.c. */
+
+void prepend_default_options PROTO ((char const *, int *, char ***));
diff --git a/gnu/usr.bin/cvs/cvsbug/Makefile b/gnu/usr.bin/cvs/cvsbug/Makefile
new file mode 100644
index 0000000..3acec13
--- /dev/null
+++ b/gnu/usr.bin/cvs/cvsbug/Makefile
@@ -0,0 +1,24 @@
+# $FreeBSD$
+
+MAINTAINER= peter@FreeBSD.org
+
+.include "${.CURDIR}/../Makefile.inc"
+
+.PATH: ${CVSDIR}/src
+.PATH: ${CVSDIR}/man
+.PATH: ${CVSDIR}
+
+SCRIPTS= cvsbug
+MAN= cvsbug.8
+
+CLEANFILES+= cvsbug version.c
+VERSION!= sed < ${CVSDIR}/configure \
+ -e '/^VERSION=/!d' -e 's/.*=\(.*\)/\1/' -e q
+
+version.c: version.c.in
+ sed -e "s,@VERSION@,${VERSION}-FreeBSD,g" ${.ALLSRC} > ${.TARGET}
+
+cvsbug: cvsbug.in
+ sed -e "s,@VERSION@,${VERSION}-FreeBSD,g" ${.ALLSRC} > ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cvs/doc/Makefile b/gnu/usr.bin/cvs/doc/Makefile
new file mode 100644
index 0000000..0907ae4
--- /dev/null
+++ b/gnu/usr.bin/cvs/doc/Makefile
@@ -0,0 +1,25 @@
+# $FreeBSD$
+
+MAINTAINER= peter@FreeBSD.org
+
+.include "${.CURDIR}/../Makefile.inc"
+
+SRCDIR= ${CVSDIR}/doc
+
+INFO= cvs cvsclient
+INFOSECTION= "Programming & development tools."
+INFOENTRY_cvs= "* CVS: (cvs). CVS Reference Manual."
+INFOENTRY_cvsclient= "* CVS-CLIENT: (cvsclient). CVS client/server Reference Manual."
+
+
+cvs.info cvsclient.info: CVSvn.texi
+
+CLEANFILES+= CVSvn.texi
+
+CVSvn.texi: ${CVSDIR}/configure
+ echo "@set CVSVN `sed < ${CVSDIR}/configure \
+ -e '/^VERSION=/!d' \
+ -e 's/.*=\(.*\)/\1/' \
+ -e q`" > $@
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/cvs/lib/Makefile b/gnu/usr.bin/cvs/lib/Makefile
new file mode 100644
index 0000000..c57e695
--- /dev/null
+++ b/gnu/usr.bin/cvs/lib/Makefile
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+MAINTAINER= peter@FreeBSD.org
+
+.include "${.CURDIR}/../Makefile.inc"
+
+.PATH: ${CVSDIR}/src
+.PATH: ${CVSDIR}/lib
+.PATH: ${CVSDIR}/man
+
+LIB= cvs
+INTERNALLIB= YES
+
+CFLAGS+= -I${.CURDIR} -I${CVSDIR}/src -I${CVSDIR}/lib
+CFLAGS+= -DHAVE_CONFIG_H
+YFLAGS=
+
+SRCS= argmatch.c getdate.y getline.c \
+ getopt.c getopt1.c savecwd.c \
+ sighandle.c stripslash.c \
+ xgetwd.c yesno.c
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/cvs/lib/config.h b/gnu/usr.bin/cvs/lib/config.h
new file mode 100644
index 0000000..4bf02bf
--- /dev/null
+++ b/gnu/usr.bin/cvs/lib/config.h
@@ -0,0 +1,335 @@
+/* $FreeBSD$ */
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* 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 the closedir function returns void instead of int. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define if your system has a working fnmatch function. */
+#define HAVE_FNMATCH 1
+
+/* Define if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if your struct stat has st_blksize. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define if your struct stat has st_rdev. */
+#define HAVE_ST_RDEV 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if utime(file, NULL) sets file's timestamp to the present. */
+#define HAVE_UTIME_NULL 1
+
+/* Define if you have <vfork.h>. */
+/* #undef HAVE_VFORK_H */
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* 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). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* 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. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define vfork as fork if vfork does not work. */
+/* #undef vfork */
+
+/* Define if you have MIT Kerberos version 4 available. */
+/* #undef HAVE_KERBEROS */
+
+/* Define if you want CVS to be able to be a remote repository client. */
+#define CLIENT_SUPPORT 1
+
+/* Define if you want CVS to be able to serve repositories to remote
+ clients. */
+#define SERVER_SUPPORT 1
+
+/* Define if you want to use the password authenticated server. */
+#define AUTH_SERVER_SUPPORT 1
+
+/* Define if you want encryption support. */
+/* #undef ENCRYPTION */
+
+/* Define if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define if you have memchr (always for CVS). */
+#define HAVE_MEMCHR 1
+
+/* Define if you have strchr (always for CVS). */
+#define HAVE_STRCHR 1
+
+/* Define if utime requires write access to the file (true on Windows,
+ but not Unix). */
+/* #undef UTIME_EXPECTS_WRITABLE */
+
+/* Define if setmode is required when writing binary data to stdout. */
+/* #undef USE_SETMODE_STDOUT */
+
+/* Define if the diff library should use setmode for binary files.
+ FIXME: Why two different macros for setmode? */
+/* #undef HAVE_SETMODE */
+
+/* Define if you have the crypt function. */
+#define HAVE_CRYPT 1
+
+/* Define if you have the getspnam function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define to force lib/regex.c to use malloc instead of alloca. */
+#define REGEX_MALLOC 1
+
+/* Define to force lib/regex.c to define re_comp et al. */
+#define _REGEX_RE_COMP 1
+
+/* Define if you have the dup2 function. */
+#define HAVE_DUP2 1
+
+/* Define if you have the fchdir function. */
+#define HAVE_FCHDIR 1
+
+/* Define if you have the fchmod function. */
+#define HAVE_FCHMOD 1
+
+/* Define if you have the fsync function. */
+#define HAVE_FSYNC 1
+
+/* Define if you have the ftime function. */
+/* #undef HAVE_FTIME */
+
+/* Define if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have the getgroups function. */
+#define HAVE_GETGROUPS 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getpassphrase function. */
+/* #undef HAVE_GETPASSPHRASE */
+
+/* Define if you have the gettimeofday function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the initgroups function. */
+#define HAVE_INITGROUPS 1
+
+/* Define if you have the krb_get_err_text function. */
+/* #undef HAVE_KRB_GET_ERR_TEXT */
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the mkdir function. */
+#define HAVE_MKDIR 1
+
+/* Define if you have the mknod function. */
+#define HAVE_MKNOD 1
+
+/* Define if you have the mkstemp function. */
+#define HAVE_MKSTEMP 1
+
+/* Define if you have the mktemp function. */
+#define HAVE_MKTEMP 1
+
+/* Define if you have the nanosleep function. */
+#define HAVE_NANOSLEEP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the readlink function. */
+#define HAVE_READLINK 1
+
+/* Define if you have the rename function. */
+#define HAVE_RENAME 1
+
+/* Define if you have the select function. */
+/* #undef HAVE_SELECT */
+
+/* Define if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define if you have the sigblock function. */
+#define HAVE_SIGBLOCK 1
+
+/* Define if you have the sigprocmask function. */
+#define HAVE_SIGPROCMASK 1
+
+/* Define if you have the sigsetmask function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define if you have the sigvec function. */
+#define HAVE_SIGVEC 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtoul function. */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the tempnam function. */
+#define HAVE_TEMPNAM 1
+
+/* Define if you have the timezone function. */
+#define HAVE_TIMEZONE 1
+
+/* Define if you have the tzset function. */
+#define HAVE_TZSET 1
+
+/* Define if you have the usleep function. */
+/* #undef HAVE_USLEEP */
+
+/* Define if you have the valloc function. */
+#define HAVE_VALLOC 1
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
+/* Define if you have the wait3 function. */
+#define HAVE_WAIT3 1
+
+/* Define if you have the waitpid function. */
+#define HAVE_WAITPID 1
+
+/* Define if you have the <direct.h> header file. */
+/* #undef HAVE_DIRECT_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_H */
+
+/* Define if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define if you have the <krb5.h> header file. */
+/* #undef HAVE_KRB5_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <ndbm.h> header file. */
+#define HAVE_NDBM_H 1
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/bsdtypes.h> header file. */
+/* #undef HAVE_SYS_BSDTYPES_H */
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Name of package */
+#define PACKAGE "cvs"
+
+/* Version number of package */
+#define VERSION "1.11.1p1"
+
+/* Path to the pr utility */
+#define PR_PROGRAM "/usr/bin/pr"
+
+/* Define if you have GSSAPI with Kerberos version 5 available. */
+/* #undef HAVE_GSSAPI */
+
+/* Define to an alternative value if GSS_C_NT_HOSTBASED_SERVICE isn't defined
+in the gssapi.h header file. MIT Kerberos 1.2.1 requires this. Only relevant
+when using GSSAPI. */
+/* #undef GSS_C_NT_HOSTBASED_SERVICE */
+
diff --git a/gnu/usr.bin/cvs/lib/config.h.proto b/gnu/usr.bin/cvs/lib/config.h.proto
new file mode 100644
index 0000000..4bf02bf
--- /dev/null
+++ b/gnu/usr.bin/cvs/lib/config.h.proto
@@ -0,0 +1,335 @@
+/* $FreeBSD$ */
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* 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 the closedir function returns void instead of int. */
+/* #undef CLOSEDIR_VOID */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define if your system has a working fnmatch function. */
+#define HAVE_FNMATCH 1
+
+/* Define if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if your struct stat has st_blksize. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define if your struct stat has st_rdev. */
+#define HAVE_ST_RDEV 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if utime(file, NULL) sets file's timestamp to the present. */
+#define HAVE_UTIME_NULL 1
+
+/* Define if you have <vfork.h>. */
+/* #undef HAVE_VFORK_H */
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef pid_t */
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* 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). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* 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. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define vfork as fork if vfork does not work. */
+/* #undef vfork */
+
+/* Define if you have MIT Kerberos version 4 available. */
+/* #undef HAVE_KERBEROS */
+
+/* Define if you want CVS to be able to be a remote repository client. */
+#define CLIENT_SUPPORT 1
+
+/* Define if you want CVS to be able to serve repositories to remote
+ clients. */
+#define SERVER_SUPPORT 1
+
+/* Define if you want to use the password authenticated server. */
+#define AUTH_SERVER_SUPPORT 1
+
+/* Define if you want encryption support. */
+/* #undef ENCRYPTION */
+
+/* Define if you have the connect function. */
+#define HAVE_CONNECT 1
+
+/* Define if you have memchr (always for CVS). */
+#define HAVE_MEMCHR 1
+
+/* Define if you have strchr (always for CVS). */
+#define HAVE_STRCHR 1
+
+/* Define if utime requires write access to the file (true on Windows,
+ but not Unix). */
+/* #undef UTIME_EXPECTS_WRITABLE */
+
+/* Define if setmode is required when writing binary data to stdout. */
+/* #undef USE_SETMODE_STDOUT */
+
+/* Define if the diff library should use setmode for binary files.
+ FIXME: Why two different macros for setmode? */
+/* #undef HAVE_SETMODE */
+
+/* Define if you have the crypt function. */
+#define HAVE_CRYPT 1
+
+/* Define if you have the getspnam function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define to force lib/regex.c to use malloc instead of alloca. */
+#define REGEX_MALLOC 1
+
+/* Define to force lib/regex.c to define re_comp et al. */
+#define _REGEX_RE_COMP 1
+
+/* Define if you have the dup2 function. */
+#define HAVE_DUP2 1
+
+/* Define if you have the fchdir function. */
+#define HAVE_FCHDIR 1
+
+/* Define if you have the fchmod function. */
+#define HAVE_FCHMOD 1
+
+/* Define if you have the fsync function. */
+#define HAVE_FSYNC 1
+
+/* Define if you have the ftime function. */
+/* #undef HAVE_FTIME */
+
+/* Define if you have the ftruncate function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have the getgroups function. */
+#define HAVE_GETGROUPS 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the getpassphrase function. */
+/* #undef HAVE_GETPASSPHRASE */
+
+/* Define if you have the gettimeofday function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the initgroups function. */
+#define HAVE_INITGROUPS 1
+
+/* Define if you have the krb_get_err_text function. */
+/* #undef HAVE_KRB_GET_ERR_TEXT */
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the mkdir function. */
+#define HAVE_MKDIR 1
+
+/* Define if you have the mknod function. */
+#define HAVE_MKNOD 1
+
+/* Define if you have the mkstemp function. */
+#define HAVE_MKSTEMP 1
+
+/* Define if you have the mktemp function. */
+#define HAVE_MKTEMP 1
+
+/* Define if you have the nanosleep function. */
+#define HAVE_NANOSLEEP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the readlink function. */
+#define HAVE_READLINK 1
+
+/* Define if you have the rename function. */
+#define HAVE_RENAME 1
+
+/* Define if you have the select function. */
+/* #undef HAVE_SELECT */
+
+/* Define if you have the sigaction function. */
+#define HAVE_SIGACTION 1
+
+/* Define if you have the sigblock function. */
+#define HAVE_SIGBLOCK 1
+
+/* Define if you have the sigprocmask function. */
+#define HAVE_SIGPROCMASK 1
+
+/* Define if you have the sigsetmask function. */
+#define HAVE_SIGSETMASK 1
+
+/* Define if you have the sigvec function. */
+#define HAVE_SIGVEC 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strstr function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the strtoul function. */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the tempnam function. */
+#define HAVE_TEMPNAM 1
+
+/* Define if you have the timezone function. */
+#define HAVE_TIMEZONE 1
+
+/* Define if you have the tzset function. */
+#define HAVE_TZSET 1
+
+/* Define if you have the usleep function. */
+/* #undef HAVE_USLEEP */
+
+/* Define if you have the valloc function. */
+#define HAVE_VALLOC 1
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
+/* Define if you have the wait3 function. */
+#define HAVE_WAIT3 1
+
+/* Define if you have the waitpid function. */
+#define HAVE_WAITPID 1
+
+/* Define if you have the <direct.h> header file. */
+/* #undef HAVE_DIRECT_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_H */
+
+/* Define if you have the <gssapi/gssapi.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_H */
+
+/* Define if you have the <gssapi/gssapi_generic.h> header file. */
+/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */
+
+/* Define if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define if you have the <krb5.h> header file. */
+/* #undef HAVE_KRB5_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <ndbm.h> header file. */
+#define HAVE_NDBM_H 1
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/bsdtypes.h> header file. */
+/* #undef HAVE_SYS_BSDTYPES_H */
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Name of package */
+#define PACKAGE "cvs"
+
+/* Version number of package */
+#define VERSION "1.11.1p1"
+
+/* Path to the pr utility */
+#define PR_PROGRAM "/usr/bin/pr"
+
+/* Define if you have GSSAPI with Kerberos version 5 available. */
+/* #undef HAVE_GSSAPI */
+
+/* Define to an alternative value if GSS_C_NT_HOSTBASED_SERVICE isn't defined
+in the gssapi.h header file. MIT Kerberos 1.2.1 requires this. Only relevant
+when using GSSAPI. */
+/* #undef GSS_C_NT_HOSTBASED_SERVICE */
+
diff --git a/gnu/usr.bin/cvs/libdiff/Makefile b/gnu/usr.bin/cvs/libdiff/Makefile
new file mode 100644
index 0000000..f668deb
--- /dev/null
+++ b/gnu/usr.bin/cvs/libdiff/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+MAINTAINER= peter@FreeBSD.org
+
+.include "${.CURDIR}/../Makefile.inc"
+
+.PATH: ${CVSDIR}/diff
+
+LIB= diff
+INTERNALLIB= YES
+
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../lib -I${CVSDIR}/lib -DHAVE_CONFIG_H
+
+SRCS = diff.c diff3.c analyze.c cmpbuf.c cmpbuf.h io.c context.c ed.c \
+ normal.c ifdef.c util.c dir.c version.c diff.h side.c
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/dc/Makefile b/gnu/usr.bin/dc/Makefile
new file mode 100644
index 0000000..8ecd2e2
--- /dev/null
+++ b/gnu/usr.bin/dc/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+BCDIR= ${.CURDIR}/../../../contrib/bc
+
+.PATH: ${BCDIR}/dc ${BCDIR}/lib ${BCDIR}/doc
+
+PROG= dc
+SRCS= array.c dc.c eval.c misc.c numeric.c stack.c string.c \
+ getopt.c getopt1.c number.c
+CFLAGS+=-I${.CURDIR}/../bc -I${BCDIR}/h -DHAVE_CONFIG_H
+DPADD= ${LIBM}
+LDADD= -lm
+SUBDIR= doc
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/dc/doc/Makefile b/gnu/usr.bin/dc/doc/Makefile
new file mode 100644
index 0000000..2b3d553
--- /dev/null
+++ b/gnu/usr.bin/dc/doc/Makefile
@@ -0,0 +1,11 @@
+# Makefile copyright Andreas Klemm <andreas@FreeBSD.ORG> 1998
+#
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../../contrib/bc/doc
+
+INFO = dc
+INFOSECTION= "System Utilities"
+INFOENTRY_dc= "* DC: (dc). The GNU Desktop Calculator."
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/dialog/COPYING b/gnu/usr.bin/dialog/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/gnu/usr.bin/dialog/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/dialog/Makefile b/gnu/usr.bin/dialog/Makefile
new file mode 100644
index 0000000..b5dfeb3
--- /dev/null
+++ b/gnu/usr.bin/dialog/Makefile
@@ -0,0 +1,13 @@
+# Makefile for dialog
+# $FreeBSD$
+
+SUBDIR= TESTS
+
+PROG= dialog
+
+CFLAGS+= -Wall -Wstrict-prototypes
+
+DPADD+= $(LIBDIALOG) $(LIBNCURSES)
+LDADD+= -ldialog -lncurses
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/dialog/README b/gnu/usr.bin/dialog/README
new file mode 100644
index 0000000..975bdac
--- /dev/null
+++ b/gnu/usr.bin/dialog/README
@@ -0,0 +1,161 @@
+
+ dialog - Display dialog boxes in shell script (version 0.3)
+ ===========================================================
+
+This is a program that will enable you to present a variety of questions or
+display messages using dialog boxes from a shell script. Currently, these
+types of dialog boxes are implemented: yes/no box, menu box, input box,
+message box, text box, info box, checklist box. The idea of writing this
+program came from the fact that most questions asked in a shell script (and
+many interactive programs as well) can be classified into these few types:
+
+
+ 1) One that requires the user to answer either yes or no.
+
+ 2) One that presents a number of options for the user to choose.
+
+ 3) One that requires the user to input a string.
+
+ 4) One that displays a message and optionally wait for a key press
+ before continuing.
+
+ 5) One that presents a list of options that can be turned on or off.
+
+
+The program 'dialog' can, say for example, be called in a shell script to
+present the first type of questions like this:
+
+
+ if dialog --yesno <question text> <height> <width>
+ then
+ ...
+ fi
+
+
+ e.g. if dialog --yesno "Do you want to continue?" 7 51
+ then
+ echo "Continuing..."
+ else
+ echo "Aborting..."
+ fi
+
+
+I've included a sample shell script for each type of boxes in the directory
+samples. The program requires ncurses to compile. Running 'dialog' without
+arguments will display the usage.
+
+
+
+FEATURES
+--------
+
+ * Friendly dialog box interface with buttons, etc.
+
+ * Auto wrap around of question text if it's too long to fit on
+ one line.
+
+ * "\n" can be inserted in question text to control line breaking
+ explicitly. The real newline character '\n' can also be used.
+
+ * run-time configruation of color settings and other options using
+ a configuration file.
+
+
+
+WHAT'S NEW SINCE VERSION 0.21?
+------------------------------
+
+ * some changes for faster screen update.
+
+ * much more flexible color settings. Can use all 16 colors
+ (8 normal, 8 highlight) of the Linux console.
+
+ * added run-time configuration using configuration file.
+
+ * some minor bug fixes and cleanups for menubox, checklist and
+ textbox.
+
+ * added a man page.
+
+ * some changes for easier porting to other Unix systems (tested
+ on Ultrix, SunOS and HPUX)
+
+
+
+INSTALLATION
+------------
+
+ 1. cd ./src
+
+ 2. Go to step 3 if your system has ncurses (e.g. Linux).
+ Edit Makefile and remove -DHAVE_NCURSES from DEFS. Also
+ remove rc.c from SRCS and rc.o from OBJS. Change LIBS as
+ appropriate (Usually, it should be '-lcurses -ltermcap').
+ Go to step 6.
+
+ 3. Edit Makefile and remove -DBROKEN_WSCRL from DEFS if you
+ are using ncurses 1.8.3 or newer. Menu scrolling should
+ be faster. DON'T REMOVE IT IF YOU ARE NOT USING AT LEAST
+ VERSION 1.8.3 OF NCURSES.
+
+ 4. Edit dialog.h and change USE_SHADOW to FALSE if you don't
+ want shadowed dialog boxes. Also change USE_COLORS to
+ FALSE if you don't want colors. Note that 'dialog' will
+ check if the terminal supports colors, and will use mono
+ settings if it doesn't, so USE_COLORS won't do any harm
+ even if you have a mono display. Also note that USE_SHADOW
+ implies USE_COLORS. These two options can be changed at
+ run-time using the run-time configuration file (see below).
+
+ 5. Edit colors.h to change default color definitions if you
+ don't like the defaults. These are only compiled in defaults,
+ you can change them at run-time using the run-time
+ configuration file.
+
+ 6. 'make depend; make install' will compile and install the
+ binaries in /usr/local/bin (change BINDIR in Makefile if
+ you want to install elsewhere).
+
+ 7. 'make install.man' will install the man page to
+ /usr/local/man (change MANDIR in Makefile if you want to
+ install elsewhere).
+
+ 8. You can then try the sample shell scripts in the samples
+ directory (make sure the environment variable DIALOG is
+ not set, the scripts use it to find the dialog binary, if
+ it's not set, "../src/dialog" will be used).
+
+ 9. Don't forget to mail me (mail address at end of this file)
+ if you find any bugs, have some good color settings to
+ contribute or just want to tell me that you like it, Don't
+ mail me if you don't like it :-)
+
+
+
+RUN-TIME CONFIGURATION
+----------------------
+
+ 1. Create a sample configuration file by typing:
+
+ "dialog --create-rc <file>"
+
+ 2. At start, 'dialog' determines the settings to use as follows:
+
+ a) if environment variable DIALOGRC is set, it's value
+ determines the name of the configuration file.
+
+ b) if the file in (a) can't be found, use the file
+ $HOME/.dialogrc as the configuration file.
+
+ c) if the file in (b) can't be found, use compiled in
+ defaults.
+
+ 3. Edit the sample configuration file and copy it to some place
+ that 'dialog' can find, as stated in step 2 above.
+
+
+
+
+Comments and bug reports welcome.
+
+- Savio Lam (lam836@cs.cuhk.hk)
diff --git a/gnu/usr.bin/dialog/README.lib b/gnu/usr.bin/dialog/README.lib
new file mode 100644
index 0000000..472c206
--- /dev/null
+++ b/gnu/usr.bin/dialog/README.lib
@@ -0,0 +1,3 @@
+Now 'dialog' splitted to this sources and library of functions,
+see /usr/src/gnu/lib/libdialog for details.
+ Ache.
diff --git a/gnu/usr.bin/dialog/TESTS/Makefile b/gnu/usr.bin/dialog/TESTS/Makefile
new file mode 100644
index 0000000..314a3ae
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+NOOBJ= noobj
+FILES= README checklist ftreebox infobox inputbox menubox msgbox \
+ prgbox radiolist textbox treebox yesno
+FILESDIR= ${SHAREDIR}/examples/dialog
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/dialog/TESTS/README b/gnu/usr.bin/dialog/TESTS/README
new file mode 100644
index 0000000..951fe3b
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/README
@@ -0,0 +1,15 @@
+These shell scripts demonstrate possibilities of the dialog(1) tool.
+
+checklist - checkbox list
+ftreebox - file tree box
+infobox - info box
+inputbox - input box
+menubox - menu
+msgbox - message box
+prgbox - program box
+radiolist - radio button list
+textbox - simple text box
+treebox - tree box
+yesno - yes/no dialog
+
+$FreeBSD$
diff --git a/gnu/usr.bin/dialog/TESTS/checklist b/gnu/usr.bin/dialog/TESTS/checklist
new file mode 100755
index 0000000..008e874
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/checklist
@@ -0,0 +1,33 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --title "CHECKLIST BOX" --clear \
+ --checklist "Hi, this is a checklist box. You can use this to \n\
+present a list of choices which can be turned on or \n\
+off. If there are more items than can fit on the \n\
+screen, the list will be scrolled. You can use the \n\
+UP/DOWN arrow keys, the first letter of the choice as a\n\
+hot key, or the number keys 1-9 to choose an option. \n\
+Press SPACE to toggle an option on/off. \n\n\
+ Which of the following are fruits?" -1 -1 5 \
+ "Apple" "It's an apple." off \
+ "Dog" "No, that's not my dog." ON \
+ "Orange" "Yeah, that's juicy." off \
+ "Cat" "No, never put a dog and a cat together!" oN \
+ "Fish" "Cats like fish." On \
+ "Lemon" "You know how it tastes." on 2> /tmp/checklist.tmp.$$
+
+retval=$?
+
+choice=`cat /tmp/checklist.tmp.$$`
+rm -f /tmp/checklist.tmp.$$
+
+case $retval in
+ 0)
+ echo "'$choice' chosen.";;
+ 1)
+ echo "Cancel pressed.";;
+ 255)
+ [ -z "$choice" ] || echo $choice ;
+ echo "ESC pressed.";;
+esac
diff --git a/gnu/usr.bin/dialog/TESTS/ftreebox b/gnu/usr.bin/dialog/TESTS/ftreebox
new file mode 100755
index 0000000..621dc1e
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/ftreebox
@@ -0,0 +1,27 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+find -xd / -type d > /tmp/ftreebox.tmp.$$
+
+$DIALOG --clear --title "FTREE BOX" \
+ --hline "Press arrows, TAB or Enter" \
+ --hfile "../COPYING" \
+ --ftree "/tmp/ftreebox.tmp.$$" "/" \
+ "This is ftree box" \
+ -1 -1 10 2>/tmp/ftree.tmp.$$
+
+retval=$?
+
+choice=`cat /tmp/ftree.tmp.$$`
+
+case $retval in
+ 0)
+ echo "'$choice' chosen.";;
+ 1)
+ echo "Cancel pressed.";;
+ 255)
+ [ -z "$choice" ] || echo $choice ;
+ echo "ESC pressed.";;
+esac
+
+rm -f /tmp/ftreebox.tmp.$$ /tmp/ftree.tmp.$$
diff --git a/gnu/usr.bin/dialog/TESTS/infobox b/gnu/usr.bin/dialog/TESTS/infobox
new file mode 100755
index 0000000..89d4736
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/infobox
@@ -0,0 +1,15 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --title "INFO BOX" \
+ --infobox "Hi, this is an information box. It is
+different from a message box in that it will
+not pause waiting for input after displaying
+the message. The pause here is only introduced
+by the sleep command, not by dialog.
+
+You have 10 seconds to read this..." -1 -1
+
+stty -echo
+sleep 10
+stty echo
diff --git a/gnu/usr.bin/dialog/TESTS/inputbox b/gnu/usr.bin/dialog/TESTS/inputbox
new file mode 100755
index 0000000..2acb846
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/inputbox
@@ -0,0 +1,28 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --title "INPUT BOX" --clear \
+ --inputbox "Hi, this is an input dialog box. You can use \n\
+this to ask questions that require the user \n\
+to input a string as the answer. You can \n\
+input strings of length longer than the \n\
+width of the input box, in that case, the \n\
+input field will be automatically scrolled. \n\
+You can use BACKSPACE, LEFT, RIGHT, HOME, END\n\
+to correct errors. \n\n\
+Try inputing your name below:" -1 -1 "John Smith" 2> /tmp/inputbox.tmp.$$
+
+retval=$?
+
+input=`cat /tmp/inputbox.tmp.$$`
+rm -f /tmp/inputbox.tmp.$$
+
+case $retval in
+ 0)
+ echo "Input string is '$input'";;
+ 1)
+ echo "Cancel pressed.";;
+ 255)
+ [ -z "$input" ] || echo $input ;
+ echo "ESC pressed.";;
+esac
diff --git a/gnu/usr.bin/dialog/TESTS/menubox b/gnu/usr.bin/dialog/TESTS/menubox
new file mode 100755
index 0000000..39fe52f
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/menubox
@@ -0,0 +1,35 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --clear --title "MENU BOX" \
+ --hline "Press 1-9, Up/Down, first letter or Enter" \
+ --menu "Hi, this is a menu box. You can use this to \n\
+present a list of choices for the user to \n\
+choose. If there are more items than can fit \n\
+on the screen, the menu will be scrolled. \n\
+You can use the UP/DOWN arrow keys, the first \n\
+letter of the choice as a hot key, or the \n\
+number keys 1-9 to choose an option.\n\
+Try it now!\n\n\
+ Choose the OS you like:" -1 -1 4 \
+ "FreeBSD" "A Real Operating System for Real Users" \
+ "Linux" "Another free Unix Clone for 386/486" \
+ "OS/2" "IBM OS/2" \
+ "WIN NT" "Microsoft Windows NT" \
+ "PCDOS" "IBM PC DOS" \
+ "MSDOS" "Microsoft DOS" 2> /tmp/menu.tmp.$$
+
+retval=$?
+
+choice=`cat /tmp/menu.tmp.$$`
+rm -f /tmp/menu.tmp.$$
+
+case $retval in
+ 0)
+ echo "'$choice' chosen.";;
+ 1)
+ echo "Cancel pressed.";;
+ 255)
+ [ -z "$choice" ] || echo $choice ;
+ echo "ESC pressed.";;
+esac
diff --git a/gnu/usr.bin/dialog/TESTS/msgbox b/gnu/usr.bin/dialog/TESTS/msgbox
new file mode 100755
index 0000000..7f1b1f8
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/msgbox
@@ -0,0 +1,14 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --title "MESSAGE BOX" --clear \
+ --msgbox "Hi, this is a simple message box. You can use this to\n\
+display any message you like. The box will remain until\n\
+you press the ENTER key." -1 -1
+
+case $? in
+ 0)
+ echo "OK";;
+ 255)
+ echo "ESC pressed.";;
+esac
diff --git a/gnu/usr.bin/dialog/TESTS/prgbox b/gnu/usr.bin/dialog/TESTS/prgbox
new file mode 100755
index 0000000..5a631f5
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/prgbox
@@ -0,0 +1,12 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --title "PROGRAM BOX: 'cal'" --clear \
+ --prgbox "cal" 13 27
+
+case $? in
+ 0)
+ echo "OK";;
+ *)
+ echo "Exit code:" $?;;
+esac
diff --git a/gnu/usr.bin/dialog/TESTS/radiolist b/gnu/usr.bin/dialog/TESTS/radiolist
new file mode 100755
index 0000000..7402790
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/radiolist
@@ -0,0 +1,33 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --title "RADIOLIST BOX" --clear \
+ --radiolist "Hi, this is a radiolist box. You can use this to \n\
+present a list of choices, one of them can be turned \n\
+on or off. If there are more items than can fit on the \n\
+screen, the list will be scrolled. You can use the \n\
+UP/DOWN arrow keys, the first letter of the choice as a\n\
+hot key, or the number keys 1-9 to choose an option. \n\
+Press SPACE to toggle an option on/off. \n\n\
+ Which of the following are fruits?" -1 -1 5 \
+ "Apple" "It's an apple." off \
+ "Dog" "No, that's not my dog." ON \
+ "Orange" "Yeah, that's juicy." off \
+ "Cat" "No, never put a dog and a cat together!" oFF \
+ "Fish" "Cats like fish." OFF \
+ "Lemon" "You know how it tastes." oFF 2> /tmp/radiolist.tmp.$$
+
+retval=$?
+
+choice=`cat /tmp/radiolist.tmp.$$`
+rm -f /tmp/radiolist.tmp.$$
+
+case $retval in
+ 0)
+ echo "'$choice' chosen.";;
+ 1)
+ echo "Cancel pressed.";;
+ 255)
+ [ -z "$choice" ] || echo $choice ;
+ echo "ESC pressed.";;
+esac
diff --git a/gnu/usr.bin/dialog/TESTS/textbox b/gnu/usr.bin/dialog/TESTS/textbox
new file mode 100755
index 0000000..ed7c2d9
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/textbox
@@ -0,0 +1,42 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+cat << EOF > /tmp/textbox.tmp.$$
+Hi, this is a text dialog box. It can be used to display text from a file.
+The file should not contain any 'tab' characters, so you should 'expand'
+the file first if it contains 'tab' characters.
+
+It's like a simple text file viewer, with these keys implemented:
+
+PGDN/SPACE - Move down one page
+PGUP/'b' - Move up one page
+DOWN/'j' - Move down one line
+UP/'k' - Move up one line
+LEFT/'h' - Scroll left
+RIGHT/'l' - Scroll right
+'0' - Move to beginning of line
+HOME/'g' - Move to beginning of file
+END/'G' - Move to end of file
+'/' - Forward search
+'?' - Backward search
+'n' - Repeat last search (forward)
+'N' - Repeat last search (backward)
+
+
+The following is a sample text file:
+
+
+EOF
+
+cat ../COPYING | expand >> /tmp/textbox.tmp.$$
+
+$DIALOG --clear --title "TEXT BOX" --textbox "/tmp/textbox.tmp.$$" 22 77
+
+case $? in
+ 0)
+ echo "OK";;
+ 255)
+ echo "EXIT choosed.";;
+esac
+
+rm -f /tmp/textbox.tmp.$$
diff --git a/gnu/usr.bin/dialog/TESTS/treebox b/gnu/usr.bin/dialog/TESTS/treebox
new file mode 100755
index 0000000..c5a546f
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/treebox
@@ -0,0 +1,25 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --clear --title "TREE BOX" \
+ --hline "Press arrows, TAB or Enter" \
+ --hfile "../COPYING" \
+ --tree "/" \
+ "This is tree box" -1 -1 10 \
+ `find -x / -type d` 2>/tmp/tree.tmp.$$
+
+retval=$?
+
+choice=`cat /tmp/tree.tmp.$$`
+
+case $retval in
+ 0)
+ echo "'$choice' chosen.";;
+ 1)
+ echo "Cancel pressed.";;
+ 255)
+ [ -z "$choice" ] || echo $choice ;
+ echo "ESC pressed.";;
+esac
+
+rm -f /tmp/tree.tmp.$$
diff --git a/gnu/usr.bin/dialog/TESTS/yesno b/gnu/usr.bin/dialog/TESTS/yesno
new file mode 100755
index 0000000..36e95c8
--- /dev/null
+++ b/gnu/usr.bin/dialog/TESTS/yesno
@@ -0,0 +1,23 @@
+#!/bin/sh
+DIALOG=${DIALOG=/usr/bin/dialog}
+
+$DIALOG --title "YES/NO BOX" --clear \
+ --hline "Press F1 or ? to see GNU GPL" \
+ --hfile ../COPYING \
+ --yesno "Hi, this is a yes/no dialog box. You can use this to ask \
+ questions that have an answer of either yes or no. \
+ BTW, do you notice that long lines will be automatically \
+ wrapped around so that they can fit in the box? You can \
+ also control line breaking explicitly by inserting \
+ 'backslash n' at any place you like, but in this case, \
+ auto wrap around will be disabled and you will have to \
+ control line breaking yourself." 15 61
+
+case $? in
+ 0)
+ echo "Yes chosen.";;
+ 1)
+ echo "No chosen.";;
+ 255)
+ echo "ESC pressed.";;
+esac
diff --git a/gnu/usr.bin/dialog/dialog.1 b/gnu/usr.bin/dialog/dialog.1
new file mode 100644
index 0000000..c9da5c1
--- /dev/null
+++ b/gnu/usr.bin/dialog/dialog.1
@@ -0,0 +1,313 @@
+.TH DIALOG 1 "2 October 1998"
+.SH NAME
+dialog \- display dialog boxes from shell scripts
+.SH SYNOPSIS
+.B dialog --clear
+.br
+.BI "dialog --create-rc " file
+.br
+.B dialog
+[
+.BI "\-\-title " title
+]
+[
+.B \-\-clear
+]
+[
+.BI "\-\-hline " line
+]
+[
+.BI "\-\-hfile " file
+]
+.B box-options
+.SH DESCRIPTION
+.B Dialog
+is a program which allows you to present a variety of questions or
+display messages in dialog box form from a shell script. The following
+types of dialog objects are currently supported:
+.LP
+.BR yes/no " box," " menu" " box," " input" " box,"
+.BR message " box," " text" " box," " info" " box,"
+.BR checklist " box," " program" " box,"
+.BR ftree " and " tree " boxes."
+.SH OPTIONS
+.TP
+.B \-\-clear
+The screen will be cleared to the
+.BR "screen attribute" " on exit."
+.TP
+.BI \-\-create-rc " file"
+.RB "Since " dialog " supports run-time configuration,"
+this can be used to dump a sample configuration file to the file specified
+by
+.IR file "."
+.TP
+.BI \-\-title " title"
+Specifies a
+.I title
+string to be displayed at the top of the dialog box.
+.TP
+.BI \-\-hline " line"
+Specifies a
+.I line
+string to be displayed at the bottom of the dialog box.
+.TP
+.BI \-\-hfile " file"
+Specifies a
+.I file
+to be displayed by pressing ? or F1.
+.TP
+.B Box Options
+.TP
+.BI \-\-yesno " text height width"
+.RB A " yes/no" " dialog box of size"
+.I height
+rows by
+.I width
+columns will be displayed. The string specified by
+.I text
+is displayed inside the dialog box. If this string is too long to fit
+in one line, it will be automatically divided into multiple lines at
+the appropriate points. The
+.I text
+string may also contain the sub-string
+.I
+"\en"
+or newline characters
+.I `\en\'
+to control line breaking explicitly. This dialog box is useful for
+asking questions that require the user to answer either yes or no.
+.RB "The dialog box has a" " Yes" " button and a " No
+button, in which the user can switch between by pressing the
+.IR TAB " key."
+.TP
+.BI \-\-msgbox " text height width"
+.RB A " message" " box is very similar to a" " yes/no" " box."
+The only difference between a
+.B message
+box and a
+.B yes/no
+box is that a
+.B message
+box has only a single
+.B OK
+button. You can use this dialog box to display any message you like.
+After reading the message, the user can press the
+.I ENTER
+key so that
+.B dialog
+will exit and the calling shell script can continue its operation.
+.TP
+.BI \-\-infobox " text height width"
+.RB An " info" " box is basically a" " message" " box."
+However, in this case,
+.B dialog
+will exit immediately after displaying the message to the user. The
+screen is not cleared when
+.B dialog
+exits, so that the message will remain on the screen until the calling
+shell script clears it later. This is useful when you want to inform
+the user that some operations are carrying on that may require some
+time to finish.
+.TP
+.BI \-\-inputbox " text height width"
+.RB "An " input " box is useful when you want to ask questions that"
+require the user to input a string as the answer. When inputing the
+string, the
+.I BACKSPACE
+key can be used to correct typing errors. If the input string is longer than
+can be fitted in the dialog box, the input field will be scrolled. On exit,
+the input string will be printed on
+.IR stderr "."
+.TP
+.BI \-\-textbox " file height width"
+.RB A " text" " box lets you display the contents of a text file in a"
+dialog box. It is like a simple text file viewer. The user can move
+through the file by using the
+.IR UP/DOWN ", " PGUP/PGDN
+.RI and " HOME/END" " keys available on most keyboards."
+If the lines are too long to be displayed in the box, the
+.I LEFT/RIGHT
+keys can be used to scroll the text region horizontally. For more
+convenience, forward and backward searching functions are also provided.
+.IP "\fB\-\-menu \fItext height width menu-height \fR[ \fItag item \fR] \fI..."
+As its name suggests, a
+.B menu
+box is a dialog box that can be used to present a list of choices in
+the form of a menu for the user to choose. Each menu entry consists of a
+.IR tag " string and an " item " string. The"
+.I tag
+gives the entry a name to distinguish it from the other entries in the
+menu. The
+.I item
+is a short description of the option that the entry represents. The
+user can move between the menu entries by pressing the
+.I UP/DOWN
+keys, the first letter of the
+.I tag
+as a hot-key, or the number keys
+.IR 1-9 ". There are"
+.I menu-height
+entries displayed in the menu at one time, but the menu will be
+scrolled if there are more entries than that. When
+.B dialog
+exits, the
+.I tag
+of the chosen menu entry will be printed on
+.IR stderr "."
+.TP
+.BI \-\-prgbox " command height width"
+.RB A " program" " box lets you display output of command in"
+dialog box.
+.IP "\fB\-\-checklist \fItext height width list-height \fR[ \fItag item status \fR] \fI..."
+.RB "A " checklist " box is similar to a " menu " box in that there are"
+multiple entries presented in the form of a menu. Instead of choosing
+one entry among the entries, each entry can be turned on or off by the
+user. The initial on/off state of each entry is specified by
+.IR status "."
+On exit, a list of the
+.I tag
+strings of those entries that are turned on will be printed on
+.IR stderr "."
+.IP "\fB\-\-ftree \fIfile FS text height width menu-height"
+.B ftree
+box is a dialog box showing the tree described by the data from the file
+.IR file "."
+The data in the file should look like find(1) output. For the
+find output, the field separator
+.I FS
+will be
+.IR \'/\' ". If"
+.IR height " and"
+.IR width " are"
+positive numbers, they set the absolute size of the whole
+.BR ftree " box. If"
+.IR height " and"
+.IR width " are negative numbers, the size of the"
+.B ftree
+box will be
+selected automatically.
+.I menu-height
+sets the height of the tree subwindow inside the
+.B ftree
+box and must be set.
+.I text
+is shown inside the
+.B ftree
+box above the tree subwindow and can contain newline characters
+.I '\en\'
+to split lines. One can navigate in the tree by pressing
+.IR UP/DOWN " or " \'+\'/\'-\' ", " PG_UP/PG_DOWN " or " \'b\'/SPACE
+.RI "and " HOME/END " or " \'g\'/\'G\' "."
+A leaf of the tree is selected by pressing
+.IR TAB " or " LEFT/RIGHT
+the
+.B OK
+button and pressing
+.IR ENTER "."
+The selected leaf (to be more
+exact, the full path to it from the root of the tree) is printed to
+.IR stderr "."
+If
+.B Cancel
+and then
+.I ENTER
+is pressed, nothing is printed to
+.IR stderr "."
+.I file
+may contain data like find(1)
+output, as well as like the output of find(1) with
+.I -d
+option. Some of the transient paths to the leaves of the tree may be
+absent. Such data is corrected when fed from file.
+.IP "\fB\-\-tree \fIFS text height width menu-height \fR[ \fIitem \fR] \fI..."
+.B tree
+box is like
+.B ftree
+box with some exceptions. First, the data is not
+entered from a file, but from the command line as
+.I item item ...
+Second, the data thus entered is not corrected in any way.
+Thus, the data like the output of find(1) with
+.I -d
+option will look incorrectly.
+.SH "RUN-TIME CONFIGURATION"
+.TP 4
+1.
+Create a sample configuration file by typing:
+.LP
+.in +1i
+"dialog --create-rc <file>"
+.TP 4
+2.
+At start,
+.B dialog
+determines the settings to use as follows:
+.RS
+.TP 4
+a)
+if environment variable
+.B DIALOGRC
+is set, its value determines the name of the configuration file.
+.TP 4
+b)
+if the file in (a) can't be found, use the file
+.I $HOME/.dialogrc
+as the configuration file.
+.TP 4
+c)
+if the file in (b) can't be found, use compiled in defaults.
+.RE
+.TP 4
+3.
+Edit the sample configuration file and copy it to some place that
+.B dialog
+can find, as stated in step 2 above.
+.SH ENVIRONMENT
+.TP 15
+.B DIALOGRC
+Define this variable if you want to specify the name of the configuration file
+to use.
+.SH FILES
+.TP 20
+.I $HOME/.dialogrc
+default configuration file
+.SH DIAGNOSTICS
+Exit status is 0 if
+.BR dialog " is exited by pressing the " Yes " or " OK
+button, and 1 if the
+.BR No " or " Cancel
+button is pressed. Otherwise, if errors occur inside
+.B dialog
+or
+.B dialog
+is exited by pressing the
+.I ESC
+key, the exit status is -1.
+.SH SEE ALSO
+dialog(3)
+.SH BUGS
+Text files containing
+.I tab
+characters may cause problems with
+.B text
+box.
+.I Tab
+characters in text files must first be expanded to spaces before being
+.RB "displayed by " text " box."
+.sp 1
+Screen update is too slow.
+.sp 1
+The
+.B ftree
+and
+.B tree
+boxes do not allow the tree to be moved to the left or to
+the right. Thus, if there are many levels of data, some of the leaves can be
+rendered invisible. A standard display with 80 characters allows for 17
+levels to be visible. Deeper levels are invisible. However, the navigation
+in the tree and selection of leaves do work.
+.SH AUTHOR
+Savio Lam (lam836@cs.cuhk.hk)
+.sp 1
+Changes by Anatoly A. Orehovsky (tolik@mpeks.tomsk.su) (ftree and tree boxes)
diff --git a/gnu/usr.bin/dialog/dialog.c b/gnu/usr.bin/dialog/dialog.c
new file mode 100644
index 0000000..ecb4f1d
--- /dev/null
+++ b/gnu/usr.bin/dialog/dialog.c
@@ -0,0 +1,426 @@
+/*
+ * dialog - Display simple dialog boxes from shell scripts
+ *
+ * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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.
+ *
+ * $FreeBSD$
+ *
+ *
+ * HISTORY:
+ *
+ * 17/12/93 - Version 0.1 released.
+ *
+ * 19/12/93 - menu will now scroll if there are more items than can fit
+ * on the screen.
+ * - added 'checklist', a dialog box with a list of options that
+ * can be turned on or off. A list of options that are on is
+ * returned on exit.
+ *
+ * 20/12/93 - Version 0.15 released.
+ *
+ * 29/12/93 - Incorporated patch from Patrick J. Volkerding
+ * (volkerdi@mhd1.moorhead.msus.edu) that made these changes:
+ * - increased MAX_LEN to 2048
+ * - added 'infobox', equivalent to a message box without pausing
+ * - added option '--clear' that will clear the screen
+ * - Explicit line breaking when printing prompt text can be
+ * invoked by real newline '\n' besides the string "\n"
+ * - an optional parameter '--title <string>' can be used to
+ * specify a title string for the dialog box
+ *
+ * 03/01/94 - added 'textbox', a dialog box for displaying text from a file.
+ * - Version 0.2 released.
+ *
+ * 04/01/94 - some fixes and improvements for 'textbox':
+ * - fixed a bug that will cause a segmentation violation when a
+ * line is longer than MAX_LEN characters. Lines will now be
+ * truncated if they are longer than MAX_LEN characters.
+ * - removed wrefresh() from print_line(). This will increase
+ * efficiency of print_page() which calls print_line().
+ * - display current position in the form of percentage into file.
+ * - Version 0.21 released.
+ *
+ * 05/01/94 - some changes for faster screen update.
+ *
+ * 07/01/94 - much more flexible color settings. Can use all 16 colors
+ * (8 normal, 8 highlight) of the Linux console.
+ *
+ * 08/01/94 - added run-time configuration using configuration file.
+ *
+ * 09/01/94 - some minor bug fixes and cleanups for menubox, checklist and
+ * textbox.
+ *
+ * 11/01/94 - added a man page.
+ *
+ * 13/01/94 - some changes for easier porting to other Unix systems (tested
+ * on Ultrix, SunOS and HPUX)
+ * - Version 0.3 released.
+ *
+ * 08/06/94 - Patches by Stuart Herbert - S.Herbert@shef.ac.uk
+ * Fixed attr_clear and the textbox stuff to work with ncurses 1.8.5
+ * Fixed the wordwrap routine - it'll actually wrap properly now
+ * Added a more 3D look to everything - having your own rc file could
+ * prove 'interesting' to say the least :-)
+ * Added radiolist option
+ * - Version 0.4 released.
+ *
+ * 09/28/98 - Patches by Anatoly A. Orehovsky - tolik@mpeks.tomsk.su
+ * Added ftree and tree options
+ *
+ */
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <dialog.h>
+
+void Usage(char *name);
+
+int main(int argc, char *argv[])
+{
+ int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
+ unsigned char *title = NULL;
+ unsigned char result[MAX_LEN];
+ char *hline = NULL, *hfile = NULL;
+
+ if (argc < 2) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ else if (!strcmp(argv[1], "--create-rc")) {
+#ifdef HAVE_NCURSES
+ if (argc != 3) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ dialog_create_rc(argv[2]);
+ return 0;
+#else
+ fprintf(stderr, "\nThis option is currently unsupported on your system.\n");
+ return -1;
+#endif
+ }
+
+ while (offset < argc-1 && !end_common_opts) { /* Common options */
+ if (!strcmp(argv[offset+1], "--title")) {
+ if (argc-offset < 3 || title != NULL) { /* No two "--title" please! */
+ Usage(argv[0]);
+ exit(-1);
+ }
+ else {
+ title = argv[offset+2];
+ offset += 2;
+ }
+ }
+ else if (!strcmp(argv[offset+1], "--hline")) {
+ if (argc-offset < 3 || hline != NULL) { /* No two "--hline" please! */
+ Usage(argv[0]);
+ exit(-1);
+ }
+ else {
+ hline = argv[offset+2];
+ use_helpline(hline);
+ offset += 2;
+ }
+ }
+ else if (!strcmp(argv[offset+1], "--hfile")) {
+ if (argc-offset < 3 || hfile != NULL) { /* No two "--hfile" please! */
+ Usage(argv[0]);
+ exit(-1);
+ }
+ else {
+ hfile = argv[offset+2];
+ use_helpfile(hfile);
+ offset += 2;
+ }
+ }
+ else if (!strcmp(argv[offset+1], "--clear")) {
+ if (clear_screen) { /* Hey, "--clear" can't appear twice! */
+ Usage(argv[0]);
+ exit(-1);
+ }
+ else if (argc == 2) { /* we only want to clear the screen */
+ init_dialog();
+ dialog_update(); /* init_dialog() will clear the screen for us */
+ end_dialog();
+ return 0;
+ }
+ else {
+ clear_screen = 1;
+ offset++;
+ }
+ }
+ else /* no more common options */
+ end_common_opts = 1;
+ }
+
+ if (argc-1 == offset) { /* no more options */
+ Usage(argv[0]);
+ exit(-1);
+ }
+
+ /* Box options */
+
+ if (!strcmp(argv[offset+1], "--yesno")) {
+ if (argc-offset != 5) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_yesno(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]));
+
+ dialog_update();
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--msgbox")) {
+ if (argc-offset != 5) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_msgbox(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]), 1);
+
+ dialog_update();
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--prgbox")) {
+ if (argc-offset != 5) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_prgbox(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]), TRUE, TRUE);
+
+ dialog_update();
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return WEXITSTATUS(retval);
+ }
+ else if (!strcmp(argv[offset+1], "--infobox")) {
+ if (argc-offset != 5) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_msgbox(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]), 0);
+
+ dialog_update();
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--textbox")) {
+ if (argc-offset != 5) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_textbox(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]));
+
+ dialog_update();
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--menu")) {
+ if (argc-offset < 8 || ((argc-offset) % 2)) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_menu(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]), atoi(argv[offset+5]),
+ (argc-offset-6)/2, argv+offset + 6, result,
+ NULL, NULL);
+ dialog_update();
+ if (retval == 0)
+ fputs(result, stderr);
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--checklist")) {
+ if (argc-offset < 9 || ((argc-offset-6) % 3)) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_checklist(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]), atoi(argv[offset+5]),
+ (argc-offset-6)/3, argv+offset + 6, result);
+
+ dialog_update();
+ if (retval == 0) {
+ unsigned char *s, *h; int first;
+
+ h = result;
+ first = 1;
+ while ((s = strchr(h, '\n')) != NULL) {
+ *s++ = '\0';
+ if (!first)
+ fputc(' ', stderr);
+ else
+ first = 0;
+ fprintf(stderr, "\"%s\"", h);
+ h = s;
+ }
+ }
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--radiolist")) {
+ if (argc-offset < 9 || ((argc-offset-6) % 3)) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_radiolist(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]), atoi(argv[offset+5]),
+ (argc-offset-6)/3, argv+offset + 6, result);
+
+ dialog_update();
+ if (retval == 0)
+ fputs(result, stderr);
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--inputbox")) {
+ if (argc-offset != 5 && argc-offset != 6) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ if (argc-offset == 6)
+ strcpy(result, argv[offset+5]);
+ else
+ *result = '\0';
+ init_dialog();
+ retval = dialog_inputbox(title, argv[offset+2], atoi(argv[offset+3]),
+ atoi(argv[offset+4]), result);
+
+ dialog_update();
+ if (retval == 0)
+ fputs(result, stderr);
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+/* ftree and tree options */
+ else if (!strcmp(argv[offset+1], "--ftree")) {
+ unsigned char *tresult;
+ if (argc-offset != 8) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_ftree(argv[offset+2], *argv[offset+3],
+ title, argv[offset+4], atoi(argv[offset+5]), atoi(argv[offset+6]),
+ atoi(argv[offset+7]), &tresult);
+
+ dialog_update();
+ if (!retval)
+ {
+ fputs(tresult, stderr);
+ free(tresult);
+ }
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+ else if (!strcmp(argv[offset+1], "--tree")) {
+ unsigned char *tresult;
+ if (argc-offset < 8) {
+ Usage(argv[0]);
+ exit(-1);
+ }
+ init_dialog();
+ retval = dialog_tree((unsigned char **)argv+offset+7, argc-offset-7,
+ *argv[offset+2], title, argv[offset+3], atoi(argv[offset+4]),
+ atoi(argv[offset+5]), atoi(argv[offset+6]), &tresult);
+
+ dialog_update();
+ if (!retval)
+ fputs(tresult, stderr);
+
+ if (clear_screen) /* clear screen before exit */
+ dialog_clear();
+ end_dialog();
+ return retval;
+ }
+
+ Usage(argv[0]);
+ exit(-1);
+}
+/* End of main() */
+
+
+/*
+ * Print program usage
+ */
+void Usage(char *name)
+{
+ fprintf(stderr, "\
+\ndialog version 0.3, by Savio Lam (lam836@cs.cuhk.hk).\
+\n patched to version %s by Stuart Herbert (S.Herbert@shef.ac.uk)\
+\n Changes Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia\
+\n patched by Anatoly A. Orehovsky (tolik@mpeks.tomsk.su)\
+\n\
+\n* Display dialog boxes from shell scripts *\
+\n\
+\nUsage: %s --clear\
+\n %s --create-rc <file>\
+\n %s [--title <title>] [--clear] [--hline <line>] [--hfile <file>]\\\
+\n <Box options>\
+\n\
+\nBox options:\
+\n\
+\n --yesno <text> <height> <width>\
+\n --msgbox <text> <height> <width>\
+\n --prgbox \"<command line>\" <height> <width>\
+\n --infobox <text> <height> <width>\
+\n --inputbox <text> <height> <width> [<init string>]\
+\n --textbox <file> <height> <width>\
+\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\
+\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\
+\n --ftree <file> <FS> <text> <height> <width> <menu height>\
+\n --tree <FS> <text> <height> <width> <menu height> <item1>...\n", VERSION, name, name, name);
+}
+/* End of Usage() */
diff --git a/gnu/usr.bin/diff/Makefile b/gnu/usr.bin/diff/Makefile
new file mode 100644
index 0000000..be853a2
--- /dev/null
+++ b/gnu/usr.bin/diff/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../contrib/diff
+
+PROG= diff
+SRCS= analyze.c cmpbuf.c context.c diff.c dir.c ed.c getopt.c getopt1.c \
+ ifdef.c io.c normal.c prepend_args.c side.c util.c version.c
+
+# Important for ctype macros!
+CFLAGS+=-funsigned-char
+
+CFLAGS+=-I${.CURDIR}/../../../contrib/diff
+CFLAGS+=-DHAVE_CONFIG_H
+CFLAGS+=-DPR_PROGRAM=\"/usr/bin/pr\"
+
+SUBDIR+=doc
+
+DPADD+= ${LIBGNUREGEX}
+LDADD+= -lgnuregex
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/diff/diff.1 b/gnu/usr.bin/diff/diff.1
new file mode 100644
index 0000000..cbad443
--- /dev/null
+++ b/gnu/usr.bin/diff/diff.1
@@ -0,0 +1,496 @@
+.\" $FreeBSD$
+.TH DIFF 1 "22sep1993" "GNU Tools" "GNU Tools"
+.SH NAME
+diff \- find differences between two files
+.SH SYNOPSIS
+.B diff
+[options] from-file to-file
+.SH DESCRIPTION
+In the simplest case,
+.I diff
+compares the contents of the two files
+.I from-file
+and
+.IR to-file .
+A file name of
+.B \-
+stands for
+text read from the standard input. As a special case,
+.B "diff \- \-"
+compares a copy of standard input to itself.
+
+If
+.I from-file
+is a directory and
+.I to-file
+is not,
+.I diff
+compares the file in
+.I from-file
+whose file name is that of
+.IR to-file ,
+and vice versa. The non-directory file must not be
+.BR \- .
+
+If both
+.I from-file
+and
+.I to-file
+are directories,
+.I diff
+compares corresponding files in both directories, in
+alphabetical order; this comparison is not recursive unless the
+.B \-r
+or
+.B \-\-recursive
+option is given.
+.I diff
+never
+compares the actual contents of a directory as if it were a file. The
+file that is fully specified may not be standard input, because standard
+input is nameless and the notion of ``file with the same name'' does not
+apply.
+
+.B diff
+options begin with
+.BR \- ,
+so normally
+.I from-file
+and
+.I to-file
+may not begin with
+.BR \- .
+However,
+.B \-\-
+as an
+argument by itself treats the remaining arguments as file names even if
+they begin with
+.BR \- .
+.SS Options
+Below is a summary of all of the options that GNU
+.I diff
+accepts.
+Most options have two equivalent names, one of which is a single letter
+preceded by
+.BR \- ,
+and the other of which is a long name preceded by
+.BR \-\- .
+Multiple single letter options (unless they take an
+argument) can be combined into a single command line word:
+.B \-ac
+is
+equivalent to
+.BR "\-a \-c" .
+Long named options can be abbreviated to
+any unique prefix of their name. Brackets
+.RB ( [
+and
+.BR ] )
+indicate that an
+option takes an optional argument.
+.TP
+.BI \- lines
+Show
+.I lines
+(an integer) lines of context. This option does not
+specify an output format by itself; it has no effect unless it is
+combined with
+.B \-c
+or
+.BR \-u .
+This option is obsolete. For proper
+operation,
+.I patch
+typically needs at least two lines of context.
+.TP
+.B \-a
+Treat all files as text and compare them line-by-line, even if they
+do not seem to be text.
+.TP
+.B \-b
+Ignore changes in amount of white space.
+.TP
+.B \-B
+Ignore changes that just insert or delete blank lines.
+.TP
+.B \-\-brief
+Report only whether the files differ, not the details of the
+differences.
+.TP
+.B \-c
+Use the context output format.
+.TP
+.BI "\-C " lines
+.br
+.ns
+.TP
+.BI \-\-context[= lines ]
+Use the context output format, showing
+.I lines
+(an integer) lines of
+context, or three if
+.I lines
+is not given.
+For proper operation,
+.I patch
+typically needs at least two lines of
+context.
+.TP
+.BI \-\-changed\-group\-format= format
+Use
+.I format
+to output a line group containing differing lines from
+both files in if-then-else format.
+.TP
+.B \-d
+Change the algorithm to perhaps find a smaller set of changes. This makes
+.I diff
+slower (sometimes much slower).
+.TP
+.BI "\-D " name
+Make merged if-then-else format output, conditional on the preprocessor
+macro
+.IR name .
+.TP
+.B \-e
+.br
+.ns
+.TP
+.B \-\-ed
+Make output that is a valid
+.I ed
+script.
+.TP
+.BI \-\-exclude= pattern
+When comparing directories, ignore files and subdirectories whose basenames
+match
+.IR pattern .
+.TP
+.BI \-\-exclude\-from= file
+When comparing directories, ignore files and subdirectories whose basenames
+match any pattern contained in
+.IR file .
+.TP
+.B \-\-expand\-tabs
+Expand tabs to spaces in the output, to preserve the alignment of tabs
+in the input files.
+.TP
+.B \-f
+Make output that looks vaguely like an
+.I ed
+script but has changes
+in the order they appear in the file.
+.TP
+.BI "\-F " regexp
+In context and unified format, for each hunk of differences, show some
+of the last preceding line that matches
+.IR regexp .
+.TP
+.B \-\-forward\-ed
+Make output that looks vaguely like an
+.B ed
+script but has changes
+in the order they appear in the file.
+.TP
+.B \-h
+This option currently has no effect; it is present for Unix
+compatibility.
+.TP
+.B \-H
+Use heuristics to speed handling of large files that have numerous
+scattered small changes.
+.TP
+.BI \-\-horizon\-lines= lines
+Do not discard the last
+.I lines
+lines of the common prefix
+and the first
+.I lines
+lines of the common suffix.
+.TP
+.B \-i
+Ignore changes in case; consider upper- and lower-case letters
+equivalent.
+.TP
+.BI "\-I " regexp
+Ignore changes that just insert or delete lines that match
+.IR regexp .
+.TP
+.BI \-\-ifdef= name
+Make merged if-then-else format output, conditional on the preprocessor
+macro
+.IR name .
+.TP
+.B \-\-ignore\-all\-space
+Ignore white space when comparing lines.
+.TP
+.B \-\-ignore\-blank\-lines
+Ignore changes that just insert or delete blank lines.
+.TP
+.B \-\-ignore\-case
+Ignore changes in case; consider upper- and lower-case to be the same.
+.TP
+.BI \-\-ignore\-matching\-lines= regexp
+Ignore changes that just insert or delete lines that match
+.IR regexp .
+.TP
+.B \-\-ignore\-space\-change
+Ignore changes in amount of white space.
+.TP
+.B \-\-initial\-tab
+Output a tab rather than a space before the text of a line in normal or
+context format. This causes the alignment of tabs in the line to look
+normal.
+.TP
+.B \-l
+Pass the output through
+.I pr
+to paginate it.
+.TP
+.BI "\-L " label
+.br
+.ns
+.TP
+.BI \-\-label= label
+Use
+.I label
+instead of the file name in the context format
+and unified format
+headers.
+.TP
+.B \-\-left\-column
+Print only the left column of two common lines in side by side format.
+.TP
+.BI \-\-line\-format= format
+Use
+.I format
+to output all input lines in in-then-else format.
+.TP
+.B \-\-minimal
+Change the algorithm to perhaps find a smaller set of changes. This
+makes
+.I diff
+slower (sometimes much slower).
+.TP
+.B \-n
+Output RCS-format diffs; like
+.B \-f
+except that each command
+specifies the number of lines affected.
+.TP
+.B \-N
+.br
+.ns
+.TP
+.B \-\-new\-file
+In directory comparison, if a file is found in only one directory,
+treat it as present but empty in the other directory.
+.TP
+.BI \-\-new\-group\-format= format
+Use
+.I format
+to output a group of lines taken from just the second
+file in if-then-else format.
+.TP
+.BI \-\-new\-line\-format= format
+Use
+.I format
+to output a line taken from just the second file in
+if-then-else format.
+.TP
+.B \-o
+Use the old traditional output format.
+.TP
+.BI \-\-old\-group\-format= format
+Use
+.I format
+to output a group of lines taken from just the first
+file in if-then-else format.
+.TP
+.BI \-\-old\-line\-format= format
+Use
+.I format
+to output a line taken from just the first file in
+if-then-else format.
+.TP
+.B \-P
+When comparing directories, if a file appears only in the second
+directory of the two, treat it as present but empty in the other.
+.TP
+.B \-\-paginate
+Pass the output through
+.I pr
+to paginate it.
+.TP
+.B \-q
+Report only whether the files differ, not the details of the
+differences.
+.TP
+.B \-\-rcs
+Output RCS-format diffs; like
+.B \-f
+except that each command
+specifies the number of lines affected.
+.TP
+.B \-r
+.br
+.ns
+.TP
+.B \-\-recursive
+When comparing directories, recursively compare any subdirectories
+found.
+.TP
+.B \-s
+.br
+.ns
+.TP
+.B \-\-report\-identical\-files
+Report when two files are the same.
+.TP
+.BI "\-S " file
+When comparing directories, start with the file
+.IR file .
+This is
+used for resuming an aborted comparison.
+.TP
+.B \-\-sdiff\-merge\-assist
+Print extra information to help
+.IR sdiff .
+.I sdiff
+uses this
+option when it runs
+.IR diff .
+This option is not intended for users
+to use directly.
+.TP
+.B \-\-show\-c\-function
+Show which C function each change is in.
+.TP
+.BI \-\-show\-function\-line= regexp
+In context and unified format, for each hunk of differences, show some
+of the last preceding line that matches
+.IR regexp .
+.TP
+.B \-\-side\-by\-side
+Use the side by side output format.
+.TP
+.B \-\-speed\-large\-files
+Use heuristics to speed handling of large files that have numerous
+scattered small changes.
+.TP
+.BI \-\-starting\-file= file
+When comparing directories, start with the file
+.IR file .
+This is
+used for resuming an aborted comparison.
+.TP
+.B \-\-suppress\-common\-lines
+Do not print common lines in side by side format.
+.TP
+.B \-t
+Expand tabs to spaces in the output, to preserve the alignment of tabs
+in the input files.
+.TP
+.B \-T
+Output a tab rather than a space before the text of a line in normal or
+context format. This causes the alignment of tabs in the line to look
+normal.
+.TP
+.B \-\-text
+Treat all files as text and compare them line-by-line, even if they
+do not appear to be text.
+.TP
+.B \-u
+Use the unified output format.
+.TP
+.BI \-\-unchanged\-group\-format= format
+Use
+.I format
+to output a group of common lines taken from both files
+in if-then-else format.
+.TP
+.BI \-\-unchanged\-line\-format= format
+Use
+.I format
+to output a line common to both files in if-then-else
+format.
+.TP
+.B \-\-unidirectional\-new\-file
+When comparing directories, if a file appears only in the second
+directory of the two, treat it as present but empty in the other.
+.TP
+.BI "\-U " lines
+.br
+.ns
+.TP
+.BI \-\-unified[= lines ]
+Use the unified output format, showing
+.I lines
+(an integer) lines of
+context, or three if
+.I lines
+is not given.
+For proper operation,
+.I patch
+typically needs at least two lines of
+context.
+.TP
+.B \-v
+.br
+.ns
+.TP
+.B \-\-version
+Output the version number of
+.IR diff .
+.TP
+.B \-w
+Ignore horizontal white space when comparing lines.
+.TP
+.BI "\-W " columns
+.br
+.ns
+.TP
+.BI \-\-width= columns
+Use an output width of
+.I columns
+in side by side format.
+.TP
+.BI "\-x " pattern
+When comparing directories, ignore files and subdirectories whose basenames
+match
+.IR pattern .
+.TP
+.BI "\-X " file
+When comparing directories, ignore files and subdirectories whose basenames
+match any pattern contained in
+.IR file .
+.TP
+.B \-y
+Use the side by side output format.
+.SH ENVIRONMENT
+The environment variable
+.B DIFF_OPTIONS
+can hold a set of default
+options for
+.I diff.
+These options are interpreted first and can be overwritten by explicit command
+line parameters.
+.SH EXAMPLES
+To save to a file some changes that you have made to your local source
+tree (possibly including new files), which you would like to show to others
+(perhaps using the
+.B send-pr(1)
+program), you could type
+.sp
+diff -crN foo.orig foo >foo.diff
+.sp
+where
+.I foo.orig
+and
+.I foo
+might be directory hierarchies or single files.
+.SH SEE ALSO
+cmp(1), comm(1), diff3(1), ed(1), patch(1), pr(1), sdiff(1).
+.SH DIAGNOSTICS
+An exit status of 0 means no differences were found, 1 means some
+differences were found, and 2 means trouble.
diff --git a/gnu/usr.bin/diff/doc/Makefile b/gnu/usr.bin/diff/doc/Makefile
new file mode 100644
index 0000000..973dbcc
--- /dev/null
+++ b/gnu/usr.bin/diff/doc/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+INFO = diff
+
+INFOENTRY_diff= "* DIFF: (diff). DIFF/PATCH Reference Manual."
+
+SRCDIR=${.CURDIR}/../../../../contrib/diff
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/diff3/Makefile b/gnu/usr.bin/diff3/Makefile
new file mode 100644
index 0000000..1acd314
--- /dev/null
+++ b/gnu/usr.bin/diff3/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../contrib/diff
+
+PROG= diff3
+SRCS= diff3.c getopt.c getopt1.c version.c
+
+# Important for ctype macros!
+CFLAGS+=-funsigned-char
+
+CFLAGS+=-I${.CURDIR}/../../../contrib/diff
+CFLAGS+=-DHAVE_CONFIG_H
+CFLAGS+=-DDIFF_PROGRAM=\"/usr/bin/diff\"
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/diff3/diff3.1 b/gnu/usr.bin/diff3/diff3.1
new file mode 100644
index 0000000..9873b08
--- /dev/null
+++ b/gnu/usr.bin/diff3/diff3.1
@@ -0,0 +1,210 @@
+.TH DIFF3 1 "22sep1993" "GNU Tools" "GNU Tools"
+.SH NAME
+diff3 \- find differences between three files
+.SH SYNOPSIS
+.B diff3
+[options] mine older yours
+.SH DESCRIPTION
+The
+.I diff3
+command compares three files and outputs descriptions
+of their differences.
+
+The files to compare are
+.IR mine ,
+.IR older ,
+and
+.IR yours .
+At most one of these three file names may be
+.BR \- ,
+which tells
+.I diff3
+to read the standard input for that file.
+.SS Options
+Below is a summary of all of the options that GNU
+.I diff3
+accepts. Multiple single letter options (unless they take an argument)
+can be combined into a single command line argument.
+.TP
+.B \-a
+Treat all files as text and compare them line-by-line, even if they
+do not appear to be text.
+.TP
+.B \-A
+Incorporate all changes from
+.I older
+to
+.I yours
+into
+.IR mine ,
+surrounding all conflicts with bracket lines.
+.TP
+.B \-B
+Old behavior of -A. Shows non-conflicts.
+.TP
+.B \-e
+Generate an
+.I ed
+script that incorporates all the changes from
+.I older
+to
+.I yours
+into
+.IR mine .
+.TP
+.B \-E
+Like
+.BR \-e ,
+except bracket lines from overlapping changes' first
+and third files.
+With
+.BR \-e ,
+an overlapping change looks like this:
+.sp
+.nf
+<<<<<<< \fImine\fP
+lines from \fImine\fP
+=======
+lines from \fIyours\fP
+>>>>>>> \fIyours\fP
+.fi
+.TP
+.B \-\-ed
+Generate an
+.I ed
+script that incorporates all the changes from
+.I older
+to
+.I yours
+into
+.IR mine .
+.TP
+.B \-\-easy\-only
+Like
+.BR \-e ,
+except output only the nonoverlapping changes.
+.TP
+.B \-i
+Generate
+.B w
+and
+.B q
+commands at the end of the
+.I ed
+script for System V compatibility. This option must be combined with
+one of the
+.B \-AeExX3
+options, and may not be combined with
+.BR \-m .
+.TP
+.B \-\-initial\-tab
+Output a tab rather than two spaces before the text of a line in normal format.
+This causes the alignment of tabs in the line to look normal.
+.TP
+.BI "\-L " label
+.ns
+.TP
+.BI \-\-label= label
+Use the label
+.I label
+for the brackets output by the
+.BR \-A ,
+.B \-E
+and
+.B \-X
+options. This option may be given up to three
+times, one for each input file. The default labels are the names of
+the input files. Thus
+.B "diff3 \-L X \-L Y \-L Z \-m A B C"
+acts like
+.BR "diff3 \-m A B C ,
+except that the output looks like it came from
+files named
+.BR X ,
+.B Y
+and
+.B Z
+rather than from files
+named
+.BR A ,
+.B B
+and
+.BR C .
+.TP
+.B \-m
+.br
+.ns
+.TP
+.B \-\-merge
+Apply the edit script to the first file and send the result to standard
+output. Unlike piping the output from
+.I diff3
+to
+.IR ed ,
+this
+works even for binary files and incomplete lines.
+.B \-A
+is assumed
+if no edit script option is specified.
+.TP
+.B \-\-overlap\-only
+Like
+.BR \-e ,
+except output only the overlapping changes.
+.TP
+.B \-\-show\-all
+Incorporate all unmerged changes from
+.I older
+to
+.I yours
+into
+.IR mine ,
+surrounding all overlapping changes with bracket lines.
+.TP
+.B \-\-show\-overlap
+Like
+.BR \-e ,
+except bracket lines from overlapping changes' first
+and third files.
+.TP
+.B \-T
+Output a tab rather than two spaces before the text of a line in normal format.
+This causes the alignment of tabs in the line to look normal.
+.TP
+.B \-\-text
+Treat all files as text and compare them line-by-line, even if they
+do not appear to be text.
+.TP
+.B \-v
+.br
+.ns
+.TP
+.B \-\-version
+Output the version number of
+.IR diff3 .
+.TP
+.B \-x
+Like
+.BR \-e ,
+except output only the overlapping changes.
+.TP
+.B \-X
+Like
+.BR \-E ,
+except output only the overlapping changes.
+In other words, like
+.BR \-x ,
+except bracket changes as in
+.BR \-E .
+.TP
+.B \-3
+Like
+.BR \-e ,
+except output only the nonoverlapping changes.
+.SH SEE ALSO
+cmp(1), comm(1), diff(1), ed(1), patch(1), sdiff(1).
+.SH DIAGNOSTICS
+An exit status of 0 means
+.I diff3
+was successful, 1 means some
+conflicts were found, and 2 means trouble.
diff --git a/gnu/usr.bin/gdb/doc/inc-hist.diff b/gnu/usr.bin/gdb/doc/inc-hist.diff
new file mode 100644
index 0000000..721db26
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/inc-hist.diff
@@ -0,0 +1,31 @@
+$FreeBSD$
+
+--- inc-hist.texi.orig Wed Apr 11 08:20:01 2001
++++ inc-hist.texi Wed Apr 11 08:21:57 2001
+@@ -26,9 +26,9 @@
+ @node Using History Interactively
+ @chapter Using History Interactively
+
+-@ifclear BashFeatures
+-@defcodeindex bt
+-@end ifclear
++@c @ifclear BashFeatures
++@c @defcodeindex bt
++@c @end ifclear
+
+ @ifset BashFeatures
+ This chapter describes how to use the @sc{gnu} History Library
+@@ -39,9 +39,10 @@
+ @end ifset
+ @ifclear BashFeatures
+ This chapter describes how to use the @sc{gnu} History Library interactively,
+-from a user's standpoint. It should be considered a user's guide. For
+-information on using the @sc{gnu} History Library in your own programs,
+-@pxref{Programming with GNU History}.
++from a user's standpoint.
++@c It should be considered a user's guide. For
++@c information on using the @sc{gnu} History Library in your own programs,
++@c @pxref{Programming with GNU History}.
+ @end ifclear
+
+ @ifset BashFeatures
diff --git a/gnu/usr.bin/gperf/Makefile b/gnu/usr.bin/gperf/Makefile
new file mode 100644
index 0000000..06cce05
--- /dev/null
+++ b/gnu/usr.bin/gperf/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+GPROFDIR= ${.CURDIR}/../../../contrib/gperf
+
+.PATH: ${GPROFDIR}/src ${GPROFDIR}/lib ${GPROFDIR}/doc
+
+SUBDIR= doc
+
+PROG_CXX= gperf
+SRCS= bool-array.cc gen-perf.cc hash-table.cc iterator.cc key-list.cc \
+ list-node.cc main.cc new.cc options.cc read-line.cc trace.cc \
+ vectors.cc version.cc
+SRCS+= hash.cc getopt.c getopt1.c
+
+CXXFLAGS+= -I${GPROFDIR}/lib -I${.CURDIR}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/gperf/config.h b/gnu/usr.bin/gperf/config.h
new file mode 100644
index 0000000..464005e
--- /dev/null
+++ b/gnu/usr.bin/gperf/config.h
@@ -0,0 +1,21 @@
+/* $FreeBSD$ */
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if the C++ compiler supports "throw ()" declarations. */
+#define HAVE_THROW_DECL 1
+
+/* Define if you have the getrlimit function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define if you have the setrlimit function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
diff --git a/gnu/usr.bin/gperf/doc/Makefile b/gnu/usr.bin/gperf/doc/Makefile
new file mode 100644
index 0000000..1c0ec79
--- /dev/null
+++ b/gnu/usr.bin/gperf/doc/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+INFO = gperf
+INFOSECTION= "Programming & development tools."
+INFOENTRY_gperf= "* Gperf: (gperf). The GNU perfect hash function generator."
+
+SRCDIR= ${.CURDIR}/../../../../contrib/gperf/doc
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/grep/AUTHORS b/gnu/usr.bin/grep/AUTHORS
new file mode 100644
index 0000000..65ff8a1
--- /dev/null
+++ b/gnu/usr.bin/grep/AUTHORS
@@ -0,0 +1,41 @@
+Mike Haertel wrote the main program and the dfa and kwset matchers.
+
+Arthur David Olson contributed the heuristics for finding fixed substrings
+at the end of dfa.c.
+
+Richard Stallman and Karl Berry wrote the regex backtracking matcher.
+
+Henry Spencer wrote the original test suite from which grep's was derived.
+
+Scott Anderson invented the Khadafy test.
+
+David MacKenzie wrote the automatic configuration software use to
+produce the configure script.
+
+Authors of the replacements for standard library routines are identified
+in the corresponding source files.
+
+The idea of using Boyer-Moore type algorithms to quickly filter out
+non-matching text before calling the regexp matcher was originally due
+to James Woods. He also contributed some code to early versions of
+GNU grep.
+
+Mike Haertel would like to thank Andrew Hume for many fascinating discussions
+of string searching issues over the years. Hume & Sunday's excellent
+paper on fast string searching (AT&T Bell Laboratories CSTR #156)
+describes some of the history of the subject, as well as providing
+exhaustive performance analysis of various implementation alternatives.
+The inner loop of GNU grep is similar to Hume & Sunday's recommended
+"Tuned Boyer Moore" inner loop.
+
+More work was done on regex.[ch] by Ulrich Drepper and Arnold
+Robbins. Regex is now part of GNU C library, see this package
+for complete details and credits.
+
+Arnold Robbins contributed to improve dfa.[ch]. In fact
+it came straight from gawk-3.0.3 with small editing and fixes.
+
+Many folks contributed see THANKS, if I omited someone please
+send me email.
+
+Alain Magloire is the current maintainer.
diff --git a/gnu/usr.bin/grep/COPYING b/gnu/usr.bin/grep/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/gnu/usr.bin/grep/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) <year> <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) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/grep/ChangeLog b/gnu/usr.bin/grep/ChangeLog
new file mode 100644
index 0000000..1e279c3
--- /dev/null
+++ b/gnu/usr.bin/grep/ChangeLog
@@ -0,0 +1,1426 @@
+2000-01-28 Alain Magloire
+
+ * src/grep.c (usage): The example "%s -i 'hello.*world' could
+ lead to confusion when progname is 'fgrep.
+ Noted by Akim Demaille.
+
+ * configure.in: Reenable, jm_INCLUDE_REGEX() since we now
+ track GNU lib C.
+ * src/Makefile.am: EXTRA_DIST new macros with regex.c regex.h.
+ Requested By Ulrich Drepper.
+
+2000-01-25 Paul Eggert
+
+ * src/grep.c (grep): If the final byte of an input file is not
+ a newline, grep now silently supplies one.
+ * doc/grep.texi, NEWS: Likewise.
+
+2000-01-25 Paul Eggert
+
+ * NEWS, doc/grep.1, doc/grep.texi: Add -I option.
+ * src/grep.c (short_options, usage, main): Likewise.
+
+ * doc/grep.texi: Fix some incorrect references to ASCII.
+
+2000-01-25 Paul Eggert
+
+ * doc/grep.1: Simplify synopsis; sort options; mention
+ environment variables; clean up some minor gaffes.
+
+2000-01-25 Paul Eggert
+
+ * doc/grep.texi:
+ Fix some errors in description of [:print:] and the like.
+
+2000-01-23 Paul Eggert
+
+ * src/dfa.c (FETCH, lex): Put brackets around if-body to avoid
+ GCC warning about ambiguous if-then-else.
+
+2000-01-23 Paul Eggert
+
+ * src/regex.c (GET_UNSIGNED_NUMBER): Allow only ASCII digits.
+ * src/dfa.c (ISASCIIDIGIT): New macro.
+ (lex): Use it instead of ISDIGIT.
+
+2000-01-23 Paul Eggert
+
+ The bug is that regular expression ranges like [a-z] compare raw
+ byte codes to the range boundaries, whereas POSIX says that they
+ should use the current collating sequence instead. For example,
+ in Solaris 7 with LC_ALL=en_US, the command
+ echo x | grep '[ -~]'
+ outputs 'x', but it shouldn't output anything since ' ' and '~'
+ sort before all letters in that locale.
+
+ * src/regex.c (compile_range): When matching a character
+ range, use the current collating sequence, as POSIX requires.
+ * src/dfa.c (lex): Likewise.
+
+2000-01-20 Alain Magloire
+
+ * tests/Makefile.am (dist-hook): Added new rule to make sure
+ that the shell scripts have the right permissions.
+ * src/posix/Makefile.am (EXTRA_DIST): added regex.h in the
+ distribution.
+ * THANKS: updated.
+
+2000-01-18 Alain Magloire
+
+ * Rectification the initial patch to add --binary-file option
+ was done by Ruslan Ermilov.
+
+2000-01-17 Paul Eggert
+
+ Sync with sources of fileutils 4.0n, tar 1.13.17, glibc 2.1.3a1.
+ Convert to ANSI C prototypes (using ansi2knr for backwards
+ compatibility), as this makes it easier to sync.
+
+ * configure.in (AC_OBJEXT): Spell in a funny way, to work around
+ a bug in automake 1.4 with ansi2knr.
+ (LIBOBJS): Add assignment so that .o files in LIBOBJS are also built
+ via the ANSI2KNR-filtering rules.
+ (AC_OUTPUT): Add src/posix/Makefile.
+ * src/Makefile.am (AUTOMAKE_OPTIONS): Add ansi2knr.
+ (SUBDIRS): New macro.
+ * src/ansi2knr.1, src/ansi2knr.c, src/posix/Makefile.am: New files.
+ * src/dfa.c, src/dosbuf.c, src/grep.c, src/kwset.c, src/search.c,
+ src/vms_fab.c:
+ Use prototypes for function definitions.
+ * src/grep.c (main): Use int counter for default context,
+ fixing an ANSI portability bug uncovered by the above changes.
+
+ * config.guess, config.sub, install-sh, missing, src/alloca.c,
+ src/getpagesize.h, src/memchr.c, src/savedir.c, src/savedir.h,
+ src/stpcpy.c:
+ Upgrade to latest version from fileutils 4.0n.
+
+ * src/getopt.c, src/getopt.h, src/getopt1.c: Upgrade to latest
+ version from tar 1.13.17.
+
+ * src/obstack.c, src/obstack.h, src/regex.c, src/regex.h:
+ Upgrade to glibc 2.1.3 alpha 1, with K&R C portability fix.
+ * src/posix/regex.h: New file, from glibc 2.1.3 alpha 1.
+
+2000-01-04 Paul Eggert
+
+ Inititial patch from David O'Brien.
+
+ Add --binary-files option.
+ * NEWS, doc/grep.1, doc/grep.texi: Document it.
+ * src/grep.c (BINARY_FILES_OPTION): New constant.
+ (long_options, grep, usage, main): New --binary-files option.
+ (binary_files): New var.
+ * src/system.h (TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM, CHAR_MAX):
+ New macros.
+ (INT_MAX, UCHAR_MAX): Define in terms of TYPE_MAXIMUM.
+
+2000-01-04 Paul Eggert
+
+ * savedir.c (savedir): Don't store past the end of an array if
+ name_size is zero and the directory is empty.
+ Reported by Dima Barsky <dima@pwd.hp.com>.
+
+1999-11-18 Paul Eggert
+
+ * m4/largefile.m4 (AC_SYS_LARGEFILE_FLAGS): Work around a
+ problem with the QNX 4.25 shell, which doesn't propagate exit
+ status of failed commands inside shell assignments.
+
+1999-11-13 Eli Zaretskii
+
+ * doc/grep.texi: Minor markup and spelling corrections. Use
+ @noindent where appropriate.
+
+ * PATCHES-{AM,AC}: rename to PATCHES.{AM,AC}
+
+1999-11-12 Eli Zaretskii
+
+ doc/grep.texi: Minor fixes and typos corrected.
+ djgpp/README: Updated version.
+
+1999-11-07 Paul Eggert
+
+ * src/grep.c (usage): Fix misspelling.
+
+1999-11-07 Paul Eggert
+
+ Don't assume that the C library has re_set_syntax and friends.
+ * src/Makefile.am (base_sources): Add regex.c, regex.h.
+ (EXTRA_DIST): Remove regex.c, regex.h.
+
+ * src/grep.c (prtext): Use out_quiet, not not_text, to decide
+ whether to set pending to zero at the end.
+ (not_text): Remove static variable, undoing latest change.
+ (grep): Likewise.
+
+ * doc/grep.texi: Tighten up the text, and fix some minor
+ spelling and usage errors. Use @enumerate rather than @table
+ @samp, since it's better for Q&A format. Add cross
+ references.
+
+1999-11-01 Alain Magloire
+
+ * src/search.c: Use the more portable [[:alnum:]]
+ to define a word instead of Ascii dependent [0-9A-Za-z]
+ * src/grep.c: make not_text global to not display text when
+ the context switches -A/-B/-C are use on binary files.
+ * make grep-2.3g available for testing.
+ * configure.in: drop support for --without-included-regex.
+ This was generating bogus bug reports, since many GNU/Linux
+ users have different version of glibc. And glibc maintainers
+ decided to drop k&r support.
+
+1999-11-01 Arnold D. Robbins
+
+ * regex.c (init_syntax_once): move below definition of
+ ISALNUM etc., then use ISALNUM to init the table, so that
+ the word ops will work if i18n'ed.
+ (SYNTAX): And subscript with 0xFF for Latin-1 characters.
+
+1999-10-26 Alain Magloire
+
+ * src/regex.c: Merge changes from GNU lib C.
+ * Updated the *.po files
+
+1999-10-26 Paul Eggert
+
+ * src/grep.c (fillbuf): Don't report buffer size overflow if
+ newalloc == save and maxalloc == save. This can happen
+ e.g. when reading a large page-aligned file that contains
+ no newlines.
+
+1999-10-21 Paul Eggert
+
+ * src/grep.c (usage): Give example. Clarify -F.
+ Explain exit status more clearly.
+
+1999-10-12 Paul Eggert
+
+ * doc/grep.texi: Shorten the commentary about egrep and {.
+ "BSD grep" -> "traditional grep".
+ * doc/grep.1: Match recent changes to grep.texi.
+
+1999-10-11 Paul Eggert
+
+ * NEWS, doc/grep.1, doc/grep.texi: New option --mmap.
+ * src/grep.c (mmap_option): New variable.
+ (long_options, reset, usage): Add --mmap.
+ Default is now read, not mmap.
+
+ * doc/grep.1: Document -Z or --null.
+
+1999-10-11 Paul Eggert
+
+ * doc/grep.texi: Fix texinfo glitches. POSIX -> POSIX.2 where
+ appropriate.
+
+1999-10-11 Paul Eggert
+
+ * acconfig.h (ssize_t): New #undef.
+
+ * configure.in (AC_CHECK_TYPE): Add ssize_t.
+
+ * src/grep.c (PREFERRED_SAVE_FACTOR): New macro.
+ (reset): If the buffer has already been allocated, set bufsalloc to
+ be bufalloc / PREFERRED_SAVE_FACTOR. This avoids problems when
+ bufsalloc == bufalloc (possible after reading a large binary file).
+ (reset): Use PREFERRED_SAVE_FACTOR instead of magic constant.
+ Do not set bufbeg; nobody uses it.
+ Always set buflim.
+ Check for lseek error.
+ Use SEEK_CUR, not a magic constant.
+ (fillbuf): Return an error indication, not a count.
+ All callers changed.
+ Do not assume ssize_t fits in int.
+ Use PREFERRED_SAVE_FACTOR instead of magic constant.
+ Clean up mmap code.
+ Do not attempt to mmap zero bytes.
+ Check for lseek error.
+ Use SEEK_SET, not a magic constant.
+ Work correctly if read is interrupted.
+ (grepfile): Work correctly if open or close is interrupted.
+
+ * src/system.h (SEEK_SET, SEEK_CUR): New macros.
+
+1999-10-02 Alain Magloire
+
+ * src/regex.[ch]: upgrade from GNU lib C source tree.
+
+ * make beta 2.3f available.
+
+1999-10-02 Paul Eggert
+
+ * NEWS: egrep is now equivalent to `grep -E'.
+ The lower bound of an interval is not optional.
+ You can specify a matcher multiple types without error.
+ -u and -U are now allowed on non-DOS hosts, and have no effect.
+ * doc/grep.texi: Likewise.
+ * doc/grep.1: Likewise.
+ Fix some troff bugs that prevented `groff' from rendering the page.
+
+ * src/egrepmat.c, src/fgrepmat.c, src/grepmat.c (default_matcher):
+ Remove.
+ (matcher): Add.
+ * src/grep.h (default_matcher): Remove.
+ (matcher): Now exported from ?grepmat.c, not grep.c.
+
+ * src/dfa.c (lex): If { would start an invalid interval specification,
+ treat it as a normal character.
+ Remove (broken) support for {,M} meaning {0,M}.
+ Diagnose bogus intervals like {1,0}.
+ (closure): maxrep is now -1 to indicate no limit, not zero;
+ zero is a valid value for maxrep, meaning an upper bound of zero.
+
+ * src/grep.c (short_options): New constant.
+ (long_options, main): -u and -U are now supported on Unix,
+ with no effect.
+ (matcher): Removed; now defined by ?grepmat.c.
+ (install_matcher): Renamed from setmatcher.
+ (setmatcher): New function.
+ (usage): Report new, more uniform option scheme.
+ (main): Do not initialize matcher; ?grepmat.c now does this.
+ Rely on setmatcher to catch matcher conflicts.
+ Default matcher is "grep".
+
+ * src/search.c (matchers):
+ Remove "posix-egrep" matcher; no longer needed.
+ (Ecompile): Likewise.
+ The egrep matcher now has POSIX behavior.
+
+ * tests/bre.tests: grep '\{' is no longer an error.
+ Fix test for interval too large, and enable it.
+ * tests/ere.tests: grep -E {1 is no longer an error
+ Likewise for a{1, a{1a, a{1a}, a{1,x}.
+
+1999-09-22 Paul Eggert
+
+ * largefile.m4 (AC_SYS_LARGEFILE_FLAGS): Work around GCC
+ 2.95.1 bug with HP-UX 10.20.
+
+1999-09-12 Paul Eggert
+
+ * src/grep.c (fillbuf): Fix typo: we sometimes reported
+ arithmetic overflow even when there wasn't any.
+
+1999-09-12 Paul Eggert
+
+ * configure.in (AC_CHECK_FUNCS): Add memmove.
+
+ * src/system.h (S_ISREG): New macro.
+ (memmove): Define if ! defined HAVE_MEMMOVE && ! defined memmove,
+ not if !defined STDC_HEADERS. This is needed for SunOS 4.1.4,
+ which defines STDC_HEADERS but lacks memmove.
+
+ * src/grep.c (bufoffset): Needed even if !defined HAVE_MMAP.
+ (reset): Always fstat the file, since we always need its size if it is
+ regular.
+ Similarly, get the buffer offset of every regular file.
+ Set bufmapped to 0 if the file's initial offset is not a multiple
+ of the page size.
+ (fillbuf): Calculate an upper bound on how much memory we should
+ allocate only for regular files, since we don't know the sizes of
+ other files.
+ Don't bother to check whether the file offset is a multiple of the page
+ size, since we now do that just once in `reset'.
+ When an mmapped area would fall past the end of the file, trim it to
+ just before instead of giving up immediately and doing a `read';
+ that avoids a worst-case behavior that could read half an mmapped file.
+ Fix bug when computing offsets on hosts that don't have mmap.
+
+1999-08-27 Paul Eggert
+
+ * src/system.h (memmove): New macro.
+
+ * src/grep.c (page_alloc): Reallocate the old buffer instead
+ of having both old and new buffers active simultaneously.
+ Remove valloc debugging variant, which no longer applies.
+
+ (fillbuf): Rejigger the buffer allocation mechanism. The old
+ mechanism could allocate more than 10*N bytes for an N-byte
+ file, which was excessive. Check for arithmetic overflow a
+ bit more carefully.
+
+1999-08-25 Paul Eggert
+
+ * src/grep.c (grepdir):
+ Don't assume that st_ino and st_dev must be integers;
+ POSIX.1 allows them to be floating-point (!).
+
+ * src/vms_fab.h (arr_ptr): `:' -> `;' to fix typo.
+
+1999-08-18 Alain Magloire
+
+ * 2.3e snapshot.
+
+1999-08-18 Alain Magloire
+
+ * src/search.c: On a CRAY J90 system running UNICOS 8.0.
+ Compilation of ./src/search.c failed because the declaration of
+ the variable "regex":
+ static struct re_pattern_buffer regex;
+ conflicted with a previous declaration search.c #includes "system.h",
+ which #includes <stdlib.h>, which declares :
+ extern char *regex __((char *_Re, char *_Subject, ...));
+ The declaration in search.c is local to that one source file.
+ I just changed its name to something less likely to conflict.
+ (I called it "regexbuf", but you could pick any name you want.)
+ Excerpt email from Dean Kopesky.
+
+1999-08-16 Paul Eggert
+
+ Upgrade large-file support to the version used in tar and
+ textutils.
+
+ * Makefile.am (ACLOCAL_AMFLAGS): Define to be empty.
+ (M4DIR, ACINCLUDE_INPUTS): New macros.
+ ($(srcdir)/acinclude.m4): New rule.
+
+ * configure.in (AC_CANONICAL_HOST, AM_C_PROTOTYPES): Add.
+ (AC_SYS_LARGEFILE): Renamed from AC_LFS, for compatibility
+ with what should appear in the next autoconf release.
+
+ * m4/largefile.m4: Renamed from m4/lfs.m4.
+
+ * src/ansi2knr.1, src/ansi2knr.c, config.guess, config.sub:
+ New files. config.guess and config.sub ar needed by the new
+ AC_SYS_LARGEFILE. ansi2knr is needed by AM_C_PROTOTYPES,
+ which in turn is needed by the new AC_SYS_LARGEFILE.
+
+1999-08-16 Alain Magloire
+
+ * 2.3d snapshot on ftp server.
+
+1999-07-26 Paul Eggert
+
+Several GNU tools have options to process arbitrary file names, even
+file names that contain newline characters. These include `find
+-print0', `perl -0', `sort -z', and `xargs -0'. It'd be handy if GNU
+grep also processed such file names. Here's a proposed patch to do
+this, relative to grep 2.3c. This patch introduces two options, one
+for the data, and one for the file names. (Sometimes one wants
+null-terminated file names in the output, and sometimes one wants to
+process lists of null-terminated strings, and these are orthogonal
+axes.)
+
+ * NEWS, doc/grep.texi: New -z or --null-data and -Z or --null options.
+ * src/grep.c (long_options, usage, main): Likewise.
+
+ * src/dfa.h (dfasyntax): New eol parameter.
+ * src/dfa.c (eolbyte): New var.
+ (dfasyntax): Set it from new parameter.
+ (lex, dfastat, build_state, dfaexec): Use it instead of '\n'.
+
+ * src/grep.h (eolbyte): New decl.
+ * src/grep.c (eolbyte): New var.
+ (nlscan, prpending, prtext, grepbuf, grep): Use it instead of '\n'.
+ (filename_mask): New var.
+ (prline, grepfile): Output NUL separator if filename_mask is zero.
+ (grep): Look for '\200' as the hallmark of a binary file, not '\0',
+ if -z or --null-data is specified, since it implies that '\0' is
+ expected as text.
+
+ * src/search.c (Gcompile, Ecompile): Pass eolbyte to dfasyntax.
+ (EGexecute, Fexecute): Use eolbyte instead of '\n'.
+
+1999-06-15 Alain Magloire
+
+ * src/grep.c, doc/grep{1,texi} :
+ --revert-match should be --invert-match.
+ Correction proposed by Karl Berry.
+
+1999-06-12 Alain Magloire
+
+ * doc/grep.{1,texi}: add description for --with-filename.
+ Noted missing by UEBAYASHI Masao.
+
+1999-03-17 Paul Eggert
+
+ * NEWS: Add GREP_OPTIONS.
+
+ * doc/grep.texi: Document GREP_OPTIONS, and the other
+ environment variables. Fix doc for [:blank:], [:cntrl:], [:punct:].
+
+ * src/grep.c (prepend_args, prepend_default_options): New functions.
+ (main): Use them to implement GREP_OPTIONS.
+ * src/system.h (getenv): New decl.
+
+1999-03-16 Volker Borchert
+
+ * configure.in: Use case case ... esac for checking Visual C++.
+ When ${CC} contains options it was not recognize.
+
+1999-03-07 Paul Eggert
+
+ * src/grep.c (usage): Don't report -E, -F, and -G unless we're grep.
+ (main): Don't match options -E, -F, and -G unless we're grep.
+ Remove after-the-fact check for options -E, -F, and -G, since
+ they're no longer needed.
+
+1999-03-05 Eli Zaretskii
+
+ * src/grep.c (main): Print the name of the default matcher instead
+ of just "grep".
+
+1999-02-06 Alain Magloire
+
+ * tests/*.awk : Linux users are seeing "Broken Pipe" on make check.
+ The problem is that grep does not drain its stdin, thus the previous
+ process in the pipeline receives a SIGPIPE. Other shells are silent
+ about this. There is actually no failure, since the broken pipe is
+ expected. You can work around it by changing the pipeline, so that
+ the input is drained, like this:
+ status=`echo 'check' | { ${GREP} -E -e pattern >/dev/null 2>&1;
+ echo $?; cat >/dev/null; }`; if test $status -ne $errnu then ... fi
+ Excerpt email from Andreas Schwab.
+
+1999-02-23 Alain Magloire
+
+ * src/grep.c : Restrict the use of -E, -F, -G
+ to only grep driver, Posix behaviour. {f,e}grep
+ the matcher is already set. This change may brake
+ scripts, warn in NEWS.
+
+ * doc/grep.{1,texi} : -C takes arguments, upgrade manual.
+
+ * beta 2.3a
+
+1999-02-23 Alain Magloire
+
+ * configure.in : Change the configure VC test from
+ 'test x$ac_cv_prog_CC = xcl;' to 'test x"$ac_cv_prog_CC" = xcl;'
+ Email from Joshua R. Poulson.
+
+1999-02-23 Paul Eggert
+
+ Fix porting bug reported by Amakawa Shuhei for SunOS 4.1.4-JL.
+ The btowc.c shipped with grep 2.3 is incorrect for Solaris
+ 2.5.1 and earlier, as it assumes UTF8, which these OSes do not
+ support. Solaris 7 supports btowc, so there's no need to ship
+ a substitute for it. The only questionable case is Solaris
+ 2.6, which lacks btowc but does support UTF8. However, 2.6
+ supports UTF8 but only as a demonstration (for an English
+ locale!); Japanese Solaris 2.6 users typically use EUC, or
+ sometimes shift-JIS, but they cannot use UTF8 since Japanese
+ UTF8 is not supported. Hence there's no point to having grep
+ substitute a btowc that uses UTF8, as it is either redundant,
+ or it will almost invariably have incorrect behavior.
+
+ * configure.in (AC_CHECK_HEADERS): Don't set USE_WCHAR.
+ (AC_CHECK_FUNCS): Add btowc, wctype.
+ (AC_REPLACE_FUNCS): Don't replace btowc; our replacement is
+ invariably doing the wrong thing anyway, at least on SunOS/Solaris.
+ Don't bother to check for wctype in -lw, as we don't support
+ wide characters on Solaris 2.5.1 or earlier anyway.
+
+ * bootstrap/Makefile.try (OBJS): Remove btowc.$(OBJEXT).
+
+ * src/btowc.c: Removed; no longer needed.
+
+1999-02-19 Paul Eggert
+
+ * NEWS: Fix typo when talking about the old behavior of
+ silently skipping directories; it was grep 2.1, not grep 2.2.
+
+1999-02-15 Alain Magloire
+
+ * bootstrap/Makefile.try : add DJGPP DEFS.
+ Done by Elie Zaretsckii.
+
+1999-02-14 Alain Magloire
+
+ * m4/gettext.m4 : Guard [] with changequote.
+ From Elie Zaretskii.
+
+ * djgpp/config.bat : Makefile.in.in --> Makefile.in-in
+ From Elie Zaretskii.
+
+ * src/dosbuf: k&r function parameter.
+
+ * release of 2.3.
+
+1999-02-10 Alain Magloire
+
+ * bootstrap/{Makefile{try,am},REAMDE} : skeleton
+ provided for system lacking the tools to autoconfigure.
+
+ * src/{e,f,}grepmat.c: added guard [HAVE_CONFIG_H]
+
+1999-02-10 Alain Magloire
+
+ * PATCHES-AC, PATCHES-AM: updated.
+
+ * m4/regex.m4 : updated.
+
+1999-02-05 Eli Zaretskii
+
+ * m4/gettext.m4 : Support DOS-style D:/foo/bar absolute file
+ names.
+
+ * aclocal.m4 (DJGPP) : Use $DJ_GPP instead, since changing the
+ latter prevents GCC from finding headers and libraries.
+
+ * djgpp/config.bat: Make building from another directory work
+
+ * djgpp/config.sed: Remove redundant command wich edited path
+ separator: now done by configure.
+
+ * src/grep.c [O_BINARY]: Add prototype for undossify_input.
+
+ * doc/grep.texi (Introduction): Typo fixed.
+
+1999-02-03 Alain Magloire
+
+ * grep-2.2f beta release.
+
+1999-02-02 Alain Magloire
+
+ * m4/{djgpp,envsep,glibc,regex,dosfile,isc-posix}.m4 :
+ New files to aid configuration and unload configure.in.
+ * m4/Makefile.am : updated.
+ * src/btowc.c : protect for wchar.h
+
+1999-01-28 Alain Magloire
+
+ * intl/Makefile.in: Replace .o with .${ac_objext} where necessary.
+ Work around a limitation of Visual C++ on Cygwin32.
+ * acconfig.h configure.in: Define `alloca' as `_alloca' when CC=cl.
+ This little hack was suggested by Ian Roxborough <irox@cygnus.com>.
+ Patch forwarded by Ben Elliston.
+
+1999-01-28 Alain Magloire
+
+ * PATCHES-AM: New file. A small patch for automake-1.4, use $(sep)
+ as the path separator base on @SEP@.
+ * PATCHES-AC configure.in : updated for autoconf-13.
+
+1999-01-27 Volker Borchert
+
+ * grep.c: fgrep -NUM not working correctly.
+ add the argument number to digit_args_val.
+
+1999-01-22 Paul Eggert
+
+ Prevent grep -r from recursing infinitely through directory loops via
+ symbolic links.
+
+ * grep.c (struct stats): New type.
+ (stats_base): New var.
+ (bufstat): Remove; subsumed by stats->stat.
+ (reset, fillbuf, grep, grepdir, grepfile): Pass struct stats * arg,
+ for directory loop checking; use this instead of the bufstat global.
+ All callers changed.
+ (grepfile): Stat the file before invoking grepdir.
+ (grepdir): Assume that the argument has already been statted.
+ No longer a need for a directory size argument, since it
+ can be gotten from the struct stats * argument.
+ Check for directory loops.
+ Create linked list of directories currently being visited,
+ to detect loops.
+
+1998-12-29 Kaveh R. Ghazi
+
+ intl/localealias.c: When building grep-2.2e using cc on Irix4,
+ I needed the following patch to intl/localealias.c.
+ (Its the same patch used by fileutils-4.0.) The patch resolves
+ conflicts between char* and unsigned char* in the i18n code.
+
+1998-12-10 Alain Magloire
+
+ * src/grep.c : Typo in contex -->context
+ Noted by Vladimir Michl.
+
+1998-12-01 Alain Magloire
+
+ * doc/Makefile.am djgpp/Makefile.am m4/Makefile.am vms/Makefile.am:
+ New files.
+
+ * m4/progtest.m4: proctect '[]' from m4.
+ Noted by Eli Z.
+
+ * PATCHES-AC: New file, add the patch for autoconf in the dist.
+
+ * acconfig.h: (HAVE_DOS_FILENAME)
+
+ * TODO: updated.
+
+ * src/search.c: remove obsolete 'gegrep,ggrep,gnugrep'
+ matchers. grep no longer depend on argv[0].
+
+ * grep-2.2e beta to test DJGPP port.
+
+1998-11-28 Paul Eggert
+
+ Various portability enhancements:
+ - Don't assume that O_BINARY implies DOS. Use separate
+ macros D_OK (for DOS-like directory access) and
+ HAVE_DOS_FILE_NAMES (for DOS-like file names).
+ - Don't assume that off_t fits into long; it doesn't on Solaris 2.6.
+ - Have is_EISDIR set errno properly on hosts with screwed-up EISDIR.
+ - Treat ':' specially in DOS file names only if it's the end of a
+ drive specifier.
+ - Protect against errno < 0.
+
+ * src/grep.c (is_EISDIR): Move defn to system.h.
+ (print_offset_sep): New function.
+ (fillbuf): Remove redundant test of O_BINARY.
+ (totalcc, totalnl): Now of type off_t.
+ (prline): Use print_offset_sep to print file offsets.
+ (grepfile): Don't set e to EISDIR; that's is_EISDIR's responsibility
+ on machines that don't work properly with EISDIR.
+ (grepdir): Don't assume ':' means slash on all DOS filenames;
+ it means it only in the file prefix.
+
+ * src/system.h (strerror): Check for negative error numbers.
+ (is_EISDIR): Depend on D_OK, not O_BINARY.
+ (SET_BINARY): Depend on HAVE_SETMODE, not __DJGPP__.
+ (IS_SLASH, FILESYSTEM_PREFIX_LEN): Depend on HAVE_DOS_FILE_NAMES,
+ not O_BINARY.
+ (CHAR_BIT): New macro.
+
+ * src/dosbuf.c (struct dos_map):
+ pos and add members are now of type off_t.
+ (dos_stripped_crs): Now of type off_t.
+ (dossified_pos): Now accepts arg and returns value of type off_t.
+
+ * configure.in (AC_CHECK_FUNCS): Add setmode.
+ (HAVE_DOS_FILENAMES): New macro
+
+1998-11-27 Eli Zaretskii
+
+ * djgpp/config.sed: New file, a Sed script to edit configure
+ script before running it on DOS/Windows.
+ * djgpp/config.bat: Updated to handle po2tbl.sed.in and
+ po/Makefile.in.in on DOS filesystems, and to run config.sed.
+
+1998-11-24 Jim Meyering
+
+ * src/grep.c : Typo s/infalid/invalid/
+ Also noted by Stanislav Brabec.
+
+1998-11-24 Eli Zaretskii
+
+ * doc/grep.texi: I found and corrected several typos.
+ I believe the GNU standards require the section that describes the
+ options to the programs to be called ``Invoking'' or ``Invoking
+ <program-name>''. This is so users and programs can easily find
+ that node in any Info file. So I changed the name of the
+ `Options' chapter to `Invoking', and corrected the
+ cross-references accordingly.
+ I added some markup to things like file names and options.
+ I added some additional index entries where that seemed useful.
+ I also corrected some index entries, such as "@cindex [:alnum:]",
+ which used a colon in them (the colons confuse Info readers).
+
+1998-11-24 Alain Magloire
+
+ * grep/doc/grep.texi : -h is not use for help.
+ Nit spotted by Jim Meyering.
+
+1998-11-23 Alain Magloire
+
+ * doc: New directory, grep.1, {e,f}grep.man move here
+ * doc/grep.texi: New info manual
+ * doc/version.texi: New
+ * doc/Makefile.am: New
+ * tests/{ere,bre}.*: New files. The spencer2 test is split
+ in two ere/bre.
+ * config.hin: New, config.h.in rename to config.hin for OS
+ with limited file system aka DOS.
+
+ * grep-2.2d release for beta.
+
+1998-11-18 Alain Magloire
+
+ * src/regex.[ch] : Updated from GLibc, previous patches were
+ integrate by Ulrich Drepper and some added ones.
+
+1998-11-16 Paul Eggert
+
+ * grep.h (__attribute__): New macro, if not GCC.
+ (fatal): Add __attribute__((noreturn)).
+ * grep.c (usage): Add __attribute__((noreturn)).
+
+1998-11-16 Paul Eggert
+
+ Remove memory leak with valloced buffers, by invoking malloc instead.
+
+ * configure.in (AC_CHECK_FUNCS), src/system.h (valloc): Remove.
+ * src/grep.c (page_alloc): New function.
+ (ubuffer, pagesize): New vars.
+ (ALIGN_TO): New macro.
+ (reset): Initialize new vars. Check for overflow in buffer size calc.
+ Use page_alloc instead of valloc.
+ (fillbuf): Likewise. Use memcpy to copy saved area.
+
+1998-11-15 Paul Eggert
+
+ * dfa.c (dfacomp), search.c (EGexecute): Don't assume char is unsigned.
+
+1998-11-14 Paul Eggert
+
+ * src/grep.c (grepdir): Fix bug: memory freed twice.
+
+ * src/search.c (Gcompile, Ecompile): Don't invoke dfainit,
+ since dfacomp does it for us, and if we also do it then we
+ leak memory.
+
+1998-11-13 Eli Zaretskii
+
+ * djgpp/config.bat: Rewrite to run the configure script via Bash.
+ * djgpp/config.site, djgpp/getconf: New files.
+ * djgpp/config.h, djgpp/*.mak, djgpp/po2tbl.sed: Remove.
+ * djgpp/README: Update instructions.
+
+ * Makefile.am (EXTRA_DIST): Update the list of DJGPP files.
+
+ * src/system.h (IS_SLASH): New macro.
+ (is_EISDIR): Define it here for DOS and Windows.
+
+ * src/grep.c (main) [O_BINARY]: Set stdout to binary mode, so the
+ EOL formats of the input and output files match, unless stdout is
+ the console device.
+ (is_EISDIR): Don't define if already defined. Accept a second
+ argument, the file name; all callers changed.
+ (grepdir): Don't free `file', inside the loop. Use IS_SLASH to
+ check whether `dir' needs a slash.
+ (grepfile): If file is a directory, set e to EISDIR.
+
+1998-11-10 Alain Magloire
+
+ * src/vms_fab.{c,h}: New file for VMS wildcard expansion
+ Written by Phillip C. Brisco.
+
+ * vms/make.com : add line to compile vms_fab.c and
+ {e,f,}grepmat.c with link for each grep/fgrep/egrep.
+ Base on patch send by Phillib C. Brisco.
+
+1998-11-09 Alain Magloire
+
+ * grep-2.2c on alpha for testing.
+
+1998-11-09 Paul Eggert
+
+ * src/grep.1: Fix `Last Change' of output by generating the date
+ from the RCS Id.
+
+ * src/grep.c (is_EISDIR): New macro.
+ (grep): If -s, suppress errors from trying to read directories.
+ (grepfile): Use is_EISDIR to simplify code.
+ (grepdir): If -s, suppress errors from trying to read directories.
+
+ * src/grep.1: Fix -q -r -s problems; describe BSD grep better.
+
+ * src/grep.c (main): Update copyright.
+
+ Specify default matcher with default_matcher extern var, not
+ DEFAULT_MATCHER macro. This is more straightforward and means
+ we need to compile grep.c just once.
+
+ * src/egrepmat.c, src/fgrepmat.c, src/grepmat.c: New files.
+
+ * src/Makefile.am (base_sources): New macro.
+ (egrep_SOURCES, fgrep_SOURCES, grep_SOURCES): Now consist of
+ $(base_sources) plus the single tailoring file.
+ (grep_LDADD, egrep_LDADD, fgrep_LDADD): Remove.
+ (EXTRA_DIST): Remove grep.c, regex.c.
+ (fgrep.o, egrep.o): Remove.
+
+ * src/grep.h (matcher): Now char const *.
+ (default_matcher): New decl.
+
+ * src/grep.c (matcher): Now char const *.
+ (setmatcher): Now accepts char const *.
+ (main): Default the matcher from default_matcher (linked externally)
+ rather than DEFAULT_MATCHER (a macro).
+
+1998-11-08 Alain Magloire
+
+ * src/grep.1: `prep.ai.mit.edu' should be replaced with `gnu.org'.
+ Nit from Paul Eggert.
+
+1998-11-06 Alain Magloire
+
+ * src/grep.c: The Matcher is not set to argv[0] but
+ explicitly by a #define MATCHER at compile time default is "grep".
+
+ * aclocal/: NEW dir. provides our own *.m4
+
+ * configure.in: Move Paul's Large Files to AC_LFS.(aclocal/lfs.m4)
+ Taken from Jim Meyering fileutils.
+
+1998-11-05 Alain Magloire
+
+ * src/grep.1: update the man pages according to the
+ changes make by Miles.
+
+ * po/*.po: updated.
+
+ * first beta release for 2.3 (2.2a).
+
+1998-11-04 Miles Bader
+
+ * src/grep.c (main): Rationalize interaction of -C/-NUM/-A/-B
+ options, and allow -C to have an optional argument. -NUM can
+ now be mixed with -C, and -A, -B always take precedence over
+ -C/-NUM, regardless of order.
+ (long_options): Let -C/--context take an optional argument.
+
+1998-11-03 Alain Magloire
+
+ * src/dfa.c: HP-UX define clrbit/setbit as macros in <sys/param.h>
+ #undef if defined.
+ Fixed by Andreas Ley and Philippe Defert.
+
+ * src/grep.1 : mention that -s follows POSIX.2 behavior.
+ Noted by Paul Eggert and others.
+
+ * tests/khadafy.sh: a typo in failure(s).
+ Spotted By Sotiris Vassilopoulos.
+
+1998-11-01 Paul Eggert
+
+ * src/system.h (IN_CTYPE_DOMAIN): New macro.
+ (ISALPHA, ISUPPER, ISLOWER, ISDIGIT, ISXDIGIT, ISSPACE,
+ ISPUNCT, ISALNUM, ISPRINT, ISGRAPH, ISCNTRL): Use
+ IN_CTYPE_DOMAIN instead of isascii.
+
+1998-08-18 Paul Eggert
+
+ Add support for new -r or --recursive (or -d recurse or
+ --directories=recurse) option.
+
+ * src/Makefile.am (grep_SOURCES): Add savedir.c, savedir.h, stpcpy.c.
+
+ * src/grep.1: Describe new options.
+
+ * src/grep.c: Include "savedir.h".
+ (long_options): Add -r or --recursive.
+ (RECURSE_DIRECTORIES): New enum value.
+ (IS_DIRECTORY_ERRNO): Remove.
+ (reset, grep): Add file name arg.
+ (grepdir, grepfile): New functions.
+ (initial_bufoffset): New var.
+ (reset): Initialize it.
+ (fillbuf): Use it.
+ (count_matches, list_files, no_filenames, suppress_errors): New static
+ vars; formerly were local to `main'.
+ (grep): Recurse through directories if the user asks for this.
+ (usage, main): Add new options.
+ (main): Change some local vars to be static, as described above.
+ Move most of the guts into grepfile function.
+ so that it can be recursed through.
+
+ * configure.in (AC_HEADER_DIRENT, AC_FUNC_CLOSEDIR_VOID): Add.
+ (AC_REPLACE_FUNCS): Add stpcpy.
+
+ * src/savedir.c, src/savedir.h, src/stpcpy.c: New files;
+ taken from fileutils 3.16u.
+
+1998-08-11 Paul Eggert
+
+ * src/system.h (initialize_main): New macro.
+ * src/grep.c (main): Invoke initialize_main first thing.
+
+1998-04-29 Paul Eggert
+
+ * NEWS, src/grep.1: Describe new -a and -d options.
+
+ * src/grep.c (long_options, usage, main):
+ New options -d or --directories and -a or --text.
+ (directories, always_text): New variables.
+ (IS_DIRECTORY_ERRNO): New macro.
+ (reset): Now returns value specifying whether to skip this file.
+ Stat the file if either mmap or directory-skipping is possible.
+ Skip the file if it's a directory and we're skipping directories.
+ (grep): Skip the file if `reset' tells us to.
+ (main): If open fails because the file is a directory, and if we're
+ skipping directories, don't report an error.
+ Remove special case for DOS and Windows.
+
+ * src/dosbuf.c (guess_type): Use the same method for guessing whether a
+ file is binary as grep.c's grep does.
+ There's no longer any need to declare `bp' to be unsigned.
+
+1998-04-26 Alain Magloire
+
+ * grep-2.2 release.
+
+ * src/dfa.c: Wrong revision was pulled out
+ for beta 2.1.1d.
+ * src/search.c: Wrong revision was pulled out
+ for beta 2.1.1d.
+
+ * src/grep.c: ck_atoi () added instead of atoi ().
+ Suggestion from Jim Meyering.
+ ck_atoi () pulled from diffutils-2.7, maintained by Paul Eggert.
+
+ * AUTHORS: Rephrase of some sentences.
+ * README: Rewording.
+ Noted and patched by Joel N. Weber II.
+
+1998-04-17 Kaveh R. Ghazi
+
+ * src/dfa.h: Don't define `const', trust autoconf to handle it.
+
+1998-04-16 Alain Magloire
+
+ * tests/{status,empty}.sh: wrong return status.
+
+ * src/grep.c: Remove the REGEX part in usage (), it was
+ consider overkill by most.
+
+1998-04-14 Eli Zaretskii
+
+ * djgpp/config.bat: Support file names with multiple dots on all
+ platforms.
+
+ * djgpp/README: Add instructions about file names illegal on
+ MS-DOS.
+
+1998-04-13 Alain Magloire
+
+ * src/dfa.c: by "popular" demand reverse
+ back to '_' not word-constituent.
+
+ * grep-2.1.1c available for testing.
+
+1998-04-13 Karl Heuer
+
+ * src/grep.c: (a) The directory check is done too early:
+ logically, if the argument is "-", then it refers to standard
+ input, regardless of whether there's something in the file
+ system answering to "-".
+ (b) The sh command "grep -l root /etc/passwd /etc/group 0<&-"
+ prints "(standard input)" instead of "/etc/passwd", because it
+ mistakenly believes that a named file will never be opened on fd
+ 0. The string "(standard input)" should be based on the file
+ having been originally specified as "-", rather than making
+ assumptions about the fd.
+ (c) the code that calls close(fd) is being done outside of the
+ test for a bad fd. Thus, if the open failed, this code will
+ attempt to close(-1). It should be done inside the "fd != -1"
+ branch.
+ This patch addresses all three of these problems.
+
+1998-04-13 Alain Magloire
+
+ * configure.in: remove the deprecated AC_ISC_POSIX macro.
+ Spotted by Karl Heuer.
+
+1998-04-03 Eli Zaretskii
+
+ * djgpp/main.mak, djgpp/src.mak, djgpp/tests.mak: Updated from the
+ relevant Makefile.in files.
+
+ * djgpp/config.bat: Create files in intl directory like the
+ configure script does.
+
+1998-03-28 Eli Zaretskii
+
+ * djgpp/main.mak, djgpp/src.mak, djgpp/tests.mak: Updated to track
+ changes in respective Makefile.in files.
+
+ * src/dosbuf.c (guess_type): Avoid running off the end of the
+ buffer. Spotted by Paul Eggert.
+
+1998-03-27 Alain Magloire
+
+ * grep-2.1.1b.tar.gz available.
+
+ * src/regex.c: CLASS_CHAR_MAX set to 256 instead of 6
+ when WCTYPE and WCHAR are not defined. When class names
+ where bigger then 6, it will not detect an error.
+ example '[[:alphabet:]]'.
+
+ * Updated the copyright of the files with emacs.
+ With emacs Jim :).
+
+1998-03-26 Jim Meyering
+
+ * src/dfa.c (IS_WORD_CONSTITUENT): Define.
+ (lex): Use IS_WORD_CONSTITUENT, not ISALNUM.
+ Don't special-case '_'.
+ (dfastate): Use IS_WORD_CONSTITUENT, not ISALNUM.
+ (dfaexec): Likewise.
+
+1998-03-25 Alain Magloire
+
+ * tests/warning.sh: typos and replace the echos with
+ a simple cat.
+ Noted By Jim Meyering.
+
+ * src/regex.c: #undef ISASCII and ISPRINT before defining
+ them(On Solaris it was define).
+ Pattern 'a[[:]:]]b' is an invalid char class and the error
+ from regex was 1(REG_NOMATCH) instead of 2 (REG_ECTYPE).
+ Fix with help from Ulrich Drepper.
+
+ * src/grep.c (usage): Ulrich wrote: "A single printf should
+ not have more than 900 bytes. For translation reasons the
+ text shouldn't be split in too many pieces since this is
+ tiresome and also does not help to generate a consistent picture."
+ Noted by Ulrich Drepper.
+ * src/grep.c (usage): Dig out and old patch from
+ Franc,ois to explain the regex in usage().
+ Ideas from Franc,ois Pinard.
+
+1998-03-23 Alain Magloire
+
+ * testing: grep-2.1.1a for testing.
+
+ * configure.in: Solaris needs '-lw' if we use wchar/wctype
+ functions.
+ * src/btowc.c: New file from GNU libc. Solaris 2.5 don't
+ have it define.
+ * configure.in : check for btowc ().
+
+ * regex.c: Include <wchar.h> before <wctype.h>, to work around
+ a Solaris 2.5 bug.
+ Patch provided by Paul Eggert.
+
+ * tests/status.sh: new file to check return status code.
+ * tests/empty.sh: new file to check for empty pattern.
+ * tests/warning.sh: new file to tell where to report errors.
+
+ * configure.in: If available, prefer support for large files
+ unless the user specified one of the CPPFLAGS, LDFLAGS, or LIBS
+ variables.
+ Done by Paul Eggert.
+
+ * src/grep.c (usage): change prep.ai.mit.edu for gnu.org.
+
+1998-03-18 Alain Magloire
+
+ * src/grep.c (usage): Formating the --help message a bit off.
+ Noted by William Bader.
+
+ * src/grep.c (main): When checking conflicting matcher for option -E the
+ matcher was to "egrep" instead of "posix-egrep".
+ Reported by kwzh@gnu.org.
+
+ * src/grep.c: Typos and rewording the --help message.
+ Reported by Karl Heuer.
+
+ * src/grep.1: The man page wording :
+ A regular expression matching a single character may be
+ followed by one of several repetition operators:
+ is unclear since 'x(yz)*z' is a valid regex.
+ Remove the "matching a single character".
+ Suggested by Harald Hanche-Olsen.
+
+ * src/grep.c (main): `-f /dev/null' now specifies no patterns
+ and therfore matches nothing.
+ Reported by Jorge Stolfi.
+ Patched by Paul Eggert.
+
+1998-03-10 Alain Magloire
+
+ * Ice storm 98(el nino). Lost grep repository disk,
+ and my $HOME directory, etc ..
+ Trying to get the emails/patch from dejanews.com
+ and start from grep-2.1.
+ sigh ....
+
+1997-11-01 Alain Magloire
+
+ * src/grep.c: For the long options, the problems are:
+ --file appears in the option table as 'no_argument'
+ instead of 'required_argument'.
+ --files-with-matches is missing from the option table.
+ The help lists '--fixed-strings' as the long option for -F,
+ the table has '--fixed-regexp'.
+ --regexp appears in the option table as 'no_argument'
+ instead of 'required_argument'.
+ --with-filename is missing from the option table.
+ Reported by Grant McDorman and Krishna Sethuraman.
+
+1997-10-19 Alain Magloire
+
+ * src/grep.c: the option "with-filename was not in the arg table.
+ Corrected by Jim Hand.
+
+ * GNU gettext library from gettext-0.10.32.
+
+ * src/grep.c: reverse back to greping directories,
+ One could skip the error message by defining
+ SKIP_DIR_ERROR. There is no clear way of doing
+ things, I hope to setle this on the next majore release
+ Thanks Paul Eggert, Eli Zaretskii and gnits for the
+ exchange.
+
+ * tests/status.sh: add this check to make sure
+ That the return status code is ok.
+
+1997-10-10 Andreas Schwab
+
+ * src/grep.1: Fix formatting.
+
+ * configure.in: Check for wctype.h, wchar.h, libintl.h and
+ isascii, which are needed for regex.c.
+
+1997-10-01 Paul Eggert
+
+ * src/grep.c (fillbuf): Don't warn about mmap failures.
+
+1997-09-7 Alain Magloire
+
+ * src/grep.c: added code for -H --with-filename.
+
+ * djgpp/*: patch wrongly apply
+ duplication of text in djgpp/{README,config.h}.
+ Filter djgpp/config.bat with unix2dos.
+
+ * djgpp/make.mak: beautify
+ From Eli Zaretskii.
+
+ * grep-2.1 release.
+
+1997-09-01 Alain Magloire
+
+ * grep-2.0f out for testing.
+
+ * update to GNU gettext library from gettext-0.10.31
+
+ * grep.c : have a nicer format for --version.
+ Noted by Ulrich Drepper.
+
+ * obstack.[ch]: updated from GNU C library
+ * configure.in: look for stdlib.h [HAVE_STDLIB_H]
+ Comments from Ulrich Drepper.
+
+1997-08-25 Philippe De Muyter <phdm@info.ucl.ac.be>
+
+ * src/dfa.c (sys/types.h): File included unconditionnaly.
+
+1997-08-16 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * grep.c (long_options) [O_BINARY]: Add DOS-specific options.
+ (fillbuf) [O_BINARY]: For DOS-style text files, strip CR
+ characters at end of line.
+ (prline) [O_BINARY]: Report correct byte offsets, even though CR
+ characters were stripped when reading the file.
+ (usage) [O_BINARY]: Add DOS-specific options.
+ (setmatcher) [HAVE_SETRLIMIT]: Set re_max_failures so that the
+ matcher won't ever overflow the stack.
+ (main) [__MSDOS__, _WIN32]: Handle backslashes and drive letters
+ in argv[0], remove the .exe suffix, and downcase the prgram name.
+ [O_BINARY]: Pass additional DOS-specific options to getopt_long
+ and handle them. Call stat before attempting to open the file, in
+ case it is a directory (DOS will fail the open call for
+ directories). Switch the input descriptor to binary mode, unless
+ it is a terminal device.
+
+ * system.h [O_BINARY]: Define macros to switch a handle to binary
+ mode, so binary files could be grep'ed on MS-DOS and MS-Windows.
+ [HAVE_SETLOCALE]: Test for HAVE_SETLOCALE instead of
+ HAVE_LC_MESSAGES, to prevent compilation error in grep.c on
+ systems which don't define HAVE_LC_MESSAGES, but have setlocale.
+
+ * dosbuf.c: New file, functions specific for MS-DOS/MS-Windows.
+ (guess_type, undossify_input, dossified_pos): New functions.
+
+ * djgpp/config.h, djgpp/config.bat, djgpp/main.mak, djgpp/src.mak,
+ djgpp/po.mak, djgpp/intl.mak, djgpp/tests.mak, djgpp/po2tbl.sed:
+ New files, for building Grep with DJGPP tools for MS-DOS and
+ MS-Windows.
+
+ * grep.1: Document DOS-specific switches.
+
+1997-08-08 Alain Magloire
+
+ * grep-2.0e: available for testing
+
+ * grep.c: change LC_MESSAGE to LC_ALL for (LC_CTYPE).
+ Suggested by Jochen Hein.
+
+ * ABOUT-NLS: updated.
+ * grep.c: --version: more verbosity (COPYRIGHT).
+ * grep.c: --help: PATTERN, FILE instead of <pattern>, <file>.
+ * INSTALL.grep: not necessary removed.
+ * configure.in: --disable-regex rename --without-include-regex.
+ * THANKS: format: first row name, second email.
+ * ChangeLog: format ISO 8601.
+ Reported by Franc,ois Pinard.
+
+ * grep.c: move dcl of struct stat st into "else" where it's used.
+ Reported by Jim Meyering.
+
+ * grep.c: totalnl should be %u in printf.
+ Reported by Michael Aichlmay
+ Corrected with guidance from Ulrich Drepper
+
+1997-07-24 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * Makefile.am: corrected an error when installing {f,e}grep.1.
+ From Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
+ From Ulrich Drepper <drepper@cygnus.com>.
+
+ * Many files: use PARAMS instead of __STDC__ for prototypes.
+ From Jim Meyering <meyering@eng.ascend.com>.
+ Patch provided by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
+
+ * dfa.[ch]: uses the one in gawk-3.0.3 with the patch from
+ Arnold (see Changelog: July 12 1997)
+
+ * grep.1: a note to say -l, -L, -q stop on first match.
+ Noted by Andrew Beattie <gaffer@tug.com>.
+
+ * grep.c: refuse to scan if the file is a directory.
+ This was causing problems on SUNs. If the directory contains
+ a file that could match the pattern, garbage was display.
+
+ * tests directory: added new set of tests from Henry Spencer
+ regex package. Change the way the tests were done to be more
+ conformant to automake.
+
+ * configure.in: added --disable-regex for folks with their own fuctions.
+
+ * grep-20d : available for testing
+
+1997-07-18 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * grep-2.0c: available for testing
+
+1997-07-17 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * src/grep.c: Cause grep to fail if `fclose (stdout)' fails.
+ From Jim Meyering <meyering@eng.ascend.com>.
+
+ * grep.c:usage() more consistency in the --help.
+
+ * egrep, fgrep were links This is in violation of GNU standards:
+ "Please don't make the behavior of a utility depend on the name used
+ to invoke it. It is useful sometimes to make a link to a utility with
+ a different name, and that should not change what it does."
+ For now egrep and fgrep will be copies of grep. A better scheme
+ should be found later.
+ After discussion with Tom Tromey <tromey@cygnus.com>.
+
+ * fgrep.man and egrep.man included: They are stubs that call grep.1.
+ * Makefile.am: modified to install {f,e,}grep[,.1].
+
+ * speed hack for -l, -L: bail out on first match.
+ From Scott Weikart <scott@igc.apc.org>.
+
+ * *.[ch]: provided prototypes for strict argument checking
+ With the help of Stewart Levin <stew@sep.stanford.edu>.
+
+1997-07-16 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * configure.in: typo in the creation of po/Makefile
+ Noted by Volker Borchert bt@teknon.de.
+
+ * grep-2.0b: make it available for testing.
+
+1997-07-15 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * src/grep.c usage(): cut the --help in smaller printf()'s
+ Noted by Ulrich Drepper <drepper@cygnus.com>.
+
+1997-07-14 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * grep-2.0a: make an alpha available for testing.
+
+1997-07-12 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * run gettextize: added the po directory filled with *.po files.
+
+ * check.sh, scriptgen.awk: fix grep paths.
+
+ * change the directory strucure: grep is now in src to comply with
+ gettext.m4.
+
+ * grep.c version.c [VERSION]: got rid of version.c,
+ it is now define via config.h.
+
+ * dfa.c: patch to speed up initialization.
+ Arnold Robbins (arnold@gnu.ai.mit.edu).
+
+1997-07-09 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * *.c [HAVE_CONFIG_H]: Macro defined.
+
+ * support for I18N in Makefile.am and configure.in.
+
+ * update all the string to use gettext(I18N).
+ Help from Franc,ois Pinard previous patch <pinard@IRO.UMontreal.CA>.
+
+1997-07-04 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * obstack.[ch]: updated from glibc.
+ Work of Ulrich Drepper <drepper@cygnus.com>.
+
+ * regex.[ch]: updated from glibc.
+ Work of Ulrich Drepper <drepper@cygnus.com>.
+
+ * grep.c: for option -e not counting '\n' for new keys.
+ From Mark Waite <markw@mddmew.fc.hp.com>.
+
+ * grep.c: for option -f allocating the right count.
+ From Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>.
+ Mike Heartel (mike@cs.uoregon.edu).
+
+ * kwset.c (bmexec): Cast tp[-2] to unsigned char before comparing.
+ From Jim Meyering <meyering@asic.sc.ti.com>.
+
+ * grep.1: various typos.
+ From Keith Bostic <bostic@bsdi.com>.
+ Mike Heartel (mike@cs.uoregon.edu).
+
+1997-06-17 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * grep.c: support for long options.
+ patch done by Franc,ois Pinard <pinard@IRO.UMontreal.CA>.
+
+ * add getopt1.c in Makefile.am.
+ Noted by Franc,ois Pinard <pinard@IRO.UMontreal.CA>
+
+ * replace getopt.[ch] and add getopt1.c.
+
+ * kwset.c: undef malloc before define it.
+ Franc,ois Pinard <pinard@IRO.UMontreal.CA>.
+
+1997-06-07 Alain Magloire <alainm@rcsm.ee.mcgill.ca>
+
+ * grep.c: format incorrect in
+ fprintf("%s: warning: %s: %s...", filename, strerror(errno)).
+ Mike Heartel (mike@cs.uoregon.edu).
+
+1996-11-19 David J MacKenzie <djm@catapult.va.pubnix.com>
+
+ * make.com: Set the logical SYS. From rdb@cocamrd.oz.au (Rodney Brown).
+
+ * grep.c (S_ISREG): Define if not defined already, for e.g.
+ SunOS 4.0.3.
+
+ * dfa.c (test_bit, set_bit, clear_bit): Renamed from tstbit,
+ setbit, clrbit to avoid conflict with HP-UX sys/param.h macros.
+
+ * memchr.c: New file, from GNU libc.
+ * grep.c (memchr): Remove definition.
+ * configure.in: Use AC_REPLACE_FUNCS for memchr.
+
+ * configure.in: Remove unused checks for memalign and unsigned char.
+ * grep.c: HAVE_WORKING_MMAP -> HAVE_MMAP.
+
+ * system.h: New file.
+ * dfa.c, kwset.c, grep.c, search.c: Use it instead of duplicating
+ portability boilerplate.
+
+ * grep.c: Include sys/types.h once, instead of three times
+ conditionally.
+ * dfa.c, kwset.c, search.c: Include sys/types.h unconditionally,
+ to always try to get size_t (needed on some old SysV's).
+
+ * dfa.c: Define strchr in terms of index, not the other way around.
+ * search.c: Use memcpy instead of bcopy.
+
+1996-11-15 David J MacKenzie <djm@catapult.va.pubnix.com>
+
+ * Many files: Update FSF address.
+ Update configuration to use autoconf v2 and automake.
+
+1993-05-22 Mike Haertel <mike@cs.uoregon.edu>
+
+ * Version 2.0 released.
diff --git a/gnu/usr.bin/grep/Makefile b/gnu/usr.bin/grep/Makefile
new file mode 100644
index 0000000..b1875fe
--- /dev/null
+++ b/gnu/usr.bin/grep/Makefile
@@ -0,0 +1,51 @@
+# $FreeBSD$
+
+GREP_LIBZ=YES
+
+PROG= grep
+SRCS= dfa.c getopt.c getopt1.c grep.c kwset.c obstack.c savedir.c search.c \
+ stpcpy.c
+
+CFLAGS+=-I${.CURDIR} -DHAVE_CONFIG_H
+
+LINKS+= ${BINDIR}/grep ${BINDIR}/egrep \
+ ${BINDIR}/grep ${BINDIR}/fgrep
+MLINKS= grep.1 egrep.1 grep.1 fgrep.1
+
+DPADD+= ${LIBGNUREGEX}
+LDADD+= -lgnuregex
+
+.if defined(GREP_LIBZ) && !empty(GREP_LIBZ)
+LDADD+= -lz
+DPADD+= ${LIBZ}
+CFLAGS+=-DHAVE_LIBZ=1
+LINKS+= ${BINDIR}/grep ${BINDIR}/zgrep \
+ ${BINDIR}/grep ${BINDIR}/zegrep \
+ ${BINDIR}/grep ${BINDIR}/zfgrep
+MLINKS+=grep.1 zgrep.1 grep.1 zegrep.1 grep.1 zfgrep.1
+.endif
+
+SUBDIR+=doc
+
+check: all
+ @failed=0; total=0; \
+ for tst in ${TESTS}; do \
+ total=$$(($$total+1)); \
+ if GREP=${.OBJDIR}/${PROG} srcdir=${.CURDIR}/tests \
+ ${.CURDIR}/tests/$$tst; then \
+ echo "PASS: $$tst"; \
+ else \
+ failed=$$(($$failed+1)); \
+ echo "FAIL: $$tst"; \
+ fi; \
+ done; \
+ if [ "$$failed" -eq 0 ]; then \
+ echo "All $$total tests passed"; \
+ else \
+ echo "$$failed of $$total tests failed"; \
+ fi
+
+TESTS= warning.sh khadafy.sh spencer1.sh bre.sh ere.sh status.sh empty.sh \
+ options.sh
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/grep/NEWS b/gnu/usr.bin/grep/NEWS
new file mode 100644
index 0000000..e763647
--- /dev/null
+++ b/gnu/usr.bin/grep/NEWS
@@ -0,0 +1,163 @@
+Version 2.4.1
+
+ - If the final byte of an input file is not a newline, grep now silently
+ supplies one.
+
+ - The new option --binary-files=TYPE makes grep assume that a binary input
+ file is of type TYPE.
+ --binary-files='binary' (the default) outputs a 1-line summary of matches.
+ --binary-files='without-match' assumes binary files do not match.
+ --binary-files='text' treats binary files as text
+ (equivalent to the -a or --text option).
+
+ - New option -I; equivalent to --binary-files='without-match'.
+
+Version 2.4:
+
+ - egrep is now equivalent to `grep -E' as required by POSIX,
+ removing a longstanding source of confusion and incompatibility.
+ `grep' is now more forgiving about stray `{'s, for backward
+ compatibility with traditional egrep.
+
+ - The lower bound of an interval is not optional.
+ You must use an explicit zero, e.g. `x{0,10}' instead of `x{,10}'.
+ (The old documentation incorrectly claimed that it was optional.)
+
+ - The --revert-match option has been renamed to --invert-match.
+
+ - The --fixed-regexp option has been renamed to --fixed-string.
+
+ - New option -H or --with-filename.
+
+ - New option --mmap. By default, GNU grep now uses read instead of mmap.
+ This is faster on some hosts, and is safer on all.
+
+ - The new option -z or --null-data causes `grep' to treat a zero byte
+ (the ASCII NUL character) as a line terminator in input data, and
+ to treat newlines as ordinary data.
+
+ - The new option -Z or --null causes `grep' to output a zero byte
+ instead of the normal separator after a file name.
+
+ - These two options can be used with commands like `find -print0',
+ `perl -0', `sort -z', and `xargs -0' to process arbitrary file names,
+ even those that contain newlines.
+
+ - The environment variable GREP_OPTIONS specifies default options;
+ e.g. GREP_OPTIONS='--directories=skip' reestablishes grep 2.1's
+ behavior of silently skipping directories.
+
+ - You can specify a matcher multiple times without error, e.g.
+ `grep -E -E' or `fgrep -F'. It is still an error to specify
+ conflicting matchers.
+
+ - -u and -U are now allowed on non-DOS hosts, and have no effect.
+
+ - Modifications of the tests scripts to go around the "Broken Pipe"
+ errors from bash. See Bash FAQ.
+
+ - New option -r or --recursive or --directories=recurse.
+ (This option was also in grep 2.3, but wasn't announced here.)
+
+ - --without-included-regex disable, was causing bogus reports .i.e
+ doing more harm then good.
+
+Version 2.3:
+
+ - When searching a binary file FOO, grep now just reports
+ `Binary file FOO matches' instead of outputting binary data.
+ This is typically more useful than the old behavior,
+ and it is also more consistent with other utilities like `diff'.
+ A file is considered to be binary if it contains a NUL (i.e. zero) byte.
+
+ The new -a or --text option causes `grep' to assume that all
+ input is text. (This option has the same meaning as with `diff'.)
+ Use it if you want binary data in your output.
+
+ - `grep' now searches directories just like ordinary files; it no longer
+ silently skips directories. This is the traditional behavior of
+ Unix text utilities (in particular, of traditional `grep').
+ Hence `grep PATTERN DIRECTORY' should report
+ `grep: DIRECTORY: Is a directory' on hosts where the operating system
+ does not permit programs to read directories directly, and
+ `grep: DIRECTORY: Binary file matches' (or nothing) otherwise.
+
+ The new -d ACTION or --directories=ACTION option affects directory handling.
+ `-d skip' causes `grep' to silently skip directories, as in grep 2.1;
+ `-d read' (the default) causes `grep' to read directories if possible,
+ as in earlier versions of grep.
+
+ - The MS-DOS and Microsoft Windows ports now behave identically to the
+ GNU and Unix ports with respect to binary files and directories.
+
+Version 2.2:
+
+Bug fix release.
+
+ - Status error number fix.
+ - Skipping directories removed.
+ - Many typos fix.
+ - -f /dev/null fix(not to consider as an empty pattern).
+ - Checks for wctype/wchar.
+ - -E was using the wrong matcher fix.
+ - bug in regex char class fix
+ - Fixes for DJGPP
+
+Version 2.1:
+
+This is a bug fix release(see Changelog) i.e. no new features.
+
+ - More compliance to GNU standard.
+ - Long options.
+ - Internationalisation.
+ - Use automake/autoconf.
+ - Directory hierarchy change.
+ - Sigvec with -e on Linux corrected.
+ - Sigvec with -f on Linux corrected.
+ - Sigvec with the mmap() corrected.
+ - Bug in kwset corrected.
+ - -q, -L and -l stop on first match.
+ - New and improve regex.[ch] from Ulrich Drepper.
+ - New and improve dfa.[ch] from Arnold Robbins.
+ - Prototypes for over zealous C compiler.
+ - Not scanning a file, if it's a directory
+ (cause problems on Sun).
+ - Ported to MS-DOS/MS-Windows with DJGPP tools.
+
+See Changelog for the full story and proper credits.
+
+Version 2.0:
+
+The most important user visible change is that egrep and fgrep have
+disappeared as separate programs into the single grep program mandated
+by POSIX 1003.2. New options -G, -E, and -F have been added,
+selecting grep, egrep, and fgrep behavior respectively. For
+compatibility with historical practice, hard links named egrep and
+fgrep are also provided. See the manual page for details.
+
+In addition, the regular expression facilities described in Posix
+draft 11.2 are now supported, except for internationalization features
+related to locale-dependent collating sequence information.
+
+There is a new option, -L, which is like -l except it lists
+files which don't contain matches. The reason this option was
+added is because '-l -v' doesn't do what you expect.
+
+Performance has been improved; the amount of improvement is platform
+dependent, but (for example) grep 2.0 typically runs at least 30% faster
+than grep 1.6 on a DECstation using the MIPS compiler. Where possible,
+grep now uses mmap() for file input; on a Sun 4 running SunOS 4.1 this
+may cut system time by as much as half, for a total reduction in running
+time by nearly 50%. On machines that don't use mmap(), the buffering
+code has been rewritten to choose more favorable alignments and buffer
+sizes for read().
+
+Portability has been substantially cleaned up, and an automatic
+configure script is now provided.
+
+The internals have changed in ways too numerous to mention.
+People brave enough to reuse the DFA matcher in other programs
+will now have their bravery amply "rewarded", for the interface
+to that file has been completely changed. Some changes were
+necessary to track the evolution of the regex package, and since
+I was changing it anyway I decided to do a general cleanup.
diff --git a/gnu/usr.bin/grep/README b/gnu/usr.bin/grep/README
new file mode 100644
index 0000000..66c1bb2
--- /dev/null
+++ b/gnu/usr.bin/grep/README
@@ -0,0 +1,26 @@
+This is GNU grep, the "fastest grep in the west" (we hope). All
+bugs reported in previous releases have been fixed. Many exciting new
+bugs have probably been introduced in this revision.
+
+GNU grep is provided "as is" with no warranty. The exact terms
+under which you may use and (re)distribute this program are detailed
+in the GNU General Public License, in the file COPYING.
+
+GNU grep is based on a fast lazy-state deterministic matcher (about
+twice as fast as stock Unix egrep) hybridized with a Boyer-Moore-Gosper
+search for a fixed string that eliminates impossible text from being
+considered by the full regexp matcher without necessarily having to
+look at every character. The result is typically many times faster
+than Unix grep or egrep. (Regular expressions containing backreferencing
+will run more slowly, however.)
+
+See the files AUTHORS and THANKS for a list of authors and other contributors.
+
+See the file INSTALL for compilation and installation instructions.
+
+See the file NEWS for a description of major changes in this release.
+
+See the file TODO for ideas on how you could help us improve grep.
+
+Send bug reports to bug-gnu-utils@gnu.org. Be sure to
+include the word "grep" in your Subject: header field.
diff --git a/gnu/usr.bin/grep/THANKS b/gnu/usr.bin/grep/THANKS
new file mode 100644
index 0000000..b0c23f9
--- /dev/null
+++ b/gnu/usr.bin/grep/THANKS
@@ -0,0 +1,49 @@
+Aharon Robbins <arnold@gnu.org>
+Akim Demaille <akim@epita.fr>
+Alain Magloire <alainm@gnu.org>
+Andreas Schwab <schwab@suse.de>
+Andreas Ley <andy@rz.uni-karlsruhe.de>
+Ben Elliston <bje@cygnus.com>
+David J MacKenzie <djm@catapult.va.pubnix.com>
+David O'Brien <obrien@freebsd.org>
+Eli Zaretskii <eliz@is.elta.co.il>
+Florian La Roche <florian@knorke.saar.de>
+Franc,ois Pinard <pinard@IRO.UMontreal.CA>
+Grant McDorman <grant@isgtec.com>
+Harald Hanche-Olsen <hanche@math.ntnu.no>
+Jeff Bailey <jbailey@nisa.net>
+Jim Hand <jhand@austx.tandem.com>
+Jim Meyering <meyering@asic.sc.ti.com>
+Jochen Hein <jochen.hein@delphi.central.de>
+Joel N. Weber II <devnull@gnu.org>
+John Hughes <john@nitelite.calvacom.fr>
+Jorge Stolfi <stolfi@dcc.unicamp.br>
+Karl Berry <karl@cs.umb.edu>
+Karl Heuer <kwzh@gnu.org>
+Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+Kazuro Furukawa <furukawa@apricot.kek.jp>
+Keith Bostic <bostic@bsdi.com>
+Krishna Sethuraman <krishna@sgihub.corp.sgi.com>
+Mark Waite <markw@mddmew.fc.hp.com>
+Martin Rex <martin.rex@sap-ag.de>
+Michael Aichlmayr <mikla@nx.com>
+Miles Bader <miles@ccs.mt.nec.co.jp>
+Olaf Kirch <okir@ns.lst.de>
+Paul Eggert <eggert@twinsun.com>
+Paul Kimoto <kimoto@spacenet.tn.cornell.edu>
+Phillip C. Brisco <phillip.craig.brisco@ccmail.census.gov>
+Philippe Defert <Philippe.Defert@cern.ch>
+Philippe De Muyter <phdm@info.ucl.ac.be>
+Roland Roberts <rroberts@muller.com>
+Ruslan Ermilov <ru@freebsd.org>
+Shannon Hill <hill@synnet.com>
+Sotiris Vassilopoulos <Sotiris.Vassilopoulos@betatech.gr>
+Stewart Levin <stew@sep.stanford.edu>
+Sydoruk Stepan <step@unitex.kiev.ua>
+Tom 'moof' Spindler <dogcow@ccs.neu.edu>
+Tom Tromey <tromey@creche.cygnus.com>
+Ulrich Drepper <drepper@cygnus.com>
+UEBAYASHI Masao <masao@nf.enveng.titech.ac.jp>
+Volker Borchert <bt@teknon.de>
+Wichert Akkerman <wakkerma@wi.leidenuniv.nl>
+William Bader <william@nscs.fast.net>
diff --git a/gnu/usr.bin/grep/config.h b/gnu/usr.bin/grep/config.h
new file mode 100644
index 0000000..70fdeb6
--- /dev/null
+++ b/gnu/usr.bin/grep/config.h
@@ -0,0 +1,209 @@
+/* $FreeBSD$ */
+
+/* config.h. Generated automatically by configure. */
+/* config.hin. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define if the closedir function returns void instead of int. */
+/* #undef CLOSEDIR_VOID */
+
+/* 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. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* 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 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. */
+#define STDC_HEADERS 1
+
+/* Define to use grep's error-checking malloc in the kwset routines. */
+#define GREP 1
+
+/* Package name. */
+#define PACKAGE "grep"
+
+/* Version number. */
+#define VERSION "2.4d"
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef ssize_t */
+
+/* Hack for Visual C++ suggested by irox. */
+/* #undef alloca */
+
+/* #undef HAVE_STPCPY */
+
+/* #undef ENABLE_NLS */
+
+/* #undef HAVE_CATGETS */
+
+/* #undef HAVE_GETTEXT */
+
+#define HAVE_LC_MESSAGES 1
+
+/*
+ * DOS specific
+ */
+/* #undef HAVE_DOS_FILE_NAMES */
+
+/* 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 btowc function. */
+/* #undef HAVE_BTOWC */
+
+/* Define if you have the dcgettext function. */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define if you have the getcwd function. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getpagesize function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if you have the isascii function. */
+#define HAVE_ISASCII 1
+
+/* Define if you have the memchr function. */
+#define HAVE_MEMCHR 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the munmap function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the setenv function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the setlocale function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the setmode function. */
+#define HAVE_SETMODE 1
+
+/* Define if you have the stpcpy function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the strcasecmp function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the wctype function. */
+/* #undef HAVE_WCTYPE */
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <libintl.h> header file. */
+/* #undef HAVE_LIBINTL_H */
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* 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 i library (-li). */
+/* #undef HAVE_LIBI */
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to make fseeko etc. visible, on some hosts. */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define if compiler has function prototypes */
+#define PROTOTYPES 1
diff --git a/gnu/usr.bin/grep/config.hin b/gnu/usr.bin/grep/config.hin
new file mode 100644
index 0000000..8922a63
--- /dev/null
+++ b/gnu/usr.bin/grep/config.hin
@@ -0,0 +1,207 @@
+/* config.hin. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define if the closedir function returns void instead of int. */
+#undef CLOSEDIR_VOID
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define 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 to use grep's error-checking malloc in the kwset routines. */
+#undef GREP
+
+/* Package name. */
+#undef PACKAGE
+
+/* Version number. */
+#undef VERSION
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef ssize_t
+
+/* Hack for Visual C++ suggested by irox. */
+#undef alloca
+
+#undef HAVE_STPCPY
+
+#undef ENABLE_NLS
+
+#undef HAVE_CATGETS
+
+#undef HAVE_GETTEXT
+
+#undef HAVE_LC_MESSAGES
+
+/*
+ * DOS specific
+ */
+#undef HAVE_DOS_FILE_NAMES
+
+/* 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 btowc function. */
+#undef HAVE_BTOWC
+
+/* 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 memchr function. */
+#undef HAVE_MEMCHR
+
+/* Define if you have the memmove function. */
+#undef HAVE_MEMMOVE
+
+/* Define if you have the munmap function. */
+#undef HAVE_MUNMAP
+
+/* Define if you have the putenv function. */
+#undef HAVE_PUTENV
+
+/* Define if you have the setenv function. */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function. */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the setmode function. */
+#undef HAVE_SETMODE
+
+/* 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 strdup function. */
+#undef HAVE_STRDUP
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the wctype function. */
+#undef HAVE_WCTYPE
+
+/* Define if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <libintl.h> header file. */
+#undef HAVE_LIBINTL_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <ndir.h> header file. */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <nl_types.h> header file. */
+#undef HAVE_NL_TYPES_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <sys/dir.h> header file. */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file. */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <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 i library (-li). */
+#undef HAVE_LIBI
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to make fseeko etc. visible, on some hosts. */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define if compiler has function prototypes */
+#undef PROTOTYPES
+
diff --git a/gnu/usr.bin/grep/dfa.c b/gnu/usr.bin/grep/dfa.c
new file mode 100644
index 0000000..76dd0b2
--- /dev/null
+++ b/gnu/usr.bin/grep/dfa.c
@@ -0,0 +1,2586 @@
+/* dfa.c - deterministic extended regexp routines for GNU
+ Copyright (C) 1988, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 June, 1988 by Mike Haertel
+ Modified July, 1988 by Arthur David Olson to assist BMG speedups */
+
+/* $FreeBSD$ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern char *calloc(), *malloc(), *realloc();
+extern void free();
+#endif
+
+#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
+#include <string.h>
+#undef index
+#define index strchr
+#else
+#include <strings.h>
+#endif
+
+#ifndef DEBUG /* use the same approach as regex.c */
+#undef assert
+#define assert(e)
+#endif /* DEBUG */
+
+#ifndef isgraph
+#define isgraph(C) (isprint(C) && !isspace(C))
+#endif
+
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+#define ISALPHA(C) isalpha(C)
+#define ISUPPER(C) isupper(C)
+#define ISLOWER(C) islower(C)
+#define ISDIGIT(C) isdigit(C)
+#define ISXDIGIT(C) isxdigit(C)
+#define ISSPACE(C) isspace(C)
+#define ISPUNCT(C) ispunct(C)
+#define ISALNUM(C) isalnum(C)
+#define ISPRINT(C) isprint(C)
+#define ISGRAPH(C) isgraph(C)
+#define ISCNTRL(C) iscntrl(C)
+#else
+#define ISALPHA(C) (isascii(C) && isalpha(C))
+#define ISUPPER(C) (isascii(C) && isupper(C))
+#define ISLOWER(C) (isascii(C) && islower(C))
+#define ISDIGIT(C) (isascii(C) && isdigit(C))
+#define ISXDIGIT(C) (isascii(C) && isxdigit(C))
+#define ISSPACE(C) (isascii(C) && isspace(C))
+#define ISPUNCT(C) (isascii(C) && ispunct(C))
+#define ISALNUM(C) (isascii(C) && isalnum(C))
+#define ISPRINT(C) (isascii(C) && isprint(C))
+#define ISGRAPH(C) (isascii(C) && isgraph(C))
+#define ISCNTRL(C) (isascii(C) && iscntrl(C))
+#endif
+
+/* ISASCIIDIGIT differs from ISDIGIT, as follows:
+ - Its arg may be any int or unsigned int; it need not be an unsigned char.
+ - It's guaranteed to evaluate its argument exactly once.
+ - It's typically faster.
+ Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
+ only '0' through '9' are digits. Prefer ISASCIIDIGIT to ISDIGIT unless
+ it's important to use the locale's definition of `digit' even when the
+ host does not conform to Posix. */
+#define ISASCIIDIGIT(c) ((unsigned) (c) - '0' <= 9)
+
+/* If we (don't) have I18N. */
+/* glibc defines _ */
+#ifndef _
+# ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# ifndef _
+# define _(Str) gettext (Str)
+# endif
+# else
+# define _(Str) (Str)
+# endif
+#endif
+
+#ifdef __FreeBSD__
+#include <gnuregex.h>
+#else
+#include "regex.h"
+#endif
+#include "dfa.h"
+
+/* HPUX, define those as macros in sys/param.h */
+#ifdef setbit
+# undef setbit
+#endif
+#ifdef clrbit
+# undef clrbit
+#endif
+
+static void dfamust PARAMS ((struct dfa *dfa));
+
+static ptr_t xcalloc PARAMS ((size_t n, size_t s));
+static ptr_t xmalloc PARAMS ((size_t n));
+static ptr_t xrealloc PARAMS ((ptr_t p, size_t n));
+#ifdef DEBUG
+static void prtok PARAMS ((token t));
+#endif
+static int tstbit PARAMS ((int b, charclass c));
+static void setbit PARAMS ((int b, charclass c));
+static void clrbit PARAMS ((int b, charclass c));
+static void copyset PARAMS ((charclass src, charclass dst));
+static void zeroset PARAMS ((charclass s));
+static void notset PARAMS ((charclass s));
+static int equal PARAMS ((charclass s1, charclass s2));
+static int charclass_index PARAMS ((charclass s));
+static int looking_at PARAMS ((const char *s));
+static token lex PARAMS ((void));
+static void addtok PARAMS ((token t));
+static void atom PARAMS ((void));
+static int nsubtoks PARAMS ((int tindex));
+static void copytoks PARAMS ((int tindex, int ntokens));
+static void closure PARAMS ((void));
+static void branch PARAMS ((void));
+static void regexp PARAMS ((int toplevel));
+static void copy PARAMS ((position_set *src, position_set *dst));
+static void insert PARAMS ((position p, position_set *s));
+static void merge PARAMS ((position_set *s1, position_set *s2, position_set *m));
+static void delete PARAMS ((position p, position_set *s));
+static int state_index PARAMS ((struct dfa *d, position_set *s,
+ int newline, int letter));
+static void build_state PARAMS ((int s, struct dfa *d));
+static void build_state_zero PARAMS ((struct dfa *d));
+static char *icatalloc PARAMS ((char *old, char *new));
+static char *icpyalloc PARAMS ((char *string));
+static char *istrstr PARAMS ((char *lookin, char *lookfor));
+static void ifree PARAMS ((char *cp));
+static void freelist PARAMS ((char **cpp));
+static char **enlist PARAMS ((char **cpp, char *new, size_t len));
+static char **comsubs PARAMS ((char *left, char *right));
+static char **addlists PARAMS ((char **old, char **new));
+static char **inboth PARAMS ((char **left, char **right));
+
+static ptr_t
+xcalloc (size_t n, size_t s)
+{
+ ptr_t r = calloc(n, s);
+
+ if (!r)
+ dfaerror(_("Memory exhausted"));
+ return r;
+}
+
+static ptr_t
+xmalloc (size_t n)
+{
+ ptr_t r = malloc(n);
+
+ assert(n != 0);
+ if (!r)
+ dfaerror(_("Memory exhausted"));
+ return r;
+}
+
+static ptr_t
+xrealloc (ptr_t p, size_t n)
+{
+ ptr_t r = realloc(p, n);
+
+ assert(n != 0);
+ if (!r)
+ dfaerror(_("Memory exhausted"));
+ return r;
+}
+
+#define CALLOC(p, t, n) ((p) = (t *) xcalloc((size_t)(n), sizeof (t)))
+#define MALLOC(p, t, n) ((p) = (t *) xmalloc((n) * sizeof (t)))
+#define REALLOC(p, t, n) ((p) = (t *) xrealloc((ptr_t) (p), (n) * sizeof (t)))
+
+/* Reallocate an array of type t if nalloc is too small for index. */
+#define REALLOC_IF_NECESSARY(p, t, nalloc, index) \
+ if ((index) >= (nalloc)) \
+ { \
+ while ((index) >= (nalloc)) \
+ (nalloc) *= 2; \
+ REALLOC(p, t, nalloc); \
+ }
+
+#ifdef DEBUG
+
+static void
+prtok (token t)
+{
+ char *s;
+
+ if (t < 0)
+ fprintf(stderr, "END");
+ else if (t < NOTCHAR)
+ fprintf(stderr, "%c", t);
+ else
+ {
+ switch (t)
+ {
+ case EMPTY: s = "EMPTY"; break;
+ case BACKREF: s = "BACKREF"; break;
+ case BEGLINE: s = "BEGLINE"; break;
+ case ENDLINE: s = "ENDLINE"; break;
+ case BEGWORD: s = "BEGWORD"; break;
+ case ENDWORD: s = "ENDWORD"; break;
+ case LIMWORD: s = "LIMWORD"; break;
+ case NOTLIMWORD: s = "NOTLIMWORD"; break;
+ case QMARK: s = "QMARK"; break;
+ case STAR: s = "STAR"; break;
+ case PLUS: s = "PLUS"; break;
+ case CAT: s = "CAT"; break;
+ case OR: s = "OR"; break;
+ case ORTOP: s = "ORTOP"; break;
+ case LPAREN: s = "LPAREN"; break;
+ case RPAREN: s = "RPAREN"; break;
+ default: s = "CSET"; break;
+ }
+ fprintf(stderr, "%s", s);
+ }
+}
+#endif /* DEBUG */
+
+/* Stuff pertaining to charclasses. */
+
+static int
+tstbit (int b, charclass c)
+{
+ return c[b / INTBITS] & 1 << b % INTBITS;
+}
+
+static void
+setbit (int b, charclass c)
+{
+ c[b / INTBITS] |= 1 << b % INTBITS;
+}
+
+static void
+clrbit (int b, charclass c)
+{
+ c[b / INTBITS] &= ~(1 << b % INTBITS);
+}
+
+static void
+copyset (charclass src, charclass dst)
+{
+ int i;
+
+ for (i = 0; i < CHARCLASS_INTS; ++i)
+ dst[i] = src[i];
+}
+
+static void
+zeroset (charclass s)
+{
+ int i;
+
+ for (i = 0; i < CHARCLASS_INTS; ++i)
+ s[i] = 0;
+}
+
+static void
+notset (charclass s)
+{
+ int i;
+
+ for (i = 0; i < CHARCLASS_INTS; ++i)
+ s[i] = ~s[i];
+}
+
+static int
+equal (charclass s1, charclass s2)
+{
+ int i;
+
+ for (i = 0; i < CHARCLASS_INTS; ++i)
+ if (s1[i] != s2[i])
+ return 0;
+ return 1;
+}
+
+/* A pointer to the current dfa is kept here during parsing. */
+static struct dfa *dfa;
+
+/* Find the index of charclass s in dfa->charclasses, or allocate a new charclass. */
+static int
+charclass_index (charclass s)
+{
+ int i;
+
+ for (i = 0; i < dfa->cindex; ++i)
+ if (equal(s, dfa->charclasses[i]))
+ return i;
+ REALLOC_IF_NECESSARY(dfa->charclasses, charclass, dfa->calloc, dfa->cindex);
+ ++dfa->cindex;
+ copyset(s, dfa->charclasses[i]);
+ return i;
+}
+
+/* Syntax bits controlling the behavior of the lexical analyzer. */
+static reg_syntax_t syntax_bits, syntax_bits_set;
+
+/* Flag for case-folding letters into sets. */
+static int case_fold;
+
+/* End-of-line byte in data. */
+static unsigned char eolbyte;
+
+/* Entry point to set syntax options. */
+void
+dfasyntax (reg_syntax_t bits, int fold, int eol)
+{
+ syntax_bits_set = 1;
+ syntax_bits = bits;
+ case_fold = fold;
+ eolbyte = eol;
+}
+
+/* Lexical analyzer. All the dross that deals with the obnoxious
+ GNU Regex syntax bits is located here. The poor, suffering
+ reader is referred to the GNU Regex documentation for the
+ meaning of the @#%!@#%^!@ syntax bits. */
+
+static char *lexstart; /* Pointer to beginning of input string. */
+static char *lexptr; /* Pointer to next input character. */
+static int lexleft; /* Number of characters remaining. */
+static token lasttok; /* Previous token returned; initially END. */
+static int laststart; /* True if we're separated from beginning or (, |
+ only by zero-width characters. */
+static int parens; /* Count of outstanding left parens. */
+static int minrep, maxrep; /* Repeat counts for {m,n}. */
+
+/* Note that characters become unsigned here. */
+#define FETCH(c, eoferr) \
+ { \
+ if (! lexleft) \
+ { \
+ if (eoferr != 0) \
+ dfaerror (eoferr); \
+ else \
+ return lasttok = END; \
+ } \
+ (c) = (unsigned char) *lexptr++; \
+ --lexleft; \
+ }
+
+#ifdef __STDC__
+#define FUNC(F, P) static int F(int c) { return P(c); }
+#else
+#define FUNC(F, P) static int F(c) int c; { return P(c); }
+#endif
+
+FUNC(is_alpha, ISALPHA)
+FUNC(is_upper, ISUPPER)
+FUNC(is_lower, ISLOWER)
+FUNC(is_digit, ISDIGIT)
+FUNC(is_xdigit, ISXDIGIT)
+FUNC(is_space, ISSPACE)
+FUNC(is_punct, ISPUNCT)
+FUNC(is_alnum, ISALNUM)
+FUNC(is_print, ISPRINT)
+FUNC(is_graph, ISGRAPH)
+FUNC(is_cntrl, ISCNTRL)
+
+static int
+is_blank (int c)
+{
+ return (c == ' ' || c == '\t');
+}
+
+/* The following list maps the names of the Posix named character classes
+ to predicate functions that determine whether a given character is in
+ the class. The leading [ has already been eaten by the lexical analyzer. */
+static struct {
+ const char *name;
+ int (*pred) PARAMS ((int));
+} prednames[] = {
+ { ":alpha:]", is_alpha },
+ { ":upper:]", is_upper },
+ { ":lower:]", is_lower },
+ { ":digit:]", is_digit },
+ { ":xdigit:]", is_xdigit },
+ { ":space:]", is_space },
+ { ":punct:]", is_punct },
+ { ":alnum:]", is_alnum },
+ { ":print:]", is_print },
+ { ":graph:]", is_graph },
+ { ":cntrl:]", is_cntrl },
+ { ":blank:]", is_blank },
+ { 0 }
+};
+
+/* Return non-zero if C is a `word-constituent' byte; zero otherwise. */
+#define IS_WORD_CONSTITUENT(C) (ISALNUM(C) || (C) == '_')
+
+static int
+looking_at (char const *s)
+{
+ size_t len;
+
+ len = strlen(s);
+ if (lexleft < len)
+ return 0;
+ return strncmp(s, lexptr, len) == 0;
+}
+
+static token
+lex (void)
+{
+ token c, c1, c2;
+ int backslash = 0, invert;
+ charclass ccl;
+ int i;
+ char lo[2];
+ char hi[2];
+
+ /* Basic plan: We fetch a character. If it's a backslash,
+ we set the backslash flag and go through the loop again.
+ On the plus side, this avoids having a duplicate of the
+ main switch inside the backslash case. On the minus side,
+ it means that just about every case begins with
+ "if (backslash) ...". */
+ for (i = 0; i < 2; ++i)
+ {
+ FETCH(c, 0);
+ switch (c)
+ {
+ case '\\':
+ if (backslash)
+ goto normal_char;
+ if (lexleft == 0)
+ dfaerror(_("Unfinished \\ escape"));
+ backslash = 1;
+ break;
+
+ case '^':
+ if (backslash)
+ goto normal_char;
+ if (syntax_bits & RE_CONTEXT_INDEP_ANCHORS
+ || lasttok == END
+ || lasttok == LPAREN
+ || lasttok == OR)
+ return lasttok = BEGLINE;
+ goto normal_char;
+
+ case '$':
+ if (backslash)
+ goto normal_char;
+ if (syntax_bits & RE_CONTEXT_INDEP_ANCHORS
+ || lexleft == 0
+ || (syntax_bits & RE_NO_BK_PARENS
+ ? lexleft > 0 && *lexptr == ')'
+ : lexleft > 1 && lexptr[0] == '\\' && lexptr[1] == ')')
+ || (syntax_bits & RE_NO_BK_VBAR
+ ? lexleft > 0 && *lexptr == '|'
+ : lexleft > 1 && lexptr[0] == '\\' && lexptr[1] == '|')
+ || ((syntax_bits & RE_NEWLINE_ALT)
+ && lexleft > 0 && *lexptr == '\n'))
+ return lasttok = ENDLINE;
+ goto normal_char;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (backslash && !(syntax_bits & RE_NO_BK_REFS))
+ {
+ laststart = 0;
+ return lasttok = BACKREF;
+ }
+ goto normal_char;
+
+ case '`':
+ if (backslash && !(syntax_bits & RE_NO_GNU_OPS))
+ return lasttok = BEGLINE; /* FIXME: should be beginning of string */
+ goto normal_char;
+
+ case '\'':
+ if (backslash && !(syntax_bits & RE_NO_GNU_OPS))
+ return lasttok = ENDLINE; /* FIXME: should be end of string */
+ goto normal_char;
+
+ case '<':
+ if (backslash && !(syntax_bits & RE_NO_GNU_OPS))
+ return lasttok = BEGWORD;
+ goto normal_char;
+
+ case '>':
+ if (backslash && !(syntax_bits & RE_NO_GNU_OPS))
+ return lasttok = ENDWORD;
+ goto normal_char;
+
+ case 'b':
+ if (backslash && !(syntax_bits & RE_NO_GNU_OPS))
+ return lasttok = LIMWORD;
+ goto normal_char;
+
+ case 'B':
+ if (backslash && !(syntax_bits & RE_NO_GNU_OPS))
+ return lasttok = NOTLIMWORD;
+ goto normal_char;
+
+ case '?':
+ if (syntax_bits & RE_LIMITED_OPS)
+ goto normal_char;
+ if (backslash != ((syntax_bits & RE_BK_PLUS_QM) != 0))
+ goto normal_char;
+ if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart)
+ goto normal_char;
+ return lasttok = QMARK;
+
+ case '*':
+ if (backslash)
+ goto normal_char;
+ if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart)
+ goto normal_char;
+ return lasttok = STAR;
+
+ case '+':
+ if (syntax_bits & RE_LIMITED_OPS)
+ goto normal_char;
+ if (backslash != ((syntax_bits & RE_BK_PLUS_QM) != 0))
+ goto normal_char;
+ if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart)
+ goto normal_char;
+ return lasttok = PLUS;
+
+ case '{':
+ if (!(syntax_bits & RE_INTERVALS))
+ goto normal_char;
+ if (backslash != ((syntax_bits & RE_NO_BK_BRACES) == 0))
+ goto normal_char;
+ if (!(syntax_bits & RE_CONTEXT_INDEP_OPS) && laststart)
+ goto normal_char;
+
+ if (syntax_bits & RE_NO_BK_BRACES)
+ {
+ /* Scan ahead for a valid interval; if it's not valid,
+ treat it as a literal '{'. */
+ int lo = -1, hi = -1;
+ char const *p = lexptr;
+ char const *lim = p + lexleft;
+ for (; p != lim && ISASCIIDIGIT (*p); p++)
+ lo = (lo < 0 ? 0 : lo * 10) + *p - '0';
+ if (p != lim && *p == ',')
+ while (++p != lim && ISASCIIDIGIT (*p))
+ hi = (hi < 0 ? 0 : hi * 10) + *p - '0';
+ else
+ hi = lo;
+ if (p == lim || *p != '}'
+ || lo < 0 || RE_DUP_MAX < hi || (0 <= hi && hi < lo))
+ goto normal_char;
+ }
+
+ minrep = 0;
+ /* Cases:
+ {M} - exact count
+ {M,} - minimum count, maximum is infinity
+ {M,N} - M through N */
+ FETCH(c, _("unfinished repeat count"));
+ if (ISASCIIDIGIT (c))
+ {
+ minrep = c - '0';
+ for (;;)
+ {
+ FETCH(c, _("unfinished repeat count"));
+ if (! ISASCIIDIGIT (c))
+ break;
+ minrep = 10 * minrep + c - '0';
+ }
+ }
+ else
+ dfaerror(_("malformed repeat count"));
+ if (c == ',')
+ {
+ FETCH (c, _("unfinished repeat count"));
+ if (! ISASCIIDIGIT (c))
+ maxrep = -1;
+ else
+ {
+ maxrep = c - '0';
+ for (;;)
+ {
+ FETCH (c, _("unfinished repeat count"));
+ if (! ISASCIIDIGIT (c))
+ break;
+ maxrep = 10 * maxrep + c - '0';
+ }
+ if (0 <= maxrep && maxrep < minrep)
+ dfaerror (_("malformed repeat count"));
+ }
+ }
+ else
+ maxrep = minrep;
+ if (!(syntax_bits & RE_NO_BK_BRACES))
+ {
+ if (c != '\\')
+ dfaerror(_("malformed repeat count"));
+ FETCH(c, _("unfinished repeat count"));
+ }
+ if (c != '}')
+ dfaerror(_("malformed repeat count"));
+ laststart = 0;
+ return lasttok = REPMN;
+
+ case '|':
+ if (syntax_bits & RE_LIMITED_OPS)
+ goto normal_char;
+ if (backslash != ((syntax_bits & RE_NO_BK_VBAR) == 0))
+ goto normal_char;
+ laststart = 1;
+ return lasttok = OR;
+
+ case '\n':
+ if (syntax_bits & RE_LIMITED_OPS
+ || backslash
+ || !(syntax_bits & RE_NEWLINE_ALT))
+ goto normal_char;
+ laststart = 1;
+ return lasttok = OR;
+
+ case '(':
+ if (backslash != ((syntax_bits & RE_NO_BK_PARENS) == 0))
+ goto normal_char;
+ ++parens;
+ laststart = 1;
+ return lasttok = LPAREN;
+
+ case ')':
+ if (backslash != ((syntax_bits & RE_NO_BK_PARENS) == 0))
+ goto normal_char;
+ if (parens == 0 && syntax_bits & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_char;
+ --parens;
+ laststart = 0;
+ return lasttok = RPAREN;
+
+ case '.':
+ if (backslash)
+ goto normal_char;
+ zeroset(ccl);
+ notset(ccl);
+ if (!(syntax_bits & RE_DOT_NEWLINE))
+ clrbit(eolbyte, ccl);
+ if (syntax_bits & RE_DOT_NOT_NULL)
+ clrbit('\0', ccl);
+ laststart = 0;
+ return lasttok = CSET + charclass_index(ccl);
+
+ case 'w':
+ case 'W':
+ if (!backslash || (syntax_bits & RE_NO_GNU_OPS))
+ goto normal_char;
+ zeroset(ccl);
+ for (c2 = 0; c2 < NOTCHAR; ++c2)
+ if (IS_WORD_CONSTITUENT(c2))
+ setbit(c2, ccl);
+ if (c == 'W')
+ notset(ccl);
+ laststart = 0;
+ return lasttok = CSET + charclass_index(ccl);
+
+ case '[':
+ if (backslash)
+ goto normal_char;
+ zeroset(ccl);
+ FETCH(c, _("Unbalanced ["));
+ if (c == '^')
+ {
+ FETCH(c, _("Unbalanced ["));
+ invert = 1;
+ }
+ else
+ invert = 0;
+ do
+ {
+ /* Nobody ever said this had to be fast. :-)
+ Note that if we're looking at some other [:...:]
+ construct, we just treat it as a bunch of ordinary
+ characters. We can do this because we assume
+ regex has checked for syntax errors before
+ dfa is ever called. */
+ if (c == '[' && (syntax_bits & RE_CHAR_CLASSES))
+ for (c1 = 0; prednames[c1].name; ++c1)
+ if (looking_at(prednames[c1].name))
+ {
+ int (*pred)() = prednames[c1].pred;
+ if (case_fold
+ && (pred == is_upper || pred == is_lower))
+ pred = is_alpha;
+
+ for (c2 = 0; c2 < NOTCHAR; ++c2)
+ if ((*pred)(c2))
+ setbit(c2, ccl);
+ lexptr += strlen(prednames[c1].name);
+ lexleft -= strlen(prednames[c1].name);
+ FETCH(c1, _("Unbalanced ["));
+ goto skip;
+ }
+ if (c == '\\' && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS))
+ FETCH(c, _("Unbalanced ["));
+ FETCH(c1, _("Unbalanced ["));
+ if (c1 == '-')
+ {
+ FETCH(c2, _("Unbalanced ["));
+ if (c2 == ']')
+ {
+ /* In the case [x-], the - is an ordinary hyphen,
+ which is left in c1, the lookahead character. */
+ --lexptr;
+ ++lexleft;
+ c2 = c;
+ }
+ else
+ {
+ if (c2 == '\\'
+ && (syntax_bits & RE_BACKSLASH_ESCAPE_IN_LISTS))
+ FETCH(c2, _("Unbalanced ["));
+ FETCH(c1, _("Unbalanced ["));
+ }
+ }
+ else
+ c2 = c;
+
+ lo[0] = c; lo[1] = '\0';
+ hi[0] = c2; hi[1] = '\0';
+ for (c = 0; c < NOTCHAR; c++)
+ {
+ char ch[2];
+ ch[0] = c; ch[1] = '\0';
+ if (strcoll (lo, ch) <= 0 && strcoll (ch, hi) <= 0)
+ {
+ setbit (c, ccl);
+ if (case_fold)
+ {
+ if (ISUPPER (c))
+ setbit (tolower (c), ccl);
+ else if (ISLOWER (c))
+ setbit (toupper (c), ccl);
+ }
+ }
+ }
+
+ skip:
+ ;
+ }
+ while ((c = c1) != ']');
+ if (invert)
+ {
+ notset(ccl);
+ if (syntax_bits & RE_HAT_LISTS_NOT_NEWLINE)
+ clrbit(eolbyte, ccl);
+ }
+ laststart = 0;
+ return lasttok = CSET + charclass_index(ccl);
+
+ default:
+ normal_char:
+ laststart = 0;
+ if (case_fold && ISALPHA(c))
+ {
+ zeroset(ccl);
+ setbit(c, ccl);
+ if (isupper(c))
+ setbit(tolower(c), ccl);
+ else
+ setbit(toupper(c), ccl);
+ return lasttok = CSET + charclass_index(ccl);
+ }
+ return c;
+ }
+ }
+
+ /* The above loop should consume at most a backslash
+ and some other character. */
+ abort();
+ return END; /* keeps pedantic compilers happy. */
+}
+
+/* Recursive descent parser for regular expressions. */
+
+static token tok; /* Lookahead token. */
+static int depth; /* Current depth of a hypothetical stack
+ holding deferred productions. This is
+ used to determine the depth that will be
+ required of the real stack later on in
+ dfaanalyze(). */
+
+/* Add the given token to the parse tree, maintaining the depth count and
+ updating the maximum depth if necessary. */
+static void
+addtok (token t)
+{
+ REALLOC_IF_NECESSARY(dfa->tokens, token, dfa->talloc, dfa->tindex);
+ dfa->tokens[dfa->tindex++] = t;
+
+ switch (t)
+ {
+ case QMARK:
+ case STAR:
+ case PLUS:
+ break;
+
+ case CAT:
+ case OR:
+ case ORTOP:
+ --depth;
+ break;
+
+ default:
+ ++dfa->nleaves;
+ case EMPTY:
+ ++depth;
+ break;
+ }
+ if (depth > dfa->depth)
+ dfa->depth = depth;
+}
+
+/* The grammar understood by the parser is as follows.
+
+ regexp:
+ regexp OR branch
+ branch
+
+ branch:
+ branch closure
+ closure
+
+ closure:
+ closure QMARK
+ closure STAR
+ closure PLUS
+ atom
+
+ atom:
+ <normal character>
+ CSET
+ BACKREF
+ BEGLINE
+ ENDLINE
+ BEGWORD
+ ENDWORD
+ LIMWORD
+ NOTLIMWORD
+ <empty>
+
+ The parser builds a parse tree in postfix form in an array of tokens. */
+
+static void
+atom (void)
+{
+ if ((tok >= 0 && tok < NOTCHAR) || tok >= CSET || tok == BACKREF
+ || tok == BEGLINE || tok == ENDLINE || tok == BEGWORD
+ || tok == ENDWORD || tok == LIMWORD || tok == NOTLIMWORD)
+ {
+ addtok(tok);
+ tok = lex();
+ }
+ else if (tok == LPAREN)
+ {
+ tok = lex();
+ regexp(0);
+ if (tok != RPAREN)
+ dfaerror(_("Unbalanced ("));
+ tok = lex();
+ }
+ else
+ addtok(EMPTY);
+}
+
+/* Return the number of tokens in the given subexpression. */
+static int
+nsubtoks (int tindex)
+{
+ int ntoks1;
+
+ switch (dfa->tokens[tindex - 1])
+ {
+ default:
+ return 1;
+ case QMARK:
+ case STAR:
+ case PLUS:
+ return 1 + nsubtoks(tindex - 1);
+ case CAT:
+ case OR:
+ case ORTOP:
+ ntoks1 = nsubtoks(tindex - 1);
+ return 1 + ntoks1 + nsubtoks(tindex - 1 - ntoks1);
+ }
+}
+
+/* Copy the given subexpression to the top of the tree. */
+static void
+copytoks (int tindex, int ntokens)
+{
+ int i;
+
+ for (i = 0; i < ntokens; ++i)
+ addtok(dfa->tokens[tindex + i]);
+}
+
+static void
+closure (void)
+{
+ int tindex, ntokens, i;
+
+ atom();
+ while (tok == QMARK || tok == STAR || tok == PLUS || tok == REPMN)
+ if (tok == REPMN)
+ {
+ ntokens = nsubtoks(dfa->tindex);
+ tindex = dfa->tindex - ntokens;
+ if (maxrep < 0)
+ addtok(PLUS);
+ if (minrep == 0)
+ addtok(QMARK);
+ for (i = 1; i < minrep; ++i)
+ {
+ copytoks(tindex, ntokens);
+ addtok(CAT);
+ }
+ for (; i < maxrep; ++i)
+ {
+ copytoks(tindex, ntokens);
+ addtok(QMARK);
+ addtok(CAT);
+ }
+ tok = lex();
+ }
+ else
+ {
+ addtok(tok);
+ tok = lex();
+ }
+}
+
+static void
+branch (void)
+{
+ closure();
+ while (tok != RPAREN && tok != OR && tok >= 0)
+ {
+ closure();
+ addtok(CAT);
+ }
+}
+
+static void
+regexp (int toplevel)
+{
+ branch();
+ while (tok == OR)
+ {
+ tok = lex();
+ branch();
+ if (toplevel)
+ addtok(ORTOP);
+ else
+ addtok(OR);
+ }
+}
+
+/* Main entry point for the parser. S is a string to be parsed, len is the
+ length of the string, so s can include NUL characters. D is a pointer to
+ the struct dfa to parse into. */
+void
+dfaparse (char *s, size_t len, struct dfa *d)
+{
+ dfa = d;
+ lexstart = lexptr = s;
+ lexleft = len;
+ lasttok = END;
+ laststart = 1;
+ parens = 0;
+
+ if (! syntax_bits_set)
+ dfaerror(_("No syntax specified"));
+
+ tok = lex();
+ depth = d->depth;
+
+ regexp(1);
+
+ if (tok != END)
+ dfaerror(_("Unbalanced )"));
+
+ addtok(END - d->nregexps);
+ addtok(CAT);
+
+ if (d->nregexps)
+ addtok(ORTOP);
+
+ ++d->nregexps;
+}
+
+/* Some primitives for operating on sets of positions. */
+
+/* Copy one set to another; the destination must be large enough. */
+static void
+copy (position_set *src, position_set *dst)
+{
+ int i;
+
+ for (i = 0; i < src->nelem; ++i)
+ dst->elems[i] = src->elems[i];
+ dst->nelem = src->nelem;
+}
+
+/* Insert a position in a set. Position sets are maintained in sorted
+ order according to index. If position already exists in the set with
+ the same index then their constraints are logically or'd together.
+ S->elems must point to an array large enough to hold the resulting set. */
+static void
+insert (position p, position_set *s)
+{
+ int i;
+ position t1, t2;
+
+ for (i = 0; i < s->nelem && p.index < s->elems[i].index; ++i)
+ continue;
+ if (i < s->nelem && p.index == s->elems[i].index)
+ s->elems[i].constraint |= p.constraint;
+ else
+ {
+ t1 = p;
+ ++s->nelem;
+ while (i < s->nelem)
+ {
+ t2 = s->elems[i];
+ s->elems[i++] = t1;
+ t1 = t2;
+ }
+ }
+}
+
+/* Merge two sets of positions into a third. The result is exactly as if
+ the positions of both sets were inserted into an initially empty set. */
+static void
+merge (position_set *s1, position_set *s2, position_set *m)
+{
+ int i = 0, j = 0;
+
+ m->nelem = 0;
+ while (i < s1->nelem && j < s2->nelem)
+ if (s1->elems[i].index > s2->elems[j].index)
+ m->elems[m->nelem++] = s1->elems[i++];
+ else if (s1->elems[i].index < s2->elems[j].index)
+ m->elems[m->nelem++] = s2->elems[j++];
+ else
+ {
+ m->elems[m->nelem] = s1->elems[i++];
+ m->elems[m->nelem++].constraint |= s2->elems[j++].constraint;
+ }
+ while (i < s1->nelem)
+ m->elems[m->nelem++] = s1->elems[i++];
+ while (j < s2->nelem)
+ m->elems[m->nelem++] = s2->elems[j++];
+}
+
+/* Delete a position from a set. */
+static void
+delete (position p, position_set *s)
+{
+ int i;
+
+ for (i = 0; i < s->nelem; ++i)
+ if (p.index == s->elems[i].index)
+ break;
+ if (i < s->nelem)
+ for (--s->nelem; i < s->nelem; ++i)
+ s->elems[i] = s->elems[i + 1];
+}
+
+/* Find the index of the state corresponding to the given position set with
+ the given preceding context, or create a new state if there is no such
+ state. Newline and letter tell whether we got here on a newline or
+ letter, respectively. */
+static int
+state_index (struct dfa *d, position_set *s, int newline, int letter)
+{
+ int hash = 0;
+ int constraint;
+ int i, j;
+
+ newline = newline ? 1 : 0;
+ letter = letter ? 1 : 0;
+
+ for (i = 0; i < s->nelem; ++i)
+ hash ^= s->elems[i].index + s->elems[i].constraint;
+
+ /* Try to find a state that exactly matches the proposed one. */
+ for (i = 0; i < d->sindex; ++i)
+ {
+ if (hash != d->states[i].hash || s->nelem != d->states[i].elems.nelem
+ || newline != d->states[i].newline || letter != d->states[i].letter)
+ continue;
+ for (j = 0; j < s->nelem; ++j)
+ if (s->elems[j].constraint
+ != d->states[i].elems.elems[j].constraint
+ || s->elems[j].index != d->states[i].elems.elems[j].index)
+ break;
+ if (j == s->nelem)
+ return i;
+ }
+
+ /* We'll have to create a new state. */
+ REALLOC_IF_NECESSARY(d->states, dfa_state, d->salloc, d->sindex);
+ d->states[i].hash = hash;
+ MALLOC(d->states[i].elems.elems, position, s->nelem);
+ copy(s, &d->states[i].elems);
+ d->states[i].newline = newline;
+ d->states[i].letter = letter;
+ d->states[i].backref = 0;
+ d->states[i].constraint = 0;
+ d->states[i].first_end = 0;
+ for (j = 0; j < s->nelem; ++j)
+ if (d->tokens[s->elems[j].index] < 0)
+ {
+ constraint = s->elems[j].constraint;
+ if (SUCCEEDS_IN_CONTEXT(constraint, newline, 0, letter, 0)
+ || SUCCEEDS_IN_CONTEXT(constraint, newline, 0, letter, 1)
+ || SUCCEEDS_IN_CONTEXT(constraint, newline, 1, letter, 0)
+ || SUCCEEDS_IN_CONTEXT(constraint, newline, 1, letter, 1))
+ d->states[i].constraint |= constraint;
+ if (! d->states[i].first_end)
+ d->states[i].first_end = d->tokens[s->elems[j].index];
+ }
+ else if (d->tokens[s->elems[j].index] == BACKREF)
+ {
+ d->states[i].constraint = NO_CONSTRAINT;
+ d->states[i].backref = 1;
+ }
+
+ ++d->sindex;
+
+ return i;
+}
+
+/* Find the epsilon closure of a set of positions. If any position of the set
+ contains a symbol that matches the empty string in some context, replace
+ that position with the elements of its follow labeled with an appropriate
+ constraint. Repeat exhaustively until no funny positions are left.
+ S->elems must be large enough to hold the result. */
+static void
+epsclosure (position_set *s, struct dfa *d)
+{
+ int i, j;
+ int *visited;
+ position p, old;
+
+ MALLOC(visited, int, d->tindex);
+ for (i = 0; i < d->tindex; ++i)
+ visited[i] = 0;
+
+ for (i = 0; i < s->nelem; ++i)
+ if (d->tokens[s->elems[i].index] >= NOTCHAR
+ && d->tokens[s->elems[i].index] != BACKREF
+ && d->tokens[s->elems[i].index] < CSET)
+ {
+ old = s->elems[i];
+ p.constraint = old.constraint;
+ delete(s->elems[i], s);
+ if (visited[old.index])
+ {
+ --i;
+ continue;
+ }
+ visited[old.index] = 1;
+ switch (d->tokens[old.index])
+ {
+ case BEGLINE:
+ p.constraint &= BEGLINE_CONSTRAINT;
+ break;
+ case ENDLINE:
+ p.constraint &= ENDLINE_CONSTRAINT;
+ break;
+ case BEGWORD:
+ p.constraint &= BEGWORD_CONSTRAINT;
+ break;
+ case ENDWORD:
+ p.constraint &= ENDWORD_CONSTRAINT;
+ break;
+ case LIMWORD:
+ p.constraint &= LIMWORD_CONSTRAINT;
+ break;
+ case NOTLIMWORD:
+ p.constraint &= NOTLIMWORD_CONSTRAINT;
+ break;
+ default:
+ break;
+ }
+ for (j = 0; j < d->follows[old.index].nelem; ++j)
+ {
+ p.index = d->follows[old.index].elems[j].index;
+ insert(p, s);
+ }
+ /* Force rescan to start at the beginning. */
+ i = -1;
+ }
+
+ free(visited);
+}
+
+/* Perform bottom-up analysis on the parse tree, computing various functions.
+ Note that at this point, we're pretending constructs like \< are real
+ characters rather than constraints on what can follow them.
+
+ Nullable: A node is nullable if it is at the root of a regexp that can
+ match the empty string.
+ * EMPTY leaves are nullable.
+ * No other leaf is nullable.
+ * A QMARK or STAR node is nullable.
+ * A PLUS node is nullable if its argument is nullable.
+ * A CAT node is nullable if both its arguments are nullable.
+ * An OR node is nullable if either argument is nullable.
+
+ Firstpos: The firstpos of a node is the set of positions (nonempty leaves)
+ that could correspond to the first character of a string matching the
+ regexp rooted at the given node.
+ * EMPTY leaves have empty firstpos.
+ * The firstpos of a nonempty leaf is that leaf itself.
+ * The firstpos of a QMARK, STAR, or PLUS node is the firstpos of its
+ argument.
+ * The firstpos of a CAT node is the firstpos of the left argument, union
+ the firstpos of the right if the left argument is nullable.
+ * The firstpos of an OR node is the union of firstpos of each argument.
+
+ Lastpos: The lastpos of a node is the set of positions that could
+ correspond to the last character of a string matching the regexp at
+ the given node.
+ * EMPTY leaves have empty lastpos.
+ * The lastpos of a nonempty leaf is that leaf itself.
+ * The lastpos of a QMARK, STAR, or PLUS node is the lastpos of its
+ argument.
+ * The lastpos of a CAT node is the lastpos of its right argument, union
+ the lastpos of the left if the right argument is nullable.
+ * The lastpos of an OR node is the union of the lastpos of each argument.
+
+ Follow: The follow of a position is the set of positions that could
+ correspond to the character following a character matching the node in
+ a string matching the regexp. At this point we consider special symbols
+ that match the empty string in some context to be just normal characters.
+ Later, if we find that a special symbol is in a follow set, we will
+ replace it with the elements of its follow, labeled with an appropriate
+ constraint.
+ * Every node in the firstpos of the argument of a STAR or PLUS node is in
+ the follow of every node in the lastpos.
+ * Every node in the firstpos of the second argument of a CAT node is in
+ the follow of every node in the lastpos of the first argument.
+
+ Because of the postfix representation of the parse tree, the depth-first
+ analysis is conveniently done by a linear scan with the aid of a stack.
+ Sets are stored as arrays of the elements, obeying a stack-like allocation
+ scheme; the number of elements in each set deeper in the stack can be
+ used to determine the address of a particular set's array. */
+void
+dfaanalyze (struct dfa *d, int searchflag)
+{
+ int *nullable; /* Nullable stack. */
+ int *nfirstpos; /* Element count stack for firstpos sets. */
+ position *firstpos; /* Array where firstpos elements are stored. */
+ int *nlastpos; /* Element count stack for lastpos sets. */
+ position *lastpos; /* Array where lastpos elements are stored. */
+ int *nalloc; /* Sizes of arrays allocated to follow sets. */
+ position_set tmp; /* Temporary set for merging sets. */
+ position_set merged; /* Result of merging sets. */
+ int wants_newline; /* True if some position wants newline info. */
+ int *o_nullable;
+ int *o_nfirst, *o_nlast;
+ position *o_firstpos, *o_lastpos;
+ int i, j;
+ position *pos;
+
+#ifdef DEBUG
+ fprintf(stderr, "dfaanalyze:\n");
+ for (i = 0; i < d->tindex; ++i)
+ {
+ fprintf(stderr, " %d:", i);
+ prtok(d->tokens[i]);
+ }
+ putc('\n', stderr);
+#endif
+
+ d->searchflag = searchflag;
+
+ MALLOC(nullable, int, d->depth);
+ o_nullable = nullable;
+ MALLOC(nfirstpos, int, d->depth);
+ o_nfirst = nfirstpos;
+ MALLOC(firstpos, position, d->nleaves);
+ o_firstpos = firstpos, firstpos += d->nleaves;
+ MALLOC(nlastpos, int, d->depth);
+ o_nlast = nlastpos;
+ MALLOC(lastpos, position, d->nleaves);
+ o_lastpos = lastpos, lastpos += d->nleaves;
+ MALLOC(nalloc, int, d->tindex);
+ for (i = 0; i < d->tindex; ++i)
+ nalloc[i] = 0;
+ MALLOC(merged.elems, position, d->nleaves);
+
+ CALLOC(d->follows, position_set, d->tindex);
+
+ for (i = 0; i < d->tindex; ++i)
+#ifdef DEBUG
+ { /* Nonsyntactic #ifdef goo... */
+#endif
+ switch (d->tokens[i])
+ {
+ case EMPTY:
+ /* The empty set is nullable. */
+ *nullable++ = 1;
+
+ /* The firstpos and lastpos of the empty leaf are both empty. */
+ *nfirstpos++ = *nlastpos++ = 0;
+ break;
+
+ case STAR:
+ case PLUS:
+ /* Every element in the firstpos of the argument is in the follow
+ of every element in the lastpos. */
+ tmp.nelem = nfirstpos[-1];
+ tmp.elems = firstpos;
+ pos = lastpos;
+ for (j = 0; j < nlastpos[-1]; ++j)
+ {
+ merge(&tmp, &d->follows[pos[j].index], &merged);
+ REALLOC_IF_NECESSARY(d->follows[pos[j].index].elems, position,
+ nalloc[pos[j].index], merged.nelem - 1);
+ copy(&merged, &d->follows[pos[j].index]);
+ }
+
+ case QMARK:
+ /* A QMARK or STAR node is automatically nullable. */
+ if (d->tokens[i] != PLUS)
+ nullable[-1] = 1;
+ break;
+
+ case CAT:
+ /* Every element in the firstpos of the second argument is in the
+ follow of every element in the lastpos of the first argument. */
+ tmp.nelem = nfirstpos[-1];
+ tmp.elems = firstpos;
+ pos = lastpos + nlastpos[-1];
+ for (j = 0; j < nlastpos[-2]; ++j)
+ {
+ merge(&tmp, &d->follows[pos[j].index], &merged);
+ REALLOC_IF_NECESSARY(d->follows[pos[j].index].elems, position,
+ nalloc[pos[j].index], merged.nelem - 1);
+ copy(&merged, &d->follows[pos[j].index]);
+ }
+
+ /* The firstpos of a CAT node is the firstpos of the first argument,
+ union that of the second argument if the first is nullable. */
+ if (nullable[-2])
+ nfirstpos[-2] += nfirstpos[-1];
+ else
+ firstpos += nfirstpos[-1];
+ --nfirstpos;
+
+ /* The lastpos of a CAT node is the lastpos of the second argument,
+ union that of the first argument if the second is nullable. */
+ if (nullable[-1])
+ nlastpos[-2] += nlastpos[-1];
+ else
+ {
+ pos = lastpos + nlastpos[-2];
+ for (j = nlastpos[-1] - 1; j >= 0; --j)
+ pos[j] = lastpos[j];
+ lastpos += nlastpos[-2];
+ nlastpos[-2] = nlastpos[-1];
+ }
+ --nlastpos;
+
+ /* A CAT node is nullable if both arguments are nullable. */
+ nullable[-2] = nullable[-1] && nullable[-2];
+ --nullable;
+ break;
+
+ case OR:
+ case ORTOP:
+ /* The firstpos is the union of the firstpos of each argument. */
+ nfirstpos[-2] += nfirstpos[-1];
+ --nfirstpos;
+
+ /* The lastpos is the union of the lastpos of each argument. */
+ nlastpos[-2] += nlastpos[-1];
+ --nlastpos;
+
+ /* An OR node is nullable if either argument is nullable. */
+ nullable[-2] = nullable[-1] || nullable[-2];
+ --nullable;
+ break;
+
+ default:
+ /* Anything else is a nonempty position. (Note that special
+ constructs like \< are treated as nonempty strings here;
+ an "epsilon closure" effectively makes them nullable later.
+ Backreferences have to get a real position so we can detect
+ transitions on them later. But they are nullable. */
+ *nullable++ = d->tokens[i] == BACKREF;
+
+ /* This position is in its own firstpos and lastpos. */
+ *nfirstpos++ = *nlastpos++ = 1;
+ --firstpos, --lastpos;
+ firstpos->index = lastpos->index = i;
+ firstpos->constraint = lastpos->constraint = NO_CONSTRAINT;
+
+ /* Allocate the follow set for this position. */
+ nalloc[i] = 1;
+ MALLOC(d->follows[i].elems, position, nalloc[i]);
+ break;
+ }
+#ifdef DEBUG
+ /* ... balance the above nonsyntactic #ifdef goo... */
+ fprintf(stderr, "node %d:", i);
+ prtok(d->tokens[i]);
+ putc('\n', stderr);
+ fprintf(stderr, nullable[-1] ? " nullable: yes\n" : " nullable: no\n");
+ fprintf(stderr, " firstpos:");
+ for (j = nfirstpos[-1] - 1; j >= 0; --j)
+ {
+ fprintf(stderr, " %d:", firstpos[j].index);
+ prtok(d->tokens[firstpos[j].index]);
+ }
+ fprintf(stderr, "\n lastpos:");
+ for (j = nlastpos[-1] - 1; j >= 0; --j)
+ {
+ fprintf(stderr, " %d:", lastpos[j].index);
+ prtok(d->tokens[lastpos[j].index]);
+ }
+ putc('\n', stderr);
+ }
+#endif
+
+ /* For each follow set that is the follow set of a real position, replace
+ it with its epsilon closure. */
+ for (i = 0; i < d->tindex; ++i)
+ if (d->tokens[i] < NOTCHAR || d->tokens[i] == BACKREF
+ || d->tokens[i] >= CSET)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "follows(%d:", i);
+ prtok(d->tokens[i]);
+ fprintf(stderr, "):");
+ for (j = d->follows[i].nelem - 1; j >= 0; --j)
+ {
+ fprintf(stderr, " %d:", d->follows[i].elems[j].index);
+ prtok(d->tokens[d->follows[i].elems[j].index]);
+ }
+ putc('\n', stderr);
+#endif
+ copy(&d->follows[i], &merged);
+ epsclosure(&merged, d);
+ if (d->follows[i].nelem < merged.nelem)
+ REALLOC(d->follows[i].elems, position, merged.nelem);
+ copy(&merged, &d->follows[i]);
+ }
+
+ /* Get the epsilon closure of the firstpos of the regexp. The result will
+ be the set of positions of state 0. */
+ merged.nelem = 0;
+ for (i = 0; i < nfirstpos[-1]; ++i)
+ insert(firstpos[i], &merged);
+ epsclosure(&merged, d);
+
+ /* Check if any of the positions of state 0 will want newline context. */
+ wants_newline = 0;
+ for (i = 0; i < merged.nelem; ++i)
+ if (PREV_NEWLINE_DEPENDENT(merged.elems[i].constraint))
+ wants_newline = 1;
+
+ /* Build the initial state. */
+ d->salloc = 1;
+ d->sindex = 0;
+ MALLOC(d->states, dfa_state, d->salloc);
+ state_index(d, &merged, wants_newline, 0);
+
+ free(o_nullable);
+ free(o_nfirst);
+ free(o_firstpos);
+ free(o_nlast);
+ free(o_lastpos);
+ free(nalloc);
+ free(merged.elems);
+}
+
+/* Find, for each character, the transition out of state s of d, and store
+ it in the appropriate slot of trans.
+
+ We divide the positions of s into groups (positions can appear in more
+ than one group). Each group is labeled with a set of characters that
+ every position in the group matches (taking into account, if necessary,
+ preceding context information of s). For each group, find the union
+ of the its elements' follows. This set is the set of positions of the
+ new state. For each character in the group's label, set the transition
+ on this character to be to a state corresponding to the set's positions,
+ and its associated backward context information, if necessary.
+
+ If we are building a searching matcher, we include the positions of state
+ 0 in every state.
+
+ The collection of groups is constructed by building an equivalence-class
+ partition of the positions of s.
+
+ For each position, find the set of characters C that it matches. Eliminate
+ any characters from C that fail on grounds of backward context.
+
+ Search through the groups, looking for a group whose label L has nonempty
+ intersection with C. If L - C is nonempty, create a new group labeled
+ L - C and having the same positions as the current group, and set L to
+ the intersection of L and C. Insert the position in this group, set
+ C = C - L, and resume scanning.
+
+ If after comparing with every group there are characters remaining in C,
+ create a new group labeled with the characters of C and insert this
+ position in that group. */
+void
+dfastate (int s, struct dfa *d, int trans[])
+{
+ position_set grps[NOTCHAR]; /* As many as will ever be needed. */
+ charclass labels[NOTCHAR]; /* Labels corresponding to the groups. */
+ int ngrps = 0; /* Number of groups actually used. */
+ position pos; /* Current position being considered. */
+ charclass matches; /* Set of matching characters. */
+ int matchesf; /* True if matches is nonempty. */
+ charclass intersect; /* Intersection with some label set. */
+ int intersectf; /* True if intersect is nonempty. */
+ charclass leftovers; /* Stuff in the label that didn't match. */
+ int leftoversf; /* True if leftovers is nonempty. */
+ static charclass letters; /* Set of characters considered letters. */
+ static charclass newline; /* Set of characters that aren't newline. */
+ position_set follows; /* Union of the follows of some group. */
+ position_set tmp; /* Temporary space for merging sets. */
+ int state; /* New state. */
+ int wants_newline; /* New state wants to know newline context. */
+ int state_newline; /* New state on a newline transition. */
+ int wants_letter; /* New state wants to know letter context. */
+ int state_letter; /* New state on a letter transition. */
+ static int initialized; /* Flag for static initialization. */
+ int i, j, k;
+
+ /* Initialize the set of letters, if necessary. */
+ if (! initialized)
+ {
+ initialized = 1;
+ for (i = 0; i < NOTCHAR; ++i)
+ if (IS_WORD_CONSTITUENT(i))
+ setbit(i, letters);
+ setbit(eolbyte, newline);
+ }
+
+ zeroset(matches);
+
+ for (i = 0; i < d->states[s].elems.nelem; ++i)
+ {
+ pos = d->states[s].elems.elems[i];
+ if (d->tokens[pos.index] >= 0 && d->tokens[pos.index] < NOTCHAR)
+ setbit(d->tokens[pos.index], matches);
+ else if (d->tokens[pos.index] >= CSET)
+ copyset(d->charclasses[d->tokens[pos.index] - CSET], matches);
+ else
+ continue;
+
+ /* Some characters may need to be eliminated from matches because
+ they fail in the current context. */
+ if (pos.constraint != 0xFF)
+ {
+ if (! MATCHES_NEWLINE_CONTEXT(pos.constraint,
+ d->states[s].newline, 1))
+ clrbit(eolbyte, matches);
+ if (! MATCHES_NEWLINE_CONTEXT(pos.constraint,
+ d->states[s].newline, 0))
+ for (j = 0; j < CHARCLASS_INTS; ++j)
+ matches[j] &= newline[j];
+ if (! MATCHES_LETTER_CONTEXT(pos.constraint,
+ d->states[s].letter, 1))
+ for (j = 0; j < CHARCLASS_INTS; ++j)
+ matches[j] &= ~letters[j];
+ if (! MATCHES_LETTER_CONTEXT(pos.constraint,
+ d->states[s].letter, 0))
+ for (j = 0; j < CHARCLASS_INTS; ++j)
+ matches[j] &= letters[j];
+
+ /* If there are no characters left, there's no point in going on. */
+ for (j = 0; j < CHARCLASS_INTS && !matches[j]; ++j)
+ continue;
+ if (j == CHARCLASS_INTS)
+ continue;
+ }
+
+ for (j = 0; j < ngrps; ++j)
+ {
+ /* If matches contains a single character only, and the current
+ group's label doesn't contain that character, go on to the
+ next group. */
+ if (d->tokens[pos.index] >= 0 && d->tokens[pos.index] < NOTCHAR
+ && !tstbit(d->tokens[pos.index], labels[j]))
+ continue;
+
+ /* Check if this group's label has a nonempty intersection with
+ matches. */
+ intersectf = 0;
+ for (k = 0; k < CHARCLASS_INTS; ++k)
+ (intersect[k] = matches[k] & labels[j][k]) ? (intersectf = 1) : 0;
+ if (! intersectf)
+ continue;
+
+ /* It does; now find the set differences both ways. */
+ leftoversf = matchesf = 0;
+ for (k = 0; k < CHARCLASS_INTS; ++k)
+ {
+ /* Even an optimizing compiler can't know this for sure. */
+ int match = matches[k], label = labels[j][k];
+
+ (leftovers[k] = ~match & label) ? (leftoversf = 1) : 0;
+ (matches[k] = match & ~label) ? (matchesf = 1) : 0;
+ }
+
+ /* If there were leftovers, create a new group labeled with them. */
+ if (leftoversf)
+ {
+ copyset(leftovers, labels[ngrps]);
+ copyset(intersect, labels[j]);
+ MALLOC(grps[ngrps].elems, position, d->nleaves);
+ copy(&grps[j], &grps[ngrps]);
+ ++ngrps;
+ }
+
+ /* Put the position in the current group. Note that there is no
+ reason to call insert() here. */
+ grps[j].elems[grps[j].nelem++] = pos;
+
+ /* If every character matching the current position has been
+ accounted for, we're done. */
+ if (! matchesf)
+ break;
+ }
+
+ /* If we've passed the last group, and there are still characters
+ unaccounted for, then we'll have to create a new group. */
+ if (j == ngrps)
+ {
+ copyset(matches, labels[ngrps]);
+ zeroset(matches);
+ MALLOC(grps[ngrps].elems, position, d->nleaves);
+ grps[ngrps].nelem = 1;
+ grps[ngrps].elems[0] = pos;
+ ++ngrps;
+ }
+ }
+
+ MALLOC(follows.elems, position, d->nleaves);
+ MALLOC(tmp.elems, position, d->nleaves);
+
+ /* If we are a searching matcher, the default transition is to a state
+ containing the positions of state 0, otherwise the default transition
+ is to fail miserably. */
+ if (d->searchflag)
+ {
+ wants_newline = 0;
+ wants_letter = 0;
+ for (i = 0; i < d->states[0].elems.nelem; ++i)
+ {
+ if (PREV_NEWLINE_DEPENDENT(d->states[0].elems.elems[i].constraint))
+ wants_newline = 1;
+ if (PREV_LETTER_DEPENDENT(d->states[0].elems.elems[i].constraint))
+ wants_letter = 1;
+ }
+ copy(&d->states[0].elems, &follows);
+ state = state_index(d, &follows, 0, 0);
+ if (wants_newline)
+ state_newline = state_index(d, &follows, 1, 0);
+ else
+ state_newline = state;
+ if (wants_letter)
+ state_letter = state_index(d, &follows, 0, 1);
+ else
+ state_letter = state;
+ for (i = 0; i < NOTCHAR; ++i)
+ trans[i] = (IS_WORD_CONSTITUENT(i)) ? state_letter : state;
+ trans[eolbyte] = state_newline;
+ }
+ else
+ for (i = 0; i < NOTCHAR; ++i)
+ trans[i] = -1;
+
+ for (i = 0; i < ngrps; ++i)
+ {
+ follows.nelem = 0;
+
+ /* Find the union of the follows of the positions of the group.
+ This is a hideously inefficient loop. Fix it someday. */
+ for (j = 0; j < grps[i].nelem; ++j)
+ for (k = 0; k < d->follows[grps[i].elems[j].index].nelem; ++k)
+ insert(d->follows[grps[i].elems[j].index].elems[k], &follows);
+
+ /* If we are building a searching matcher, throw in the positions
+ of state 0 as well. */
+ if (d->searchflag)
+ for (j = 0; j < d->states[0].elems.nelem; ++j)
+ insert(d->states[0].elems.elems[j], &follows);
+
+ /* Find out if the new state will want any context information. */
+ wants_newline = 0;
+ if (tstbit(eolbyte, labels[i]))
+ for (j = 0; j < follows.nelem; ++j)
+ if (PREV_NEWLINE_DEPENDENT(follows.elems[j].constraint))
+ wants_newline = 1;
+
+ wants_letter = 0;
+ for (j = 0; j < CHARCLASS_INTS; ++j)
+ if (labels[i][j] & letters[j])
+ break;
+ if (j < CHARCLASS_INTS)
+ for (j = 0; j < follows.nelem; ++j)
+ if (PREV_LETTER_DEPENDENT(follows.elems[j].constraint))
+ wants_letter = 1;
+
+ /* Find the state(s) corresponding to the union of the follows. */
+ state = state_index(d, &follows, 0, 0);
+ if (wants_newline)
+ state_newline = state_index(d, &follows, 1, 0);
+ else
+ state_newline = state;
+ if (wants_letter)
+ state_letter = state_index(d, &follows, 0, 1);
+ else
+ state_letter = state;
+
+ /* Set the transitions for each character in the current label. */
+ for (j = 0; j < CHARCLASS_INTS; ++j)
+ for (k = 0; k < INTBITS; ++k)
+ if (labels[i][j] & 1 << k)
+ {
+ int c = j * INTBITS + k;
+
+ if (c == eolbyte)
+ trans[c] = state_newline;
+ else if (IS_WORD_CONSTITUENT(c))
+ trans[c] = state_letter;
+ else if (c < NOTCHAR)
+ trans[c] = state;
+ }
+ }
+
+ for (i = 0; i < ngrps; ++i)
+ free(grps[i].elems);
+ free(follows.elems);
+ free(tmp.elems);
+}
+
+/* Some routines for manipulating a compiled dfa's transition tables.
+ Each state may or may not have a transition table; if it does, and it
+ is a non-accepting state, then d->trans[state] points to its table.
+ If it is an accepting state then d->fails[state] points to its table.
+ If it has no table at all, then d->trans[state] is NULL.
+ TODO: Improve this comment, get rid of the unnecessary redundancy. */
+
+static void
+build_state (int s, struct dfa *d)
+{
+ int *trans; /* The new transition table. */
+ int i;
+
+ /* Set an upper limit on the number of transition tables that will ever
+ exist at once. 1024 is arbitrary. The idea is that the frequently
+ used transition tables will be quickly rebuilt, whereas the ones that
+ were only needed once or twice will be cleared away. */
+ if (d->trcount >= 1024)
+ {
+ for (i = 0; i < d->tralloc; ++i)
+ if (d->trans[i])
+ {
+ free((ptr_t) d->trans[i]);
+ d->trans[i] = NULL;
+ }
+ else if (d->fails[i])
+ {
+ free((ptr_t) d->fails[i]);
+ d->fails[i] = NULL;
+ }
+ d->trcount = 0;
+ }
+
+ ++d->trcount;
+
+ /* Set up the success bits for this state. */
+ d->success[s] = 0;
+ if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 1, d->states[s].letter, 0,
+ s, *d))
+ d->success[s] |= 4;
+ if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 0, d->states[s].letter, 1,
+ s, *d))
+ d->success[s] |= 2;
+ if (ACCEPTS_IN_CONTEXT(d->states[s].newline, 0, d->states[s].letter, 0,
+ s, *d))
+ d->success[s] |= 1;
+
+ MALLOC(trans, int, NOTCHAR);
+ dfastate(s, d, trans);
+
+ /* Now go through the new transition table, and make sure that the trans
+ and fail arrays are allocated large enough to hold a pointer for the
+ largest state mentioned in the table. */
+ for (i = 0; i < NOTCHAR; ++i)
+ if (trans[i] >= d->tralloc)
+ {
+ int oldalloc = d->tralloc;
+
+ while (trans[i] >= d->tralloc)
+ d->tralloc *= 2;
+ REALLOC(d->realtrans, int *, d->tralloc + 1);
+ d->trans = d->realtrans + 1;
+ REALLOC(d->fails, int *, d->tralloc);
+ REALLOC(d->success, int, d->tralloc);
+ REALLOC(d->newlines, int, d->tralloc);
+ while (oldalloc < d->tralloc)
+ {
+ d->trans[oldalloc] = NULL;
+ d->fails[oldalloc++] = NULL;
+ }
+ }
+
+ /* Keep the newline transition in a special place so we can use it as
+ a sentinel. */
+ d->newlines[s] = trans[eolbyte];
+ trans[eolbyte] = -1;
+
+ if (ACCEPTING(s, *d))
+ d->fails[s] = trans;
+ else
+ d->trans[s] = trans;
+}
+
+static void
+build_state_zero (struct dfa *d)
+{
+ d->tralloc = 1;
+ d->trcount = 0;
+ CALLOC(d->realtrans, int *, d->tralloc + 1);
+ d->trans = d->realtrans + 1;
+ CALLOC(d->fails, int *, d->tralloc);
+ MALLOC(d->success, int, d->tralloc);
+ MALLOC(d->newlines, int, d->tralloc);
+ build_state(0, d);
+}
+
+/* Search through a buffer looking for a match to the given struct dfa.
+ Find the first occurrence of a string matching the regexp in the buffer,
+ and the shortest possible version thereof. Return a pointer to the first
+ character after the match, or NULL if none is found. Begin points to
+ the beginning of the buffer, and end points to the first character after
+ its end. We store a newline in *end to act as a sentinel, so end had
+ better point somewhere valid. Newline is a flag indicating whether to
+ allow newlines to be in the matching string. If count is non-
+ NULL it points to a place we're supposed to increment every time we
+ see a newline. Finally, if backref is non-NULL it points to a place
+ where we're supposed to store a 1 if backreferencing happened and the
+ match needs to be verified by a backtracking matcher. Otherwise
+ we store a 0 in *backref. */
+char *
+dfaexec (struct dfa *d, char *begin, char *end,
+ int newline, int *count, int *backref)
+{
+ register int s, s1, tmp; /* Current state. */
+ register unsigned char *p; /* Current input character. */
+ register int **trans, *t; /* Copy of d->trans so it can be optimized
+ into a register. */
+ register unsigned char eol = eolbyte; /* Likewise for eolbyte. */
+ static int sbit[NOTCHAR]; /* Table for anding with d->success. */
+ static int sbit_init;
+
+ if (! sbit_init)
+ {
+ int i;
+
+ sbit_init = 1;
+ for (i = 0; i < NOTCHAR; ++i)
+ sbit[i] = (IS_WORD_CONSTITUENT(i)) ? 2 : 1;
+ sbit[eol] = 4;
+ }
+
+ if (! d->tralloc)
+ build_state_zero(d);
+
+ s = s1 = 0;
+ p = (unsigned char *) begin;
+ trans = d->trans;
+ *end = eol;
+
+ for (;;)
+ {
+ while ((t = trans[s]) != 0) { /* hand-optimized loop */
+ s1 = t[*p++];
+ if ((t = trans[s1]) == 0) {
+ tmp = s ; s = s1 ; s1 = tmp ; /* swap */
+ break;
+ }
+ s = t[*p++];
+ }
+
+ if (s >= 0 && p <= (unsigned char *) end && d->fails[s])
+ {
+ if (d->success[s] & sbit[*p])
+ {
+ if (backref)
+ *backref = (d->states[s].backref != 0);
+ return (char *) p;
+ }
+
+ s1 = s;
+ s = d->fails[s][*p++];
+ continue;
+ }
+
+ /* If the previous character was a newline, count it. */
+ if (count && (char *) p <= end && p[-1] == eol)
+ ++*count;
+
+ /* Check if we've run off the end of the buffer. */
+ if ((char *) p > end)
+ return NULL;
+
+ if (s >= 0)
+ {
+ build_state(s, d);
+ trans = d->trans;
+ continue;
+ }
+
+ if (p[-1] == eol && newline)
+ {
+ s = d->newlines[s1];
+ continue;
+ }
+
+ s = 0;
+ }
+}
+
+/* Initialize the components of a dfa that the other routines don't
+ initialize for themselves. */
+void
+dfainit (struct dfa *d)
+{
+ d->calloc = 1;
+ MALLOC(d->charclasses, charclass, d->calloc);
+ d->cindex = 0;
+
+ d->talloc = 1;
+ MALLOC(d->tokens, token, d->talloc);
+ d->tindex = d->depth = d->nleaves = d->nregexps = 0;
+
+ d->searchflag = 0;
+ d->tralloc = 0;
+
+ d->musts = 0;
+}
+
+/* Parse and analyze a single string of the given length. */
+void
+dfacomp (char *s, size_t len, struct dfa *d, int searchflag)
+{
+ if (case_fold) /* dummy folding in service of dfamust() */
+ {
+ char *lcopy;
+ int i;
+
+ lcopy = malloc(len);
+ if (!lcopy)
+ dfaerror(_("out of memory"));
+
+ /* This is a kludge. */
+ case_fold = 0;
+ for (i = 0; i < len; ++i)
+ if (ISUPPER ((unsigned char) s[i]))
+ lcopy[i] = tolower ((unsigned char) s[i]);
+ else
+ lcopy[i] = s[i];
+
+ dfainit(d);
+ dfaparse(lcopy, len, d);
+ free(lcopy);
+ dfamust(d);
+ d->cindex = d->tindex = d->depth = d->nleaves = d->nregexps = 0;
+ case_fold = 1;
+ dfaparse(s, len, d);
+ dfaanalyze(d, searchflag);
+ }
+ else
+ {
+ dfainit(d);
+ dfaparse(s, len, d);
+ dfamust(d);
+ dfaanalyze(d, searchflag);
+ }
+}
+
+/* Free the storage held by the components of a dfa. */
+void
+dfafree (struct dfa *d)
+{
+ int i;
+ struct dfamust *dm, *ndm;
+
+ free((ptr_t) d->charclasses);
+ free((ptr_t) d->tokens);
+ for (i = 0; i < d->sindex; ++i)
+ free((ptr_t) d->states[i].elems.elems);
+ free((ptr_t) d->states);
+ for (i = 0; i < d->tindex; ++i)
+ if (d->follows[i].elems)
+ free((ptr_t) d->follows[i].elems);
+ free((ptr_t) d->follows);
+ for (i = 0; i < d->tralloc; ++i)
+ if (d->trans[i])
+ free((ptr_t) d->trans[i]);
+ else if (d->fails[i])
+ free((ptr_t) d->fails[i]);
+ if (d->realtrans) free((ptr_t) d->realtrans);
+ if (d->fails) free((ptr_t) d->fails);
+ if (d->newlines) free((ptr_t) d->newlines);
+ if (d->success) free((ptr_t) d->success);
+ for (dm = d->musts; dm; dm = ndm)
+ {
+ ndm = dm->next;
+ free(dm->must);
+ free((ptr_t) dm);
+ }
+}
+
+/* Having found the postfix representation of the regular expression,
+ try to find a long sequence of characters that must appear in any line
+ containing the r.e.
+ Finding a "longest" sequence is beyond the scope here;
+ we take an easy way out and hope for the best.
+ (Take "(ab|a)b"--please.)
+
+ We do a bottom-up calculation of sequences of characters that must appear
+ in matches of r.e.'s represented by trees rooted at the nodes of the postfix
+ representation:
+ sequences that must appear at the left of the match ("left")
+ sequences that must appear at the right of the match ("right")
+ lists of sequences that must appear somewhere in the match ("in")
+ sequences that must constitute the match ("is")
+
+ When we get to the root of the tree, we use one of the longest of its
+ calculated "in" sequences as our answer. The sequence we find is returned in
+ d->must (where "d" is the single argument passed to "dfamust");
+ the length of the sequence is returned in d->mustn.
+
+ The sequences calculated for the various types of node (in pseudo ANSI c)
+ are shown below. "p" is the operand of unary operators (and the left-hand
+ operand of binary operators); "q" is the right-hand operand of binary
+ operators.
+
+ "ZERO" means "a zero-length sequence" below.
+
+ Type left right is in
+ ---- ---- ----- -- --
+ char c # c # c # c # c
+
+ CSET ZERO ZERO ZERO ZERO
+
+ STAR ZERO ZERO ZERO ZERO
+
+ QMARK ZERO ZERO ZERO ZERO
+
+ PLUS p->left p->right ZERO p->in
+
+ CAT (p->is==ZERO)? (q->is==ZERO)? (p->is!=ZERO && p->in plus
+ p->left : q->right : q->is!=ZERO) ? q->in plus
+ p->is##q->left p->right##q->is p->is##q->is : p->right##q->left
+ ZERO
+
+ OR longest common longest common (do p->is and substrings common to
+ leading trailing q->is have same p->in and q->in
+ (sub)sequence (sub)sequence length and
+ of p->left of p->right content) ?
+ and q->left and q->right p->is : NULL
+
+ If there's anything else we recognize in the tree, all four sequences get set
+ to zero-length sequences. If there's something we don't recognize in the tree,
+ we just return a zero-length sequence.
+
+ Break ties in favor of infrequent letters (choosing 'zzz' in preference to
+ 'aaa')?
+
+ And. . .is it here or someplace that we might ponder "optimizations" such as
+ egrep 'psi|epsilon' -> egrep 'psi'
+ egrep 'pepsi|epsilon' -> egrep 'epsi'
+ (Yes, we now find "epsi" as a "string
+ that must occur", but we might also
+ simplify the *entire* r.e. being sought)
+ grep '[c]' -> grep 'c'
+ grep '(ab|a)b' -> grep 'ab'
+ grep 'ab*' -> grep 'a'
+ grep 'a*b' -> grep 'b'
+
+ There are several issues:
+
+ Is optimization easy (enough)?
+
+ Does optimization actually accomplish anything,
+ or is the automaton you get from "psi|epsilon" (for example)
+ the same as the one you get from "psi" (for example)?
+
+ Are optimizable r.e.'s likely to be used in real-life situations
+ (something like 'ab*' is probably unlikely; something like is
+ 'psi|epsilon' is likelier)? */
+
+static char *
+icatalloc (char *old, char *new)
+{
+ char *result;
+ size_t oldsize, newsize;
+
+ newsize = (new == NULL) ? 0 : strlen(new);
+ if (old == NULL)
+ oldsize = 0;
+ else if (newsize == 0)
+ return old;
+ else oldsize = strlen(old);
+ if (old == NULL)
+ result = (char *) malloc(newsize + 1);
+ else
+ result = (char *) realloc((void *) old, oldsize + newsize + 1);
+ if (result != NULL && new != NULL)
+ (void) strcpy(result + oldsize, new);
+ return result;
+}
+
+static char *
+icpyalloc (char *string)
+{
+ return icatalloc((char *) NULL, string);
+}
+
+static char *
+istrstr (char *lookin, char *lookfor)
+{
+ char *cp;
+ size_t len;
+
+ len = strlen(lookfor);
+ for (cp = lookin; *cp != '\0'; ++cp)
+ if (strncmp(cp, lookfor, len) == 0)
+ return cp;
+ return NULL;
+}
+
+static void
+ifree (char *cp)
+{
+ if (cp != NULL)
+ free(cp);
+}
+
+static void
+freelist (char **cpp)
+{
+ int i;
+
+ if (cpp == NULL)
+ return;
+ for (i = 0; cpp[i] != NULL; ++i)
+ {
+ free(cpp[i]);
+ cpp[i] = NULL;
+ }
+}
+
+static char **
+enlist (char **cpp, char *new, size_t len)
+{
+ int i, j;
+
+ if (cpp == NULL)
+ return NULL;
+ if ((new = icpyalloc(new)) == NULL)
+ {
+ freelist(cpp);
+ return NULL;
+ }
+ new[len] = '\0';
+ /* Is there already something in the list that's new (or longer)? */
+ for (i = 0; cpp[i] != NULL; ++i)
+ if (istrstr(cpp[i], new) != NULL)
+ {
+ free(new);
+ return cpp;
+ }
+ /* Eliminate any obsoleted strings. */
+ j = 0;
+ while (cpp[j] != NULL)
+ if (istrstr(new, cpp[j]) == NULL)
+ ++j;
+ else
+ {
+ free(cpp[j]);
+ if (--i == j)
+ break;
+ cpp[j] = cpp[i];
+ cpp[i] = NULL;
+ }
+ /* Add the new string. */
+ cpp = (char **) realloc((char *) cpp, (i + 2) * sizeof *cpp);
+ if (cpp == NULL)
+ return NULL;
+ cpp[i] = new;
+ cpp[i + 1] = NULL;
+ return cpp;
+}
+
+/* Given pointers to two strings, return a pointer to an allocated
+ list of their distinct common substrings. Return NULL if something
+ seems wild. */
+static char **
+comsubs (char *left, char *right)
+{
+ char **cpp;
+ char *lcp;
+ char *rcp;
+ size_t i, len;
+
+ if (left == NULL || right == NULL)
+ return NULL;
+ cpp = (char **) malloc(sizeof *cpp);
+ if (cpp == NULL)
+ return NULL;
+ cpp[0] = NULL;
+ for (lcp = left; *lcp != '\0'; ++lcp)
+ {
+ len = 0;
+ rcp = index(right, *lcp);
+ while (rcp != NULL)
+ {
+ for (i = 1; lcp[i] != '\0' && lcp[i] == rcp[i]; ++i)
+ continue;
+ if (i > len)
+ len = i;
+ rcp = index(rcp + 1, *lcp);
+ }
+ if (len == 0)
+ continue;
+ if ((cpp = enlist(cpp, lcp, len)) == NULL)
+ break;
+ }
+ return cpp;
+}
+
+static char **
+addlists (char **old, char **new)
+{
+ int i;
+
+ if (old == NULL || new == NULL)
+ return NULL;
+ for (i = 0; new[i] != NULL; ++i)
+ {
+ old = enlist(old, new[i], strlen(new[i]));
+ if (old == NULL)
+ break;
+ }
+ return old;
+}
+
+/* Given two lists of substrings, return a new list giving substrings
+ common to both. */
+static char **
+inboth (char **left, char **right)
+{
+ char **both;
+ char **temp;
+ int lnum, rnum;
+
+ if (left == NULL || right == NULL)
+ return NULL;
+ both = (char **) malloc(sizeof *both);
+ if (both == NULL)
+ return NULL;
+ both[0] = NULL;
+ for (lnum = 0; left[lnum] != NULL; ++lnum)
+ {
+ for (rnum = 0; right[rnum] != NULL; ++rnum)
+ {
+ temp = comsubs(left[lnum], right[rnum]);
+ if (temp == NULL)
+ {
+ freelist(both);
+ return NULL;
+ }
+ both = addlists(both, temp);
+ freelist(temp);
+ free(temp);
+ if (both == NULL)
+ return NULL;
+ }
+ }
+ return both;
+}
+
+typedef struct
+{
+ char **in;
+ char *left;
+ char *right;
+ char *is;
+} must;
+
+static void
+resetmust (must *mp)
+{
+ mp->left[0] = mp->right[0] = mp->is[0] = '\0';
+ freelist(mp->in);
+}
+
+static void
+dfamust (struct dfa *dfa)
+{
+ must *musts;
+ must *mp;
+ char *result;
+ int ri;
+ int i;
+ int exact;
+ token t;
+ static must must0;
+ struct dfamust *dm;
+ static char empty_string[] = "";
+
+ result = empty_string;
+ exact = 0;
+ musts = (must *) malloc((dfa->tindex + 1) * sizeof *musts);
+ if (musts == NULL)
+ return;
+ mp = musts;
+ for (i = 0; i <= dfa->tindex; ++i)
+ mp[i] = must0;
+ for (i = 0; i <= dfa->tindex; ++i)
+ {
+ mp[i].in = (char **) malloc(sizeof *mp[i].in);
+ mp[i].left = malloc(2);
+ mp[i].right = malloc(2);
+ mp[i].is = malloc(2);
+ if (mp[i].in == NULL || mp[i].left == NULL ||
+ mp[i].right == NULL || mp[i].is == NULL)
+ goto done;
+ mp[i].left[0] = mp[i].right[0] = mp[i].is[0] = '\0';
+ mp[i].in[0] = NULL;
+ }
+#ifdef DEBUG
+ fprintf(stderr, "dfamust:\n");
+ for (i = 0; i < dfa->tindex; ++i)
+ {
+ fprintf(stderr, " %d:", i);
+ prtok(dfa->tokens[i]);
+ }
+ putc('\n', stderr);
+#endif
+ for (ri = 0; ri < dfa->tindex; ++ri)
+ {
+ switch (t = dfa->tokens[ri])
+ {
+ case LPAREN:
+ case RPAREN:
+ goto done; /* "cannot happen" */
+ case EMPTY:
+ case BEGLINE:
+ case ENDLINE:
+ case BEGWORD:
+ case ENDWORD:
+ case LIMWORD:
+ case NOTLIMWORD:
+ case BACKREF:
+ resetmust(mp);
+ break;
+ case STAR:
+ case QMARK:
+ if (mp <= musts)
+ goto done; /* "cannot happen" */
+ --mp;
+ resetmust(mp);
+ break;
+ case OR:
+ case ORTOP:
+ if (mp < &musts[2])
+ goto done; /* "cannot happen" */
+ {
+ char **new;
+ must *lmp;
+ must *rmp;
+ int j, ln, rn, n;
+
+ rmp = --mp;
+ lmp = --mp;
+ /* Guaranteed to be. Unlikely, but. . . */
+ if (strcmp(lmp->is, rmp->is) != 0)
+ lmp->is[0] = '\0';
+ /* Left side--easy */
+ i = 0;
+ while (lmp->left[i] != '\0' && lmp->left[i] == rmp->left[i])
+ ++i;
+ lmp->left[i] = '\0';
+ /* Right side */
+ ln = strlen(lmp->right);
+ rn = strlen(rmp->right);
+ n = ln;
+ if (n > rn)
+ n = rn;
+ for (i = 0; i < n; ++i)
+ if (lmp->right[ln - i - 1] != rmp->right[rn - i - 1])
+ break;
+ for (j = 0; j < i; ++j)
+ lmp->right[j] = lmp->right[(ln - i) + j];
+ lmp->right[j] = '\0';
+ new = inboth(lmp->in, rmp->in);
+ if (new == NULL)
+ goto done;
+ freelist(lmp->in);
+ free((char *) lmp->in);
+ lmp->in = new;
+ }
+ break;
+ case PLUS:
+ if (mp <= musts)
+ goto done; /* "cannot happen" */
+ --mp;
+ mp->is[0] = '\0';
+ break;
+ case END:
+ if (mp != &musts[1])
+ goto done; /* "cannot happen" */
+ for (i = 0; musts[0].in[i] != NULL; ++i)
+ if (strlen(musts[0].in[i]) > strlen(result))
+ result = musts[0].in[i];
+ if (strcmp(result, musts[0].is) == 0)
+ exact = 1;
+ goto done;
+ case CAT:
+ if (mp < &musts[2])
+ goto done; /* "cannot happen" */
+ {
+ must *lmp;
+ must *rmp;
+
+ rmp = --mp;
+ lmp = --mp;
+ /* In. Everything in left, plus everything in
+ right, plus catenation of
+ left's right and right's left. */
+ lmp->in = addlists(lmp->in, rmp->in);
+ if (lmp->in == NULL)
+ goto done;
+ if (lmp->right[0] != '\0' &&
+ rmp->left[0] != '\0')
+ {
+ char *tp;
+
+ tp = icpyalloc(lmp->right);
+ if (tp == NULL)
+ goto done;
+ tp = icatalloc(tp, rmp->left);
+ if (tp == NULL)
+ goto done;
+ lmp->in = enlist(lmp->in, tp,
+ strlen(tp));
+ free(tp);
+ if (lmp->in == NULL)
+ goto done;
+ }
+ /* Left-hand */
+ if (lmp->is[0] != '\0')
+ {
+ lmp->left = icatalloc(lmp->left,
+ rmp->left);
+ if (lmp->left == NULL)
+ goto done;
+ }
+ /* Right-hand */
+ if (rmp->is[0] == '\0')
+ lmp->right[0] = '\0';
+ lmp->right = icatalloc(lmp->right, rmp->right);
+ if (lmp->right == NULL)
+ goto done;
+ /* Guaranteed to be */
+ if (lmp->is[0] != '\0' && rmp->is[0] != '\0')
+ {
+ lmp->is = icatalloc(lmp->is, rmp->is);
+ if (lmp->is == NULL)
+ goto done;
+ }
+ else
+ lmp->is[0] = '\0';
+ }
+ break;
+ default:
+ if (t < END)
+ {
+ /* "cannot happen" */
+ goto done;
+ }
+ else if (t == '\0')
+ {
+ /* not on *my* shift */
+ goto done;
+ }
+ else if (t >= CSET)
+ {
+ /* easy enough */
+ resetmust(mp);
+ }
+ else
+ {
+ /* plain character */
+ resetmust(mp);
+ mp->is[0] = mp->left[0] = mp->right[0] = t;
+ mp->is[1] = mp->left[1] = mp->right[1] = '\0';
+ mp->in = enlist(mp->in, mp->is, (size_t)1);
+ if (mp->in == NULL)
+ goto done;
+ }
+ break;
+ }
+#ifdef DEBUG
+ fprintf(stderr, " node: %d:", ri);
+ prtok(dfa->tokens[ri]);
+ fprintf(stderr, "\n in:");
+ for (i = 0; mp->in[i]; ++i)
+ fprintf(stderr, " \"%s\"", mp->in[i]);
+ fprintf(stderr, "\n is: \"%s\"\n", mp->is);
+ fprintf(stderr, " left: \"%s\"\n", mp->left);
+ fprintf(stderr, " right: \"%s\"\n", mp->right);
+#endif
+ ++mp;
+ }
+ done:
+ if (strlen(result))
+ {
+ dm = (struct dfamust *) malloc(sizeof (struct dfamust));
+ dm->exact = exact;
+ dm->must = malloc(strlen(result) + 1);
+ strcpy(dm->must, result);
+ dm->next = dfa->musts;
+ dfa->musts = dm;
+ }
+ mp = musts;
+ for (i = 0; i <= dfa->tindex; ++i)
+ {
+ freelist(mp[i].in);
+ ifree((char *) mp[i].in);
+ ifree(mp[i].left);
+ ifree(mp[i].right);
+ ifree(mp[i].is);
+ }
+ free((char *) mp);
+}
diff --git a/gnu/usr.bin/grep/dfa.h b/gnu/usr.bin/grep/dfa.h
new file mode 100644
index 0000000..2a7fed2
--- /dev/null
+++ b/gnu/usr.bin/grep/dfa.h
@@ -0,0 +1,374 @@
+/* dfa.h - declarations for GNU deterministic regexp compiler
+ Copyright (C) 1988, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 June, 1988 by Mike Haertel */
+
+/* $FreeBSD$ */
+
+/* FIXME:
+ 2. We should not export so much of the DFA internals.
+ In addition to clobbering modularity, we eat up valuable
+ name space. */
+
+# undef PARAMS
+#if __STDC__
+# ifndef _PTR_T
+# define _PTR_T
+ typedef void * ptr_t;
+# endif
+# define PARAMS(x) x
+#else
+# ifndef _PTR_T
+# define _PTR_T
+ typedef char * ptr_t;
+# endif
+# define PARAMS(x) ()
+#endif
+
+/* Number of bits in an unsigned char. */
+#ifndef CHARBITS
+#define CHARBITS 8
+#endif
+
+/* First integer value that is greater than any character code. */
+#define NOTCHAR (1 << CHARBITS)
+
+/* INTBITS need not be exact, just a lower bound. */
+#ifndef INTBITS
+#define INTBITS (CHARBITS * sizeof (int))
+#endif
+
+/* Number of ints required to hold a bit for every character. */
+#define CHARCLASS_INTS ((NOTCHAR + INTBITS - 1) / INTBITS)
+
+/* Sets of unsigned characters are stored as bit vectors in arrays of ints. */
+typedef int charclass[CHARCLASS_INTS];
+
+/* The regexp is parsed into an array of tokens in postfix form. Some tokens
+ are operators and others are terminal symbols. Most (but not all) of these
+ codes are returned by the lexical analyzer. */
+
+typedef enum
+{
+ END = -1, /* END is a terminal symbol that matches the
+ end of input; any value of END or less in
+ the parse tree is such a symbol. Accepting
+ states of the DFA are those that would have
+ a transition on END. */
+
+ /* Ordinary character values are terminal symbols that match themselves. */
+
+ EMPTY = NOTCHAR, /* EMPTY is a terminal symbol that matches
+ the empty string. */
+
+ BACKREF, /* BACKREF is generated by \<digit>; it
+ it not completely handled. If the scanner
+ detects a transition on backref, it returns
+ a kind of "semi-success" indicating that
+ the match will have to be verified with
+ a backtracking matcher. */
+
+ BEGLINE, /* BEGLINE is a terminal symbol that matches
+ the empty string if it is at the beginning
+ of a line. */
+
+ ENDLINE, /* ENDLINE is a terminal symbol that matches
+ the empty string if it is at the end of
+ a line. */
+
+ BEGWORD, /* BEGWORD is a terminal symbol that matches
+ the empty string if it is at the beginning
+ of a word. */
+
+ ENDWORD, /* ENDWORD is a terminal symbol that matches
+ the empty string if it is at the end of
+ a word. */
+
+ LIMWORD, /* LIMWORD is a terminal symbol that matches
+ the empty string if it is at the beginning
+ or the end of a word. */
+
+ NOTLIMWORD, /* NOTLIMWORD is a terminal symbol that
+ matches the empty string if it is not at
+ the beginning or end of a word. */
+
+ QMARK, /* QMARK is an operator of one argument that
+ matches zero or one occurences of its
+ argument. */
+
+ STAR, /* STAR is an operator of one argument that
+ matches the Kleene closure (zero or more
+ occurrences) of its argument. */
+
+ PLUS, /* PLUS is an operator of one argument that
+ matches the positive closure (one or more
+ occurrences) of its argument. */
+
+ REPMN, /* REPMN is a lexical token corresponding
+ to the {m,n} construct. REPMN never
+ appears in the compiled token vector. */
+
+ CAT, /* CAT is an operator of two arguments that
+ matches the concatenation of its
+ arguments. CAT is never returned by the
+ lexical analyzer. */
+
+ OR, /* OR is an operator of two arguments that
+ matches either of its arguments. */
+
+ ORTOP, /* OR at the toplevel in the parse tree.
+ This is used for a boyer-moore heuristic. */
+
+ LPAREN, /* LPAREN never appears in the parse tree,
+ it is only a lexeme. */
+
+ RPAREN, /* RPAREN never appears in the parse tree. */
+
+ CSET /* CSET and (and any value greater) is a
+ terminal symbol that matches any of a
+ class of characters. */
+} token;
+
+/* Sets are stored in an array in the compiled dfa; the index of the
+ array corresponding to a given set token is given by SET_INDEX(t). */
+#define SET_INDEX(t) ((t) - CSET)
+
+/* Sometimes characters can only be matched depending on the surrounding
+ context. Such context decisions depend on what the previous character
+ was, and the value of the current (lookahead) character. Context
+ dependent constraints are encoded as 8 bit integers. Each bit that
+ is set indicates that the constraint succeeds in the corresponding
+ context.
+
+ bit 7 - previous and current are newlines
+ bit 6 - previous was newline, current isn't
+ bit 5 - previous wasn't newline, current is
+ bit 4 - neither previous nor current is a newline
+ bit 3 - previous and current are word-constituents
+ bit 2 - previous was word-constituent, current isn't
+ bit 1 - previous wasn't word-constituent, current is
+ bit 0 - neither previous nor current is word-constituent
+
+ Word-constituent characters are those that satisfy isalnum().
+
+ The macro SUCCEEDS_IN_CONTEXT determines whether a a given constraint
+ succeeds in a particular context. Prevn is true if the previous character
+ was a newline, currn is true if the lookahead character is a newline.
+ Prevl and currl similarly depend upon whether the previous and current
+ characters are word-constituent letters. */
+#define MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \
+ ((constraint) & 1 << (((prevn) ? 2 : 0) + ((currn) ? 1 : 0) + 4))
+#define MATCHES_LETTER_CONTEXT(constraint, prevl, currl) \
+ ((constraint) & 1 << (((prevl) ? 2 : 0) + ((currl) ? 1 : 0)))
+#define SUCCEEDS_IN_CONTEXT(constraint, prevn, currn, prevl, currl) \
+ (MATCHES_NEWLINE_CONTEXT(constraint, prevn, currn) \
+ && MATCHES_LETTER_CONTEXT(constraint, prevl, currl))
+
+/* The following macros give information about what a constraint depends on. */
+#define PREV_NEWLINE_DEPENDENT(constraint) \
+ (((constraint) & 0xc0) >> 2 != ((constraint) & 0x30))
+#define PREV_LETTER_DEPENDENT(constraint) \
+ (((constraint) & 0x0c) >> 2 != ((constraint) & 0x03))
+
+/* Tokens that match the empty string subject to some constraint actually
+ work by applying that constraint to determine what may follow them,
+ taking into account what has gone before. The following values are
+ the constraints corresponding to the special tokens previously defined. */
+#define NO_CONSTRAINT 0xff
+#define BEGLINE_CONSTRAINT 0xcf
+#define ENDLINE_CONSTRAINT 0xaf
+#define BEGWORD_CONSTRAINT 0xf2
+#define ENDWORD_CONSTRAINT 0xf4
+#define LIMWORD_CONSTRAINT 0xf6
+#define NOTLIMWORD_CONSTRAINT 0xf9
+
+/* States of the recognizer correspond to sets of positions in the parse
+ tree, together with the constraints under which they may be matched.
+ So a position is encoded as an index into the parse tree together with
+ a constraint. */
+typedef struct
+{
+ unsigned index; /* Index into the parse array. */
+ unsigned constraint; /* Constraint for matching this position. */
+} position;
+
+/* Sets of positions are stored as arrays. */
+typedef struct
+{
+ position *elems; /* Elements of this position set. */
+ int nelem; /* Number of elements in this set. */
+} position_set;
+
+/* A state of the dfa consists of a set of positions, some flags,
+ and the token value of the lowest-numbered position of the state that
+ contains an END token. */
+typedef struct
+{
+ int hash; /* Hash of the positions of this state. */
+ position_set elems; /* Positions this state could match. */
+ char newline; /* True if previous state matched newline. */
+ char letter; /* True if previous state matched a letter. */
+ char backref; /* True if this state matches a \<digit>. */
+ unsigned char constraint; /* Constraint for this state to accept. */
+ int first_end; /* Token value of the first END in elems. */
+} dfa_state;
+
+/* Element of a list of strings, at least one of which is known to
+ appear in any R.E. matching the DFA. */
+struct dfamust
+{
+ int exact;
+ char *must;
+ struct dfamust *next;
+};
+
+/* A compiled regular expression. */
+struct dfa
+{
+ /* Stuff built by the scanner. */
+ charclass *charclasses; /* Array of character sets for CSET tokens. */
+ int cindex; /* Index for adding new charclasses. */
+ int calloc; /* Number of charclasses currently allocated. */
+
+ /* Stuff built by the parser. */
+ token *tokens; /* Postfix parse array. */
+ int tindex; /* Index for adding new tokens. */
+ int talloc; /* Number of tokens currently allocated. */
+ int depth; /* Depth required of an evaluation stack
+ used for depth-first traversal of the
+ parse tree. */
+ int nleaves; /* Number of leaves on the parse tree. */
+ int nregexps; /* Count of parallel regexps being built
+ with dfaparse(). */
+
+ /* Stuff owned by the state builder. */
+ dfa_state *states; /* States of the dfa. */
+ int sindex; /* Index for adding new states. */
+ int salloc; /* Number of states currently allocated. */
+
+ /* Stuff built by the structure analyzer. */
+ position_set *follows; /* Array of follow sets, indexed by position
+ index. The follow of a position is the set
+ of positions containing characters that
+ could conceivably follow a character
+ matching the given position in a string
+ matching the regexp. Allocated to the
+ maximum possible position index. */
+ int searchflag; /* True if we are supposed to build a searching
+ as opposed to an exact matcher. A searching
+ matcher finds the first and shortest string
+ matching a regexp anywhere in the buffer,
+ whereas an exact matcher finds the longest
+ string matching, but anchored to the
+ beginning of the buffer. */
+
+ /* Stuff owned by the executor. */
+ int tralloc; /* Number of transition tables that have
+ slots so far. */
+ int trcount; /* Number of transition tables that have
+ actually been built. */
+ int **trans; /* Transition tables for states that can
+ never accept. If the transitions for a
+ state have not yet been computed, or the
+ state could possibly accept, its entry in
+ this table is NULL. */
+ int **realtrans; /* Trans always points to realtrans + 1; this
+ is so trans[-1] can contain NULL. */
+ int **fails; /* Transition tables after failing to accept
+ on a state that potentially could do so. */
+ int *success; /* Table of acceptance conditions used in
+ dfaexec and computed in build_state. */
+ int *newlines; /* Transitions on newlines. The entry for a
+ newline in any transition table is always
+ -1 so we can count lines without wasting
+ too many cycles. The transition for a
+ newline is stored separately and handled
+ as a special case. Newline is also used
+ as a sentinel at the end of the buffer. */
+ struct dfamust *musts; /* List of strings, at least one of which
+ is known to appear in any r.e. matching
+ the dfa. */
+};
+
+/* Some macros for user access to dfa internals. */
+
+/* ACCEPTING returns true if s could possibly be an accepting state of r. */
+#define ACCEPTING(s, r) ((r).states[s].constraint)
+
+/* ACCEPTS_IN_CONTEXT returns true if the given state accepts in the
+ specified context. */
+#define ACCEPTS_IN_CONTEXT(prevn, currn, prevl, currl, state, dfa) \
+ SUCCEEDS_IN_CONTEXT((dfa).states[state].constraint, \
+ prevn, currn, prevl, currl)
+
+/* FIRST_MATCHING_REGEXP returns the index number of the first of parallel
+ regexps that a given state could accept. Parallel regexps are numbered
+ starting at 1. */
+#define FIRST_MATCHING_REGEXP(state, dfa) (-(dfa).states[state].first_end)
+
+/* Entry points. */
+
+/* dfasyntax() takes three arguments; the first sets the syntax bits described
+ earlier in this file, the second sets the case-folding flag, and the
+ third specifies the line terminator. */
+extern void dfasyntax PARAMS ((reg_syntax_t, int, int));
+
+/* Compile the given string of the given length into the given struct dfa.
+ Final argument is a flag specifying whether to build a searching or an
+ exact matcher. */
+extern void dfacomp PARAMS ((char *, size_t, struct dfa *, int));
+
+/* Execute the given struct dfa on the buffer of characters. The
+ first char * points to the beginning, and the second points to the
+ first character after the end of the buffer, which must be a writable
+ place so a sentinel end-of-buffer marker can be stored there. The
+ second-to-last argument is a flag telling whether to allow newlines to
+ be part of a string matching the regexp. The next-to-last argument,
+ if non-NULL, points to a place to increment every time we see a
+ newline. The final argument, if non-NULL, points to a flag that will
+ be set if further examination by a backtracking matcher is needed in
+ order to verify backreferencing; otherwise the flag will be cleared.
+ Returns NULL if no match is found, or a pointer to the first
+ character after the first & shortest matching string in the buffer. */
+extern char *dfaexec PARAMS ((struct dfa *, char *, char *, int, int *, int *));
+
+/* Free the storage held by the components of a struct dfa. */
+extern void dfafree PARAMS ((struct dfa *));
+
+/* Entry points for people who know what they're doing. */
+
+/* Initialize the components of a struct dfa. */
+extern void dfainit PARAMS ((struct dfa *));
+
+/* Incrementally parse a string of given length into a struct dfa. */
+extern void dfaparse PARAMS ((char *, size_t, struct dfa *));
+
+/* Analyze a parsed regexp; second argument tells whether to build a searching
+ or an exact matcher. */
+extern void dfaanalyze PARAMS ((struct dfa *, int));
+
+/* Compute, for each possible character, the transitions out of a given
+ state, storing them in an array of integers. */
+extern void dfastate PARAMS ((int, struct dfa *, int []));
+
+/* Error handling. */
+
+/* dfaerror() is called by the regexp routines whenever an error occurs. It
+ takes a single argument, a NUL-terminated string describing the error.
+ The default dfaerror() prints the error message to stderr and exits.
+ The user can provide a different dfafree() if so desired. */
+extern void dfaerror PARAMS ((const char *));
diff --git a/gnu/usr.bin/grep/doc/Makefile b/gnu/usr.bin/grep/doc/Makefile
new file mode 100644
index 0000000..82620f9
--- /dev/null
+++ b/gnu/usr.bin/grep/doc/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+INFO= grep
+INFOSECTION= "System Utilities"
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/grep/doc/grep.texi b/gnu/usr.bin/grep/doc/grep.texi
new file mode 100644
index 0000000..49493de
--- /dev/null
+++ b/gnu/usr.bin/grep/doc/grep.texi
@@ -0,0 +1,985 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename grep.info
+@settitle grep, print lines matching a pattern
+@c %**end of header
+
+@c This file has the new style title page commands.
+@c Run `makeinfo' rather than `texinfo-format-buffer'.
+
+@c smallbook
+
+@c tex
+@c \overfullrule=0pt
+@c end tex
+
+@include version.texi
+
+@c Combine indices.
+@syncodeindex ky cp
+@syncodeindex pg cp
+@syncodeindex tp cp
+
+@defcodeindex op
+@syncodeindex op fn
+@syncodeindex vr fn
+
+@ifinfo
+@direntry
+* grep: (grep). print lines matching a pattern.
+@end direntry
+This file documents @command{grep}, a pattern matching engine.
+
+
+Published by the Free Software Foundation,
+59 Temple Place - Suite 330
+Boston, MA 02111-1307, USA
+
+Copyright 1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@setchapternewpage off
+
+@titlepage
+@title grep, searching for a pattern
+@subtitle version @value{VERSION}, @value{UPDATED}
+@author Alain Magloire et al.
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1999 Free Software Foundation, Inc.
+
+@sp 2
+Published by the Free Software Foundation, @*
+59 Temple Place - Suite 330, @*
+Boston, MA 02111-1307, USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@end titlepage
+@page
+
+
+@ifnottex
+@node Top
+@top Grep
+
+@command{grep} searches for lines matching a pattern.
+
+This document was produced for version @value{VERSION} of @sc{gnu}
+@command{grep}.
+@end ifnottex
+
+@menu
+* Introduction:: Introduction.
+* Invoking:: Invoking @command{grep}; description of options.
+* Diagnostics:: Exit status returned by @command{grep}.
+* Grep Programs:: @command{grep} programs.
+* Regular Expressions:: Regular Expressions.
+* Usage:: Examples.
+* Reporting Bugs:: Reporting Bugs.
+* Concept Index:: A menu with all the topics in this manual.
+* Index:: A menu with all @command{grep} commands
+ and command-line options.
+@end menu
+
+
+@node Introduction
+@chapter Introduction
+
+@cindex Searching for a pattern.
+
+@command{grep} searches the input files
+for lines containing a match to a given
+pattern list. When it finds a match in a line, it copies the line to standard
+output (by default), or does whatever other sort of output you have requested
+with options.
+
+Though @command{grep} expects to do the matching on text,
+it has no limits on input line length other than available memory,
+and it can match arbitrary characters within a line.
+If the final byte of an input file is not a newline,
+@command{grep} silently supplies one.
+Since newline is also a separator for the list of patterns, there
+is no way to match newline characters in a text.
+
+@node Invoking
+@chapter Invoking @command{grep}
+
+@command{grep} comes with a rich set of options from @sc{posix.2} and @sc{gnu}
+extensions.
+
+@table @samp
+
+@item -c
+@itemx --count
+@opindex -c
+@opindex -count
+@cindex counting lines
+Suppress normal output; instead print a count of matching
+lines for each input file. With the @samp{-v}, @samp{--invert-match} option,
+count non-matching lines.
+
+@item -e @var{pattern}
+@itemx --regexp=@var{pattern}
+@opindex -e
+@opindex --regexp=@var{pattern}
+@cindex pattern list
+Use @var{pattern} as the pattern; useful to protect patterns
+beginning with a @samp{-}.
+
+@item -f @var{file}
+@itemx --file=@var{file}
+@opindex -f
+@opindex --file
+@cindex pattern from file
+Obtain patterns from @var{file}, one per line. The empty
+file contains zero patterns, and therefore matches nothing.
+
+@item -i
+@itemx --ignore-case
+@opindex -i
+@opindex --ignore-case
+@cindex case insensitive search
+Ignore case distinctions in both the pattern and the input files.
+
+@item -l
+@itemx --files-with-matches
+@opindex -l
+@opindex --files-with-matches
+@cindex names of matching files
+Suppress normal output; instead print the name of each input
+file from which output would normally have been printed.
+The scanning of every file will stop on the first match.
+
+@item -n
+@itemx --line-number
+@opindex -n
+@opindex --line-number
+@cindex line numbering
+Prefix each line of output with the line number within its input file.
+
+@item -q
+@itemx --quiet
+@itemx --silent
+@opindex -q
+@opindex --quiet
+@opindex --silent
+@cindex quiet, silent
+Quiet; suppress normal output. The scanning of every file will stop on
+the first match. Also see the @samp{-s} or @samp{--no-messages} option.
+
+@item -s
+@itemx --no-messages
+@opindex -s
+@opindex --no-messages
+@cindex suppress error messages
+Suppress error messages about nonexistent or unreadable files.
+Portability note: unlike @sc{gnu} @command{grep}, traditional
+@command{grep} did not conform to @sc{posix.2}, because traditional
+@command{grep} lacked a @samp{-q} option and its @samp{-s} option behaved
+like @sc{gnu} @command{grep}'s @samp{-q} option. Shell scripts intended
+to be portable to traditional @command{grep} should avoid both
+@samp{-q} and @samp{-s} and should redirect
+output to @file{/dev/null} instead.
+
+@item -v
+@itemx --invert-match
+@opindex -v
+@opindex --invert-match
+@cindex invert matching
+@cindex print non-matching lines
+Invert the sense of matching, to select non-matching lines.
+
+@item -x
+@itemx --line-regexp
+@opindex -x
+@opindex --line-regexp
+@cindex match the whole line
+Select only those matches that exactly match the whole line.
+
+@end table
+
+@section @sc{gnu} Extensions
+
+@table @samp
+
+@item -A @var{num}
+@itemx --after-context=@var{num}
+@opindex -A
+@opindex --after-context
+@cindex after context
+@cindex context lines, after match
+Print @var{num} lines of trailing context after matching lines.
+
+@item -B @var{num}
+@itemx --before-context=@var{num}
+@opindex -B
+@opindex --before-context
+@cindex before context
+@cindex context lines, before match
+Print @var{num} lines of leading context before matching lines.
+
+@item -C @var{num}
+@itemx --context=[@var{num}]
+@opindex -C
+@opindex --context
+@cindex context
+Print @var{num} lines (default 2) of output context.
+
+
+@item -@var{num}
+@opindex -NUM
+Same as @samp{--context=@var{num}} lines of leading and trailing
+context. However, grep will never print any given line more than once.
+
+
+@item -V
+@itemx --version
+@opindex -V
+@opindex --version
+@cindex Version, printing
+Print the version number of @command{grep} to the standard output stream.
+This version number should be included in all bug reports.
+
+@item --help
+@opindex --help
+@cindex Usage summary, printing
+Print a usage message briefly summarizing these command-line options
+and the bug-reporting address, then exit.
+
+@itemx --binary-files=@var{type}
+@opindex --binary-files
+@cindex binary files
+If the first few bytes of a file indicate that the file contains binary
+data, assume that the file is of type @var{type}. By default,
+@var{type} is @samp{binary}, and @command{grep} normally outputs either
+a one-line message saying that a binary file matches, or no message if
+there is no match. If @var{type} is @samp{without-match},
+@command{grep} assumes that a binary file does not match;
+this is equivalent to the @samp{-I} option. If @var{type}
+is @samp{text}, @command{grep} processes a binary file as if it were
+text; this is equivalent to the @samp{-a} option.
+@emph{Warning:} @samp{--binary-files=text} might output binary garbage,
+which can have nasty side effects if the output is a terminal and if the
+terminal driver interprets some of it as commands.
+
+@item -b
+@itemx --byte-offset
+@opindex -b
+@opindex --byte-offset
+@cindex byte offset
+Print the byte offset within the input file before each line of output.
+When @command{grep} runs on @sc{ms-dos} or MS-Windows, the printed
+byte offsets
+depend on whether the @samp{-u} (@samp{--unix-byte-offsets}) option is
+used; see below.
+
+@item -d @var{action}
+@itemx --directories=@var{action}
+@opindex -d
+@opindex --directories
+@cindex directory search
+If an input file is a directory, use @var{action} to process it.
+By default, @var{action} is @samp{read}, which means that directories are
+read just as if they were ordinary files (some operating systems
+and filesystems disallow this, and will cause @command{grep} to print error
+messages for every directory). If @var{action} is @samp{skip},
+directories are silently skipped. If @var{action} is @samp{recurse},
+@command{grep} reads all files under each directory, recursively; this is
+equivalent to the @samp{-r} option.
+
+@item -H
+@itemx --with-filename
+@opindex -H
+@opindex --With-filename
+@cindex with filename prefix
+Print the filename for each match.
+
+@item -h
+@itemx --no-filename
+@opindex -h
+@opindex --no-filename
+@cindex no filename prefix
+Suppress the prefixing of filenames on output when multiple files are searched.
+
+@item -L
+@itemx --files-without-match
+@opindex -L
+@opindex --files-without-match
+@cindex files which don't match
+Suppress normal output; instead print the name of each input
+file from which no output would normally have been printed.
+The scanning of every file will stop on the first match.
+
+@item -a
+@itemx --text
+@opindex -a
+@opindex --text
+@cindex suppress binary data
+@cindex binary files
+Process a binary file as if it were text; this is equivalent to the
+@samp{--binary-files=text} option.
+
+@item -I
+Process a binary file as if it did not contain matching data; this is
+equivalent to the @samp{--binary-files=without-match} option.
+
+@item -w
+@itemx --word-regexp
+@opindex -w
+@opindex --word-regexp
+@cindex matching whole words
+Select only those lines containing matches that form
+whole words. The test is that the matching substring
+must either be at the beginning of the line, or preceded
+by a non-word constituent character. Similarly,
+it must be either at the end of the line or followed by
+a non-word constituent character. Word-constituent
+characters are letters, digits, and the underscore.
+
+@item -r
+@itemx --recursive
+@opindex -r
+@opindex --recursive
+@cindex recursive search
+@cindex searching directory trees
+For each directory mentioned in the command line, read and process all
+files in that directory, recursively. This is the same as the @samp{-d
+recurse} option.
+
+@item -y
+@opindex -y
+@cindex case insensitive search, obsolete option
+Obsolete synonym for @samp{-i}.
+
+@item -U
+@itemx --binary
+@opindex -U
+@opindex --binary
+@cindex DOS/Windows binary files
+@cindex binary files, DOS/Windows
+Treat the file(s) as binary. By default, under @sc{ms-dos}
+and MS-Windows, @command{grep} guesses the file type by looking
+at the contents of the first 32kB read from the file.
+If @command{grep} decides the file is a text file, it strips the
+@code{CR} characters from the original file contents (to make
+regular expressions with @code{^} and @code{$} work correctly).
+Specifying @samp{-U} overrules this guesswork, causing all
+files to be read and passed to the matching mechanism
+verbatim; if the file is a text file with @code{CR/LF} pairs
+at the end of each line, this will cause some regular
+expressions to fail. This option has no effect on platforms other than
+@sc{ms-dos} and MS-Windows.
+
+@item -u
+@itemx --unix-byte-offsets
+@opindex -u
+@opindex --unix-byte-offsets
+@cindex DOS byte offsets
+@cindex byte offsets, on DOS/Windows
+Report Unix-style byte offsets. This switch causes
+@command{grep} to report byte offsets as if the file were Unix style
+text file, i.e., the byte offsets ignore the @code{CR} characters which were
+stripped. This will produce results identical to running @command{grep} on
+a Unix machine. This option has no effect unless @samp{-b}
+option is also used; it has no effect on platforms other than @sc{ms-dos} and
+MS-Windows.
+
+@item --mmap
+@opindex --mmap
+@cindex memory mapped input
+If possible, use the @code{mmap} system call to read input, instead of
+the default @code{read} system call. In some situations, @samp{--mmap}
+yields better performance. However, @samp{--mmap} can cause undefined
+behavior (including core dumps) if an input file shrinks while
+@command{grep} is operating, or if an I/O error occurs.
+
+@item -Z
+@itemx --null
+@opindex -Z
+@opindex --null
+@cindex zero-terminated file names
+Output a zero byte (the @sc{ascii} @code{NUL} character) instead of the
+character that normally follows a file name. For example, @samp{grep
+-lZ} outputs a zero byte after each file name instead of the usual
+newline. This option makes the output unambiguous, even in the presence
+of file names containing unusual characters like newlines. This option
+can be used with commands like @samp{find -print0}, @samp{perl -0},
+@samp{sort -z}, and @samp{xargs -0} to process arbitrary file names,
+even those that contain newline characters.
+
+@item -z
+@itemx --null-data
+@opindex -z
+@opindex --null-data
+@cindex zero-terminated lines
+Treat the input as a set of lines, each terminated by a zero byte (the
+@sc{ascii} @code{NUL} character) instead of a newline. Like the @samp{-Z}
+or @samp{--null} option, this option can be used with commands like
+@samp{sort -z} to process arbitrary file names.
+
+@end table
+
+Several additional options control which variant of the @command{grep}
+matching engine is used. @xref{Grep Programs}.
+
+@section Environment Variables
+
+Grep's behavior is affected by the following environment variables.
+@cindex environment variables
+
+@table @code
+
+@item GREP_OPTIONS
+@vindex GREP_OPTIONS
+@cindex default options environment variable
+This variable specifies default options to be placed in front of any
+explicit options. For example, if @code{GREP_OPTIONS} is
+@samp{--binary-files=without-match --directories=skip}, @command{grep}
+behaves as if the two options @samp{--binary-files=without-match} and
+@samp{--directories=skip} had been specified before
+any explicit options. Option specifications are separated by
+whitespace. A backslash escapes the next character, so it can be used to
+specify an option containing whitespace or a backslash.
+
+@item LC_ALL
+@itemx LC_MESSAGES
+@itemx LANG
+@vindex LC_ALL
+@vindex LC_MESSAGES
+@vindex LANG
+@cindex language of messages
+@cindex message language
+@cindex national language support
+@cindex NLS
+@cindex translation of message language
+These variables specify the @code{LC_MESSAGES} locale, which determines
+the language that @command{grep} uses for messages. The locale is determined
+by the first of these variables that is set. American English is used
+if none of these environment variables are set, or if the message
+catalog is not installed, or if @command{grep} was not compiled with national
+language support (@sc{nls}).
+
+@item LC_ALL
+@itemx LC_CTYPE
+@itemx LANG
+@vindex LC_ALL
+@vindex LC_CTYPE
+@vindex LANG
+@cindex character type
+@cindex national language support
+@cindex NLS
+These variables specify the @code{LC_CTYPE} locale, which determines the
+type of characters, e.g., which characters are whitespace. The locale is
+determined by the first of these variables that is set. The @sc{posix}
+locale is used if none of these environment variables are set, or if the
+locale catalog is not installed, or if @command{grep} was not compiled with
+national language support (@sc{nls}).
+
+@item POSIXLY_CORRECT
+@vindex POSIXLY_CORRECT
+If set, @command{grep} behaves as @sc{posix.2} requires; otherwise,
+@command{grep} behaves more like other @sc{gnu} programs. @sc{posix.2}
+requires that options that
+follow file names must be treated as file names; by default, such
+options are permuted to the front of the operand list and are treated as
+options. Also, @sc{posix.2} requires that unrecognized options be
+diagnosed as
+``illegal'', but since they are not really against the law the default
+is to diagnose them as ``invalid''. @code{POSIXLY_CORRECT} also
+disables @code{_@var{N}_GNU_nonoption_argv_flags_}, described below.
+
+@item _@var{N}_GNU_nonoption_argv_flags_
+@vindex _@var{N}_GNU_nonoption_argv_flags_
+(Here @code{@var{N}} is @command{grep}'s numeric process ID.) If the
+@var{i}th character of this environment variable's value is @samp{1}, do
+not consider the @var{i}th operand of @command{grep} to be an option, even if
+it appears to be one. A shell can put this variable in the environment
+for each command it runs, specifying which operands are the results of
+file name wildcard expansion and therefore should not be treated as
+options. This behavior is available only with the @sc{gnu} C library, and
+only when @code{POSIXLY_CORRECT} is not set.
+
+@end table
+
+@node Diagnostics
+@chapter Diagnostics
+
+Normally, exit status is 0 if matches were found, and 1 if no matches
+were found (the @samp{-v} option inverts the sense of the exit status).
+Exit status is 2 if there were syntax errors in the pattern,
+inaccessible input files, or other system errors.
+
+@node Grep Programs
+@chapter @command{grep} programs
+
+@command{grep} searches the named input files (or standard input if no
+files are named, or the file name @file{-} is given) for lines containing
+a match to the given pattern. By default, @command{grep} prints the
+matching lines. There are three major variants of @command{grep},
+controlled by the following options.
+
+@table @samp
+
+@item -G
+@itemx --basic-regexp
+@opindex -G
+@opindex --basic-regexp
+@cindex matching basic regular expressions
+Interpret pattern as a basic regular expression. This is the default.
+
+@item -E
+@itemx --extended-regexp
+@opindex -E
+@opindex --extended-regexp
+@cindex matching extended regular expressions
+Interpret pattern as an extended regular expression.
+
+
+@item -F
+@itemx --fixed-strings
+@opindex -F
+@opindex --fixed-strings
+@cindex matching fixed strings
+Interpret pattern as a list of fixed strings, separated
+by newlines, any of which is to be matched.
+
+@end table
+
+In addition, two variant programs @sc{egrep} and @sc{fgrep} are available.
+@sc{egrep} is the same as @samp{grep -E}. @sc{fgrep} is the
+same as @samp{grep -F}.
+
+@node Regular Expressions
+@chapter Regular Expressions
+@cindex regular expressions
+
+A @dfn{regular expression} is a pattern that describes a set of strings.
+Regular expressions are constructed analogously to arithmetic expressions,
+by using various operators to combine smaller expressions.
+@command{grep} understands two different versions of regular expression
+syntax: ``basic'' and ``extended''. In @sc{gnu} @command{grep}, there is no
+difference in available functionality using either syntax.
+In other implementations, basic regular expressions are less powerful.
+The following description applies to extended regular expressions;
+differences for basic regular expressions are summarized afterwards.
+
+The fundamental building blocks are the regular expressions that match
+a single character. Most characters, including all letters and digits,
+are regular expressions that match themselves. Any metacharacter
+with special meaning may be quoted by preceding it with a backslash.
+A list of characters enclosed by @samp{[} and @samp{]} matches any
+single character in that list; if the first character of the list is the
+caret @samp{^}, then it
+matches any character @strong{not} in the list. For example, the regular
+expression @samp{[0123456789]} matches any single digit.
+A range of characters may be specified by giving the first
+and last characters, separated by a hyphen.
+
+Finally, certain named classes of characters are predefined, as follows.
+Their interpretation depends on the @code{LC_CTYPE} locale; the
+interpretation below is that of the @sc{posix} locale, which is the default
+if no @code{LC_CTYPE} locale is specified.
+
+@cindex classes of characters
+@cindex character classes
+@table @samp
+
+@item [:alnum:]
+@opindex alnum
+@cindex alphanumeric characters
+Alphanumeric characters:
+@samp{[:alpha:]} and @samp{[:digit:]}.
+
+@item [:alpha:]
+@opindex alpha
+@cindex alphabetic characters
+Alphabetic characters:
+@samp{[:lower:]} and @samp{[:upper:]}.
+
+@item [:blank:]
+@opindex blank
+@cindex blank characters
+Blank characters:
+space and tab.
+
+@item [:cntrl:]
+@opindex cntrl
+@cindex control characters
+Control characters. In @sc{ascii}, these characters have octal codes 000
+through 037, and 177 (@code{DEL}). In other character sets, these are
+the equivalent characters, if any.
+
+@item [:digit:]
+@opindex digit
+@cindex digit characters
+@cindex numeric characters
+Digits: @code{0 1 2 3 4 5 6 7 8 9}.
+
+@item [:graph:]
+@opindex graph
+@cindex graphic characters
+Graphical characters:
+@samp{[:alnum:]} and @samp{[:punct:]}.
+
+@item [:lower:]
+@opindex lower
+@cindex lower-case letters
+Lower-case letters:
+@code{a b c d e f g h i j k l m n o p q r s t u v w x y z}.
+
+@item [:print:]
+@opindex print
+@cindex printable characters
+Printable characters:
+@samp{[:alnum:]}, @samp{[:punct:]}, and space.
+
+@item [:punct:]
+@opindex punct
+@cindex punctuation characters
+Punctuation characters:
+@code{!@: " # $ % & ' ( ) * + , - .@: / : ; < = > ?@: @@ [ \ ] ^ _ ` @{ | @} ~}.
+
+@item [:space:]
+@opindex space
+@cindex space characters
+@cindex whitespace characters
+Space characters:
+tab, newline, vertical tab, form feed, carriage return, and space.
+
+@item [:upper:]
+@opindex upper
+@cindex upper-case letters
+Upper-case letters:
+@code{A B C D E F G H I J K L M N O P Q R S T U V W X Y Z}.
+
+@item [:xdigit:]
+@opindex xdigit
+@cindex xdigit class
+@cindex hexadecimal digits
+Hexadecimal digits:
+@code{0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f}.
+
+@end table
+For example, @samp{[[:alnum:]]} means @samp{[0-9A-Za-z]}, except the latter
+depends upon the @sc{posix} locale and the @sc{ascii} character
+encoding, whereas the former is independent of locale and character set.
+(Note that the brackets in these class names are
+part of the symbolic names, and must be included in addition to
+the brackets delimiting the bracket list.) Most metacharacters lose
+their special meaning inside lists. To include a literal @samp{]}, place it
+first in the list. Similarly, to include a literal @samp{^}, place it anywhere
+but first. Finally, to include a literal @samp{-}, place it last.
+
+The period @samp{.} matches any single character. The symbol @samp{\w}
+is a synonym for @samp{[[:alnum:]]} and @samp{\W} is a synonym for
+@samp{[^[:alnum]]}.
+
+The caret @samp{^} and the dollar sign @samp{$} are metacharacters that
+respectively match the empty string at the beginning and end
+of a line. The symbols @samp{\<} and @samp{\>} respectively match the
+empty string at the beginning and end of a word. The symbol
+@samp{\b} matches the empty string at the edge of a word, and @samp{\B}
+matches the empty string provided it's not at the edge of a word.
+
+A regular expression may be followed by one of several
+repetition operators:
+
+
+@table @samp
+
+@item ?
+@opindex ?
+@cindex question mark
+@cindex match sub-expression at most once
+The preceding item is optional and will be matched at most once.
+
+@item *
+@opindex *
+@cindex asterisk
+@cindex match sub-expression zero or more times
+The preceding item will be matched zero or more times.
+
+@item +
+@opindex +
+@cindex plus sign
+The preceding item will be matched one or more times.
+
+@item @{@var{n}@}
+@opindex @{n@}
+@cindex braces, one argument
+@cindex match sub-expression n times
+The preceding item is matched exactly @var{n} times.
+
+@item @{@var{n},@}
+@opindex @{n,@}
+@cindex braces, second argument omitted
+@cindex match sub-expression n or more times
+The preceding item is matched n or more times.
+
+@item @{@var{n},@var{m}@}
+@opindex @{n,m@}
+@cindex braces, two arguments
+The preceding item is matched at least @var{n} times, but not more than
+@var{m} times.
+
+@end table
+
+Two regular expressions may be concatenated; the resulting regular
+expression matches any string formed by concatenating two substrings
+that respectively match the concatenated subexpressions.
+
+Two regular expressions may be joined by the infix operator @samp{|}; the
+resulting regular expression matches any string matching either
+subexpression.
+
+Repetition takes precedence over concatenation, which in turn
+takes precedence over alternation. A whole subexpression may be
+enclosed in parentheses to override these precedence rules.
+
+The backreference @samp{\@var{n}}, where @var{n} is a single digit, matches the
+substring previously matched by the @var{n}th parenthesized subexpression
+of the regular expression.
+
+@cindex basic regular expressions
+In basic regular expressions the metacharacters @samp{?}, @samp{+},
+@samp{@{}, @samp{|}, @samp{(}, and @samp{)} lose their special meaning;
+instead use the backslashed versions @samp{\?}, @samp{\+}, @samp{\@{},
+@samp{\|}, @samp{\(}, and @samp{\)}.
+
+@cindex interval specifications
+Traditional @command{egrep} did not support the @samp{@{} metacharacter,
+and some @command{egrep} implementations support @samp{\@{} instead, so
+portable scripts should avoid @samp{@{} in @samp{egrep} patterns and
+should use @samp{[@{]} to match a literal @samp{@{}.
+
+@sc{gnu} @command{egrep} attempts to support traditional usage by
+assuming that @samp{@{} is not special if it would be the start of an
+invalid interval specification. For example, the shell command
+@samp{egrep '@{1'} searches for the two-character string @samp{@{1}
+instead of reporting a syntax error in the regular expression.
+@sc{posix.2} allows this behavior as an extension, but portable scripts
+should avoid it.
+
+@node Usage
+@chapter Usage
+
+@cindex Usage, examples
+Here is an example shell command that invokes @sc{gnu} @command{grep}:
+
+@example
+grep -i 'hello.*world' menu.h main.c
+@end example
+
+@noindent
+This lists all lines in the files @file{menu.h} and @file{main.c} that
+contain the string @samp{hello} followed by the string @samp{world};
+this is because @samp{.*} matches zero or more characters within a line.
+@xref{Regular Expressions}. The @samp{-i} option causes @command{grep}
+to ignore case, causing it to match the line @samp{Hello, world!}, which
+it would not otherwise match. @xref{Invoking}, for more details about
+how to invoke @command{grep}.
+
+@cindex Using @command{grep}, Q&A
+@cindex FAQ about @command{grep} usage
+Here are some common questions and answers about @command{grep} usage.
+
+@enumerate
+
+@item
+How can I list just the names of matching files?
+
+@example
+grep -l 'main' *.c
+@end example
+
+@noindent
+lists the names of all C files in the current directory whose contents
+mention @samp{main}.
+
+@item
+How do I search directories recursively?
+
+@example
+grep -r 'hello' /home/gigi
+@end example
+
+@noindent
+searches for @samp{hello} in all files under the directory
+@file{/home/gigi}. For more control of which files are searched, use
+@command{find}, @command{grep} and @command{xargs}. For example,
+the following command searches only C files:
+
+@smallexample
+find /home/gigi -name '*.c' -print | xargs grep 'hello' /dev/null
+@end smallexample
+
+@item
+What if a pattern has a leading @samp{-}?
+
+@example
+grep -e '--cut here--' *
+@end example
+
+@noindent
+searches for all lines matching @samp{--cut here--}. Without @samp{-e},
+@command{grep} would attempt to parse @samp{--cut here--} as a list of
+options.
+
+@item
+Suppose I want to search for a whole word, not a part of a word?
+
+@example
+grep -w 'hello' *
+@end example
+
+@noindent
+searches only for instances of @samp{hello} that are entire words; it
+does not match @samp{Othello}. For more control, use @samp{\<} and
+@samp{\>} to match the start and end of words. For example:
+
+@example
+grep 'hello\>' *
+@end example
+
+@noindent
+searches only for words ending in @samp{hello}, so it matches the word
+@samp{Othello}.
+
+@item
+How do I output context around the matching lines?
+
+@example
+grep -C 2 'hello' *
+@end example
+
+@noindent
+prints two lines of context around each matching line.
+
+@item
+How do I force grep to print the name of the file?
+
+Append @file{/dev/null}:
+
+@example
+grep 'eli' /etc/passwd /dev/null
+@end example
+
+@item
+Why do people use strange regular expressions on @command{ps} output?
+
+@example
+ps -ef | grep '[c]ron'
+@end example
+
+If the pattern had been written without the square brackets, it would
+have matched not only the @command{ps} output line for @command{cron},
+but also the @command{ps} output line for @command{grep}.
+
+@item
+Why does @command{grep} report ``Binary file matches''?
+
+If @command{grep} listed all matching ``lines'' from a binary file, it
+would probably generate output that is not useful, and it might even
+muck up your display. So @sc{gnu} @command{grep} suppresses output from
+files that appear to be binary files. To force @sc{gnu} @command{grep}
+to output lines even from files that appear to be binary, use the
+@samp{-a} or @samp{--binary-files=text} option. To eliminate the
+``Binary file matches'' messages, use the @samp{-I} or
+@samp{--binary-files=without-match} option.
+
+@item
+Why doesn't @samp{grep -lv} print nonmatching file names?
+
+@samp{grep -lv} lists the names of all files containing one or more
+lines that do not match. To list the names of all files that contain no
+matching lines, use the @samp{-L} or @samp{--files-without-match}
+option.
+
+@item
+I can do @sc{or} with @samp{|}, but what about @sc{and}?
+
+@example
+grep 'paul' /etc/motd | grep 'franc,ois'
+@end example
+
+@noindent
+finds all lines that contain both @samp{paul} and @samp{franc,ois}.
+
+@item
+How can I search in both standard input and in files?
+
+Use the special file name @samp{-}:
+
+@example
+cat /etc/passwd | grep 'alain' - /etc/motd
+@end example
+@end enumerate
+
+@node Reporting Bugs
+@chapter Reporting bugs
+
+@cindex Bugs, reporting
+Email bug reports to @email{bug-gnu-utils@@gnu.org}.
+Be sure to include the word ``grep'' somewhere in the ``Subject:'' field.
+
+Large repetition counts in the @samp{@{m,n@}} construct may cause
+@command{grep} to use lots of memory. In addition, certain other
+obscure regular expressions require exponential time and
+space, and may cause grep to run out of memory.
+Backreferences are very slow, and may require exponential time.
+
+@page
+@node Concept Index
+@unnumbered Concept Index
+
+This is a general index of all issues discussed in this manual, with the
+exception of the @command{grep} commands and command-line options.
+
+@printindex cp
+
+@page
+@node Index
+@unnumbered Index
+
+This is an alphabetical list of all @command{grep} commands, command-line
+options, and environment variables.
+
+@printindex fn
+
+@contents
+@bye
diff --git a/gnu/usr.bin/grep/doc/version.texi b/gnu/usr.bin/grep/doc/version.texi
new file mode 100644
index 0000000..5246f40
--- /dev/null
+++ b/gnu/usr.bin/grep/doc/version.texi
@@ -0,0 +1,3 @@
+@set UPDATED 27 January 2000
+@set EDITION 2.4d
+@set VERSION 2.4d
diff --git a/gnu/usr.bin/grep/getopt.c b/gnu/usr.bin/grep/getopt.c
new file mode 100644
index 0000000..d176d3e
--- /dev/null
+++ b/gnu/usr.bin/grep/getopt.c
@@ -0,0 +1,1049 @@
+/* Getopt for GNU.
+ NOTE: The canonical source of this file is maintained with the GNU
+ C Library. Bugs can be reported to bug-glibc@gnu.org.
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute 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. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#else
+# if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+# ifndef const
+# define const
+# endif
+# endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+# define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+# include <stdlib.h>
+# include <unistd.h>
+#endif /* GNU C library. */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+# include <string.h>
+# endif
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+ When compiling libc, the _ macro is predefined. */
+# ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(msgid) gettext (msgid)
+# else
+# define _(msgid) (msgid)
+# endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+# include <string.h>
+# define my_index strchr
+#else
+
+# if HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# define SWAP_FLAGS(ch1, ch2) \
+ if (nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#ifdef _LIBC
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ if (nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len = strlen (orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', nonoption_flags_max_len - len);
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ optarg = NULL;
+
+ if (optind == 0 || !__getopt_initialized)
+ {
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring);
+ __getopt_initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+
+ nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/grep/getopt.h b/gnu/usr.bin/grep/getopt.h
new file mode 100644
index 0000000..39f4a16
--- /dev/null
+++ b/gnu/usr.bin/grep/getopt.h
@@ -0,0 +1,169 @@
+/* Declarations for getopt.
+ Copyright (C) 1989,90,91,92,93,94,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@gnu.org.
+ This program is free software; you can redistribute 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 _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+# if defined __STDC__ && __STDC__
+ const char *name;
+# else
+ char *name;
+# endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+#endif /* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `getopt' that there are no more
+ options.
+
+ If OPTS begins with `--', then non-option arguments are treated as
+ arguments to the option '\0'. This behavior is specific to the GNU
+ `getopt'. */
+
+#if (defined __STDC__ && __STDC__) || defined PROTOTYPES
+# ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
+# else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+# endif /* __GNU_LIBRARY__ */
+
+# ifndef __need_getopt
+extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+extern int getopt_long_only (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only);
+# endif
+#else /* not ((defined __STDC__ && __STDC__) || defined PROTOTYPES) */
+extern int getopt ();
+# ifndef __need_getopt
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+# endif
+#endif /* (defined __STDC__ && __STDC__) || defined PROTOTYPES */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations. */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/gnu/usr.bin/grep/getopt1.c b/gnu/usr.bin/grep/getopt1.c
new file mode 100644
index 0000000..9c82565
--- /dev/null
+++ b/gnu/usr.bin/grep/getopt1.c
@@ -0,0 +1,188 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,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@gnu.org.
+
+ This program is free software; you can redistribute 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#else
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+#endif
+
+#include "getopt.h"
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/grep/getpagesize.h b/gnu/usr.bin/grep/getpagesize.h
new file mode 100644
index 0000000..4e513c3
--- /dev/null
+++ b/gnu/usr.bin/grep/getpagesize.h
@@ -0,0 +1,35 @@
+/* Emulate getpagesize on systems that lack it. */
+
+#ifndef HAVE_GETPAGESIZE
+
+#ifdef VMS
+#define getpagesize() 512
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _SC_PAGESIZE
+#define getpagesize() sysconf(_SC_PAGESIZE)
+#else
+
+#include <sys/param.h>
+
+#ifdef EXEC_PAGESIZE
+#define getpagesize() EXEC_PAGESIZE
+#else
+#ifdef NBPG
+#define getpagesize() NBPG * CLSIZE
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* no CLSIZE */
+#else /* no NBPG */
+#ifdef NBPC
+#define getpagesize() NBPC
+#endif /* NBPC */
+#endif /* no NBPG */
+#endif /* no EXEC_PAGESIZE */
+#endif /* no _SC_PAGESIZE */
+
+#endif /* not HAVE_GETPAGESIZE */
diff --git a/gnu/usr.bin/grep/grep.1 b/gnu/usr.bin/grep/grep.1
new file mode 100644
index 0000000..94089c4
--- /dev/null
+++ b/gnu/usr.bin/grep/grep.1
@@ -0,0 +1,625 @@
+.\" grep man page
+.\" $FreeBSD$
+.if !\n(.g \{\
+. if !\w|\*(lq| \{\
+. ds lq ``
+. if \w'\(lq' .ds lq "\(lq
+. \}
+. if !\w|\*(rq| \{\
+. ds rq ''
+. if \w'\(rq' .ds rq "\(rq
+. \}
+.\}
+.de Id
+.ds Dt \\$4
+..
+.Id $Id: grep.1,v 1.9 2000/01/26 03:42:16 alainm Exp $
+.TH GREP 1 \*(Dt "GNU Project"
+.SH NAME
+grep, egrep, fgrep, zgrep \- print lines matching a pattern
+.SH SYNOPSIS
+.B grep
+.RI [ options ]
+.I PATTERN
+.RI [ FILE .\|.\|.]
+.br
+.B grep
+.RI [ options ]
+.RB [ \-e
+.I PATTERN
+|
+.B \-f
+.IR FILE ]
+.RI [ FILE .\|.\|.]
+.SH DESCRIPTION
+.B grep
+searches the named input
+.IR FILE s
+(or standard input if no files are named, or
+the file name
+.B \-
+is given)
+for lines containing a match to the given
+.IR PATTERN .
+By default,
+.B grep
+prints the matching lines.
+.PP
+In addition, two variant programs
+.B egrep
+and
+.B fgrep
+are available.
+.B egrep
+is the same as
+.BR "grep\ \-E" .
+.B fgrep
+is the same as
+.BR "grep\ \-F" .
+.B zgrep
+is the same as
+.BR "grep\ \-Z" .
+.SH OPTIONS
+.TP
+.BI \-A " NUM" "\fR,\fP \-\^\-after-context=" NUM
+Print
+.I NUM
+lines of trailing context after matching lines.
+.TP
+.BR \-a ", " \-\^\-text
+Process a binary file as if it were text; this is equivalent to the
+.B \-\^\-binary-files=text
+option.
+.TP
+.BI \-B " NUM" "\fR,\fP \-\^\-before-context=" NUM
+Print
+.I NUM
+lines of leading context before matching lines.
+.TP
+\fB\-C\fP [\fINUM\fP], \fB\-\fP\fINUM\fP, \fB\-\^\-context\fP[\fB=\fP\fINUM\fP]
+Print
+.I NUM
+lines (default 2) of output context.
+.TP
+.BR \-b ", " \-\^\-byte-offset
+Print the byte offset within the input file before
+each line of output.
+.TP
+.BI \-\^\-binary-files= TYPE
+If the first few bytes of a file indicate that the file contains binary
+data, assume that the file is of type
+.IR TYPE .
+By default,
+.I TYPE
+is
+.BR binary ,
+and
+.B grep
+normally outputs either
+a one-line message saying that a binary file matches, or no message if
+there is no match.
+If
+.I TYPE
+is
+.BR without-match ,
+.B grep
+assumes that a binary file does not match; this is equivalent to the
+.B \-I
+option.
+If
+.I TYPE
+is
+.BR text ,
+.B grep
+processes a binary file as if it were text; this is equivalent to the
+.B \-a
+option.
+.I Warning:
+.B "grep \-\^\-binary-files=text"
+might output binary garbage,
+which can have nasty side effects if the output is a terminal and if the
+terminal driver interprets some of it as commands.
+.TP
+.BR \-c ", " \-\^\-count
+Suppress normal output; instead print a count of
+matching lines for each input file.
+With the
+.BR \-v ", " \-\^\-invert-match
+option (see below), count non-matching lines.
+.TP
+.BI \-d " ACTION" "\fR,\fP \-\^\-directories=" ACTION
+If an input file is a directory, use
+.I ACTION
+to process it. By default,
+.I ACTION
+is
+.BR read ,
+which means that directories are read just as if they were ordinary files.
+If
+.I ACTION
+is
+.BR skip ,
+directories are silently skipped.
+If
+.I ACTION
+is
+.BR recurse ,
+.B
+grep reads all files under each directory, recursively;
+this is equivalent to the
+.B \-r
+option.
+.TP
+.BR \-E ", " \-\^\-extended-regexp
+Interpret
+.I PATTERN
+as an extended regular expression (see below).
+.TP
+.BI \-e " PATTERN" "\fR,\fP \-\^\-regexp=" PATTERN
+Use
+.I PATTERN
+as the pattern; useful to protect patterns beginning with
+.BR \- .
+.TP
+.BR \-F ", " \-\^\-fixed-strings
+Interpret
+.I PATTERN
+as a list of fixed strings, separated by newlines,
+any of which is to be matched.
+.TP
+.BI \-f " FILE" "\fR,\fP \-\^\-file=" FILE
+Obtain patterns from
+.IR FILE ,
+one per line.
+The empty file contains zero patterns, and therfore matches nothing.
+.TP
+.BR \-G ", " \-\^\-basic-regexp
+Interpret
+.I PATTERN
+as a basic regular expression (see below). This is the default.
+.TP
+.BR \-H ", " \-\^\-with-filename
+Print the filename for each match.
+.TP
+.BR \-h ", " \-\^\-no-filename
+Suppress the prefixing of filenames on output
+when multiple files are searched.
+.TP
+.B \-\^\-help
+Output a brief help message.
+.TP
+.BR \-I
+Process a binary file as if it did not contain matching data; this is
+equivalent to the
+.B \-\^\-binary-files=without-match
+option.
+.TP
+.BR \-i ", " \-\^\-ignore-case
+Ignore case distinctions in both the
+.I PATTERN
+and the input files.
+.TP
+.BR \-L ", " \-\^\-files-without-match
+Suppress normal output; instead print the name
+of each input file from which no output would
+normally have been printed. The scanning will stop
+on the first match.
+.TP
+.BR \-l ", " \-\^\-files-with-matches
+Suppress normal output; instead print
+the name of each input file from which output
+would normally have been printed. The scanning will
+stop on the first match.
+.TP
+.B \-\^\-mmap
+If possible, use the
+.BR mmap (2)
+system call to read input, instead of
+the default
+.BR read (2)
+system call. In some situations,
+.B \-\^\-mmap
+yields better performance. However,
+.B \-\^\-mmap
+can cause undefined behavior (including core dumps)
+if an input file shrinks while
+.B grep
+is operating, or if an I/O error occurs.
+.TP
+.BR \-n ", " \-\^\-line-number
+Prefix each line of output with the line number
+within its input file.
+.TP
+.BR \-q ", " \-\^\-quiet ", " \-\^\-silent
+Quiet; suppress normal output. The scanning will stop
+on the first match.
+Also see the
+.B \-s
+or
+.B \-\^\-no-messages
+option below.
+.TP
+.BR \-r ", " \-\^\-recursive
+Read all files under each directory, recursively;
+this is equivalent to the
+.B "\-d recurse"
+option.
+.TP
+.BR \-s ", " \-\^\-no-messages
+Suppress error messages about nonexistent or unreadable files.
+Portability note: unlike \s-1GNU\s0
+.BR grep ,
+traditional
+.B grep
+did not conform to \s-1POSIX.2\s0, because traditional
+.B grep
+lacked a
+.B \-q
+option and its
+.B \-s
+option behaved like \s-1GNU\s0
+.BR grep 's
+.B \-q
+option.
+Shell scripts intended to be portable to traditional
+.B grep
+should avoid both
+.B \-q
+and
+.B \-s
+and should redirect output to /dev/null instead.
+.TP
+.BR \-U ", " \-\^\-binary
+Treat the file(s) as binary. By default, under MS-DOS and MS-Windows,
+.BR grep
+guesses the file type by looking at the contents of the first 32KB
+read from the file. If
+.BR grep
+decides the file is a text file, it strips the CR characters from the
+original file contents (to make regular expressions with
+.B ^
+and
+.B $
+work correctly). Specifying
+.B \-U
+overrules this guesswork, causing all files to be read and passed to the
+matching mechanism verbatim; if the file is a text file with CR/LF
+pairs at the end of each line, this will cause some regular
+expressions to fail.
+This option has no effect on platforms other than MS-DOS and
+MS-Windows.
+.TP
+.BR \-u ", " \-\^\-unix-byte-offsets
+Report Unix-style byte offsets. This switch causes
+.B grep
+to report byte offsets as if the file were Unix-style text file, i.e. with
+CR characters stripped off. This will produce results identical to running
+.B grep
+on a Unix machine. This option has no effect unless
+.B \-b
+option is also used;
+it has no effect on platforms other than MS-DOS and MS-Windows.
+.TP
+.BR \-V ", " \-\^\-version
+Print the version number of
+.B grep
+to standard error. This version number should
+be included in all bug reports (see below).
+.TP
+.BR \-v ", " \-\^\-invert-match
+Invert the sense of matching, to select non-matching lines.
+.TP
+.BR \-w ", " \-\^\-word-regexp
+Select only those lines containing matches that form whole words.
+The test is that the matching substring must either be at the
+beginning of the line, or preceded by a non-word constituent
+character. Similarly, it must be either at the end of the line
+or followed by a non-word constituent character. Word-constituent
+characters are letters, digits, and the underscore.
+.TP
+.BR \-x ", " \-\^\-line-regexp
+Select only those matches that exactly match the whole line.
+.TP
+.B \-y
+Obsolete synonym for
+.BR \-i .
+.TP
+.B \-\^\-null
+Output a zero byte (the \s-1ASCII\s0
+.B NUL
+character) instead of the character that normally follows a file name.
+For example,
+.B "grep \-l \-\^\-null"
+outputs a zero byte after each file name instead of the usual newline.
+This option makes the output unambiguous, even in the presence of file
+names containing unusual characters like newlines. This option can be
+used with commands like
+.BR "find \-print0" ,
+.BR "perl \-0" ,
+.BR "sort \-z" ,
+and
+.B "xargs \-0"
+to process arbitrary file names,
+even those that contain newline characters.
+.TP
+.BR \-Z ", " \-\^\-decompress
+Decompress the input data before searching.
+This option is only available if compiled with zlib(3) library.
+.SH "REGULAR EXPRESSIONS"
+A regular expression is a pattern that describes a set of strings.
+Regular expressions are constructed analogously to arithmetic
+expressions, by using various operators to combine smaller expressions.
+.PP
+.B grep
+understands two different versions of regular expression syntax:
+\*(lqbasic\*(rq and \*(lqextended.\*(rq In
+.RB "\s-1GNU\s0\ " grep ,
+there is no difference in available functionality using either syntax.
+In other implementations, basic regular expressions are less powerful.
+The following description applies to extended regular expressions;
+differences for basic regular expressions are summarized afterwards.
+.PP
+The fundamental building blocks are the regular expressions that match
+a single character. Most characters, including all letters and digits,
+are regular expressions that match themselves. Any metacharacter with
+special meaning may be quoted by preceding it with a backslash.
+.PP
+A list of characters enclosed by
+.B [
+and
+.B ]
+matches any single
+character in that list; if the first character of the list
+is the caret
+.B ^
+then it matches any character
+.I not
+in the list.
+For example, the regular expression
+.B [0123456789]
+matches any single digit. A range of characters
+may be specified by giving the first and last characters, separated
+by a hyphen.
+Finally, certain named classes of characters are predefined.
+Their names are self explanatory, and they are
+.BR [:alnum:] ,
+.BR [:alpha:] ,
+.BR [:cntrl:] ,
+.BR [:digit:] ,
+.BR [:graph:] ,
+.BR [:lower:] ,
+.BR [:print:] ,
+.BR [:punct:] ,
+.BR [:space:] ,
+.BR [:upper:] ,
+and
+.BR [:xdigit:].
+For example,
+.B [[:alnum:]]
+means
+.BR [0-9A-Za-z] ,
+except the latter form depends upon the \s-1POSIX\s0 locale and the
+\s-1ASCII\s0 character encoding, whereas the former is independent
+of locale and character set.
+(Note that the brackets in these class names are part of the symbolic
+names, and must be included in addition to the brackets delimiting
+the bracket list.) Most metacharacters lose their special meaning
+inside lists. To include a literal
+.B ]
+place it first in the list. Similarly, to include a literal
+.B ^
+place it anywhere but first. Finally, to include a literal
+.B \-
+place it last.
+.PP
+The period
+.B .
+matches any single character.
+The symbol
+.B \ew
+is a synonym for
+.B [[:alnum:]]
+and
+.B \eW
+is a synonym for
+.BR [^[:alnum]] .
+.PP
+The caret
+.B ^
+and the dollar sign
+.B $
+are metacharacters that respectively match the empty string at the
+beginning and end of a line.
+The symbols
+.B \e<
+and
+.B \e>
+respectively match the empty string at the beginning and end of a word.
+The symbol
+.B \eb
+matches the empty string at the edge of a word,
+and
+.B \eB
+matches the empty string provided it's
+.I not
+at the edge of a word.
+.PP
+A regular expression may be followed by one of several repetition operators:
+.PD 0
+.TP
+.B ?
+The preceding item is optional and matched at most once.
+.TP
+.B *
+The preceding item will be matched zero or more times.
+.TP
+.B +
+The preceding item will be matched one or more times.
+.TP
+.BI { n }
+The preceding item is matched exactly
+.I n
+times.
+.TP
+.BI { n ,}
+The preceding item is matched
+.I n
+or more times.
+.TP
+.BI { n , m }
+The preceding item is matched at least
+.I n
+times, but not more than
+.I m
+times.
+.PD
+.PP
+Two regular expressions may be concatenated; the resulting
+regular expression matches any string formed by concatenating
+two substrings that respectively match the concatenated
+subexpressions.
+.PP
+Two regular expressions may be joined by the infix operator
+.BR | ;
+the resulting regular expression matches any string matching
+either subexpression.
+.PP
+Repetition takes precedence over concatenation, which in turn
+takes precedence over alternation. A whole subexpression may be
+enclosed in parentheses to override these precedence rules.
+.PP
+The backreference
+.BI \e n\c
+\&, where
+.I n
+is a single digit, matches the substring
+previously matched by the
+.IR n th
+parenthesized subexpression of the regular expression.
+.PP
+In basic regular expressions the metacharacters
+.BR ? ,
+.BR + ,
+.BR { ,
+.BR | ,
+.BR ( ,
+and
+.BR )
+lose their special meaning; instead use the backslashed
+versions
+.BR \e? ,
+.BR \e+ ,
+.BR \e{ ,
+.BR \e| ,
+.BR \e( ,
+and
+.BR \e) .
+.PP
+Traditional
+.B egrep
+did not support the
+.B {
+metacharacter, and some
+.B egrep
+implementations support
+.B \e{
+instead, so portable scripts should avoid
+.B {
+in
+.B egrep
+patterns and should use
+.B [{]
+to match a literal
+.BR { .
+.PP
+\s-1GNU\s0
+.B egrep
+attempts to support traditional usage by assuming that
+.B {
+is not special if it would be the start of an invalid interval
+specification. For example, the shell command
+.B "egrep '{1'"
+searches for the two-character string
+.B {1
+instead of reporting a syntax error in the regular expression.
+\s-1POSIX.2\s0 allows this behavior as an extension, but portable scripts
+should avoid it.
+.SH "ENVIRONMENT VARIABLES"
+.TP
+.B GREP_OPTIONS
+This variable specifies default options to be placed in front of any
+explicit options. For example, if
+.B GREP_OPTIONS
+is
+.BR "'\-\^\-binary-files=without-match \-\^\-directories=skip'" ,
+.B grep
+behaves as if the two options
+.B \-\^\-binary-files=without-match
+and
+.B \-\^\-directories=skip
+had been specified before any explicit options.
+Option specifications are separated by whitespace.
+A backslash escapes the next character,
+so it can be used to specify an option containing whitespace or a backslash.
+.TP
+\fBLC_ALL\fP, \fBLC_MESSAGES\fP, \fBLANG\fP
+These variables specify the
+.B LC_MESSAGES
+locale, which determines the language that
+.B grep
+uses for messages.
+The locale is determined by the first of these variables that is set.
+American English is used if none of these environment variables are set,
+or if the message catalog is not installed, or if
+.B grep
+was not compiled with national language support (\s-1NLS\s0).
+.TP
+\fBLC_ALL\fP, \fBLC_CTYPE\fP, \fBLANG\fP
+These variables specify the
+.B LC_CTYPE
+locale, which determines the type of characters, e.g., which
+characters are whitespace.
+The locale is determined by the first of these variables that is set.
+The \s-1POSIX\s0 locale is used if none of these environment variables
+are set, or if the locale catalog is not installed, or if
+.B grep
+was not compiled with national language support (\s-1NLS\s0).
+.TP
+.B POSIXLY_CORRECT
+If set,
+.B grep
+behaves as \s-1POSIX.2\s0 requires; otherwise,
+.B grep
+behaves more like other \s-1GNU\s0 programs.
+\s-1POSIX.2\s0 requires that options that follow file names must be
+treated as file names; by default, such options are permuted to the
+front of the operand list and are treated as options.
+Also, \s-1POSIX.2\s0 requires that unrecognized options be diagnosed as
+\*(lqillegal\*(rq, but since they are not really against the law the default
+is to diagnose them as \*(lqinvalid\*(rq.
+.SH DIAGNOSTICS
+Normally, exit status is 0 if matches were found,
+and 1 if no matches were found. (The
+.B \-v
+option inverts the sense of the exit status.)
+Exit status is 2 if there were syntax errors
+in the pattern, inaccessible input files, or
+other system errors.
+.SH BUGS
+Email bug reports to
+.BR bug-gnu-utils@gnu.org .
+Be sure to include the word \*(lqgrep\*(rq somewhere in the
+\*(lqSubject:\*(rq field.
+.PP
+Large repetition counts in the
+.BI { m , n }
+construct may cause grep to use lots of memory.
+In addition,
+certain other obscure regular expressions require exponential time
+and space, and may cause
+.B grep
+to run out of memory.
+.PP
+Backreferences are very slow, and may require exponential time.
+.\" Work around problems with some troff -man implementations.
+.br
diff --git a/gnu/usr.bin/grep/grep.c b/gnu/usr.bin/grep/grep.c
new file mode 100644
index 0000000..e021824
--- /dev/null
+++ b/gnu/usr.bin/grep/grep.c
@@ -0,0 +1,1501 @@
+/* grep.c - main driver file for grep.
+ Copyright (C) 1992, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 July 1992 by Mike Haertel. */
+/* Builtin decompression 1997 by Wolfram Schneider <wosch@FreeBSD.org>. */
+
+/* $FreeBSD$ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#if defined(HAVE_MMAP)
+# include <sys/mman.h>
+#endif
+#if defined(HAVE_SETRLIMIT)
+# include <sys/time.h>
+# include <sys/resource.h>
+#endif
+#include <stdio.h>
+#include "system.h"
+#include "getopt.h"
+#include "getpagesize.h"
+#include "grep.h"
+#include "savedir.h"
+
+#undef MAX
+#define MAX(A,B) ((A) > (B) ? (A) : (B))
+
+struct stats
+{
+ struct stats *parent;
+ struct stat stat;
+};
+
+/* base of chain of stat buffers, used to detect directory loops */
+static struct stats stats_base;
+
+/* if non-zero, display usage information and exit */
+static int show_help;
+
+/* If non-zero, print the version on standard output and exit. */
+static int show_version;
+
+/* If nonzero, use mmap if possible. */
+static int mmap_option;
+
+/* If zero, output nulls after filenames. */
+static int filename_mask;
+
+/* Short options. */
+static char const short_options[] =
+"0123456789A:B:C::EFGHIRUVX:abcd:e:f:hiLlnqrsuvwxyZz";
+
+/* Non-boolean long options that have no corresponding short equivalents. */
+enum
+{
+ BINARY_FILES_OPTION = CHAR_MAX + 1
+};
+
+/* Long options equivalences. */
+static struct option long_options[] =
+{
+ {"after-context", required_argument, NULL, 'A'},
+ {"basic-regexp", no_argument, NULL, 'G'},
+ {"before-context", required_argument, NULL, 'B'},
+ {"binary-files", required_argument, NULL, BINARY_FILES_OPTION},
+ {"byte-offset", no_argument, NULL, 'b'},
+ {"context", optional_argument, NULL, 'C'},
+ {"count", no_argument, NULL, 'c'},
+ {"directories", required_argument, NULL, 'd'},
+ {"extended-regexp", no_argument, NULL, 'E'},
+ {"file", required_argument, NULL, 'f'},
+ {"files-with-matches", no_argument, NULL, 'l'},
+ {"files-without-match", no_argument, NULL, 'L'},
+ {"fixed-regexp", no_argument, NULL, 'F'},
+ {"fixed-strings", no_argument, NULL, 'F'},
+ {"help", no_argument, &show_help, 1},
+ {"ignore-case", no_argument, NULL, 'i'},
+ {"line-number", no_argument, NULL, 'n'},
+ {"line-regexp", no_argument, NULL, 'x'},
+ {"mmap", no_argument, &mmap_option, 1},
+ {"no-filename", no_argument, NULL, 'h'},
+ {"no-messages", no_argument, NULL, 's'},
+#if HAVE_LIBZ > 0
+ {"decompress", no_argument, NULL, 'Z'},
+ {"null", no_argument, &filename_mask, 0},
+#else
+ {"null", no_argument, NULL, 'Z'},
+#endif
+ {"null-data", no_argument, NULL, 'z'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"recursive", no_argument, NULL, 'r'},
+ {"regexp", required_argument, NULL, 'e'},
+ {"invert-match", no_argument, NULL, 'v'},
+ {"silent", no_argument, NULL, 'q'},
+ {"text", no_argument, NULL, 'a'},
+ {"binary", no_argument, NULL, 'U'},
+ {"unix-byte-offsets", no_argument, NULL, 'u'},
+ {"version", no_argument, NULL, 'V'},
+ {"with-filename", no_argument, NULL, 'H'},
+ {"word-regexp", no_argument, NULL, 'w'},
+ {0, 0, 0, 0}
+};
+
+/* Define flags declared in grep.h. */
+char const *matcher;
+int match_icase;
+int match_words;
+int match_lines;
+unsigned char eolbyte;
+
+/* For error messages. */
+static char *prog;
+static char const *filename;
+static int errseen;
+
+/* How to handle directories. */
+static enum
+ {
+ READ_DIRECTORIES,
+ RECURSE_DIRECTORIES,
+ SKIP_DIRECTORIES
+ } directories;
+
+static int ck_atoi PARAMS ((char const *, int *));
+static void usage PARAMS ((int)) __attribute__((noreturn));
+static void error PARAMS ((const char *, int));
+static void setmatcher PARAMS ((char const *));
+static int install_matcher PARAMS ((char const *));
+static int prepend_args PARAMS ((char const *, char *, char **));
+static void prepend_default_options PARAMS ((char const *, int *, char ***));
+static char *page_alloc PARAMS ((size_t, char **));
+static int reset PARAMS ((int, char const *, struct stats *));
+static int fillbuf PARAMS ((size_t, struct stats *));
+static int grepbuf PARAMS ((char *, char *));
+static void prtext PARAMS ((char *, char *, int *));
+static void prpending PARAMS ((char *));
+static void prline PARAMS ((char *, char *, int));
+static void print_offset_sep PARAMS ((off_t, int));
+static void nlscan PARAMS ((char *));
+static int grep PARAMS ((int, char const *, struct stats *));
+static int grepdir PARAMS ((char const *, struct stats *));
+static int grepfile PARAMS ((char const *, struct stats *));
+#if O_BINARY
+static inline int undossify_input PARAMS ((register char *, size_t));
+#endif
+
+/* Functions we'll use to search. */
+static void (*compile) PARAMS ((char *, size_t));
+static char *(*execute) PARAMS ((char *, size_t, char **));
+
+/* Print a message and possibly an error string. Remember
+ that something awful happened. */
+static void
+error (const char *mesg, int errnum)
+{
+ if (errnum)
+ fprintf (stderr, "%s: %s: %s\n", prog, mesg, strerror (errnum));
+ else
+ fprintf (stderr, "%s: %s\n", prog, mesg);
+ errseen = 1;
+}
+
+/* Like error (), but die horribly after printing. */
+void
+fatal (const char *mesg, int errnum)
+{
+ error (mesg, errnum);
+ exit (2);
+}
+
+/* Interface to handle errors and fix library lossage. */
+char *
+xmalloc (size_t size)
+{
+ char *result;
+
+ result = malloc (size);
+ if (size && !result)
+ fatal (_("memory exhausted"), 0);
+ return result;
+}
+
+/* Interface to handle errors and fix some library lossage. */
+char *
+xrealloc (char *ptr, size_t size)
+{
+ char *result;
+
+ if (ptr)
+ result = realloc (ptr, size);
+ else
+ result = malloc (size);
+ if (size && !result)
+ fatal (_("memory exhausted"), 0);
+ return result;
+}
+
+/* Convert STR to a positive integer, storing the result in *OUT.
+ If STR is not a valid integer, return -1 (otherwise 0). */
+static int
+ck_atoi (char const *str, int *out)
+{
+ char const *p;
+ for (p = str; *p; p++)
+ if (*p < '0' || *p > '9')
+ return -1;
+
+ *out = atoi (optarg);
+ return 0;
+}
+
+
+/* Hairy buffering mechanism for grep. The intent is to keep
+ all reads aligned on a page boundary and multiples of the
+ page size. */
+
+static char *ubuffer; /* Unaligned base of buffer. */
+static char *buffer; /* Base of buffer. */
+static size_t bufsalloc; /* Allocated size of buffer save region. */
+static size_t bufalloc; /* Total buffer size. */
+#define PREFERRED_SAVE_FACTOR 5 /* Preferred value of bufalloc / bufsalloc. */
+static int bufdesc; /* File descriptor. */
+static char *bufbeg; /* Beginning of user-visible stuff. */
+static char *buflim; /* Limit of user-visible stuff. */
+static size_t pagesize; /* alignment of memory pages */
+static off_t bufoffset; /* Read offset; defined on regular files. */
+
+#if defined(HAVE_MMAP)
+static int bufmapped; /* True if buffer is memory-mapped. */
+static off_t initial_bufoffset; /* Initial value of bufoffset. */
+#endif
+
+#if HAVE_LIBZ > 0
+#include <zlib.h>
+static gzFile gzbufdesc; /* zlib file descriptor. */
+static int Zflag; /* uncompress before searching. */
+#endif
+
+/* Return VAL aligned to the next multiple of ALIGNMENT. VAL can be
+ an integer or a pointer. Both args must be free of side effects. */
+#define ALIGN_TO(val, alignment) \
+ ((size_t) (val) % (alignment) == 0 \
+ ? (val) \
+ : (val) + ((alignment) - (size_t) (val) % (alignment)))
+
+/* Return the address of a page-aligned buffer of size SIZE,
+ reallocating it from *UP. Set *UP to the newly allocated (but
+ possibly unaligned) buffer used to build the aligned buffer. To
+ free the buffer, free (*UP). */
+static char *
+page_alloc (size_t size, char **up)
+{
+ size_t asize = size + pagesize - 1;
+ if (size <= asize)
+ {
+ char *p = *up ? realloc (*up, asize) : malloc (asize);
+ if (p)
+ {
+ *up = p;
+ return ALIGN_TO (p, pagesize);
+ }
+ }
+ return NULL;
+}
+
+/* Reset the buffer for a new file, returning zero if we should skip it.
+ Initialize on the first time through. */
+static int
+reset (int fd, char const *file, struct stats *stats)
+{
+ if (pagesize)
+ bufsalloc = ALIGN_TO (bufalloc / PREFERRED_SAVE_FACTOR, pagesize);
+ else
+ {
+ size_t ubufsalloc;
+ pagesize = getpagesize ();
+ if (pagesize == 0)
+ abort ();
+#ifndef BUFSALLOC
+ ubufsalloc = MAX (8192, pagesize);
+#else
+ ubufsalloc = BUFSALLOC;
+#endif
+ bufsalloc = ALIGN_TO (ubufsalloc, pagesize);
+ bufalloc = PREFERRED_SAVE_FACTOR * bufsalloc;
+ /* The 1 byte of overflow is a kludge for dfaexec(), which
+ inserts a sentinel newline at the end of the buffer
+ being searched. There's gotta be a better way... */
+ if (bufsalloc < ubufsalloc
+ || bufalloc / PREFERRED_SAVE_FACTOR != bufsalloc
+ || bufalloc + 1 < bufalloc
+ || ! (buffer = page_alloc (bufalloc + 1, &ubuffer)))
+ fatal (_("memory exhausted"), 0);
+ }
+#if HAVE_LIBZ > 0
+ if (Zflag)
+ {
+ gzbufdesc = gzdopen(fd, "r");
+ if (gzbufdesc == NULL)
+ fatal(_("memory exhausted"), 0);
+ }
+#endif
+
+ buflim = buffer;
+ bufdesc = fd;
+
+ if (fstat (fd, &stats->stat) != 0)
+ {
+ error ("fstat", errno);
+ return 0;
+ }
+ if (directories == SKIP_DIRECTORIES && S_ISDIR (stats->stat.st_mode))
+ return 0;
+ if (
+#if HAVE_LIBZ > 0
+ Zflag ||
+#endif
+ S_ISREG (stats->stat.st_mode))
+ {
+ if (file)
+ bufoffset = 0;
+ else
+ {
+ bufoffset = lseek (fd, 0, SEEK_CUR);
+ if (bufoffset < 0)
+ {
+ error ("lseek", errno);
+ return 0;
+ }
+ }
+#ifdef HAVE_MMAP
+ initial_bufoffset = bufoffset;
+ bufmapped = mmap_option && bufoffset % pagesize == 0;
+#endif
+ }
+ else
+ {
+#ifdef HAVE_MMAP
+ bufmapped = 0;
+#endif
+ }
+ return 1;
+}
+
+/* Read new stuff into the buffer, saving the specified
+ amount of old stuff. When we're done, 'bufbeg' points
+ to the beginning of the buffer contents, and 'buflim'
+ points just after the end. Return zero if there's an error. */
+static int
+fillbuf (size_t save, struct stats *stats)
+{
+ size_t fillsize = 0;
+ int cc = 1;
+ size_t readsize;
+
+ /* Offset from start of unaligned buffer to start of old stuff
+ that we want to save. */
+ size_t saved_offset = buflim - ubuffer - save;
+
+ if (bufsalloc < save)
+ {
+ size_t aligned_save = ALIGN_TO (save, pagesize);
+ size_t maxalloc = (size_t) -1;
+ size_t newalloc;
+
+ if (S_ISREG (stats->stat.st_mode))
+ {
+ /* Calculate an upper bound on how much memory we should allocate.
+ We can't use ALIGN_TO here, since off_t might be longer than
+ size_t. Watch out for arithmetic overflow. */
+ off_t to_be_read = stats->stat.st_size - bufoffset;
+ size_t slop = to_be_read % pagesize;
+ off_t aligned_to_be_read = to_be_read + (slop ? pagesize - slop : 0);
+ off_t maxalloc_off = aligned_save + aligned_to_be_read;
+ if (0 <= maxalloc_off && maxalloc_off == (size_t) maxalloc_off)
+ maxalloc = maxalloc_off;
+ }
+
+ /* Grow bufsalloc until it is at least as great as `save'; but
+ if there is an overflow, just grow it to the next page boundary. */
+ while (bufsalloc < save)
+ if (bufsalloc < bufsalloc * 2)
+ bufsalloc *= 2;
+ else
+ {
+ bufsalloc = aligned_save;
+ break;
+ }
+
+ /* Grow the buffer size to be PREFERRED_SAVE_FACTOR times
+ bufsalloc.... */
+ newalloc = PREFERRED_SAVE_FACTOR * bufsalloc;
+ if (maxalloc < newalloc)
+ {
+ /* ... except don't grow it more than a pagesize past the
+ file size, as that might cause unnecessary memory
+ exhaustion if the file is large. */
+ newalloc = maxalloc;
+ bufsalloc = aligned_save;
+ }
+
+ /* Check that the above calculations made progress, which might
+ not occur if there is arithmetic overflow. If there's no
+ progress, or if the new buffer size is larger than the old
+ and buffer reallocation fails, report memory exhaustion. */
+ if (bufsalloc < save || newalloc < save
+ || (newalloc == save && newalloc != maxalloc)
+ || (bufalloc < newalloc
+ && ! (buffer
+ = page_alloc ((bufalloc = newalloc) + 1, &ubuffer))))
+ fatal (_("memory exhausted"), 0);
+ }
+
+ bufbeg = buffer + bufsalloc - save;
+ memmove (bufbeg, ubuffer + saved_offset, save);
+ readsize = bufalloc - bufsalloc;
+
+#if defined(HAVE_MMAP)
+ if (bufmapped)
+ {
+ size_t mmapsize = readsize;
+
+ /* Don't mmap past the end of the file; some hosts don't allow this.
+ Use `read' on the last page. */
+ if (stats->stat.st_size - bufoffset < mmapsize)
+ {
+ mmapsize = stats->stat.st_size - bufoffset;
+ mmapsize -= mmapsize % pagesize;
+ }
+
+ if (mmapsize
+ && (mmap ((caddr_t) (buffer + bufsalloc), mmapsize,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
+ bufdesc, bufoffset)
+ != (caddr_t) -1))
+ {
+ /* Do not bother to use madvise with MADV_SEQUENTIAL or
+ MADV_WILLNEED on the mmapped memory. One might think it
+ would help, but it slows us down about 30% on SunOS 4.1. */
+ fillsize = mmapsize;
+ }
+ else
+ {
+ /* Stop using mmap on this file. Synchronize the file
+ offset. Do not warn about mmap failures. On some hosts
+ (e.g. Solaris 2.5) mmap can fail merely because some
+ other process has an advisory read lock on the file.
+ There's no point alarming the user about this misfeature. */
+ bufmapped = 0;
+ if (bufoffset != initial_bufoffset
+ && lseek (bufdesc, bufoffset, SEEK_SET) < 0)
+ {
+ error ("lseek", errno);
+ cc = 0;
+ }
+ }
+ }
+#endif /*HAVE_MMAP*/
+
+ if (! fillsize)
+ {
+ ssize_t bytesread;
+ do
+#if HAVE_LIBZ > 0
+ if (Zflag)
+ bytesread = gzread (gzbufdesc, buffer + bufsalloc, readsize);
+ else
+#endif
+ bytesread = read (bufdesc, buffer + bufsalloc, readsize);
+ while (bytesread < 0 && errno == EINTR);
+ if (bytesread < 0)
+ cc = 0;
+ else
+ fillsize = bytesread;
+ }
+
+ bufoffset += fillsize;
+#if O_BINARY
+ if (fillsize)
+ fillsize = undossify_input (buffer + bufsalloc, fillsize);
+#endif
+ buflim = buffer + bufsalloc + fillsize;
+ return cc;
+}
+
+/* Flags controlling the style of output. */
+static enum
+ {
+ BINARY_BINARY_FILES,
+ TEXT_BINARY_FILES,
+ WITHOUT_MATCH_BINARY_FILES
+ } binary_files; /* How to handle binary files. */
+static int out_quiet; /* Suppress all normal output. */
+static int out_invert; /* Print nonmatching stuff. */
+static int out_file; /* Print filenames. */
+static int out_line; /* Print line numbers. */
+static int out_byte; /* Print byte offsets. */
+static int out_before; /* Lines of leading context. */
+static int out_after; /* Lines of trailing context. */
+static int count_matches; /* Count matching lines. */
+static int list_files; /* List matching files. */
+static int no_filenames; /* Suppress file names. */
+static int suppress_errors; /* Suppress diagnostics. */
+
+/* Internal variables to keep track of byte count, context, etc. */
+static off_t totalcc; /* Total character count before bufbeg. */
+static char *lastnl; /* Pointer after last newline counted. */
+static char *lastout; /* Pointer after last character output;
+ NULL if no character has been output
+ or if it's conceptually before bufbeg. */
+static off_t totalnl; /* Total newline count before lastnl. */
+static int pending; /* Pending lines of output. */
+static int done_on_match; /* Stop scanning file on first match */
+
+#if O_BINARY
+# include "dosbuf.c"
+#endif
+
+static void
+nlscan (char *lim)
+{
+ char *beg;
+ for (beg = lastnl; (beg = memchr (beg, eolbyte, lim - beg)); beg++)
+ totalnl++;
+ lastnl = lim;
+}
+
+static void
+print_offset_sep (off_t pos, int sep)
+{
+ /* Do not rely on printf to print pos, since off_t may be longer than long,
+ and long long is not portable. */
+
+ char buf[sizeof pos * CHAR_BIT];
+ char *p = buf + sizeof buf - 1;
+ *p = sep;
+
+ do
+ *--p = '0' + pos % 10;
+ while ((pos /= 10) != 0);
+
+ fwrite (p, 1, buf + sizeof buf - p, stdout);
+}
+
+static void
+prline (char *beg, char *lim, int sep)
+{
+ if (out_file)
+ printf ("%s%c", filename, sep & filename_mask);
+ if (out_line)
+ {
+ nlscan (beg);
+ print_offset_sep (++totalnl, sep);
+ lastnl = lim;
+ }
+ if (out_byte)
+ {
+ off_t pos = totalcc + (beg - bufbeg);
+#if O_BINARY
+ pos = dossified_pos (pos);
+#endif
+ print_offset_sep (pos, sep);
+ }
+ fwrite (beg, 1, lim - beg, stdout);
+ if (ferror (stdout))
+ error (_("writing output"), errno);
+ lastout = lim;
+}
+
+/* Print pending lines of trailing context prior to LIM. */
+static void
+prpending (char *lim)
+{
+ char *nl;
+
+ if (!lastout)
+ lastout = bufbeg;
+ while (pending > 0 && lastout < lim)
+ {
+ --pending;
+ if ((nl = memchr (lastout, eolbyte, lim - lastout)) != 0)
+ ++nl;
+ else
+ nl = lim;
+ prline (lastout, nl, '-');
+ }
+}
+
+/* Print the lines between BEG and LIM. Deal with context crap.
+ If NLINESP is non-null, store a count of lines between BEG and LIM. */
+static void
+prtext (char *beg, char *lim, int *nlinesp)
+{
+ static int used; /* avoid printing "--" before any output */
+ char *bp, *p, *nl;
+ char eol = eolbyte;
+ int i, n;
+
+ if (!out_quiet && pending > 0)
+ prpending (beg);
+
+ p = beg;
+
+ if (!out_quiet)
+ {
+ /* Deal with leading context crap. */
+
+ bp = lastout ? lastout : bufbeg;
+ for (i = 0; i < out_before; ++i)
+ if (p > bp)
+ do
+ --p;
+ while (p > bp && p[-1] != eol);
+
+ /* We only print the "--" separator if our output is
+ discontiguous from the last output in the file. */
+ if ((out_before || out_after) && used && p != lastout)
+ puts ("--");
+
+ while (p < beg)
+ {
+ nl = memchr (p, eol, beg - p);
+ prline (p, nl + 1, '-');
+ p = nl + 1;
+ }
+ }
+
+ if (nlinesp)
+ {
+ /* Caller wants a line count. */
+ for (n = 0; p < lim; ++n)
+ {
+ if ((nl = memchr (p, eol, lim - p)) != 0)
+ ++nl;
+ else
+ nl = lim;
+ if (!out_quiet)
+ prline (p, nl, ':');
+ p = nl;
+ }
+ *nlinesp = n;
+ }
+ else
+ if (!out_quiet)
+ prline (beg, lim, ':');
+
+ pending = out_quiet ? 0 : out_after;
+ used = 1;
+}
+
+/* Scan the specified portion of the buffer, matching lines (or
+ between matching lines if OUT_INVERT is true). Return a count of
+ lines printed. */
+static int
+grepbuf (char *beg, char *lim)
+{
+ int nlines, n;
+ register char *p, *b;
+ char *endp;
+ char eol = eolbyte;
+
+ nlines = 0;
+ p = beg;
+ while ((b = (*execute)(p, lim - p, &endp)) != 0)
+ {
+ /* Avoid matching the empty line at the end of the buffer. */
+ if (b == lim && ((b > beg && b[-1] == eol) || b == beg))
+ break;
+ if (!out_invert)
+ {
+ prtext (b, endp, (int *) 0);
+ nlines += 1;
+ if (done_on_match)
+ return nlines;
+ }
+ else if (p < b)
+ {
+ prtext (p, b, &n);
+ nlines += n;
+ }
+ p = endp;
+ }
+ if (out_invert && p < lim)
+ {
+ prtext (p, lim, &n);
+ nlines += n;
+ }
+ return nlines;
+}
+
+/* Search a given file. Normally, return a count of lines printed;
+ but if the file is a directory and we search it recursively, then
+ return -2 if there was a match, and -1 otherwise. */
+static int
+grep (int fd, char const *file, struct stats *stats)
+{
+ int nlines, i;
+ int not_text;
+ size_t residue, save;
+ char *beg, *lim;
+ char eol = eolbyte;
+
+ if (!reset (fd, file, stats))
+ return 0;
+
+ if (file && directories == RECURSE_DIRECTORIES
+ && S_ISDIR (stats->stat.st_mode))
+ {
+ /* Close fd now, so that we don't open a lot of file descriptors
+ when we recurse deeply. */
+#if HAVE_LIBZ > 0
+ if (Zflag)
+ gzclose(gzbufdesc);
+ else
+#endif
+ if (close (fd) != 0)
+ error (file, errno);
+ return grepdir (file, stats) - 2;
+ }
+
+ totalcc = 0;
+ lastout = 0;
+ totalnl = 0;
+ pending = 0;
+
+ nlines = 0;
+ residue = 0;
+ save = 0;
+
+ if (! fillbuf (save, stats))
+ {
+ if (! (is_EISDIR (errno, file) && suppress_errors))
+ error (filename, errno);
+ return 0;
+ }
+
+ not_text = (((binary_files == BINARY_BINARY_FILES && !out_quiet)
+ || binary_files == WITHOUT_MATCH_BINARY_FILES)
+ && memchr (bufbeg, eol ? '\0' : '\200', buflim - bufbeg));
+ if (not_text && binary_files == WITHOUT_MATCH_BINARY_FILES)
+ return 0;
+ done_on_match += not_text;
+ out_quiet += not_text;
+
+ for (;;)
+ {
+ lastnl = bufbeg;
+ if (lastout)
+ lastout = bufbeg;
+ if (buflim - bufbeg == save)
+ break;
+ beg = bufbeg + save - residue;
+ for (lim = buflim; lim > beg && lim[-1] != eol; --lim)
+ ;
+ residue = buflim - lim;
+ if (beg < lim)
+ {
+ nlines += grepbuf (beg, lim);
+ if (pending)
+ prpending (lim);
+ if (nlines && done_on_match && !out_invert)
+ goto finish_grep;
+ }
+ i = 0;
+ beg = lim;
+ while (i < out_before && beg > bufbeg && beg != lastout)
+ {
+ ++i;
+ do
+ --beg;
+ while (beg > bufbeg && beg[-1] != eol);
+ }
+ if (beg != lastout)
+ lastout = 0;
+ save = residue + lim - beg;
+ totalcc += buflim - bufbeg - save;
+ if (out_line)
+ nlscan (beg);
+ if (! fillbuf (save, stats))
+ {
+ if (! (is_EISDIR (errno, file) && suppress_errors))
+ error (filename, errno);
+ goto finish_grep;
+ }
+ }
+ if (residue)
+ {
+ *buflim++ = eol;
+ nlines += grepbuf (bufbeg + save - residue, buflim);
+ if (pending)
+ prpending (buflim);
+ }
+
+ finish_grep:
+ done_on_match -= not_text;
+ out_quiet -= not_text;
+ if ((not_text & ~out_quiet) && nlines != 0)
+ printf (_("Binary file %s matches\n"), filename);
+ return nlines;
+}
+
+static int
+grepfile (char const *file, struct stats *stats)
+{
+ int desc;
+ int count;
+ int status;
+
+ if (! file)
+ {
+ desc = 0;
+ filename = _("(standard input)");
+ }
+ else
+ {
+ while ((desc = open (file, O_RDONLY)) < 0 && errno == EINTR)
+ continue;
+
+ if (desc < 0)
+ {
+ int e = errno;
+
+ if (is_EISDIR (e, file) && directories == RECURSE_DIRECTORIES)
+ {
+ if (stat (file, &stats->stat) != 0)
+ {
+ error (file, errno);
+ return 1;
+ }
+
+ return grepdir (file, stats);
+ }
+
+ if (!suppress_errors)
+ {
+ if (directories == SKIP_DIRECTORIES)
+ switch (e)
+ {
+#ifdef EISDIR
+ case EISDIR:
+ return 1;
+#endif
+ case EACCES:
+ /* When skipping directories, don't worry about
+ directories that can't be opened. */
+ if (stat (file, &stats->stat) == 0
+ && S_ISDIR (stats->stat.st_mode))
+ return 1;
+ break;
+ }
+
+ error (file, e);
+ }
+
+ return 1;
+ }
+
+ filename = file;
+ }
+
+#if O_BINARY
+ /* Set input to binary mode. Pipes are simulated with files
+ on DOS, so this includes the case of "foo | grep bar". */
+ if (!isatty (desc))
+ SET_BINARY (desc);
+#endif
+
+ count = grep (desc, file, stats);
+ if (count < 0)
+ status = count + 2;
+ else
+ {
+ if (count_matches)
+ {
+ if (out_file)
+ printf ("%s%c", filename, ':' & filename_mask);
+ printf ("%d\n", count);
+ }
+
+ status = !count;
+ if (list_files == 1 - 2 * status)
+ printf ("%s%c", filename, '\n' & filename_mask);
+
+#if HAVE_LIBZ > 0
+ if (Zflag)
+ gzclose(gzbufdesc);
+ else
+#endif
+ if (file)
+ while (close (desc) != 0)
+ if (errno != EINTR)
+ {
+ error (file, errno);
+ break;
+ }
+ }
+
+ return status;
+}
+
+static int
+grepdir (char const *dir, struct stats *stats)
+{
+ int status = 1;
+ struct stats *ancestor;
+ char *name_space;
+
+ for (ancestor = stats; (ancestor = ancestor->parent) != 0; )
+ if (ancestor->stat.st_ino == stats->stat.st_ino
+ && ancestor->stat.st_dev == stats->stat.st_dev)
+ {
+ if (!suppress_errors)
+ fprintf (stderr, _("%s: warning: %s: %s\n"), prog, dir,
+ _("recursive directory loop"));
+ return 1;
+ }
+
+ name_space = savedir (dir, (unsigned) stats->stat.st_size);
+
+ if (! name_space)
+ {
+ if (errno)
+ {
+ if (!suppress_errors)
+ error (dir, errno);
+ }
+ else
+ fatal (_("Memory exhausted"), 0);
+ }
+ else
+ {
+ size_t dirlen = strlen (dir);
+ int needs_slash = ! (dirlen == FILESYSTEM_PREFIX_LEN (dir)
+ || IS_SLASH (dir[dirlen - 1]));
+ char *file = NULL;
+ char *namep = name_space;
+ struct stats child;
+ child.parent = stats;
+ out_file += !no_filenames;
+ while (*namep)
+ {
+ size_t namelen = strlen (namep);
+ file = xrealloc (file, dirlen + 1 + namelen + 1);
+ strcpy (file, dir);
+ file[dirlen] = '/';
+ strcpy (file + dirlen + needs_slash, namep);
+ namep += namelen + 1;
+ status &= grepfile (file, &child);
+ }
+ out_file -= !no_filenames;
+ if (file)
+ free (file);
+ free (name_space);
+ }
+
+ return status;
+}
+
+static void
+usage (int status)
+{
+ if (status != 0)
+ {
+ fprintf (stderr, _("Usage: %s [OPTION]... PATTERN [FILE]...\n"), prog);
+ fprintf (stderr, _("Try `%s --help' for more information.\n"), prog);
+ }
+ else
+ {
+ printf (_("Usage: %s [OPTION]... PATTERN [FILE] ...\n"), prog);
+ printf (_("\
+Search for PATTERN in each FILE or standard input.\n\
+Example: %s -i 'hello world' menu.h main.c\n\
+\n\
+Regexp selection and interpretation:\n"), prog);
+ printf (_("\
+ -E, --extended-regexp PATTERN is an extended regular expression\n\
+ -F, --fixed-strings PATTERN is a set of newline-separated strings\n\
+ -G, --basic-regexp PATTERN is a basic regular expression\n"));
+ printf (_("\
+ -e, --regexp=PATTERN use PATTERN as a regular expression\n\
+ -f, --file=FILE obtain PATTERN from FILE\n\
+ -i, --ignore-case ignore case distinctions\n\
+ -w, --word-regexp force PATTERN to match only whole words\n\
+ -x, --line-regexp force PATTERN to match only whole lines\n\
+ -z, --null-data a data line ends in 0 byte, not newline\n"));
+ printf (_("\
+\n\
+Miscellaneous:\n\
+ -s, --no-messages suppress error messages\n\
+ -v, --invert-match select non-matching lines\n\
+ -V, --version print version information and exit\n\
+ --help display this help and exit\n\
+ -Z, --decompress decompress input before searching (HAVE_LIBZ=1)\n\
+ --mmap use memory-mapped input if possible\n"));
+ printf (_("\
+\n\
+Output control:\n\
+ -b, --byte-offset print the byte offset with output lines\n\
+ -n, --line-number print line number with output lines\n\
+ -H, --with-filename print the filename for each match\n\
+ -h, --no-filename suppress the prefixing filename on output\n\
+ -q, --quiet, --silent suppress all normal output\n\
+ --binary-files=TYPE assume that binary files are TYPE\n\
+ TYPE is 'binary', 'text', or 'without-match'.\n\
+ -a, --text equivalent to --binary-files=text\n\
+ -I equivalent to --binary-files=without-match\n\
+ -d, --directories=ACTION how to handle directories\n\
+ ACTION is 'read', 'recurse', or 'skip'.\n\
+ -r, --recursive equivalent to --directories=recurse.\n\
+ -L, --files-without-match only print FILE names containing no match\n\
+ -l, --files-with-matches only print FILE names containing matches\n\
+ -c, --count only print a count of matching lines per FILE\n\
+ --null print 0 byte after FILE name\n"));
+ printf (_("\
+\n\
+Context control:\n\
+ -B, --before-context=NUM print NUM lines of leading context\n\
+ -A, --after-context=NUM print NUM lines of trailing context\n\
+ -C, --context[=NUM] print NUM (default 2) lines of output context\n\
+ unless overridden by -A or -B\n\
+ -NUM same as --context=NUM\n\
+ -U, --binary do not strip CR characters at EOL (MSDOS)\n\
+ -u, --unix-byte-offsets report offsets as if CRs were not there (MSDOS)\n\
+\n\
+`egrep' means `grep -E'. `fgrep' means `grep -F'.\n\
+With no FILE, or when FILE is -, read standard input. If less than\n\
+two FILEs given, assume -h. Exit status is 0 if match, 1 if no match,\n\
+and 2 if trouble.\n"));
+ printf (_("\nReport bugs to <bug-gnu-utils@gnu.org>.\n"));
+ }
+ exit (status);
+}
+
+/* Set the matcher to M, reporting any conflicts. */
+static void
+setmatcher (char const *m)
+{
+ if (matcher && strcmp (matcher, m) != 0)
+ fatal (_("conflicting matchers specified"), 0);
+ matcher = m;
+}
+
+/* Go through the matchers vector and look for the specified matcher.
+ If we find it, install it in compile and execute, and return 1. */
+static int
+install_matcher (char const *name)
+{
+ int i;
+#ifdef HAVE_SETRLIMIT
+ struct rlimit rlim;
+#endif
+
+ for (i = 0; matchers[i].name; ++i)
+ if (strcmp (name, matchers[i].name) == 0)
+ {
+ compile = matchers[i].compile;
+ execute = matchers[i].execute;
+#if HAVE_SETRLIMIT && defined(RLIMIT_STACK)
+ /* I think every platform needs to do this, so that regex.c
+ doesn't oveflow the stack. The default value of
+ `re_max_failures' is too large for some platforms: it needs
+ more than 3MB-large stack.
+
+ The test for HAVE_SETRLIMIT should go into `configure'. */
+ if (!getrlimit (RLIMIT_STACK, &rlim))
+ {
+ long newlim;
+ extern long int re_max_failures; /* from regex.c */
+
+ /* Approximate the amount regex.c needs, plus some more. */
+ newlim = re_max_failures * 2 * 20 * sizeof (char *);
+ if (newlim > rlim.rlim_max)
+ {
+ newlim = rlim.rlim_max;
+ re_max_failures = newlim / (2 * 20 * sizeof (char *));
+ }
+ if (rlim.rlim_cur < newlim)
+ rlim.rlim_cur = newlim;
+
+ setrlimit (RLIMIT_STACK, &rlim);
+ }
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+/* Find the white-space-separated options specified by OPTIONS, and
+ using BUF to store copies of these options, set ARGV[0], ARGV[1],
+ etc. to the option copies. Return the number N of options found.
+ Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0]
+ etc. Backslash can be used to escape whitespace (and backslashes). */
+static int
+prepend_args (char const *options, char *buf, char **argv)
+{
+ char const *o = options;
+ char *b = buf;
+ int n = 0;
+
+ for (;;)
+ {
+ while (ISSPACE ((unsigned char) *o))
+ o++;
+ if (!*o)
+ return n;
+ if (argv)
+ argv[n] = b;
+ n++;
+
+ do
+ if ((*b++ = *o++) == '\\' && *o)
+ b[-1] = *o++;
+ while (*o && ! ISSPACE ((unsigned char) *o));
+
+ *b++ = '\0';
+ }
+}
+
+/* Prepend the whitespace-separated options in OPTIONS to the argument
+ vector of a main program with argument count *PARGC and argument
+ vector *PARGV. */
+static void
+prepend_default_options (char const *options, int *pargc, char ***pargv)
+{
+ if (options)
+ {
+ char *buf = xmalloc (strlen (options) + 1);
+ int prepended = prepend_args (options, buf, (char **) NULL);
+ int argc = *pargc;
+ char * const *argv = *pargv;
+ char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp);
+ *pargc = prepended + argc;
+ *pargv = pp;
+ *pp++ = *argv++;
+ pp += prepend_args (options, buf, pp);
+ while ((*pp++ = *argv++))
+ continue;
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ char *keys;
+ size_t keycc, oldcc, keyalloc;
+ int with_filenames;
+ int opt, cc, status;
+ int default_context;
+ unsigned digit_args_val;
+ FILE *fp;
+ extern char *optarg;
+ extern int optind;
+
+ initialize_main (&argc, &argv);
+ prog = argv[0];
+ if (prog && strrchr (prog, '/'))
+ prog = strrchr (prog, '/') + 1;
+
+#if HAVE_LIBZ > 0
+ if (prog[0] == 'z') {
+ Zflag = 1;
+ ++prog;
+ }
+#endif
+
+#if defined(__MSDOS__) || defined(_WIN32)
+ /* DOS and MS-Windows use backslashes as directory separators, and usually
+ have an .exe suffix. They also have case-insensitive filesystems. */
+ if (prog)
+ {
+ char *p = prog;
+ char *bslash = strrchr (argv[0], '\\');
+
+ if (bslash && bslash >= prog) /* for mixed forward/backslash case */
+ prog = bslash + 1;
+ else if (prog == argv[0]
+ && argv[0][0] && argv[0][1] == ':') /* "c:progname" */
+ prog = argv[0] + 2;
+
+ /* Collapse the letter-case, so `strcmp' could be used hence. */
+ for ( ; *p; p++)
+ if (*p >= 'A' && *p <= 'Z')
+ *p += 'a' - 'A';
+
+ /* Remove the .exe extension, if any. */
+ if ((p = strrchr (prog, '.')) && strcmp (p, ".exe") == 0)
+ *p = '\0';
+ }
+#endif
+
+ keys = NULL;
+ keycc = 0;
+ with_filenames = 0;
+ eolbyte = '\n';
+ filename_mask = ~0;
+
+ /* The value -1 means to use DEFAULT_CONTEXT. */
+ out_after = out_before = -1;
+ /* Default before/after context: chaged by -C/-NUM options */
+ default_context = 0;
+ /* Accumulated value of individual digits in a -NUM option */
+ digit_args_val = 0;
+
+
+/* Internationalization. */
+#if HAVE_SETLOCALE
+ setlocale (LC_ALL, "");
+#endif
+#if ENABLE_NLS
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
+#endif
+
+ prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv);
+
+ while ((opt = getopt_long (argc, argv, short_options, long_options, NULL))
+ != -1)
+ switch (opt)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ digit_args_val = 10 * digit_args_val + opt - '0';
+ default_context = digit_args_val;
+ break;
+ case 'A':
+ if (optarg)
+ {
+ if (ck_atoi (optarg, &out_after))
+ fatal (_("invalid context length argument"), 0);
+ }
+ break;
+ case 'B':
+ if (optarg)
+ {
+ if (ck_atoi (optarg, &out_before))
+ fatal (_("invalid context length argument"), 0);
+ }
+ break;
+ case 'C':
+ /* Set output match context, but let any explicit leading or
+ trailing amount specified with -A or -B stand. */
+ if (optarg)
+ {
+ if (ck_atoi (optarg, &default_context))
+ fatal (_("invalid context length argument"), 0);
+ }
+ else
+ default_context = 2;
+ break;
+ case 'E':
+ setmatcher ("egrep");
+ break;
+ case 'F':
+ setmatcher ("fgrep");
+ break;
+ case 'G':
+ setmatcher ("grep");
+ break;
+ case 'H':
+ with_filenames = 1;
+ break;
+ case 'I':
+ binary_files = WITHOUT_MATCH_BINARY_FILES;
+ break;
+ case 'U':
+#if O_BINARY
+ dos_use_file_type = DOS_BINARY;
+#endif
+ break;
+ case 'u':
+#if O_BINARY
+ dos_report_unix_offset = 1;
+#endif
+ break;
+ case 'V':
+ show_version = 1;
+ break;
+ case 'X':
+ setmatcher (optarg);
+ break;
+ case 'a':
+ binary_files = TEXT_BINARY_FILES;
+ break;
+ case 'b':
+ out_byte = 1;
+ break;
+ case 'c':
+ out_quiet = 1;
+ count_matches = 1;
+ break;
+ case 'd':
+ if (strcmp (optarg, "read") == 0)
+ directories = READ_DIRECTORIES;
+ else if (strcmp (optarg, "skip") == 0)
+ directories = SKIP_DIRECTORIES;
+ else if (strcmp (optarg, "recurse") == 0)
+ directories = RECURSE_DIRECTORIES;
+ else
+ fatal (_("unknown directories method"), 0);
+ break;
+ case 'e':
+ cc = strlen (optarg);
+ keys = xrealloc (keys, keycc + cc + 1);
+ strcpy (&keys[keycc], optarg);
+ keycc += cc;
+ keys[keycc++] = '\n';
+ break;
+ case 'f':
+ fp = strcmp (optarg, "-") != 0 ? fopen (optarg, "r") : stdin;
+ if (!fp)
+ fatal (optarg, errno);
+ for (keyalloc = 1; keyalloc <= keycc + 1; keyalloc *= 2)
+ ;
+ keys = xrealloc (keys, keyalloc);
+ oldcc = keycc;
+ while (!feof (fp)
+ && (cc = fread (keys + keycc, 1, keyalloc - 1 - keycc, fp)) > 0)
+ {
+ keycc += cc;
+ if (keycc == keyalloc - 1)
+ keys = xrealloc (keys, keyalloc *= 2);
+ }
+ if (fp != stdin)
+ fclose(fp);
+ /* Append final newline if file ended in non-newline. */
+ if (oldcc != keycc && keys[keycc - 1] != '\n')
+ keys[keycc++] = '\n';
+ break;
+ case 'h':
+ no_filenames = 1;
+ break;
+ case 'i':
+ case 'y': /* For old-timers . . . */
+ match_icase = 1;
+ break;
+ case 'L':
+ /* Like -l, except list files that don't contain matches.
+ Inspired by the same option in Hume's gre. */
+ out_quiet = 1;
+ list_files = -1;
+ done_on_match = 1;
+ break;
+ case 'l':
+ out_quiet = 1;
+ list_files = 1;
+ done_on_match = 1;
+ break;
+ case 'n':
+ out_line = 1;
+ break;
+ case 'q':
+ done_on_match = 1;
+ out_quiet = 1;
+ break;
+ case 'R':
+ case 'r':
+ directories = RECURSE_DIRECTORIES;
+ break;
+ case 's':
+ suppress_errors = 1;
+ break;
+ case 'v':
+ out_invert = 1;
+ break;
+ case 'w':
+ match_words = 1;
+ break;
+ case 'x':
+ match_lines = 1;
+ break;
+ case 'Z':
+#if HAVE_LIBZ > 0
+ Zflag = 1;
+#else
+ filename_mask = 0;
+#endif
+ break;
+ case 'z':
+ eolbyte = '\0';
+ break;
+ case BINARY_FILES_OPTION:
+ if (strcmp (optarg, "binary") == 0)
+ binary_files = BINARY_BINARY_FILES;
+ else if (strcmp (optarg, "text") == 0)
+ binary_files = TEXT_BINARY_FILES;
+ else if (strcmp (optarg, "without-match") == 0)
+ binary_files = WITHOUT_MATCH_BINARY_FILES;
+ else
+ fatal (_("unknown binary-files type"), 0);
+ break;
+ case 0:
+ /* long options */
+ break;
+ default:
+ usage (2);
+ break;
+ }
+
+ if (out_after < 0)
+ out_after = default_context;
+ if (out_before < 0)
+ out_before = default_context;
+
+ if (! matcher)
+ matcher = prog;
+
+ if (show_version)
+ {
+ printf (_("%s (GNU grep) %s\n"), matcher, VERSION);
+ printf ("\n");
+ printf (_("\
+Copyright (C) 1988, 1992-1998, 1999 Free Software Foundation, Inc.\n"));
+ printf (_("\
+This is free software; see the source for copying conditions. There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"));
+ printf ("\n");
+ exit (0);
+ }
+
+ if (show_help)
+ usage (0);
+
+ if (keys)
+ {
+ if (keycc == 0)
+ /* No keys were specified (e.g. -f /dev/null). Match nothing. */
+ out_invert ^= 1;
+ else
+ /* Strip trailing newline. */
+ --keycc;
+ }
+ else
+ if (optind < argc)
+ {
+ keys = argv[optind++];
+ keycc = strlen (keys);
+ }
+ else
+ usage (2);
+
+ if (!install_matcher (matcher) && !install_matcher ("default"))
+ abort ();
+
+ (*compile)(keys, keycc);
+
+ if ((argc - optind > 1 && !no_filenames) || with_filenames)
+ out_file = 1;
+
+#if O_BINARY
+ /* Output is set to binary mode because we shouldn't convert
+ NL to CR-LF pairs, especially when grepping binary files. */
+ if (!isatty (1))
+ SET_BINARY (1);
+#endif
+
+
+ if (optind < argc)
+ {
+ status = 1;
+ do
+ {
+ char *file = argv[optind];
+ status &= grepfile (strcmp (file, "-") == 0 ? (char *) NULL : file,
+ &stats_base);
+ }
+ while ( ++optind < argc);
+ }
+ else
+ status = grepfile ((char *) NULL, &stats_base);
+
+ if (fclose (stdout) == EOF)
+ error (_("writing output"), errno);
+
+ exit (errseen ? 2 : status);
+}
diff --git a/gnu/usr.bin/grep/grep.h b/gnu/usr.bin/grep/grep.h
new file mode 100644
index 0000000..264ad20
--- /dev/null
+++ b/gnu/usr.bin/grep/grep.h
@@ -0,0 +1,48 @@
+/* grep.h - interface to grep driver for searching subroutines.
+ Copyright (C) 1992, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) || __STRICT_ANSI__
+# define __attribute__(x)
+#endif
+
+extern void fatal PARAMS ((const char *, int)) __attribute__((noreturn));
+extern char *xmalloc PARAMS ((size_t size));
+extern char *xrealloc PARAMS ((char *ptr, size_t size));
+
+/* Grep.c expects the matchers vector to be terminated
+ by an entry with a NULL name, and to contain at least
+ an entry named "default". */
+
+extern struct matcher
+{
+ char *name;
+ void (*compile) PARAMS ((char *, size_t));
+ char *(*execute) PARAMS ((char *, size_t, char **));
+} matchers[];
+
+/* Exported from fgrepmat.c, egrepmat.c, grepmat.c. */
+extern char const *matcher;
+
+/* The following flags are exported from grep for the matchers
+ to look at. */
+extern int match_icase; /* -i */
+extern int match_words; /* -w */
+extern int match_lines; /* -x */
+extern unsigned char eolbyte; /* -z */
diff --git a/gnu/usr.bin/grep/kwset.c b/gnu/usr.bin/grep/kwset.c
new file mode 100644
index 0000000..92dbf09
--- /dev/null
+++ b/gnu/usr.bin/grep/kwset.c
@@ -0,0 +1,775 @@
+/* kwset.c - search for any of a set of keywords.
+ Copyright (C) 1989, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 August 1989 by Mike Haertel.
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+/* The algorithm implemented by these routines bears a startling resemblence
+ to one discovered by Beate Commentz-Walter, although it is not identical.
+ See "A String Matching Algorithm Fast on the Average," Technical Report,
+ IBM-Germany, Scientific Center Heidelberg, Tiergartenstrasse 15, D-6900
+ Heidelberg, Germany. See also Aho, A.V., and M. Corasick, "Efficient
+ String Matching: An Aid to Bibliographic Search," CACM June 1975,
+ Vol. 18, No. 6, which describes the failure function used below. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <sys/types.h>
+#include "system.h"
+#include "kwset.h"
+#include "obstack.h"
+
+#ifdef GREP
+extern char *xmalloc();
+# undef malloc
+# define malloc xmalloc
+#endif
+
+#define NCHAR (UCHAR_MAX + 1)
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+/* Balanced tree of edges and labels leaving a given trie node. */
+struct tree
+{
+ struct tree *llink; /* Left link; MUST be first field. */
+ struct tree *rlink; /* Right link (to larger labels). */
+ struct trie *trie; /* Trie node pointed to by this edge. */
+ unsigned char label; /* Label on this edge. */
+ char balance; /* Difference in depths of subtrees. */
+};
+
+/* Node of a trie representing a set of reversed keywords. */
+struct trie
+{
+ unsigned int accepting; /* Word index of accepted word, or zero. */
+ struct tree *links; /* Tree of edges leaving this node. */
+ struct trie *parent; /* Parent of this node. */
+ struct trie *next; /* List of all trie nodes in level order. */
+ struct trie *fail; /* Aho-Corasick failure function. */
+ int depth; /* Depth of this node from the root. */
+ int shift; /* Shift function for search failures. */
+ int maxshift; /* Max shift of self and descendents. */
+};
+
+/* Structure returned opaquely to the caller, containing everything. */
+struct kwset
+{
+ struct obstack obstack; /* Obstack for node allocation. */
+ int words; /* Number of words in the trie. */
+ struct trie *trie; /* The trie itself. */
+ int mind; /* Minimum depth of an accepting node. */
+ int maxd; /* Maximum depth of any node. */
+ unsigned char delta[NCHAR]; /* Delta table for rapid search. */
+ struct trie *next[NCHAR]; /* Table of children of the root. */
+ char *target; /* Target string if there's only one. */
+ int mind2; /* Used in Boyer-Moore search for one string. */
+ char *trans; /* Character translation table. */
+};
+
+/* prototypes */
+static void enqueue PARAMS((struct tree *, struct trie **));
+static void treefails PARAMS((register struct tree *, struct trie *, struct trie *));
+static void treedelta PARAMS((register struct tree *,register unsigned int, unsigned char *));
+static int hasevery PARAMS((register struct tree *, register struct tree *));
+static void treenext PARAMS((struct tree *, struct trie **));
+static char * bmexec PARAMS((kwset_t, char *, size_t));
+static char * cwexec PARAMS((kwset_t, char *, size_t, struct kwsmatch *));
+
+/* Allocate and initialize a keyword set object, returning an opaque
+ pointer to it. Return NULL if memory is not available. */
+kwset_t
+kwsalloc (char *trans)
+{
+ struct kwset *kwset;
+
+ kwset = (struct kwset *) malloc(sizeof (struct kwset));
+ if (!kwset)
+ return 0;
+
+ obstack_init(&kwset->obstack);
+ kwset->words = 0;
+ kwset->trie
+ = (struct trie *) obstack_alloc(&kwset->obstack, sizeof (struct trie));
+ if (!kwset->trie)
+ {
+ kwsfree((kwset_t) kwset);
+ return 0;
+ }
+ kwset->trie->accepting = 0;
+ kwset->trie->links = 0;
+ kwset->trie->parent = 0;
+ kwset->trie->next = 0;
+ kwset->trie->fail = 0;
+ kwset->trie->depth = 0;
+ kwset->trie->shift = 0;
+ kwset->mind = INT_MAX;
+ kwset->maxd = -1;
+ kwset->target = 0;
+ kwset->trans = trans;
+
+ return (kwset_t) kwset;
+}
+
+/* Add the given string to the contents of the keyword set. Return NULL
+ for success, an error message otherwise. */
+char *
+kwsincr (kwset_t kws, char *text, size_t len)
+{
+ struct kwset *kwset;
+ register struct trie *trie;
+ register unsigned char label;
+ register struct tree *link;
+ register int depth;
+ struct tree *links[12];
+ enum { L, R } dirs[12];
+ struct tree *t, *r, *l, *rl, *lr;
+
+ kwset = (struct kwset *) kws;
+ trie = kwset->trie;
+ text += len;
+
+ /* Descend the trie (built of reversed keywords) character-by-character,
+ installing new nodes when necessary. */
+ while (len--)
+ {
+ label = kwset->trans ? kwset->trans[(unsigned char) *--text] : *--text;
+
+ /* Descend the tree of outgoing links for this trie node,
+ looking for the current character and keeping track
+ of the path followed. */
+ link = trie->links;
+ links[0] = (struct tree *) &trie->links;
+ dirs[0] = L;
+ depth = 1;
+
+ while (link && label != link->label)
+ {
+ links[depth] = link;
+ if (label < link->label)
+ dirs[depth++] = L, link = link->llink;
+ else
+ dirs[depth++] = R, link = link->rlink;
+ }
+
+ /* The current character doesn't have an outgoing link at
+ this trie node, so build a new trie node and install
+ a link in the current trie node's tree. */
+ if (!link)
+ {
+ link = (struct tree *) obstack_alloc(&kwset->obstack,
+ sizeof (struct tree));
+ if (!link)
+ return _("memory exhausted");
+ link->llink = 0;
+ link->rlink = 0;
+ link->trie = (struct trie *) obstack_alloc(&kwset->obstack,
+ sizeof (struct trie));
+ if (!link->trie)
+ return _("memory exhausted");
+ link->trie->accepting = 0;
+ link->trie->links = 0;
+ link->trie->parent = trie;
+ link->trie->next = 0;
+ link->trie->fail = 0;
+ link->trie->depth = trie->depth + 1;
+ link->trie->shift = 0;
+ link->label = label;
+ link->balance = 0;
+
+ /* Install the new tree node in its parent. */
+ if (dirs[--depth] == L)
+ links[depth]->llink = link;
+ else
+ links[depth]->rlink = link;
+
+ /* Back up the tree fixing the balance flags. */
+ while (depth && !links[depth]->balance)
+ {
+ if (dirs[depth] == L)
+ --links[depth]->balance;
+ else
+ ++links[depth]->balance;
+ --depth;
+ }
+
+ /* Rebalance the tree by pointer rotations if necessary. */
+ if (depth && ((dirs[depth] == L && --links[depth]->balance)
+ || (dirs[depth] == R && ++links[depth]->balance)))
+ {
+ switch (links[depth]->balance)
+ {
+ case (char) -2:
+ switch (dirs[depth + 1])
+ {
+ case L:
+ r = links[depth], t = r->llink, rl = t->rlink;
+ t->rlink = r, r->llink = rl;
+ t->balance = r->balance = 0;
+ break;
+ case R:
+ r = links[depth], l = r->llink, t = l->rlink;
+ rl = t->rlink, lr = t->llink;
+ t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl;
+ l->balance = t->balance != 1 ? 0 : -1;
+ r->balance = t->balance != (char) -1 ? 0 : 1;
+ t->balance = 0;
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case 2:
+ switch (dirs[depth + 1])
+ {
+ case R:
+ l = links[depth], t = l->rlink, lr = t->llink;
+ t->llink = l, l->rlink = lr;
+ t->balance = l->balance = 0;
+ break;
+ case L:
+ l = links[depth], r = l->rlink, t = r->llink;
+ lr = t->llink, rl = t->rlink;
+ t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl;
+ l->balance = t->balance != 1 ? 0 : -1;
+ r->balance = t->balance != (char) -1 ? 0 : 1;
+ t->balance = 0;
+ break;
+ default:
+ abort ();
+ }
+ break;
+ default:
+ abort ();
+ }
+
+ if (dirs[depth - 1] == L)
+ links[depth - 1]->llink = t;
+ else
+ links[depth - 1]->rlink = t;
+ }
+ }
+
+ trie = link->trie;
+ }
+
+ /* Mark the node we finally reached as accepting, encoding the
+ index number of this word in the keyword set so far. */
+ if (!trie->accepting)
+ trie->accepting = 1 + 2 * kwset->words;
+ ++kwset->words;
+
+ /* Keep track of the longest and shortest string of the keyword set. */
+ if (trie->depth < kwset->mind)
+ kwset->mind = trie->depth;
+ if (trie->depth > kwset->maxd)
+ kwset->maxd = trie->depth;
+
+ return 0;
+}
+
+/* Enqueue the trie nodes referenced from the given tree in the
+ given queue. */
+static void
+enqueue (struct tree *tree, struct trie **last)
+{
+ if (!tree)
+ return;
+ enqueue(tree->llink, last);
+ enqueue(tree->rlink, last);
+ (*last) = (*last)->next = tree->trie;
+}
+
+/* Compute the Aho-Corasick failure function for the trie nodes referenced
+ from the given tree, given the failure function for their parent as
+ well as a last resort failure node. */
+static void
+treefails (register struct tree *tree, struct trie *fail, struct trie *recourse)
+{
+ register struct tree *link;
+
+ if (!tree)
+ return;
+
+ treefails(tree->llink, fail, recourse);
+ treefails(tree->rlink, fail, recourse);
+
+ /* Find, in the chain of fails going back to the root, the first
+ node that has a descendent on the current label. */
+ while (fail)
+ {
+ link = fail->links;
+ while (link && tree->label != link->label)
+ if (tree->label < link->label)
+ link = link->llink;
+ else
+ link = link->rlink;
+ if (link)
+ {
+ tree->trie->fail = link->trie;
+ return;
+ }
+ fail = fail->fail;
+ }
+
+ tree->trie->fail = recourse;
+}
+
+/* Set delta entries for the links of the given tree such that
+ the preexisting delta value is larger than the current depth. */
+static void
+treedelta (register struct tree *tree,
+ register unsigned int depth,
+ unsigned char delta[])
+{
+ if (!tree)
+ return;
+ treedelta(tree->llink, depth, delta);
+ treedelta(tree->rlink, depth, delta);
+ if (depth < delta[tree->label])
+ delta[tree->label] = depth;
+}
+
+/* Return true if A has every label in B. */
+static int
+hasevery (register struct tree *a, register struct tree *b)
+{
+ if (!b)
+ return 1;
+ if (!hasevery(a, b->llink))
+ return 0;
+ if (!hasevery(a, b->rlink))
+ return 0;
+ while (a && b->label != a->label)
+ if (b->label < a->label)
+ a = a->llink;
+ else
+ a = a->rlink;
+ return !!a;
+}
+
+/* Compute a vector, indexed by character code, of the trie nodes
+ referenced from the given tree. */
+static void
+treenext (struct tree *tree, struct trie *next[])
+{
+ if (!tree)
+ return;
+ treenext(tree->llink, next);
+ treenext(tree->rlink, next);
+ next[tree->label] = tree->trie;
+}
+
+/* Compute the shift for each trie node, as well as the delta
+ table and next cache for the given keyword set. */
+char *
+kwsprep (kwset_t kws)
+{
+ register struct kwset *kwset;
+ register int i;
+ register struct trie *curr, *fail;
+ register char *trans;
+ unsigned char delta[NCHAR];
+ struct trie *last, *next[NCHAR];
+
+ kwset = (struct kwset *) kws;
+
+ /* Initial values for the delta table; will be changed later. The
+ delta entry for a given character is the smallest depth of any
+ node at which an outgoing edge is labeled by that character. */
+ if (kwset->mind < 256)
+ for (i = 0; i < NCHAR; ++i)
+ delta[i] = kwset->mind;
+ else
+ for (i = 0; i < NCHAR; ++i)
+ delta[i] = 255;
+
+ /* Check if we can use the simple boyer-moore algorithm, instead
+ of the hairy commentz-walter algorithm. */
+ if (kwset->words == 1 && kwset->trans == 0)
+ {
+ /* Looking for just one string. Extract it from the trie. */
+ kwset->target = obstack_alloc(&kwset->obstack, kwset->mind);
+ for (i = kwset->mind - 1, curr = kwset->trie; i >= 0; --i)
+ {
+ kwset->target[i] = curr->links->label;
+ curr = curr->links->trie;
+ }
+ /* Build the Boyer Moore delta. Boy that's easy compared to CW. */
+ for (i = 0; i < kwset->mind; ++i)
+ delta[(unsigned char) kwset->target[i]] = kwset->mind - (i + 1);
+ kwset->mind2 = kwset->mind;
+ /* Find the minimal delta2 shift that we might make after
+ a backwards match has failed. */
+ for (i = 0; i < kwset->mind - 1; ++i)
+ if (kwset->target[i] == kwset->target[kwset->mind - 1])
+ kwset->mind2 = kwset->mind - (i + 1);
+ }
+ else
+ {
+ /* Traverse the nodes of the trie in level order, simultaneously
+ computing the delta table, failure function, and shift function. */
+ for (curr = last = kwset->trie; curr; curr = curr->next)
+ {
+ /* Enqueue the immediate descendents in the level order queue. */
+ enqueue(curr->links, &last);
+
+ curr->shift = kwset->mind;
+ curr->maxshift = kwset->mind;
+
+ /* Update the delta table for the descendents of this node. */
+ treedelta(curr->links, curr->depth, delta);
+
+ /* Compute the failure function for the decendents of this node. */
+ treefails(curr->links, curr->fail, kwset->trie);
+
+ /* Update the shifts at each node in the current node's chain
+ of fails back to the root. */
+ for (fail = curr->fail; fail; fail = fail->fail)
+ {
+ /* If the current node has some outgoing edge that the fail
+ doesn't, then the shift at the fail should be no larger
+ than the difference of their depths. */
+ if (!hasevery(fail->links, curr->links))
+ if (curr->depth - fail->depth < fail->shift)
+ fail->shift = curr->depth - fail->depth;
+
+ /* If the current node is accepting then the shift at the
+ fail and its descendents should be no larger than the
+ difference of their depths. */
+ if (curr->accepting && fail->maxshift > curr->depth - fail->depth)
+ fail->maxshift = curr->depth - fail->depth;
+ }
+ }
+
+ /* Traverse the trie in level order again, fixing up all nodes whose
+ shift exceeds their inherited maxshift. */
+ for (curr = kwset->trie->next; curr; curr = curr->next)
+ {
+ if (curr->maxshift > curr->parent->maxshift)
+ curr->maxshift = curr->parent->maxshift;
+ if (curr->shift > curr->maxshift)
+ curr->shift = curr->maxshift;
+ }
+
+ /* Create a vector, indexed by character code, of the outgoing links
+ from the root node. */
+ for (i = 0; i < NCHAR; ++i)
+ next[i] = 0;
+ treenext(kwset->trie->links, next);
+
+ if ((trans = kwset->trans) != 0)
+ for (i = 0; i < NCHAR; ++i)
+ kwset->next[i] = next[(unsigned char) trans[i]];
+ else
+ for (i = 0; i < NCHAR; ++i)
+ kwset->next[i] = next[i];
+ }
+
+ /* Fix things up for any translation table. */
+ if ((trans = kwset->trans) != 0)
+ for (i = 0; i < NCHAR; ++i)
+ kwset->delta[i] = delta[(unsigned char) trans[i]];
+ else
+ for (i = 0; i < NCHAR; ++i)
+ kwset->delta[i] = delta[i];
+
+ return 0;
+}
+
+#define U(C) ((unsigned char) (C))
+
+/* Fast boyer-moore search. */
+static char *
+bmexec (kwset_t kws, char *text, size_t size)
+{
+ struct kwset *kwset;
+ register unsigned char *d1;
+ register char *ep, *sp, *tp;
+ register int d, gc, i, len, md2;
+
+ kwset = (struct kwset *) kws;
+ len = kwset->mind;
+
+ if (len == 0)
+ return text;
+ if (len > size)
+ return 0;
+ if (len == 1)
+ return memchr(text, kwset->target[0], size);
+
+ d1 = kwset->delta;
+ sp = kwset->target + len;
+ gc = U(sp[-2]);
+ md2 = kwset->mind2;
+ tp = text + len;
+
+ /* Significance of 12: 1 (initial offset) + 10 (skip loop) + 1 (md2). */
+ if (size > 12 * len)
+ /* 11 is not a bug, the initial offset happens only once. */
+ for (ep = text + size - 11 * len;;)
+ {
+ while (tp <= ep)
+ {
+ d = d1[U(tp[-1])], tp += d;
+ d = d1[U(tp[-1])], tp += d;
+ if (d == 0)
+ goto found;
+ d = d1[U(tp[-1])], tp += d;
+ d = d1[U(tp[-1])], tp += d;
+ d = d1[U(tp[-1])], tp += d;
+ if (d == 0)
+ goto found;
+ d = d1[U(tp[-1])], tp += d;
+ d = d1[U(tp[-1])], tp += d;
+ d = d1[U(tp[-1])], tp += d;
+ if (d == 0)
+ goto found;
+ d = d1[U(tp[-1])], tp += d;
+ d = d1[U(tp[-1])], tp += d;
+ }
+ break;
+ found:
+ if (U(tp[-2]) == gc)
+ {
+ for (i = 3; i <= len && U(tp[-i]) == U(sp[-i]); ++i)
+ ;
+ if (i > len)
+ return tp - len;
+ }
+ tp += md2;
+ }
+
+ /* Now we have only a few characters left to search. We
+ carefully avoid ever producing an out-of-bounds pointer. */
+ ep = text + size;
+ d = d1[U(tp[-1])];
+ while (d <= ep - tp)
+ {
+ d = d1[U((tp += d)[-1])];
+ if (d != 0)
+ continue;
+ if (U(tp[-2]) == gc)
+ {
+ for (i = 3; i <= len && U(tp[-i]) == U(sp[-i]); ++i)
+ ;
+ if (i > len)
+ return tp - len;
+ }
+ d = md2;
+ }
+
+ return 0;
+}
+
+/* Hairy multiple string search. */
+static char *
+cwexec (kwset_t kws, char *text, size_t len, struct kwsmatch *kwsmatch)
+{
+ struct kwset *kwset;
+ struct trie **next, *trie, *accept;
+ char *beg, *lim, *mch, *lmch;
+ register unsigned char c, *delta;
+ register int d;
+ register char *end, *qlim;
+ register struct tree *tree;
+ register char *trans;
+
+#ifdef lint
+ accept = NULL;
+#endif
+
+ /* Initialize register copies and look for easy ways out. */
+ kwset = (struct kwset *) kws;
+ if (len < kwset->mind)
+ return 0;
+ next = kwset->next;
+ delta = kwset->delta;
+ trans = kwset->trans;
+ lim = text + len;
+ end = text;
+ if ((d = kwset->mind) != 0)
+ mch = 0;
+ else
+ {
+ mch = text, accept = kwset->trie;
+ goto match;
+ }
+
+ if (len >= 4 * kwset->mind)
+ qlim = lim - 4 * kwset->mind;
+ else
+ qlim = 0;
+
+ while (lim - end >= d)
+ {
+ if (qlim && end <= qlim)
+ {
+ end += d - 1;
+ while ((d = delta[c = *end]) && end < qlim)
+ {
+ end += d;
+ end += delta[(unsigned char) *end];
+ end += delta[(unsigned char) *end];
+ }
+ ++end;
+ }
+ else
+ d = delta[c = (end += d)[-1]];
+ if (d)
+ continue;
+ beg = end - 1;
+ trie = next[c];
+ if (trie->accepting)
+ {
+ mch = beg;
+ accept = trie;
+ }
+ d = trie->shift;
+ while (beg > text)
+ {
+ c = trans ? trans[(unsigned char) *--beg] : *--beg;
+ tree = trie->links;
+ while (tree && c != tree->label)
+ if (c < tree->label)
+ tree = tree->llink;
+ else
+ tree = tree->rlink;
+ if (tree)
+ {
+ trie = tree->trie;
+ if (trie->accepting)
+ {
+ mch = beg;
+ accept = trie;
+ }
+ }
+ else
+ break;
+ d = trie->shift;
+ }
+ if (mch)
+ goto match;
+ }
+ return 0;
+
+ match:
+ /* Given a known match, find the longest possible match anchored
+ at or before its starting point. This is nearly a verbatim
+ copy of the preceding main search loops. */
+ if (lim - mch > kwset->maxd)
+ lim = mch + kwset->maxd;
+ lmch = 0;
+ d = 1;
+ while (lim - end >= d)
+ {
+ if ((d = delta[c = (end += d)[-1]]) != 0)
+ continue;
+ beg = end - 1;
+ if (!(trie = next[c]))
+ {
+ d = 1;
+ continue;
+ }
+ if (trie->accepting && beg <= mch)
+ {
+ lmch = beg;
+ accept = trie;
+ }
+ d = trie->shift;
+ while (beg > text)
+ {
+ c = trans ? trans[(unsigned char) *--beg] : *--beg;
+ tree = trie->links;
+ while (tree && c != tree->label)
+ if (c < tree->label)
+ tree = tree->llink;
+ else
+ tree = tree->rlink;
+ if (tree)
+ {
+ trie = tree->trie;
+ if (trie->accepting && beg <= mch)
+ {
+ lmch = beg;
+ accept = trie;
+ }
+ }
+ else
+ break;
+ d = trie->shift;
+ }
+ if (lmch)
+ {
+ mch = lmch;
+ goto match;
+ }
+ if (!d)
+ d = 1;
+ }
+
+ if (kwsmatch)
+ {
+ kwsmatch->index = accept->accepting / 2;
+ kwsmatch->beg[0] = mch;
+ kwsmatch->size[0] = accept->depth;
+ }
+ return mch;
+}
+
+/* Search through the given text for a match of any member of the
+ given keyword set. Return a pointer to the first character of
+ the matching substring, or NULL if no match is found. If FOUNDLEN
+ is non-NULL store in the referenced location the length of the
+ matching substring. Similarly, if FOUNDIDX is non-NULL, store
+ in the referenced location the index number of the particular
+ keyword matched. */
+char *
+kwsexec (kwset_t kws, char *text, size_t size, struct kwsmatch *kwsmatch)
+{
+ struct kwset *kwset;
+ char *ret;
+
+ kwset = (struct kwset *) kws;
+ if (kwset->words == 1 && kwset->trans == 0)
+ {
+ ret = bmexec(kws, text, size);
+ if (kwsmatch != 0 && ret != 0)
+ {
+ kwsmatch->index = 0;
+ kwsmatch->beg[0] = ret;
+ kwsmatch->size[0] = kwset->mind;
+ }
+ return ret;
+ }
+ else
+ return cwexec(kws, text, size, kwsmatch);
+}
+
+/* Free the components of the given keyword set. */
+void
+kwsfree (kwset_t kws)
+{
+ struct kwset *kwset;
+
+ kwset = (struct kwset *) kws;
+ obstack_free(&kwset->obstack, 0);
+ free(kws);
+}
diff --git a/gnu/usr.bin/grep/kwset.h b/gnu/usr.bin/grep/kwset.h
new file mode 100644
index 0000000..f812b2e
--- /dev/null
+++ b/gnu/usr.bin/grep/kwset.h
@@ -0,0 +1,59 @@
+/* kwset.h - header declaring the keyword set library.
+ Copyright (C) 1989, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 August 1989 by Mike Haertel.
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+/* $FreeBSD$ */
+
+struct kwsmatch
+{
+ int index; /* Index number of matching keyword. */
+ char *beg[1]; /* Begin pointer for each submatch. */
+ size_t size[1]; /* Length of each submatch. */
+};
+
+typedef ptr_t kwset_t;
+
+/* Return an opaque pointer to a newly allocated keyword set, or NULL
+ if enough memory cannot be obtained. The argument if non-NULL
+ specifies a table of character translations to be applied to all
+ pattern and search text. */
+extern kwset_t kwsalloc PARAMS((char *));
+
+/* Incrementally extend the keyword set to include the given string.
+ Return NULL for success, or an error message. Remember an index
+ number for each keyword included in the set. */
+extern char *kwsincr PARAMS((kwset_t, char *, size_t));
+
+/* When the keyword set has been completely built, prepare it for
+ use. Return NULL for success, or an error message. */
+extern char *kwsprep PARAMS((kwset_t));
+
+/* Search through the given buffer for a member of the keyword set.
+ Return a pointer to the leftmost longest match found, or NULL if
+ no match is found. If foundlen is non-NULL, store the length of
+ the matching substring in the integer it points to. Similarly,
+ if foundindex is non-NULL, store the index of the particular
+ keyword found therein. */
+extern char *kwsexec PARAMS((kwset_t, char *, size_t, struct kwsmatch *));
+
+/* Deallocate the given keyword set and all its associated storage. */
+extern void kwsfree PARAMS((kwset_t));
+
diff --git a/gnu/usr.bin/grep/obstack.c b/gnu/usr.bin/grep/obstack.c
new file mode 100644
index 0000000..17c6313
--- /dev/null
+++ b/gnu/usr.bin/grep/obstack.c
@@ -0,0 +1,598 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+ Copyright (C) 1988-1994,96,97,98,99 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "obstack.h"
+
+/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
+ incremented whenever callers compiled using an old obstack.h can no
+ longer properly call the functions in this obstack.c. */
+#define OBSTACK_INTERFACE_VERSION 1
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself, and the installed library
+ supports the same library interface we do. This code is part of the GNU
+ C Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object
+ files, it is simpler to just do this in the source for each such file. */
+
+#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
+#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
+#include <gnu-versions.h>
+#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+
+#ifndef ELIDE_CODE
+
+
+#if defined (__STDC__) && __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment. */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT \
+ ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+ But in fact it might be less smart and round addresses to as much as
+ DEFAULT_ROUNDING. So we prepare for it to do that. */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+ On some machines, copying successive ints does not work;
+ in such a case, redefine COPYING_UNIT to `long' (if that works)
+ or `char' as a last resort. */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+
+/* The functions allocating more room by calling `obstack_chunk_alloc'
+ jump to the handler pointed to by `obstack_alloc_failed_handler'.
+ This can be set to a user defined function which should either
+ abort gracefully or use longjump - but shouldn't return. This
+ variable by default points to the internal function
+ `print_and_abort'. */
+#if defined (__STDC__) && __STDC__
+static void print_and_abort (void);
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+#else
+static void print_and_abort ();
+void (*obstack_alloc_failed_handler) () = print_and_abort;
+#endif
+
+/* Exit value used when `print_and_abort' is used. */
+#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+int obstack_exit_failure = EXIT_FAILURE;
+
+/* The non-GNU-C macros copy the obstack into this global variable
+ to avoid multiple evaluation. */
+
+struct obstack *_obstack;
+
+/* Define a macro that either calls functions with the traditional malloc/free
+ calling interface, or calls functions with the mmalloc/mfree interface
+ (that adds an extra first argument), based on the state of use_extra_arg.
+ For free, do not use ?:, since some compilers, like the MIPS compilers,
+ do not allow (expr) ? void : void. */
+
+#if defined (__STDC__) && __STDC__
+#define CALL_CHUNKFUN(h, size) \
+ (((h) -> use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+ do { \
+ if ((h) -> use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+ } while (0)
+#else
+#define CALL_CHUNKFUN(h, size) \
+ (((h) -> use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+ do { \
+ if ((h) -> use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(void (*) ()) (h)->freefun) ((old_chunk)); \
+ } while (0)
+#endif
+
+
+/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
+ Objects start on multiples of ALIGNMENT (0 means use default).
+ CHUNKFUN is the function to use to allocate chunks,
+ and FREEFUN the function to free them.
+
+ Return nonzero if successful, calls obstack_alloc_failed_handler if
+ allocation fails. */
+
+int
+_obstack_begin (h, size, alignment, chunkfun, freefun)
+ struct obstack *h;
+ int size;
+ int alignment;
+#if defined (__STDC__) && __STDC__
+ POINTER (*chunkfun) (long);
+ void (*freefun) (void *);
+#else
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+#endif
+{
+ register struct _obstack_chunk *chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = (int) DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+#if defined (__STDC__) && __STDC__
+ h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
+ h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+#endif
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ h->use_extra_arg = 0;
+
+ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+ if (!chunk)
+ (*obstack_alloc_failed_handler) ();
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+ /* The initial chunk now contains no empty object. */
+ h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
+ return 1;
+}
+
+int
+_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
+ struct obstack *h;
+ int size;
+ int alignment;
+#if defined (__STDC__) && __STDC__
+ POINTER (*chunkfun) (POINTER, long);
+ void (*freefun) (POINTER, POINTER);
+#else
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+#endif
+ POINTER arg;
+{
+ register struct _obstack_chunk *chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = (int) DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+#if defined(__STDC__) && __STDC__
+ h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
+ h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+#endif
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ h->extra_arg = arg;
+ h->use_extra_arg = 1;
+
+ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+ if (!chunk)
+ (*obstack_alloc_failed_handler) ();
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+ /* The initial chunk now contains no empty object. */
+ h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
+ return 1;
+}
+
+/* Allocate a new current chunk for the obstack *H
+ on the assumption that LENGTH bytes need to be added
+ to the current object, or a new object of length LENGTH allocated.
+ Copies any partial object from the end of the old chunk
+ to the beginning of the new one. */
+
+void
+_obstack_newchunk (h, length)
+ struct obstack *h;
+ int length;
+{
+ register struct _obstack_chunk *old_chunk = h->chunk;
+ register struct _obstack_chunk *new_chunk;
+ register long new_size;
+ register long obj_size = h->next_free - h->object_base;
+ register long i;
+ long already;
+
+ /* Compute size for new chunk. */
+ new_size = (obj_size + length) + (obj_size >> 3) + 100;
+ if (new_size < h->chunk_size)
+ new_size = h->chunk_size;
+
+ /* Allocate and initialize the new chunk. */
+ new_chunk = CALL_CHUNKFUN (h, new_size);
+ if (!new_chunk)
+ (*obstack_alloc_failed_handler) ();
+ h->chunk = new_chunk;
+ new_chunk->prev = old_chunk;
+ new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
+
+ /* Move the existing object to the new chunk.
+ Word at a time is fast and is safe if the object
+ is sufficiently aligned. */
+ if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+ {
+ for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+ i >= 0; i--)
+ ((COPYING_UNIT *)new_chunk->contents)[i]
+ = ((COPYING_UNIT *)h->object_base)[i];
+ /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+ but that can cross a page boundary on a machine
+ which does not do strict alignment for COPYING_UNITS. */
+ already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+ }
+ else
+ already = 0;
+ /* Copy remaining bytes one by one. */
+ for (i = already; i < obj_size; i++)
+ new_chunk->contents[i] = h->object_base[i];
+
+ /* If the object just copied was the only data in OLD_CHUNK,
+ free that chunk and remove it from the chain.
+ But not if that chunk might contain an empty object. */
+ if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
+ {
+ new_chunk->prev = old_chunk->prev;
+ CALL_FREEFUN (h, old_chunk);
+ }
+
+ h->object_base = new_chunk->contents;
+ h->next_free = h->object_base + obj_size;
+ /* The new chunk certainly contains no empty object yet. */
+ h->maybe_empty_object = 0;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+ This is here for debugging.
+ If you use it in a program, you are probably losing. */
+
+#if defined (__STDC__) && __STDC__
+/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
+ obstack.h because it is just for debugging. */
+int _obstack_allocated_p (struct obstack *h, POINTER obj);
+#endif
+
+int
+_obstack_allocated_p (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ /* We use >= rather than > since the object cannot be exactly at
+ the beginning of the chunk but might be an empty object exactly
+ at the end of an adjacent chunk. */
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+ {
+ plp = lp->prev;
+ lp = plp;
+ }
+ return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+ more recently than OBJ. If OBJ is zero, free everything in H. */
+
+#undef obstack_free
+
+/* This function has two names with identical definitions.
+ This is the first one, called from non-ANSI code. */
+
+void
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
+
+ lp = h->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+ {
+ plp = lp->prev;
+ CALL_FREEFUN (h, lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ if (lp)
+ {
+ h->object_base = h->next_free = (char *) (obj);
+ h->chunk_limit = lp->limit;
+ h->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+/* This function is used from ANSI code. */
+
+void
+obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
+
+ lp = h->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+ {
+ plp = lp->prev;
+ CALL_FREEFUN (h, lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ if (lp)
+ {
+ h->object_base = h->next_free = (char *) (obj);
+ h->chunk_limit = lp->limit;
+ h->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+int
+_obstack_memory_used (h)
+ struct obstack *h;
+{
+ register struct _obstack_chunk* lp;
+ register int nbytes = 0;
+
+ for (lp = h->chunk; lp != 0; lp = lp->prev)
+ {
+ nbytes += lp->limit - (char *) lp;
+ }
+ return nbytes;
+}
+
+/* Define the error handler. */
+#ifndef _
+# ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# ifndef _
+# define _(Str) gettext (Str)
+# endif
+# else
+# define _(Str) (Str)
+# endif
+#endif
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <libio/iolibio.h>
+# define fputs(s, f) _IO_fputs (s, f)
+#endif
+
+static void
+print_and_abort ()
+{
+ fputs (_("memory exhausted"), stderr);
+ fputc ('\n', stderr);
+ exit (obstack_exit_failure);
+}
+
+#if 0
+/* These are now turned off because the applications do not use it
+ and it uses bcopy via obstack_grow, which causes trouble on sysV. */
+
+/* Now define the functional versions of the obstack macros.
+ Define them to simply use the corresponding macros to do the job. */
+
+#if defined (__STDC__) && __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+ they won't pass through the macro names in parentheses. */
+
+/* The function names appear in parentheses in order to prevent
+ the macro-definitions of the names from being expanded there. */
+
+POINTER (obstack_base) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_room (obstack);
+}
+
+int (obstack_make_room) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_make_room (obstack, length);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+#endif /* 0 */
+
+#endif /* !ELIDE_CODE */
diff --git a/gnu/usr.bin/grep/obstack.h b/gnu/usr.bin/grep/obstack.h
new file mode 100644
index 0000000..4d49ce0
--- /dev/null
+++ b/gnu/usr.bin/grep/obstack.h
@@ -0,0 +1,593 @@
+/* obstack.h - object stack macros
+ Copyright (C) 1988,89,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects. Each object starts life
+small, and may grow to maturity. (Consider building a word syllable
+by syllable.) An object can move while it is growing. Once it has
+been "finished" it never changes address again. So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
+by calling `obstack_chunk_free'. You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables. Unless you are "fascist pig with a read-only mind"
+--Gosper's immortal quote from HAKMEM item 154, out of context--you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols. At the time you are reading a symbol you don't know
+how long it is. One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer. This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently. Use one obstack for all symbol
+names. As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it. Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses. When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk. When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies. No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk. We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object. This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+ We allocate large chunks.
+ We carve out one object at a time from the current chunk.
+ Once carved, an object never moves.
+ We are free to append data of any size to the currently
+ growing object.
+ Exactly one object is growing in an obstack at any one time.
+ You can run one obstack per control block.
+ You may have as many control blocks as you dare.
+ Because of the way we do it, you can `unwind' an obstack
+ back to a previous state. (You may remove objects much
+ as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once. */
+
+#ifndef _OBSTACK_H
+#define _OBSTACK_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* We use subtraction of (char *) 0 instead of casting to int
+ because on word-addressable machines a simple cast to int
+ may ignore the byte-within-word field of the pointer. */
+
+#ifndef __PTR_TO_INT
+# define __PTR_TO_INT(P) ((P) - (char *) 0)
+#endif
+
+#ifndef __INT_TO_PTR
+# define __INT_TO_PTR(P) ((P) + (char *) 0)
+#endif
+
+/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is
+ defined, as with GNU C, use that; that way we don't pollute the
+ namespace with <stddef.h>'s symbols. Otherwise, if <stddef.h> is
+ available, include it and use ptrdiff_t. In traditional C, long is
+ the best that we can do. */
+
+#ifdef __PTRDIFF_TYPE__
+# define PTR_INT_TYPE __PTRDIFF_TYPE__
+#else
+# ifdef HAVE_STDDEF_H
+# include <stddef.h>
+# define PTR_INT_TYPE ptrdiff_t
+# else
+# define PTR_INT_TYPE long
+# endif
+#endif
+
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
+#else
+# ifdef memcpy
+# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
+# else
+# define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N))
+# endif
+#endif
+
+struct _obstack_chunk /* Lives at front of each chunk. */
+{
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
+};
+
+struct obstack /* control current object in current chunk */
+{
+ long chunk_size; /* preferred size to allocate chunks in */
+ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
+ PTR_INT_TYPE temp; /* Temporary for some macros. */
+ int alignment_mask; /* Mask of alignment for each object. */
+#if defined __STDC__ && __STDC__
+ /* These prototypes vary based on `use_extra_arg', and we use
+ casts to the prototypeless function type in all assignments,
+ but having prototypes here quiets -Wstrict-prototypes. */
+ struct _obstack_chunk *(*chunkfun) (void *, long);
+ void (*freefun) (void *, struct _obstack_chunk *);
+ void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+#else
+ struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
+ void (*freefun) (); /* User's function to free a chunk. */
+ char *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+#endif
+ unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
+ unsigned maybe_empty_object:1;/* There is a possibility that the current
+ chunk contains a zero-length object. This
+ prevents freeing the chunk if we allocate
+ a bigger chunk to replace it. */
+ unsigned alloc_failed:1; /* No longer used, as we now call the failed
+ handler on error, but retained for binary
+ compatibility. */
+};
+
+/* Declare the external functions we use; they are in obstack.c. */
+
+#if defined __STDC__ && __STDC__
+extern void _obstack_newchunk (struct obstack *, int);
+extern void _obstack_free (struct obstack *, void *);
+extern int _obstack_begin (struct obstack *, int, int,
+ void *(*) (long), void (*) (void *));
+extern int _obstack_begin_1 (struct obstack *, int, int,
+ void *(*) (void *, long),
+ void (*) (void *, void *), void *);
+extern int _obstack_memory_used (struct obstack *);
+#else
+extern void _obstack_newchunk ();
+extern void _obstack_free ();
+extern int _obstack_begin ();
+extern int _obstack_begin_1 ();
+extern int _obstack_memory_used ();
+#endif
+
+#if defined __STDC__ && __STDC__
+
+/* Do the function-declarations after the structs
+ but before defining the macros. */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, void *data, int size);
+void obstack_grow0 (struct obstack *obstack, void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_make_room (struct obstack *obstack, int size);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+int obstack_memory_used (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+ so we do not declare them. */
+
+/* Error handler called when `obstack_chunk_alloc' failed to allocate
+ more memory. This can be set to a user defined function which
+ should either abort gracefully or use longjump - but shouldn't
+ return. The default action is to print a message and abort. */
+#if defined __STDC__ && __STDC__
+extern void (*obstack_alloc_failed_handler) (void);
+#else
+extern void (*obstack_alloc_failed_handler) ();
+#endif
+
+/* Exit value used when `print_and_abort' is used. */
+extern int obstack_exit_failure;
+
+/* Pointer to beginning of object being allocated or to be allocated next.
+ Note that this might not be the final address of the object
+ because a new chunk might be needed to hold the final size. */
+
+#define obstack_base(h) ((h)->object_base)
+
+/* Size for allocating ordinary chunks. */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk. */
+
+#define obstack_next_free(h) ((h)->next_free)
+
+/* Mask specifying low bits that should be clear in address of an object. */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+/* To prevent prototype warnings provide complete argument list in
+ standard C version. */
+#if defined __STDC__ && __STDC__
+
+# define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free)
+
+# define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free)
+
+# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ (void *(*) (long)) (chunkfun), (void (*) (void *)) (freefun))
+
+# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+ _obstack_begin_1 ((h), (size), (alignment), \
+ (void *(*) (void *, long)) (chunkfun), \
+ (void (*) (void *, void *)) (freefun), (arg))
+
+# define obstack_chunkfun(h, newchunkfun) \
+ ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
+
+# define obstack_freefun(h, newfreefun) \
+ ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
+
+#else
+
+# define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
+
+# define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
+
+# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ (void *(*) ()) (chunkfun), (void (*) ()) (freefun))
+
+# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+ _obstack_begin_1 ((h), (size), (alignment), \
+ (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg))
+
+# define obstack_chunkfun(h, newchunkfun) \
+ ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun))
+
+# define obstack_freefun(h, newfreefun) \
+ ((h) -> freefun = (void (*)()) (newfreefun))
+
+#endif
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#define obstack_memory_used(h) _obstack_memory_used (h)
+
+#if defined __GNUC__ && defined __STDC__ && __STDC__
+/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
+ does not implement __extension__. But that compiler doesn't define
+ __GNUC_MINOR__. */
+# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
+# define __extension__
+# endif
+
+/* For GNU C, if not -traditional,
+ we can define these macros to compute all args only once
+ without using a global variable.
+ Also, we can avoid using the `temp' slot, to make faster code. */
+
+# define obstack_object_size(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->next_free - __o->object_base); })
+
+# define obstack_room(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->chunk_limit - __o->next_free); })
+
+# define obstack_make_room(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->chunk_limit - __o->next_free < __len) \
+ _obstack_newchunk (__o, __len); \
+ (void) 0; })
+
+# define obstack_empty_p(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
+
+# define obstack_grow(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->next_free + __len > __o->chunk_limit) \
+ _obstack_newchunk (__o, __len); \
+ _obstack_memcpy (__o->next_free, (char *) (where), __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+# define obstack_grow0(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->next_free + __len + 1 > __o->chunk_limit) \
+ _obstack_newchunk (__o, __len + 1); \
+ _obstack_memcpy (__o->next_free, (char *) (where), __len); \
+ __o->next_free += __len; \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+# define obstack_1grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ if (__o->next_free + 1 > __o->chunk_limit) \
+ _obstack_newchunk (__o, 1); \
+ *(__o->next_free)++ = (datum); \
+ (void) 0; })
+
+/* These assume that the obstack alignment is good enough for pointers or ints,
+ and that the data added so far to the current object
+ shares that much alignment. */
+
+# define obstack_ptr_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ _obstack_newchunk (__o, sizeof (void *)); \
+ *((void **)__o->next_free)++ = ((void *)datum); \
+ (void) 0; })
+
+# define obstack_int_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ if (__o->next_free + sizeof (int) > __o->chunk_limit) \
+ _obstack_newchunk (__o, sizeof (int)); \
+ *((int *)__o->next_free)++ = ((int)datum); \
+ (void) 0; })
+
+# define obstack_ptr_grow_fast(h,aptr) (*((void **) (h)->next_free)++ = (void *)aptr)
+# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint)
+
+# define obstack_blank(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->chunk_limit - __o->next_free < __len) \
+ _obstack_newchunk (__o, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+# define obstack_alloc(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy0(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+/* The local variable is named __o1 to avoid a name conflict
+ when obstack_blank is called. */
+# define obstack_finish(OBSTACK) \
+__extension__ \
+({ struct obstack *__o1 = (OBSTACK); \
+ void *value; \
+ value = (void *) __o1->object_base; \
+ if (__o1->next_free == value) \
+ __o1->maybe_empty_object = 1; \
+ __o1->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
+ & ~ (__o1->alignment_mask)); \
+ if (__o1->next_free - (char *)__o1->chunk \
+ > __o1->chunk_limit - (char *)__o1->chunk) \
+ __o1->next_free = __o1->chunk_limit; \
+ __o1->object_base = __o1->next_free; \
+ value; })
+
+# define obstack_free(OBSTACK, OBJ) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (OBJ); \
+ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ __o->next_free = __o->object_base = (char *)__obj; \
+ else (obstack_free) (__o, __obj); })
+
+#else /* not __GNUC__ or not __STDC__ */
+
+# define obstack_object_size(h) \
+ (unsigned) ((h)->next_free - (h)->object_base)
+
+# define obstack_room(h) \
+ (unsigned) ((h)->chunk_limit - (h)->next_free)
+
+# define obstack_empty_p(h) \
+ ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
+
+/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
+ so that we can avoid having void expressions
+ in the arms of the conditional expression.
+ Casting the third operand to void was tried before,
+ but some compilers won't accept it. */
+
+# define obstack_make_room(h,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
+
+# define obstack_grow(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
+ _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \
+ (h)->next_free += (h)->temp)
+
+# define obstack_grow0(h,where,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
+ _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \
+ (h)->next_free += (h)->temp, \
+ *((h)->next_free)++ = 0)
+
+# define obstack_1grow(h,datum) \
+( (((h)->next_free + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), 1), 0) : 0), \
+ (*((h)->next_free)++ = (datum)))
+
+# define obstack_ptr_grow(h,datum) \
+( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
+ (*((char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *) datum)))
+
+# define obstack_int_grow(h,datum) \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
+ (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = ((int) datum)))
+
+# define obstack_ptr_grow_fast(h,aptr) (*((char **) (h)->next_free)++ = (char *) aptr)
+# define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint)
+
+# define obstack_blank(h,length) \
+( (h)->temp = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
+ ((h)->next_free += (h)->temp))
+
+# define obstack_alloc(h,length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+# define obstack_copy(h,where,length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_copy0(h,where,length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_finish(h) \
+( ((h)->next_free == (h)->object_base \
+ ? (((h)->maybe_empty_object = 1), 0) \
+ : 0), \
+ (h)->temp = __PTR_TO_INT ((h)->object_base), \
+ (h)->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
+ & ~ ((h)->alignment_mask)), \
+ (((h)->next_free - (char *) (h)->chunk \
+ > (h)->chunk_limit - (char *) (h)->chunk) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ __INT_TO_PTR ((h)->temp))
+
+# if defined __STDC__ && __STDC__
+# define obstack_free(h,obj) \
+( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
+ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
+# else
+# define obstack_free(h,obj) \
+( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
+ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
+# endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+#ifdef __cplusplus
+} /* C++ */
+#endif
+
+#endif /* obstack.h */
diff --git a/gnu/usr.bin/grep/savedir.c b/gnu/usr.bin/grep/savedir.c
new file mode 100644
index 0000000..29b3842
--- /dev/null
+++ b/gnu/usr.bin/grep/savedir.c
@@ -0,0 +1,137 @@
+/* savedir.c -- save the list of files in a directory in a string
+ Copyright (C) 1990, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute 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. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#ifdef CLOSEDIR_VOID
+/* Fake a return value. */
+# define CLOSEDIR(d) (closedir (d), 0)
+#else
+# define CLOSEDIR(d) closedir (d)
+#endif
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#else
+char *malloc ();
+char *realloc ();
+#endif
+#ifndef NULL
+# define NULL 0
+#endif
+
+#ifndef stpcpy
+char *stpcpy ();
+#endif
+
+#include "savedir.h"
+
+/* Return a freshly allocated string containing the filenames
+ in directory DIR, separated by '\0' characters;
+ the end is marked by two '\0' characters in a row.
+ NAME_SIZE is the number of bytes to initially allocate
+ for the string; it will be enlarged as needed.
+ Return NULL if DIR cannot be opened or if out of memory. */
+
+char *
+savedir (const char *dir, off_t name_size)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char *name_space;
+ char *namep;
+
+ dirp = opendir (dir);
+ if (dirp == NULL)
+ return NULL;
+
+ /* Be sure name_size is at least `1' so there's room for
+ the final NUL byte. */
+ name_size += !name_size;
+
+ name_space = (char *) malloc (name_size);
+ if (name_space == NULL)
+ {
+ closedir (dirp);
+ return NULL;
+ }
+ namep = name_space;
+
+ while ((dp = readdir (dirp)) != NULL)
+ {
+ /* Skip "." and ".." (some NFS filesystems' directories lack them). */
+ if (dp->d_name[0] != '.'
+ || (dp->d_name[1] != '\0'
+ && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
+ {
+ off_t size_needed = (namep - name_space) + NAMLEN (dp) + 2;
+
+ if (size_needed > name_size)
+ {
+ char *new_name_space;
+
+ while (size_needed > name_size)
+ name_size += 1024;
+
+ new_name_space = realloc (name_space, name_size);
+ if (new_name_space == NULL)
+ {
+ closedir (dirp);
+ return NULL;
+ }
+ namep += new_name_space - name_space;
+ name_space = new_name_space;
+ }
+ namep = stpcpy (namep, dp->d_name) + 1;
+ }
+ }
+ *namep = '\0';
+ if (CLOSEDIR (dirp))
+ {
+ free (name_space);
+ return NULL;
+ }
+ return name_space;
+}
diff --git a/gnu/usr.bin/grep/savedir.h b/gnu/usr.bin/grep/savedir.h
new file mode 100644
index 0000000..89be04d
--- /dev/null
+++ b/gnu/usr.bin/grep/savedir.h
@@ -0,0 +1,15 @@
+#if !defined SAVEDIR_H_
+# define SAVEDIR_H_
+
+# ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+# endif
+
+char *
+savedir PARAMS ((const char *dir, off_t name_size));
+
+#endif
diff --git a/gnu/usr.bin/grep/search.c b/gnu/usr.bin/grep/search.c
new file mode 100644
index 0000000..f24c1a4
--- /dev/null
+++ b/gnu/usr.bin/grep/search.c
@@ -0,0 +1,427 @@
+/* search.c - searching subroutines using dfa, kwset and regex for grep.
+ Copyright (C) 1992, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public 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 August 1992 by Mike Haertel. */
+
+/* $FreeBSD$ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <sys/types.h>
+#include "system.h"
+#include "grep.h"
+#ifdef __FreeBSD__
+#include <gnuregex.h>
+#else
+#include "regex.h"
+#endif
+#include "dfa.h"
+#include "kwset.h"
+
+#define NCHAR (UCHAR_MAX + 1)
+
+static void Gcompile PARAMS((char *, size_t));
+static void Ecompile PARAMS((char *, size_t));
+static char *EGexecute PARAMS((char *, size_t, char **));
+static void Fcompile PARAMS((char *, size_t));
+static char *Fexecute PARAMS((char *, size_t, char **));
+static void kwsinit PARAMS((void));
+
+/* Here is the matchers vector for the main program. */
+struct matcher matchers[] = {
+ { "default", Gcompile, EGexecute },
+ { "grep", Gcompile, EGexecute },
+ { "egrep", Ecompile, EGexecute },
+ { "awk", Ecompile, EGexecute },
+ { "fgrep", Fcompile, Fexecute },
+ { 0, 0, 0 },
+};
+
+/* For -w, we also consider _ to be word constituent. */
+#define WCHAR(C) (ISALNUM(C) || (C) == '_')
+
+/* DFA compiled regexp. */
+static struct dfa dfa;
+
+/* Regex compiled regexp. */
+static struct re_pattern_buffer regexbuf;
+
+/* KWset compiled pattern. For Ecompile and Gcompile, we compile
+ a list of strings, at least one of which is known to occur in
+ any string matching the regexp. */
+static kwset_t kwset;
+
+/* Last compiled fixed string known to exactly match the regexp.
+ If kwsexec() returns < lastexact, then we don't need to
+ call the regexp matcher at all. */
+static int lastexact;
+
+void
+dfaerror (char const *mesg)
+{
+ fatal(mesg, 0);
+}
+
+static void
+kwsinit (void)
+{
+ static char trans[NCHAR];
+ int i;
+
+ if (match_icase)
+ for (i = 0; i < NCHAR; ++i)
+ trans[i] = TOLOWER(i);
+
+ if (!(kwset = kwsalloc(match_icase ? trans : (char *) 0)))
+ fatal("memory exhausted", 0);
+}
+
+/* If the DFA turns out to have some set of fixed strings one of
+ which must occur in the match, then we build a kwset matcher
+ to find those strings, and thus quickly filter out impossible
+ matches. */
+static void
+kwsmusts (void)
+{
+ struct dfamust *dm;
+ char *err;
+
+ if (dfa.musts)
+ {
+ kwsinit();
+ /* First, we compile in the substrings known to be exact
+ matches. The kwset matcher will return the index
+ of the matching string that it chooses. */
+ for (dm = dfa.musts; dm; dm = dm->next)
+ {
+ if (!dm->exact)
+ continue;
+ ++lastexact;
+ if ((err = kwsincr(kwset, dm->must, strlen(dm->must))) != 0)
+ fatal(err, 0);
+ }
+ /* Now, we compile the substrings that will require
+ the use of the regexp matcher. */
+ for (dm = dfa.musts; dm; dm = dm->next)
+ {
+ if (dm->exact)
+ continue;
+ if ((err = kwsincr(kwset, dm->must, strlen(dm->must))) != 0)
+ fatal(err, 0);
+ }
+ if ((err = kwsprep(kwset)) != 0)
+ fatal(err, 0);
+ }
+}
+
+static void
+Gcompile (char *pattern, size_t size)
+{
+ const char *err;
+
+ re_set_syntax(RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE);
+ dfasyntax(RE_SYNTAX_GREP | RE_HAT_LISTS_NOT_NEWLINE, match_icase, eolbyte);
+
+ if ((err = re_compile_pattern(pattern, size, &regexbuf)) != 0)
+ fatal(err, 0);
+
+ /* In the match_words and match_lines cases, we use a different pattern
+ for the DFA matcher that will quickly throw out cases that won't work.
+ Then if DFA succeeds we do some hairy stuff using the regex matcher
+ to decide whether the match should really count. */
+ if (match_words || match_lines)
+ {
+ /* In the whole-word case, we use the pattern:
+ (^|[^A-Za-z_])(userpattern)([^A-Za-z_]|$).
+ In the whole-line case, we use the pattern:
+ ^(userpattern)$.
+ BUG: Using [A-Za-z_] is locale-dependent!
+ So will use [:alnum:] */
+
+ char *n = malloc(size + 50);
+ int i = 0;
+
+ strcpy(n, "");
+
+ if (match_lines)
+ strcpy(n, "^\\(");
+ if (match_words)
+ strcpy(n, "\\(^\\|[^[:alnum:]_]\\)\\(");
+
+ i = strlen(n);
+ memcpy(n + i, pattern, size);
+ i += size;
+
+ if (match_words)
+ strcpy(n + i, "\\)\\([^[:alnum:]_]\\|$\\)");
+ if (match_lines)
+ strcpy(n + i, "\\)$");
+
+ i += strlen(n + i);
+ dfacomp(n, i, &dfa, 1);
+ }
+ else
+ dfacomp(pattern, size, &dfa, 1);
+
+ kwsmusts();
+}
+
+static void
+Ecompile (char *pattern, size_t size)
+{
+ const char *err;
+
+ if (strcmp(matcher, "awk") == 0)
+ {
+ re_set_syntax(RE_SYNTAX_AWK);
+ dfasyntax(RE_SYNTAX_AWK, match_icase, eolbyte);
+ }
+ else
+ {
+ re_set_syntax (RE_SYNTAX_POSIX_EGREP);
+ dfasyntax (RE_SYNTAX_POSIX_EGREP, match_icase, eolbyte);
+ }
+
+ if ((err = re_compile_pattern(pattern, size, &regexbuf)) != 0)
+ fatal(err, 0);
+
+ /* In the match_words and match_lines cases, we use a different pattern
+ for the DFA matcher that will quickly throw out cases that won't work.
+ Then if DFA succeeds we do some hairy stuff using the regex matcher
+ to decide whether the match should really count. */
+ if (match_words || match_lines)
+ {
+ /* In the whole-word case, we use the pattern:
+ (^|[^A-Za-z_])(userpattern)([^A-Za-z_]|$).
+ In the whole-line case, we use the pattern:
+ ^(userpattern)$.
+ BUG: Using [A-Za-z_] is locale-dependent!
+ so will use the char class */
+
+ char *n = malloc(size + 50);
+ int i = 0;
+
+ strcpy(n, "");
+
+ if (match_lines)
+ strcpy(n, "^(");
+ if (match_words)
+ strcpy(n, "(^|[^[:alnum:]_])(");
+
+ i = strlen(n);
+ memcpy(n + i, pattern, size);
+ i += size;
+
+ if (match_words)
+ strcpy(n + i, ")([^[:alnum:]_]|$)");
+ if (match_lines)
+ strcpy(n + i, ")$");
+
+ i += strlen(n + i);
+ dfacomp(n, i, &dfa, 1);
+ }
+ else
+ dfacomp(pattern, size, &dfa, 1);
+
+ kwsmusts();
+}
+
+static char *
+EGexecute (char *buf, size_t size, char **endp)
+{
+ register char *buflim, *beg, *end, save;
+ char eol = eolbyte;
+ int backref, start, len;
+ struct kwsmatch kwsm;
+ static struct re_registers regs; /* This is static on account of a BRAIN-DEAD
+ Q@#%!# library interface in regex.c. */
+
+ buflim = buf + size;
+
+ for (beg = end = buf; end < buflim; beg = end + 1)
+ {
+ if (kwset)
+ {
+ /* Find a possible match using the KWset matcher. */
+ beg = kwsexec(kwset, beg, buflim - beg, &kwsm);
+ if (!beg)
+ goto failure;
+ /* Narrow down to the line containing the candidate, and
+ run it through DFA. */
+ end = memchr(beg, eol, buflim - beg);
+ if (!end)
+ end = buflim;
+ while (beg > buf && beg[-1] != eol)
+ --beg;
+ save = *end;
+ if (kwsm.index < lastexact)
+ goto success;
+ if (!dfaexec(&dfa, beg, end, 0, (int *) 0, &backref))
+ {
+ *end = save;
+ continue;
+ }
+ *end = save;
+ /* Successful, no backreferences encountered. */
+ if (!backref)
+ goto success;
+ }
+ else
+ {
+ /* No good fixed strings; start with DFA. */
+ save = *buflim;
+ beg = dfaexec(&dfa, beg, buflim, 0, (int *) 0, &backref);
+ *buflim = save;
+ if (!beg)
+ goto failure;
+ /* Narrow down to the line we've found. */
+ end = memchr(beg, eol, buflim - beg);
+ if (!end)
+ end = buflim;
+ while (beg > buf && beg[-1] != eol)
+ --beg;
+ /* Successful, no backreferences encountered! */
+ if (!backref)
+ goto success;
+ }
+ /* If we've made it to this point, this means DFA has seen
+ a probable match, and we need to run it through Regex. */
+ regexbuf.not_eol = 0;
+ if ((start = re_search(&regexbuf, beg, end - beg, 0, end - beg, &regs)) >= 0)
+ {
+ len = regs.end[0] - start;
+ if ((!match_lines && !match_words)
+ || (match_lines && len == end - beg))
+ goto success;
+ /* If -w, check if the match aligns with word boundaries.
+ We do this iteratively because:
+ (a) the line may contain more than one occurence of the pattern, and
+ (b) Several alternatives in the pattern might be valid at a given
+ point, and we may need to consider a shorter one to find a word
+ boundary. */
+ if (match_words)
+ while (start >= 0)
+ {
+ if ((start == 0 || !WCHAR ((unsigned char) beg[start - 1]))
+ && (len == end - beg
+ || !WCHAR ((unsigned char) beg[start + len])))
+ goto success;
+ if (len > 0)
+ {
+ /* Try a shorter length anchored at the same place. */
+ --len;
+ regexbuf.not_eol = 1;
+ len = re_match(&regexbuf, beg, start + len, start, &regs);
+ }
+ if (len <= 0)
+ {
+ /* Try looking further on. */
+ if (start == end - beg)
+ break;
+ ++start;
+ regexbuf.not_eol = 0;
+ start = re_search(&regexbuf, beg, end - beg,
+ start, end - beg - start, &regs);
+ len = regs.end[0] - start;
+ }
+ }
+ }
+ }
+
+ failure:
+ return 0;
+
+ success:
+ *endp = end < buflim ? end + 1 : end;
+ return beg;
+}
+
+static void
+Fcompile (char *pattern, size_t size)
+{
+ char *beg, *lim, *err;
+
+ kwsinit();
+ beg = pattern;
+ do
+ {
+ for (lim = beg; lim < pattern + size && *lim != '\n'; ++lim)
+ ;
+ if ((err = kwsincr(kwset, beg, lim - beg)) != 0)
+ fatal(err, 0);
+ if (lim < pattern + size)
+ ++lim;
+ beg = lim;
+ }
+ while (beg < pattern + size);
+
+ if ((err = kwsprep(kwset)) != 0)
+ fatal(err, 0);
+}
+
+static char *
+Fexecute (char *buf, size_t size, char **endp)
+{
+ register char *beg, *try, *end;
+ register size_t len;
+ char eol = eolbyte;
+ struct kwsmatch kwsmatch;
+
+ for (beg = buf; beg <= buf + size; ++beg)
+ {
+ if (!(beg = kwsexec(kwset, beg, buf + size - beg, &kwsmatch)))
+ return 0;
+ len = kwsmatch.size[0];
+ if (match_lines)
+ {
+ if (beg > buf && beg[-1] != eol)
+ continue;
+ if (beg + len < buf + size && beg[len] != eol)
+ continue;
+ goto success;
+ }
+ else if (match_words)
+ for (try = beg; len && try;)
+ {
+ if (try > buf && WCHAR((unsigned char) try[-1]))
+ break;
+ if (try + len < buf + size && WCHAR((unsigned char) try[len]))
+ {
+ try = kwsexec(kwset, beg, --len, &kwsmatch);
+ len = kwsmatch.size[0];
+ }
+ else
+ goto success;
+ }
+ else
+ goto success;
+ }
+
+ return 0;
+
+ success:
+ if ((end = memchr(beg + len, eol, (buf + size) - (beg + len))) != 0)
+ ++end;
+ else
+ end = buf + size;
+ *endp = end;
+ while (beg > buf && beg[-1] != '\n')
+ --beg;
+ return beg;
+}
diff --git a/gnu/usr.bin/grep/stpcpy.c b/gnu/usr.bin/grep/stpcpy.c
new file mode 100644
index 0000000..a01636c
--- /dev/null
+++ b/gnu/usr.bin/grep/stpcpy.c
@@ -0,0 +1,50 @@
+/* stpcpy.c -- copy a string and return pointer to end of new string
+ Copyright (C) 1992, 1995, 1997, 1998 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. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#undef __stpcpy
+#undef stpcpy
+
+#ifndef weak_alias
+# define __stpcpy stpcpy
+#endif
+
+/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
+char *
+__stpcpy (char *dest, const char *src)
+{
+ register char *d = dest;
+ register const char *s = src;
+
+ do
+ *d++ = *s;
+ while (*s++ != '\0');
+
+ return d - 1;
+}
+#ifdef weak_alias
+weak_alias (__stpcpy, stpcpy)
+#endif
diff --git a/gnu/usr.bin/grep/system.h b/gnu/usr.bin/grep/system.h
new file mode 100644
index 0000000..3cd9b56
--- /dev/null
+++ b/gnu/usr.bin/grep/system.h
@@ -0,0 +1,207 @@
+/* Portability cruft. Include after config.h and sys/types.h.
+ Copyright (C) 1996, 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#undef PARAMS
+#if defined (__STDC__) && __STDC__
+# ifndef _PTR_T
+# define _PTR_T
+ typedef void * ptr_t;
+# endif
+# define PARAMS(x) x
+#else
+# ifndef _PTR_T
+# define _PTR_T
+ typedef char * ptr_t;
+# endif
+# define PARAMS(x) ()
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <fcntl.h>
+# include <unistd.h>
+#else
+# define O_RDONLY 0
+# define SEEK_SET 0
+# define SEEK_CUR 1
+int open(), read(), close();
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifndef HAVE_STRERROR
+extern int sys_nerr;
+extern char *sys_errlist[];
+# define strerror(E) (0 <= (E) && (E) < sys_nerr ? _(sys_errlist[E]) : _("Unknown system error"))
+#endif
+
+/* Some operating systems treat text and binary files differently. */
+#if O_BINARY
+# include <io.h>
+# ifdef HAVE_SETMODE
+# define SET_BINARY(fd) setmode (fd, O_BINARY)
+# else
+# define SET_BINARY(fd) _setmode (fd, O_BINARY)
+# endif
+#else
+# ifndef O_BINARY
+# define O_BINARY 0
+# define SET_BINARY(fd) (void)0
+# endif
+#endif
+
+#ifdef HAVE_DOS_FILE_NAMES
+# define IS_SLASH(c) ((c) == '/' || (c) == '\\')
+# define FILESYSTEM_PREFIX_LEN(f) ((f)[0] && (f)[1] == ':' ? 2 : 0)
+#endif
+
+#ifndef IS_SLASH
+# define IS_SLASH(c) ((c) == '/')
+#endif
+
+#ifndef FILESYSTEM_PREFIX_LEN
+# define FILESYSTEM_PREFIX_LEN(f) 0
+#endif
+
+/* This assumes _WIN32, like DJGPP, has D_OK. Does it? In what header? */
+#ifdef D_OK
+# ifdef EISDIR
+# define is_EISDIR(e, f) \
+ ((e) == EISDIR \
+ || ((e) == EACCES && access (f, D_OK) == 0 && ((e) = EISDIR, 1)))
+# else
+# define is_EISDIR(e, f) ((e) == EACCES && access (f, D_OK) == 0)
+# endif
+#endif
+
+#ifndef is_EISDIR
+# ifdef EISDIR
+# define is_EISDIR(e, f) ((e) == EISDIR)
+# else
+# define is_EISDIR(e, f) 0
+# endif
+#endif
+
+#if STAT_MACROS_BROKEN
+# undef S_ISDIR
+# undef S_ISREG
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+# define S_ISDIR(Mode) (((Mode) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+# define S_ISREG(Mode) (((Mode) & S_IFMT) == S_IFREG)
+#endif
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#else
+char *getenv ();
+ptr_t malloc(), realloc(), calloc();
+void free();
+#endif
+
+#if __STDC__
+# include <stddef.h>
+#endif
+#ifdef STDC_HEADERS
+# include <limits.h>
+#endif
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+/* The extra casts work around common compiler bugs. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \
+ : (t) 0))
+#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+#ifndef CHAR_MAX
+# define CHAR_MAX TYPE_MAXIMUM (char)
+#endif
+#ifndef INT_MAX
+# define INT_MAX TYPE_MAXIMUM (int)
+#endif
+#ifndef UCHAR_MAX
+# define UCHAR_MAX TYPE_MAXIMUM (unsigned char)
+#endif
+
+#if !defined(STDC_HEADERS) && defined(HAVE_STRING_H) && defined(HAVE_MEMORY_H)
+# include <memory.h>
+#endif
+#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
+# include <string.h>
+#else
+# include <strings.h>
+# undef strchr
+# define strchr index
+# undef strrchr
+# define strrchr rindex
+# undef memcpy
+# define memcpy(d, s, n) bcopy (s, d, n)
+#endif
+#ifndef HAVE_MEMCHR
+ptr_t memchr();
+#endif
+#if ! defined HAVE_MEMMOVE && ! defined memmove
+# define memmove(d, s, n) bcopy (s, d, n)
+#endif
+
+#include <ctype.h>
+
+#ifndef isgraph
+# define isgraph(C) (isprint(C) && !isspace(C))
+#endif
+
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+# define IN_CTYPE_DOMAIN(c) 1
+#else
+# define IN_CTYPE_DOMAIN(c) isascii(c)
+#endif
+
+#define ISALPHA(C) (IN_CTYPE_DOMAIN (C) && isalpha (C))
+#define ISUPPER(C) (IN_CTYPE_DOMAIN (C) && isupper (C))
+#define ISLOWER(C) (IN_CTYPE_DOMAIN (C) && islower (C))
+#define ISDIGIT(C) (IN_CTYPE_DOMAIN (C) && isdigit (C))
+#define ISXDIGIT(C) (IN_CTYPE_DOMAIN (C) && isxdigit (C))
+#define ISSPACE(C) (IN_CTYPE_DOMAIN (C) && isspace (C))
+#define ISPUNCT(C) (IN_CTYPE_DOMAIN (C) && ispunct (C))
+#define ISALNUM(C) (IN_CTYPE_DOMAIN (C) && isalnum (C))
+#define ISPRINT(C) (IN_CTYPE_DOMAIN (C) && isprint (C))
+#define ISGRAPH(C) (IN_CTYPE_DOMAIN (C) && isgraph (C))
+#define ISCNTRL(C) (IN_CTYPE_DOMAIN (C) && iscntrl (C))
+
+#define TOLOWER(C) (ISUPPER(C) ? tolower(C) : (C))
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(String) gettext (String)
+#else
+# define _(String) String
+#endif
+#define N_(String) String
+
+#if HAVE_SETLOCALE
+# include <locale.h>
+#endif
+
+#ifndef initialize_main
+#define initialize_main(argcp, argvp)
+#endif
diff --git a/gnu/usr.bin/grep/tests/bre.awk b/gnu/usr.bin/grep/tests/bre.awk
new file mode 100644
index 0000000..9c9fef8
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/bre.awk
@@ -0,0 +1,26 @@
+BEGIN {
+ FS="@";
+ n = 0;
+ printf ("# Generated Spencer BRE Test\n");
+ printf ("failures=0\n");
+}
+
+$0 ~ /^#/ { next; }
+
+NF == 3 {
+ printf ("status=`echo '%s' | { ${GREP} -e '%s' > /dev/null 2>&1; echo $?; cat >/dev/null; }`\n",$3, $2);
+ printf ("if test $status -ne %s ; then\n", $1);
+ printf ("\techo Spencer bre test \\#%d failed\n", ++n);
+ printf ("\tfailures=1\n");
+ printf ("fi\n");
+}
+
+NF == 4 {
+#don't alarm users
+# printf ("echo '%s' | ${GREP} -e '%s' > /dev/null 2>&1\n",$3, $2);
+# printf ("if test $? -ne %s ; then\n", $1);
+# printf ("\techo Expected non conformance \\#%d ... continuing\n", ++n);
+# printf ("fi\n");
+}
+
+END { printf ("exit $failures\n"); }
diff --git a/gnu/usr.bin/grep/tests/bre.sh b/gnu/usr.bin/grep/tests/bre.sh
new file mode 100755
index 0000000..eecdd3e
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/bre.sh
@@ -0,0 +1,13 @@
+#! /bin/sh
+# Regression test for GNU grep.
+
+: ${srcdir=.}
+
+failures=0
+
+# . . . and the following by Henry Spencer.
+
+${AWK-awk} -f $srcdir/bre.awk $srcdir/bre.tests > bre.script
+
+sh bre.script && exit $failures
+exit 1
diff --git a/gnu/usr.bin/grep/tests/bre.tests b/gnu/usr.bin/grep/tests/bre.tests
new file mode 100644
index 0000000..1ed159d
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/bre.tests
@@ -0,0 +1,62 @@
+0@a\(b\)c@abc
+0@a(@a(
+2@a\(@EPAREN
+2@a\(b@EPAREN
+0@a(b@a(b
+0@a)@a)
+2@a\)@EPAREN
+2@\)@EPAREN
+0@a\(\)b@ab
+0@a^b@a^b@TO CORRECT
+0@a$b@a$b
+0@\($\)\(^\)@@
+0@a*\(^b$\)c*@b
+0@|@|
+0@*@*
+0@\(\)@abc
+2@\(\{1\}a\)@BADRPT@TO CORRECT
+0@^*@*
+2@^\{1\}@BADRPT@TO CORRECT
+0@\{@{
+1@a\(b*\)c\1d@abbcbd
+1@a\(b*\)c\1d@abbcbbbd
+1@^\(.\)\1@abc
+0@a\(\([bc]\)\2\)*d@abbccd
+1@a\(\([bc]\)\2\)*d@abbcbd
+0@a\(\(b\)*\2\)*d@abbbd
+0@\(a\)\1bcd@aabcd
+0@\(a\)\1bc*d@aabcd
+0@\(a\)\1bc*d@aabd
+0@\(a\)\1bc*d@aabcccd
+0@\(a\)\1bc*[ce]d@aabcccd@TO CORRECT
+0@^\(a\)\1b\(c\)*cd$@aabcccd
+0@a\(*\)b@a*b
+0@a\(**\)b@ab
+2@a\(***\)b@BADRPT@TO CORRECT
+0@*a@*a
+0@**a@a
+2@***a@BADRPT@TO CORRECT
+0@a\{1\}b@ab
+0@a\{1,\}b@ab
+0@a\{1,2\}b@aab
+2@a\{1@EBRACE
+2@a\{1a@EBRACE
+2@a\{1a\}@BADBR
+2@a\{,2\}@BADBR
+2@a\{,\}@BADBR
+2@a\{1,x\}@BADBR
+2@a\{1,x@EBRACE
+2@a\{32768\}@BADBR
+2@a\{1,0\}@BADBR
+0@ab\{0,0\}c@abcac
+0@ab\{0,1\}c@abcac
+0@ab\{0,3\}c@abbcac
+0@ab\{1,1\}c@acabc
+0@ab\{1,3\}c@acabc
+0@ab\{2,2\}c@abcabbc
+0@ab\{2,4\}c@abcabbc
+2@a\{1\}\{1\}@BADRPT@TO CORRECT
+2@a*\{1\}@BADRPT@TO CORRECT
+2@a\{1\}*@BADRPT@TO CORRECT
+1@a\(b\)?c\1d@acd
+0@-\{0,1\}[0-9]*$@-5
diff --git a/gnu/usr.bin/grep/tests/empty.sh b/gnu/usr.bin/grep/tests/empty.sh
new file mode 100755
index 0000000..8c75196
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/empty.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+# test that the empty file means no pattern
+# and an empty pattern means match all.
+
+: ${srcdir=.}
+
+failures=0
+
+# should return 0 found a match
+echo "abcd" | ${GREP} -E -e '' > /dev/null 2>&1
+if test $? -ne 0 ; then
+ echo "Status: Wrong status code, test \#1 failed"
+ failures=1
+fi
+
+# should return 1 found no match
+echo "abcd" | ${GREP} -E -f /dev/null > /dev/null 2>&1
+if test $? -ne 1 ; then
+ echo "Status: Wrong status code, test \#2 failed"
+ failures=1
+fi
+
+# should return 0 found a match
+echo "abcd" | ${GREP} -E -f /dev/null -e "abc" > /dev/null 2>&1
+if test $? -ne 0 ; then
+ echo "Status: Wrong status code, test \#3 failed"
+ failures=1
+fi
+
+exit $failures
diff --git a/gnu/usr.bin/grep/tests/ere.awk b/gnu/usr.bin/grep/tests/ere.awk
new file mode 100644
index 0000000..8f6a5b5
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/ere.awk
@@ -0,0 +1,31 @@
+BEGIN {
+ FS="@";
+ n = 0;
+ printf ("# Generated Spencer ERE Test\n");
+ printf ("failures=0\n");
+}
+
+$0 ~ /^#/ { next; }
+
+NF == 3 {
+ printf ("status=`echo '%s' | { ${GREP} -E -e '%s' > /dev/null 2>&1; echo $?; cat >/dev/null; }`\n",$3, $2);
+ printf ("if test $status -ne %s ; then\n", $1);
+ printf ("\techo Spencer ere test \\#%d failed\n", ++n);
+ printf ("\tfailures=1\n");
+ printf ("fi\n");
+}
+
+NF == 4 {
+# don't alarm the user for now
+# printf ("echo '%s'|${GREP} -E -e '%s' > /dev/null 2>&1\n",$3, $2);
+# printf ("if test $? -ne %s ; then\n", $1);
+# printf ("\techo Expected non conformance \\#%d ... continuing\n", ++n);
+# printf ("fi\n");
+}
+
+NF == 5 {
+# don't alarm the user for now
+ next;
+}
+
+END { printf ("exit $failures\n"); }
diff --git a/gnu/usr.bin/grep/tests/ere.sh b/gnu/usr.bin/grep/tests/ere.sh
new file mode 100755
index 0000000..5bf1695
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/ere.sh
@@ -0,0 +1,13 @@
+#! /bin/sh
+# Regression test for GNU grep.
+
+: ${srcdir=.}
+
+failures=0
+
+# . . . and the following by Henry Spencer.
+
+${AWK-awk} -f $srcdir/ere.awk $srcdir/ere.tests > ere.script
+
+sh ere.script && exit $failures
+exit 1
diff --git a/gnu/usr.bin/grep/tests/ere.tests b/gnu/usr.bin/grep/tests/ere.tests
new file mode 100644
index 0000000..20ef2b1
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/ere.tests
@@ -0,0 +1,215 @@
+0@a@a
+0@abc@abc
+0@abc|de@abc
+0@a|b|c@abc
+0@a(b)c@abc
+2@a(@EPAREN
+0@a\(@a(
+2@a(b@EPAREN
+0@a)@a)@POSIX BOTCH
+0@)@)@POSIX BOTCH
+0@a()b@ab
+0@^abc$@abc
+1@a^b@a^b
+1@a$b@a$b
+0@^@abc
+0@$@abc
+0@^$@@
+0@$^@@
+0@^^@@
+0@$$@@
+0@a*(^b$)c*@b
+2@|@EMPTY@NO ALTERNATION
+2@*@BADRPT@TO CORRECT
+2@+@BADRPT@TO CORRECT
+2@?@BADRPT@TO CORRECT
+1@&C@PASS
+0@()@abc
+2@a||b@EMPTY@NO ALTERNATION
+2@|ab@EMPTY@NO ALTERNATION
+2@ab|@EMPTY@NO ALTERNATION
+2@(|a)b@EMPTY@NO ALTERNATION
+2@(a|)b@EMPTY@NO ALTERNATION
+2@(*a)@BADRPT@TO CORRECT
+2@(+a)@BADRPT@TO CORRECT
+2@(?a)@BADRPT@TO CORRECT
+2@({1}a)@BADRPT@TO CORRECT
+2@(a|*b)@BADRPT@NO ALTERNATION
+2@(a|+b)@BADRPT@NO ALTERNATION
+2@(a|?b)@BADRPT@NO ALTERNATION
+2@(a|{1}b)@BADRPT@NO ALTERNATION
+2@^*@BADRPT@TO CORRECT
+2@^+@BADRPT@TO CORRECT
+2@^?@BADRPT@TO CORRECT
+2@^{1}@BADRPT@TO CORRECT
+0@a.c@abc
+0@a[bc]d@abd
+0@a\*c@a*c
+0@a\\b@a\b@TO CORRECT
+0@a\\\*b@a\*b@SHELL TROUBLE
+0@a\bc@abc@TO CORRECT
+2@a\@EESCAPE@SHELL TROUBLE
+0@a\\bc@a\bc@TO CORRECT
+0@a\[b@a[b
+2@a[b@EBRACK
+0@a$@a
+1@a$@a$
+1@a\$@a@SHELL TROUBLE
+0@a\$@a$@SHELL TROUBLE
+1@a\\$@a
+1@a\\$@a$@SHELL TROUBLE
+1@a\\$@a\$@SHELL TROUBLE
+0@a\\$@a\@SHEL TROUBLE
+0@ab*c@abc
+0@ab+c@abc
+0@ab?c@abc
+0@{@{@TO CORRECT
+0@{abc@{abc@TO CORRECT
+0@{1@{1
+2@{1}@BADRPT@TO CORRECT
+0@a{b@a{b@TO CORRECT
+0@a{1}b@ab
+0@a{1,}b@ab
+0@a{1,2}b@aab
+0@a{1@a{1
+1@a{1a@aa
+0@a{1a}@a{1a}
+0@a{,2}@a{,2}
+0@a{,}@a{,}
+0@a{1,*}@a{1,,,}
+2@a{1,x@EBRACE@TO CORRECT
+2@a{300}@BADBR@TO CORRECT
+2@a{1,0}@BADBR@TO CORRECT
+0@ab{0,0}c@abcac
+0@ab{0,1}c@abcac
+0@ab{0,3}c@abbcac
+0@ab{1,1}c@acabc
+0@ab{1,3}c@acabc
+0@ab{2,2}c@abcabbc
+0@ab{2,4}c@abcabbc
+2@a**@BADRPT@TO CORRECT
+2@a++@BADRPT@TO CORRECT
+2@a??@BADRPT@TO CORRECT
+2@a*+@BADRPT@TO CORRECT
+2@a*?@BADRPT@TO CORRECT
+2@a+*@BADRPT@TO CORRECT
+2@a+?@BADRPT@TO CORRECT
+2@a?*@BADRPT@TO CORRECT
+2@a?+@BADRPT@TO CORRECT
+2@a{1}{1}@BADRPT@TO CORRECT
+2@a*{1}@BADRPT@TO CORRECT
+2@a+{1}@BADRPT@TO CORRECT
+2@a?{1}@BADRPT@TO CORRECT
+2@a{1}*@BADRPT@TO CORRECT
+2@a{1}+@BADRPT@TO CORRECT
+2@a{1}?@BADRPT@TO CORRECT
+0@a*{b}@a{b}@TO CORRECT
+0@a[b]c@abc
+0@a[ab]c@abc
+0@a[^ab]c@adc
+0@a[]b]c@a]c
+0@a[[b]c@a[c
+0@a[-b]c@a-c
+0@a[^]b]c@adc
+0@a[^-b]c@adc
+0@a[b-]c@a-c
+2@a[b@EBRACK
+2@a[]@EBRACK
+0@a[1-3]c@a2c
+2@a[3-1]c@ERANGE@TO CORRECT
+2@a[1-3-5]c@ERANGE@TO CORRECT
+0@a[[.-.]--]c@a-c@TO CORRECT
+2@a[1-@ERANGE
+2@a[[.@EBRACK
+2@a[[.x@EBRACK
+2@a[[.x.@EBRACK
+2@a[[.x.]@EBRACK@TO CORRECT
+0@a[[.x.]]@ax@TO CORRECT
+2@a[[.x,.]]@ECOLLATE@TO CORRECT
+0@a[[.one.]]b@a1b@TO CORRECT
+2@a[[.notdef.]]b@ECOLLATE@TO CORRECT
+0@a[[.].]]b@a]b@TO CORRECT
+0@a[[:alpha:]]c@abc
+2@a[[:notdef:]]c@ECTYPE
+2@a[[:@EBRACK
+2@a[[:alpha@EBRACK
+2@a[[:alpha:]@EBRACK
+2@a[[:alpha,:]@ECTYPE
+2@a[[:]:]]b@ECTYPE
+2@a[[:-:]]b@ECTYPE
+2@a[[:alph:]]@ECTYPE
+2@a[[:alphabet:]]@ECTYPE
+0@[[:digit:]]+@a019b
+0@[[:lower:]]+@AabC
+0@[[:upper:]]+@aBCd
+0@[[:xdigit:]]+@p0f3Cq
+0@a[[=b=]]c@abc@TO CORRECT
+2@a[[=@EBRACK
+2@a[[=b@EBRACK
+2@a[[=b=@EBRACK
+2@a[[=b=]@EBRACK@TO CORRECT
+2@a[[=b,=]]@ECOLLATE@TO CORRECT
+0@a[[=one=]]b@a1b@TO CORRECT
+0@a(((b)))c@abc
+0@a(b|(c))d@abd
+0@a(b*|c)d@abbd
+0@a[ab]{20}@aaaaabaaaabaaaabaaaab
+0@a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab]@aaaaabaaaabaaaabaaaab
+0@a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night)@aaaaabaaaabaaaabaaaabweeknights
+0@12345678901234567890123456789@a12345678901234567890123456789b
+0@123456789012345678901234567890@a123456789012345678901234567890b
+0@1234567890123456789012345678901@a1234567890123456789012345678901b
+0@12345678901234567890123456789012@a12345678901234567890123456789012b
+0@123456789012345678901234567890123@a123456789012345678901234567890123b
+0@1234567890123456789012345678901234567890123456789012345678901234567890@a1234567890123456789012345678901234567890123456789012345678901234567890b
+0@[ab][cd][ef][gh][ij][kl][mn]@xacegikmoq
+0@[ab][cd][ef][gh][ij][kl][mn][op]@xacegikmoq
+0@[ab][cd][ef][gh][ij][kl][mn][op][qr]@xacegikmoqy
+0@[ab][cd][ef][gh][ij][kl][mn][op][q]@xacegikmoqy
+0@abc@xabcy
+0@aBc@Abc@TO CORRECT
+0@a[Bc]*d@abBCcd@TO CORRECT
+0@0[[:upper:]]1@0a1@TO CORRECT
+0@0[[:lower:]]1@0A1@TO CORRECT
+1@a[^b]c@abc
+1@a[^b]c@aBc@TO CORRECT
+0@a[^b]c@adc
+0@[a]b[c]@abc
+0@[a]b[a]@aba
+0@[abc]b[abc]@abc
+0@[abc]b[abd]@abd
+0@a(b?c)+d@accd
+0@(wee|week)(knights|night)@weeknights
+0@(we|wee|week|frob)(knights|night|day)@weeknights
+0@a[bc]d@xyzaaabcaababdacd
+0@a[ab]c@aaabc
+0@a*@b
+0@/\*.*\*/@/*x*/
+0@/\*.*\*/@/*x*/y/*z*/
+0@/\*([^*]|\*[^/])*\*/@/*x*/
+0@/\*([^*]|\*[^/])*\*/@/*x*/y/*z*/
+0@/\*([^*]|\*[^/])*\*/@/*x**/y/*z*/
+0@/\*([^*]|\*+[^*/])*\*+/@/*x*/
+0@/\*([^*]|\*+[^*/])*\*+/@/*x*/y/*z*/
+0@/\*([^*]|\*+[^*/])*\*+/@/*x**/y/*z*/
+0@/\*([^*]|\*+[^*/])*\*+/@/*x****/y/*z*/
+0@/\*([^*]|\*+[^*/])*\*+/@/*x**x*/y/*z*/
+0@/\*([^*]|\*+[^*/])*\*+/@/*x***x/y/*z*/
+0@aZb@a@TO CORRECT
+0@[[:<:]]a@a@TO CORRECT
+1@[[:<:]]a@ba@TO CORRECT
+0@[[:<:]]a@-a@TO CORRECT
+0@a[[:>:]]@a@TO CORRECT
+1@a[[:>:]]@ab@TO CORRECT
+0@a[[:>:]]@a-@TO CORRECT
+0@[[:<:]]a.c[[:>:]]@axcd-dayc-dazce-abc@TO CORRECT
+0@[[:<:]]a.c[[:>:]]@axcd-dayc-dazce-abc-q@TO CORRECT
+0@[[:<:]]a.c[[:>:]]@axc-dayc-dazce-abc@TO CORRECT
+0@[[:<:]]b.c[[:>:]]@a_bxc-byc_d-bzc-q@TO CORRECT
+0@[[:<:]].x..[[:>:]]@y_xa_-_xb_y-_xc_-axdc@TO CORRECT
+1@[[:<:]]a_b[[:>:]]@x_a_b@TO CORRECT
+0@(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A])@A1
+0@abcdefghijklmnop@abcdefghijklmnop
+0@abcdefghijklmnopqrstuv@abcdefghijklmnopqrstuv
+0@CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a@CC11
+0@a?b@ab
diff --git a/gnu/usr.bin/grep/tests/khadafy.lines b/gnu/usr.bin/grep/tests/khadafy.lines
new file mode 100644
index 0000000..57e21a1
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/khadafy.lines
@@ -0,0 +1,32 @@
+1) Muammar Qaddafi
+2) Mo'ammar Gadhafi
+3) Muammar Kaddafi
+4) Muammar Qadhafi
+5) Moammar El Kadhafi
+6) Muammar Gadafi
+7) Mu'ammar al-Qadafi
+8) Moamer El Kazzafi
+9) Moamar al-Gaddafi
+10) Mu'ammar Al Qathafi
+11) Muammar Al Qathafi
+12) Mo'ammar el-Gadhafi
+13) Moamar El Kadhafi
+14) Muammar al-Qadhafi
+15) Mu'ammar al-Qadhdhafi
+16) Mu'ammar Qadafi
+17) Moamar Gaddafi
+18) Mu'ammar Qadhdhafi
+19) Muammar Khaddafi
+20) Muammar al-Khaddafi
+21) Mu'amar al-Kadafi
+22) Muammar Ghaddafy
+23) Muammar Ghadafi
+24) Muammar Ghaddafi
+25) Muamar Kaddafi
+26) Muammar Quathafi
+27) Muammar Gheddafi
+28) Muamar Al-Kaddafi
+29) Moammar Khadafy
+30) Moammar Qudhafi
+31) Mu'ammar al-Qaddafi
+32) Mulazim Awwal Mu'ammar Muhammad Abu Minyar al-Qadhafi
diff --git a/gnu/usr.bin/grep/tests/khadafy.regexp b/gnu/usr.bin/grep/tests/khadafy.regexp
new file mode 100644
index 0000000..46fe8dd
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/khadafy.regexp
@@ -0,0 +1 @@
+M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]
diff --git a/gnu/usr.bin/grep/tests/khadafy.sh b/gnu/usr.bin/grep/tests/khadafy.sh
new file mode 100755
index 0000000..141b3d8
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/khadafy.sh
@@ -0,0 +1,20 @@
+#! /bin/sh
+# Regression test for GNU grep.
+
+: ${srcdir=.}
+: ${GREP=../src/grep}
+
+failures=0
+
+# The Khadafy test is brought to you by Scott Anderson . . .
+
+${GREP} -E -f $srcdir/khadafy.regexp $srcdir/khadafy.lines > khadafy.out
+if cmp $srcdir/khadafy.lines khadafy.out
+then
+ :
+else
+ echo Khadafy test failed -- output left on khadafy.out
+ failures=1
+fi
+
+exit $failures
diff --git a/gnu/usr.bin/grep/tests/options.sh b/gnu/usr.bin/grep/tests/options.sh
new file mode 100755
index 0000000..3415018
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/options.sh
@@ -0,0 +1,36 @@
+#! /bin/sh
+# Test for POSIX.2 options for grep
+#
+# grep [ -E| -F][ -c| -l| -q ][-insvx] -e pattern_list
+# [-f pattern_file] ... [file. ..]
+# grep [ -E| -F][ -c| -l| -q ][-insvx][-e pattern_list]
+# -f pattern_file ... [file ...]
+# grep [ -E| -F][ -c| -l| -q ][-insvx] pattern_list [file...]
+#
+
+: ${srcdir=.}
+
+failures=0
+
+# checking for -E extended regex
+echo "abababccccccd" | ${GREP} -E -e 'c{3}' > /dev/null 2>&1
+if test $? -ne 0 ; then
+ echo "Options: Wrong status code, test \#1 failed"
+ failures=1
+fi
+
+# checking for basic regex
+echo "abababccccccd" | ${GREP} -G -e 'c\{3\}' > /dev/null 2>&1
+if test $? -ne 0 ; then
+ echo "Options: Wrong status code, test \#2 failed"
+ failures=1
+fi
+
+# checking for fixed string
+echo "abababccccccd" | ${GREP} -F -e 'c\{3\}' > /dev/null 2>&1
+if test $? -ne 1 ; then
+ echo "Options: Wrong status code, test \#3 failed"
+ failures=1
+fi
+
+exit $failures
diff --git a/gnu/usr.bin/grep/tests/spencer1.awk b/gnu/usr.bin/grep/tests/spencer1.awk
new file mode 100644
index 0000000..70c6118
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/spencer1.awk
@@ -0,0 +1,14 @@
+BEGIN {
+ FS = "@";
+ printf ("failures=0\n");
+}
+
+$0 !~ /^#/ && NF = 3 {
+ printf ("status=`echo '%s'| { ${GREP} -E -e '%s' > /dev/null 2>&1; echo $?; cat >/dev/null; }`\n",$3, $2);
+ printf ("if test $status -ne %s ; then\n", $1);
+ printf ("\techo Spencer test \\#%d failed\n", ++n);
+ printf ("\tfailures=1\n");
+ printf ("fi\n");
+}
+
+END { printf ("exit $failures\n"); }
diff --git a/gnu/usr.bin/grep/tests/spencer1.sh b/gnu/usr.bin/grep/tests/spencer1.sh
new file mode 100755
index 0000000..f09b3fa
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/spencer1.sh
@@ -0,0 +1,13 @@
+#! /bin/sh
+# Regression test for GNU grep.
+
+: ${srcdir=.}
+
+failures=0
+
+# . . . and the following by Henry Spencer.
+
+${AWK-awk} -f $srcdir/spencer1.awk $srcdir/spencer1.tests > spencer1.script
+
+sh spencer1.script && exit $failures
+exit 1
diff --git a/gnu/usr.bin/grep/tests/spencer1.tests b/gnu/usr.bin/grep/tests/spencer1.tests
new file mode 100644
index 0000000..2a60f00
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/spencer1.tests
@@ -0,0 +1,122 @@
+0@abc@abc
+1@abc@xbc
+1@abc@axc
+1@abc@abx
+0@abc@xabcy
+0@abc@ababc
+0@ab*c@abc
+0@ab*bc@abc
+0@ab*bc@abbc
+0@ab*bc@abbbbc
+0@ab+bc@abbc
+1@ab+bc@abc
+1@ab+bc@abq
+0@ab+bc@abbbbc
+0@ab?bc@abbc
+0@ab?bc@abc
+1@ab?bc@abbbbc
+0@ab?c@abc
+0@^abc$@abc
+1@^abc$@abcc
+0@^abc@abcc
+1@^abc$@aabc
+0@abc$@aabc
+0@^@abc
+0@$@abc
+0@a.c@abc
+0@a.c@axc
+0@a.*c@axyzc
+1@a.*c@axyzd
+1@a[bc]d@abc
+0@a[bc]d@abd
+1@a[b-d]e@abd
+0@a[b-d]e@ace
+0@a[b-d]@aac
+0@a[-b]@a-
+0@a[b-]@a-
+1@a[b-a]@-
+2@a[]b@-
+2@a[@-
+0@a]@a]
+0@a[]]b@a]b
+0@a[^bc]d@aed
+1@a[^bc]d@abd
+0@a[^-b]c@adc
+1@a[^-b]c@a-c
+1@a[^]b]c@a]c
+0@a[^]b]c@adc
+0@ab|cd@abc
+0@ab|cd@abcd
+0@()ef@def
+0@()*@-
+1@*a@-
+0@^*@-
+0@$*@-
+1@(*)b@-
+1@$b@b
+2@a\@-
+0@a\(b@a(b
+0@a\(*b@ab
+0@a\(*b@a((b
+1@a\x@a\x
+2@abc)@-
+2@(abc@-
+0@((a))@abc
+0@(a)b(c)@abc
+0@a+b+c@aabbabc
+0@a**@-
+0@a*?@-
+0@(a*)*@-
+0@(a*)+@-
+0@(a|)*@-
+0@(a*|b)*@-
+0@(a+|b)*@ab
+0@(a+|b)+@ab
+0@(a+|b)?@ab
+0@[^ab]*@cde
+0@(^)*@-
+0@(ab|)*@-
+2@)(@-
+1@abc@
+1@abc@
+0@a*@
+0@([abc])*d@abbbcd
+0@([abc])*bcd@abcd
+0@a|b|c|d|e@e
+0@(a|b|c|d|e)f@ef
+0@((a*|b))*@-
+0@abcd*efg@abcdefg
+0@ab*@xabyabbbz
+0@ab*@xayabbbz
+0@(ab|cd)e@abcde
+0@[abhgefdc]ij@hij
+1@^(ab|cd)e@abcde
+0@(abc|)ef@abcdef
+0@(a|b)c*d@abcd
+0@(ab|ab*)bc@abc
+0@a([bc]*)c*@abc
+0@a([bc]*)(c*d)@abcd
+0@a([bc]+)(c*d)@abcd
+0@a([bc]*)(c+d)@abcd
+0@a[bcd]*dcdcde@adcdcde
+1@a[bcd]+dcdcde@adcdcde
+0@(ab|a)b*c@abc
+0@((a)(b)c)(d)@abcd
+0@[A-Za-z_][A-Za-z0-9_]*@alpha
+0@^a(bc+|b[eh])g|.h$@abh
+0@(bc+d$|ef*g.|h?i(j|k))@effgz
+0@(bc+d$|ef*g.|h?i(j|k))@ij
+1@(bc+d$|ef*g.|h?i(j|k))@effg
+1@(bc+d$|ef*g.|h?i(j|k))@bcdd
+0@(bc+d$|ef*g.|h?i(j|k))@reffgz
+1@((((((((((a))))))))))@-
+0@(((((((((a)))))))))@a
+1@multiple words of text@uh-uh
+0@multiple words@multiple words, yeah
+0@(.*)c(.*)@abcde
+1@\((.*),@(.*)\)
+1@[k]@ab
+0@abcd@abcd
+0@a(bc)d@abcd
+0@a[-]?c@ac
+0@(....).*\1@beriberi
diff --git a/gnu/usr.bin/grep/tests/status.sh b/gnu/usr.bin/grep/tests/status.sh
new file mode 100755
index 0000000..50fc912
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/status.sh
@@ -0,0 +1,38 @@
+#! /bin/sh
+# Test for status code for GNU grep.
+# status code
+# 0 match found
+# 1 no match
+# 2 file not found
+
+: ${srcdir=.}
+
+failures=0
+
+# should return 0 found a match
+echo "abcd" | ${GREP} -E -e 'abc' > /dev/null 2>&1
+if test $? -ne 0 ; then
+ echo "Status: Wrong status code, test \#1 failed"
+ failures=1
+fi
+
+# should return 1 found no match
+echo "abcd" | ${GREP} -E -e 'zbc' > /dev/null 2>&1
+if test $? -ne 1 ; then
+ echo "Status: Wrong status code, test \#2 failed"
+ failures=1
+fi
+
+# the filename MMMMMMMM.MMM should not exist hopefully
+# should return 2 file not found
+if test -b MMMMMMMM.MMM; then
+ echo "Please remove MMMMMMMM.MMM to run check"
+else
+ ${GREP} -E -e 'abc' MMMMMMMM.MMM> /dev/null 2>&1
+ if test $? -ne 2 ; then
+ echo "Status: Wrong status code, test \#3 failed"
+ failures=1
+ fi
+fi
+
+exit $failures
diff --git a/gnu/usr.bin/grep/tests/warning.sh b/gnu/usr.bin/grep/tests/warning.sh
new file mode 100755
index 0000000..d2dc6d5
--- /dev/null
+++ b/gnu/usr.bin/grep/tests/warning.sh
@@ -0,0 +1,19 @@
+#! /bin/sh
+#
+# Tell them not to be alarmed.
+
+: ${srcdir=.}
+
+failures=0
+
+#
+cat <<\EOF
+
+Please, do not be alarmed if some of the tests failed.
+Report them to <bug-gnu-utils@gnu.org>,
+with the line number, the name of the file,
+and grep version number 'grep --version'.
+Make sure you have the word grep in the subject.
+Thank You.
+
+EOF
diff --git a/gnu/usr.bin/groff/Makefile b/gnu/usr.bin/groff/Makefile
new file mode 100644
index 0000000..7c61f71
--- /dev/null
+++ b/gnu/usr.bin/groff/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= contrib doc font man src tmac
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/Makefile.inc b/gnu/usr.bin/groff/Makefile.inc
new file mode 100644
index 0000000..d5cd9fb
--- /dev/null
+++ b/gnu/usr.bin/groff/Makefile.inc
@@ -0,0 +1,165 @@
+# $FreeBSD$
+
+BINDIR?= /usr/bin
+SHELL= /bin/sh
+
+# Define `page' to be letter if your PostScript printer uses 8.5x11
+# paper (USA) and define it to be A4, if it uses A4 paper (rest of the
+# world).
+PAGE=letter
+
+# Normally the Postscript driver, grops, produces output that conforms
+# to version 3.0 of the Adobe Document Structuring Conventions.
+# Unfortunately some spoolers and previewers can't handle such output.
+# The BROKEN_SPOOLER_FLAGS variable tells grops what it should do to
+# make its output acceptable to such programs. This variable controls
+# only the default behaviour of grops; the behaviour can be changed at
+# runtime by the grops -b option (and so by groff -P-b).
+# Use a value of 0 if your spoolers and previewers are able to handle
+# conforming PostScript correctly.
+# Add 1 if no %%{Begin,End}DocumentSetup comments should be generated;
+# this is needed for early versions of TranScript that get confused by
+# anything between the %%EndProlog line and the first %%Page: comment.
+# Add 2 if lines in included files beginning with %! should be
+# stripped out; this is needed for the OpenWindows 2.0 pageview previewer.
+# Add 4 if %%Page, %%Trailer and %%EndProlog comments should be
+# stripped out of included files; this is needed for spoolers that
+# don't understand the %%{Begin,End}Document comments. I suspect this
+# includes early versions of TranScript.
+# Add 8 if the first line of the PostScript output should be %!PS-Adobe-2.0
+# rather than %!PS-Adobe-3.0; this is needed when using Sun's Newsprint
+# with a printer that requires page reversal.
+BROKEN_SPOOLER_FLAGS=7
+
+# DEVICE is the default device.
+DEVICE=ps
+
+# PSPRINT is the command to use for printing a PostScript file,
+# for example `lpr'.
+PSPRINT=lpr
+
+# DVIPRINT is the command to use for printing a TeX dvi file,
+# for example `lpr -d'.
+DVIPRINT=lpr -d
+########################################################################
+# Don't touch...
+
+g=
+tmac_s_prefix=
+tmac_m_prefix=
+tmac_an_prefix=
+fontdir=/usr/share/groff_font
+fontpath=$(fontdir)
+tmacdir=/usr/share/tmac
+systemtmacdir=/usr/share/tmac
+localtmacdir=/usr/share/tmac
+tmacpath=$(tmacdir)
+indexext=.i
+common_words_file=/usr/share/dict/eign
+indexdir=/usr/share/dict/papers
+indexname=Ind
+
+########################################################################
+# Libraries
+
+# Bad assumption, if one exists they all exist
+.if exists(${.OBJDIR}/${TOPREL}/src/libs/libgroff)
+LIBGROFF= ${.OBJDIR}/${TOPREL}/src/libs/libgroff/libgroff.a
+LIBDRIVER= ${.OBJDIR}/${TOPREL}/src/libs/libdriver/libdriver.a
+LIBBIB= ${.OBJDIR}/${TOPREL}/src/libs/libbib/libbib.a
+.else
+LIBGROFF= ${.CURDIR}/${TOPREL}/src/libs/libgroff/libgroff.a
+LIBDRIVER= ${.CURDIR}/${TOPREL}/src/libs/libdriver/libdriver.a
+LIBBIB= ${.CURDIR}/${TOPREL}/src/libs/libbib/libbib.a
+.endif
+
+CFLAGS+= -DHAVE_STDLIB_H=1\
+ -DHAVE_UNISTD_H=1\
+ -DHAVE_DIRENT_H=1\
+ -DHAVE_LIMITS_H=1\
+ -DHAVE_STRING_H=1\
+ -DHAVE_STRINGS_H=1\
+ -DHAVE_MATH_H=1\
+ -DRET_TYPE_SRAND_IS_VOID=1\
+ -DHAVE_SYS_NERR=1\
+ -DHAVE_SYS_ERRLIST=1\
+ -DHAVE_CC_LIMITS_H=1\
+ -DRETSIGTYPE=void\
+ -DHAVE_STRUCT_EXCEPTION=1\
+ -DHAVE_GETPAGESIZE=1\
+ -DHAVE_MMAP=1\
+ -DHAVE_FMOD=1\
+ -DHAVE_STRTOL=1\
+ -DHAVE_GETCWD=1\
+ -DHAVE_STRERROR=1\
+ -DHAVE_PUTENV=1\
+ -DHAVE_RENAME=1\
+ -DHAVE_MKSTEMP=1\
+ -DHAVE_STRCASECMP=1\
+ -DHAVE_STRNCASECMP=1\
+ -DHAVE_STRSEP=1\
+ -DHAVE_STRDUP=1\
+ -DSYS_SIGLIST_DECLARED=1
+
+CFLAGS+= -I${GROFF_DIST}/src/include -I${.CURDIR}/${TOPREL}/src/include
+CXXFLAGS+= -fno-rtti -fno-exceptions
+
+.y.o:
+ $(YACC) $(YFLAGS) $(.IMPSRC)
+ mv -f y.tab.c $(.PREFIX).cc
+ mv -f y.tab.h $(.PREFIX)_tab.h
+ ${CXX} ${CXXFLAGS} -c $(.PREFIX).cc -o ${.TARGET}
+
+.y.cc:
+ $(YACC) $(YFLAGS) $(.IMPSRC)
+ mv -f y.tab.c $(.PREFIX).cc
+ mv -f y.tab.h $(.PREFIX)_tab.h
+
+.SUFFIXES: .man .1 .2 .3 .4 .5 .6 .7 .8
+
+version=`cat $(GROFF_DIST)/VERSION`
+revision=`sed -e 's/^0$$//' -e 's/^[1-9].*$$/.&/' $(GROFF_DIST)/REVISION`
+
+.man.8 .man.7 .man.6 .man.5 .man.4 .man.3 .man.2 .man.1:
+ @${ECHO} Making $@ from $<
+ @-rm -f $@
+ @sed -e "s;@BINDIR@;${BINDIR};g" \
+ -e "s;@FONTDIR@;$(fontdir);g" \
+ -e "s;@FONTPATH@;$(fontpath);g" \
+ -e "s;@MACRODIR@;$(tmacdir);g" \
+ -e "s;@SYSTEMMACRODIR@;$(systemtmacdir);g" \
+ -e "s;@LOCALMACRODIR@;$(localtmacdir);g" \
+ -e "s;@MACROPATH@;$(tmacpath);g" \
+ -e "s;@DEVICE@;$(DEVICE);g" \
+ -e "s;@DEFAULT_INDEX@;$(indexdir)/$(indexname);g" \
+ -e "s;@DEFAULT_INDEX_NAME@;$(indexname);g" \
+ -e "s;@INDEX_SUFFIX@;$(indexext);g" \
+ -e "s;@COMMON_WORDS_FILE@;$(common_words_file);g" \
+ -e "s;@MAN1EXT@;1;g" \
+ -e "s;@MAN5EXT@;5;g" \
+ -e "s;@MAN7EXT@;7;g" \
+ -e "s;@TMAC_S_PREFIX@;$(tmac_s_prefix);g" \
+ -e "s;@TMAC_M_PREFIX@;$(tmac_m_prefix);g" \
+ -e "s;@TMAC_AN_PREFIX@;$(tmac_an_prefix);g" \
+ -e "s;@TMAC_MDIR@;$(tmacdir)/mm;g" \
+ -e "s;@BROKEN_SPOOLER_FLAGS@;$(BROKEN_SPOOLER_FLAGS);g" \
+ -e "s;@VERSION@;$(version)$(revision);g" \
+ -e "s;@MDATE@;`$(SHELL) ${GROFF_DIST}/mdate.sh $<`;g" \
+ -e "s;@g@;$(g);g" \
+ -e "s;@G@;`echo $(g) | tr [a-z] [A-Z]`;g" \
+ $< >$@
+
+.SUFFIXES: .sh .pl
+
+.sh .pl:
+ @${ECHO} Making ${.TARGET} from ${.IMPSRC}
+ @sed -e "s|@BINDIR@|${BINDIR}|g" \
+ -e "s|@VERSION@|$(version)$(revision)|" \
+ -e "s|@g@|$(g)|g" \
+ ${.IMPSRC} >${.TARGET}
+
+TOPREL?= ..
+GROFF_DIST= ${.CURDIR}/${TOPREL}/../../../contrib/groff
+DIST_SUBDIR?= ${.CURDIR:T}
+DIST_DIR= ${GROFF_DIST}/${DIST_SUBDIR}
+.PATH: ${DIST_DIR}
diff --git a/gnu/usr.bin/groff/contrib/Makefile b/gnu/usr.bin/groff/contrib/Makefile
new file mode 100644
index 0000000..6718107
--- /dev/null
+++ b/gnu/usr.bin/groff/contrib/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= mm
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/contrib/Makefile.inc b/gnu/usr.bin/groff/contrib/Makefile.inc
new file mode 100644
index 0000000..d5552c5
--- /dev/null
+++ b/gnu/usr.bin/groff/contrib/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+DIST_SUBDIR= contrib/${.CURDIR:T}
+TOPREL= ../..
+
+.include "../Makefile.inc"
diff --git a/gnu/usr.bin/groff/contrib/mm/Makefile b/gnu/usr.bin/groff/contrib/mm/Makefile
new file mode 100644
index 0000000..0356802
--- /dev/null
+++ b/gnu/usr.bin/groff/contrib/mm/Makefile
@@ -0,0 +1,30 @@
+# $FreeBSD$
+
+SCRIPTS= mmroff.pl
+MAN= mmroff.7
+
+TMACDIR?= ${SHAREDIR}/tmac
+
+FILES= m.tmac mse.tmac
+FILESDIR_m.tmac=${TMACDIR}
+FILESDIR_mse.tmac=${TMACDIR}
+FILES+= 0.MT 5.MT 4.MT ms.cov se_ms.cov
+FILESDIR= ${TMACDIR}/mm
+LOCALE= locale se_locale
+
+MAN+= groff_mm.7 groff_mmse.7
+MLINKS= groff_mm.7 mm.7 groff_mmse.7 mmse.7
+
+CLEANFILES+= ${MAN}
+
+.include <bsd.prog.mk>
+
+.PATH: ${DIST_DIR}/mm
+
+beforeinstall:
+.for locale in ${LOCALE}
+.if !exists(${DESTDIR}${TMACDIR}/mm/${locale})
+ ${INSTALL} -c -o ${FILESOWN} -g ${FILESGRP} -m ${FILESMODE} \
+ /dev/null ${DESTDIR}${TMACDIR}/mm/${locale}
+.endif
+.endfor
diff --git a/gnu/usr.bin/groff/doc/Makefile b/gnu/usr.bin/groff/doc/Makefile
new file mode 100644
index 0000000..6381812
--- /dev/null
+++ b/gnu/usr.bin/groff/doc/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+INFO= groff
+SRCDIR= ${DIST_DIR}
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/groff/font/Makefile b/gnu/usr.bin/groff/font/Makefile
new file mode 100644
index 0000000..d78fc81
--- /dev/null
+++ b/gnu/usr.bin/groff/font/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SUBDIR= devX100 devX100-12 devX75 devX75-12 \
+ devascii devcp1047 devdvi devhtml devkoi8-r \
+ devlatin1 devlbp devlj4 devps devutf8
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/font/Makefile.dev b/gnu/usr.bin/groff/font/Makefile.dev
new file mode 100644
index 0000000..85be29a
--- /dev/null
+++ b/gnu/usr.bin/groff/font/Makefile.dev
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+DEVICEDIR?= ${fontdir}/dev${DEV}
+
+all: ${DEVFILES}
+
+beforeinstall: ${DEVFILES}
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \
+ ${.ALLSRC} ${DESTDIR}${DEVICEDIR}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/font/Makefile.inc b/gnu/usr.bin/groff/font/Makefile.inc
new file mode 100644
index 0000000..22a1a42
--- /dev/null
+++ b/gnu/usr.bin/groff/font/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+DIST_SUBDIR= font/${.CURDIR:T}
+TOPREL= ../..
+
+.include "../Makefile.inc"
diff --git a/gnu/usr.bin/groff/font/Makefile.tty b/gnu/usr.bin/groff/font/Makefile.tty
new file mode 100644
index 0000000..d515835
--- /dev/null
+++ b/gnu/usr.bin/groff/font/Makefile.tty
@@ -0,0 +1,30 @@
+# $FreeBSD$
+
+FONTS?=R I B BI S L CW
+DEVFILES=$(FONTS) DESC
+CLEANFILES=$(DEVFILES)
+
+RES=240
+CPI=10
+LPI=6
+
+$(FONTS): R.proto
+ @${ECHO} Making ${.TARGET}
+ @(charwidth=`expr $(RES) / $(CPI)` ; \
+ sed -e "s/^name [A-Z]*$$/name ${.TARGET}/" \
+ -e "s/^\\([^ ]*\\) [0-9]+ /\\1 $$charwidth /" \
+ -e "s/^spacewidth [0-9]+$$/spacewidth $$charwidth/" \
+ -e "s/^internalname .*$$/internalname $@/" \
+ -e "/^internalname/s/BI/3/" \
+ -e "/^internalname/s/B/2/" \
+ -e "/^internalname/s/I/1/" \
+ -e "/^internalname .*[^ 0-9]/d" \
+ ${.ALLSRC} >$.${.TARGET})
+
+DESC: DESC.proto
+ @${ECHO} Making ${.TARGET}
+ @sed -e "s/^res .*$$/res $(RES)/" \
+ -e "s/^hor .*$$/hor `expr $(RES) / $(CPI)`/" \
+ -e "s/^vert .*$$/vert `expr $(RES) / $(LPI)`/" \
+ -e "s/^fonts .*$$/fonts `set $(FONTS); echo $$#` $(FONTS)/" \
+ ${.ALLSRC} >${.TARGET}
diff --git a/gnu/usr.bin/groff/font/devX100-12/Makefile b/gnu/usr.bin/groff/font/devX100-12/Makefile
new file mode 100644
index 0000000..9a136b8
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devX100-12/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+NOOBJ=
+
+.include "../Makefile.inc"
+.include "${DIST_DIR}/Makefile.sub"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devX100/Makefile b/gnu/usr.bin/groff/font/devX100/Makefile
new file mode 100644
index 0000000..9a136b8
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devX100/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+NOOBJ=
+
+.include "../Makefile.inc"
+.include "${DIST_DIR}/Makefile.sub"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devX75-12/Makefile b/gnu/usr.bin/groff/font/devX75-12/Makefile
new file mode 100644
index 0000000..9a136b8
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devX75-12/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+NOOBJ=
+
+.include "../Makefile.inc"
+.include "${DIST_DIR}/Makefile.sub"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devX75/Makefile b/gnu/usr.bin/groff/font/devX75/Makefile
new file mode 100644
index 0000000..9a136b8
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devX75/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+NOOBJ=
+
+.include "../Makefile.inc"
+.include "${DIST_DIR}/Makefile.sub"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devascii/Makefile b/gnu/usr.bin/groff/font/devascii/Makefile
new file mode 100644
index 0000000..544ec16
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devascii/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+DEV= ascii
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devcp1047/Makefile b/gnu/usr.bin/groff/font/devcp1047/Makefile
new file mode 100644
index 0000000..d0a887a
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devcp1047/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+DEV= cp1047
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devdvi/Makefile b/gnu/usr.bin/groff/font/devdvi/Makefile
new file mode 100644
index 0000000..cb747a5
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devdvi/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+DEV= dvi
+DEVFILES= DESC R I B BI CW CWI MI S EX H HI HB SA SB \
+ generate/CompileFonts generate/Makefile generate/msam.map\
+ generate/msbm.map generate/texb.map generate/texex.map \
+ generate/texi.map generate/texmi.map generate/texr.map \
+ generate/texsy.map generate/textt.map
+
+CLEANFILES+= DESC
+
+DESC: DESC.in
+ cat ${DIST_DIR}/DESC.in >DESC
+ test -z '${DVIPRINT}' || echo print '${DVIPRINT}' >>DESC
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devhtml/Makefile b/gnu/usr.bin/groff/font/devhtml/Makefile
new file mode 100644
index 0000000..f44b144
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devhtml/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+DEV= html
+FONTS= R I B BI CR S
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devkoi8-r/DESC.proto b/gnu/usr.bin/groff/font/devkoi8-r/DESC.proto
new file mode 100644
index 0000000..041ceba
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devkoi8-r/DESC.proto
@@ -0,0 +1,8 @@
+res 240
+hor 24
+vert 40
+unitwidth 10
+sizes 10 0
+fonts 6 R I B BI S L
+tcommand
+postpro grotty
diff --git a/gnu/usr.bin/groff/font/devkoi8-r/Makefile b/gnu/usr.bin/groff/font/devkoi8-r/Makefile
new file mode 100644
index 0000000..399d2b6
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devkoi8-r/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+DEV= koi8-r
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devkoi8-r/R.proto b/gnu/usr.bin/groff/font/devkoi8-r/R.proto
new file mode 100644
index 0000000..9a26116
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devkoi8-r/R.proto
@@ -0,0 +1,314 @@
+# $FreeBSD$
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0041
+" 24 0 0042
+dq "
+lq "
+rq "
+# 24 0 0043
+sh "
+$ 24 0 0044
+Do "
+% 24 0 0045
+& 24 0 0046
+' 24 0 0047
+aa "
+fm "
+aq "
+cq "
+( 24 0 0050
+) 24 0 0051
+* 24 0 0052
+** "
++ 24 0 0053
+pl "
+, 24 0 0054
+\- 24 0 0055
+hy "
+- "
+mi "
+en "
+. 24 0 0056
+/ 24 0 0057
+sl "
+f/ "
+0 24 0 0060
+1 24 0 0061
+2 24 0 0062
+3 24 0 0063
+4 24 0 0064
+5 24 0 0065
+6 24 0 0066
+7 24 0 0067
+8 24 0 0070
+9 24 0 0071
+: 24 0 0072
+; 24 0 0073
+< 24 0 0074
+la "
+fo "
+= 24 0 0075
+eq "
+> 24 0 0076
+ra "
+fc "
+? 24 0 0077
+@ 24 0 0100
+at "
+A 24 0 0101
+*A "
+B 24 0 0102
+*B "
+C 24 0 0103
+D 24 0 0104
+E 24 0 0105
+*E "
+F 24 0 0106
+G 24 0 0107
+H 24 0 0110
+*Y "
+I 24 0 0111
+*I "
+J 24 0 0112
+K 24 0 0113
+*K "
+L 24 0 0114
+M 24 0 0115
+*M "
+N 24 0 0116
+*N "
+O 24 0 0117
+ci "
+*O "
+P 24 0 0120
+*R "
+Q 24 0 0121
+R 24 0 0122
+S 24 0 0123
+T 24 0 0124
+*T "
+U 24 0 0125
+V 24 0 0126
+W 24 0 0127
+X 24 0 0130
+*X "
+Y 24 0 0131
+*U "
+Z 24 0 0132
+*Z "
+[ 24 0 0133
+lB "
+\ 24 0 0134
+rs "
+] 24 0 0135
+rB "
+a^ 24 0 0136
+^ "
+ha "
+_ 24 0 0137
+ru "
+ul "
+` 24 0 0140
+oq "
+ga "
+a 24 0 0141
+b 24 0 0142
+c 24 0 0143
+d 24 0 0144
+e 24 0 0145
+f 24 0 0146
+g 24 0 0147
+h 24 0 0150
+i 24 0 0151
+.i "
+j 24 0 0152
+k 24 0 0153
+l 24 0 0154
+m 24 0 0155
+n 24 0 0156
+o 24 0 0157
+*o "
+p 24 0 0160
+q 24 0 0161
+r 24 0 0162
+s 24 0 0163
+t 24 0 0164
+u 24 0 0165
+v 24 0 0166
+w 24 0 0167
+x 24 0 0170
+mu "
+y 24 0 0171
+z 24 0 0172
+lC 24 0 0173
+{ "
+ba 24 0 0174
+or "
+bv "
+br "
+| "
+lb "
+lc "
+lf "
+lk "
+lt "
+rb "
+rc "
+rf "
+rk "
+rt "
+rC 24 0 0175
+} "
+a~ 24 0 0176
+~ "
+ap "
+ti "
+char128 24 0 0200
+char129 24 0 0201
+char130 24 0 0202
+char131 24 0 0203
+char132 24 0 0204
+char133 24 0 0205
+char134 24 0 0206
+char135 24 0 0207
+char136 24 0 0210
+char137 24 0 0211
+char138 24 0 0212
+char139 24 0 0213
+char140 24 0 0214
+char141 24 0 0215
+char142 24 0 0216
+char143 24 0 0217
+char144 24 0 0220
+char145 24 0 0221
+char146 24 0 0222
+char147 24 0 0223
+char148 24 0 0224
+bu 24 0 0225
+char149 "
+sr 24 0 0226
+char150 "
+~~ 24 0 0227
+~= "
+char151 "
+<= 24 0 0230
+char152 "
+>= 24 0 0231
+char153 "
+char154 24 0 0232
+char155 24 0 0233
+de 24 0 0234
+char156 "
+S2 24 0 0235
+char157 "
+pc 24 0 0236
+char158 "
+di 24 0 0237
+char159 "
+char160 24 0 0240
+char161 24 0 0241
+char162 24 0 0242
+:e 24 0 0243
+char163 "
+char164 24 0 0244
+char165 24 0 0245
+char166 24 0 0246
+char167 24 0 0247
+char168 24 0 0250
+char169 24 0 0251
+char170 24 0 0252
+char171 24 0 0253
+char172 24 0 0254
+char173 24 0 0255
+char174 24 0 0256
+char175 24 0 0257
+char176 24 0 0260
+char177 24 0 0261
+char178 24 0 0262
+:E 24 0 0263
+char179 "
+char180 24 0 0264
+char181 24 0 0265
+char182 24 0 0266
+char183 24 0 0267
+char184 24 0 0270
+char185 24 0 0271
+char186 24 0 0272
+char187 24 0 0273
+char188 24 0 0274
+char189 24 0 0275
+char190 24 0 0276
+co 24 0 0277
+char191 "
+char192 24 0 0300
+char193 24 0 0301
+char194 24 0 0302
+char195 24 0 0303
+char196 24 0 0304
+char197 24 0 0305
+*f 24 0 0306
+char198 "
+char199 24 0 0307
+char200 24 0 0310
+char201 24 0 0311
+char202 24 0 0312
+char203 24 0 0313
+char204 24 0 0314
+char205 24 0 0315
+char206 24 0 0316
+char207 24 0 0317
+*p 24 0 0320
+char208 "
+char209 24 0 0321
+char210 24 0 0322
+char211 24 0 0323
+char212 24 0 0324
+char213 24 0 0325
+char214 24 0 0326
+char215 24 0 0327
+char216 24 0 0330
+char217 24 0 0331
+char218 24 0 0332
+char219 24 0 0333
+char220 24 0 0334
+char221 24 0 0335
+char222 24 0 0336
+char223 24 0 0337
+char224 24 0 0340
+char225 24 0 0341
+char226 24 0 0342
+char227 24 0 0343
+char228 24 0 0344
+char229 24 0 0345
+*F 24 0 0346
+char230 "
+*G 24 0 0347
+char231 "
+char232 24 0 0350
+char233 24 0 0351
+char234 24 0 0352
+char235 24 0 0353
+char236 24 0 0354
+char237 24 0 0355
+char238 24 0 0356
+char239 24 0 0357
+*P 24 0 0360
+char240 "
+char241 24 0 0361
+char242 24 0 0362
+char243 24 0 0363
+char244 24 0 0364
+char245 24 0 0365
+char246 24 0 0366
+char247 24 0 0367
+char248 24 0 0370
+char249 24 0 0371
+char250 24 0 0372
+char251 24 0 0373
+char252 24 0 0374
+char253 24 0 0375
+char254 24 0 0376
+char255 24 0 0377
diff --git a/gnu/usr.bin/groff/font/devlatin1/Makefile b/gnu/usr.bin/groff/font/devlatin1/Makefile
new file mode 100644
index 0000000..2383202
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devlatin1/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+DEV= latin1
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devlbp/Makefile b/gnu/usr.bin/groff/font/devlbp/Makefile
new file mode 100644
index 0000000..4ea437e
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devlbp/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+DEV= lbp
+LBPPRINT= ${PSPRINT}
+DEVFILES= DESC HB HBI HI HR TB TBI TI TR
+
+CLEANFILES+= DESC
+
+DESC: DESC.in
+ cat ${.ALLSRC} >${.TARGET}
+ if test "${PAGE}" = A4; then \
+ echo "papersize a4" >>${.TARGET}; \
+ else \
+ echo "papersize letter" >>${.TARGET}; \
+ fi
+ test -z '${LBPPRINT}' || echo print '${LBPPRINT}' >>${.TARGET}
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devlj4/Makefile b/gnu/usr.bin/groff/font/devlj4/Makefile
new file mode 100644
index 0000000..504677c
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devlj4/Makefile
@@ -0,0 +1,25 @@
+# $FreeBSD$
+
+DEV= lj4
+LJ4RES= 600
+LJ4PRINT= ${PSPRINT}
+DEVFILES= DESC \
+ ALBB ALBR AOB AOI AOR CB CBI CI CR GB GBI GI GR \
+ LGB LGI LGR OB OBI OI OR TB TBI TI TR UB UBI UI UR \
+ UCB UCBI UCI UCR CLARENDON CORONET MARIGOLD S \
+ generate/Makefile generate/text.map generate/special.map
+
+CLEANFILES+= DESC
+
+DESC: DESC.in
+ echo "res ${LJ4RES}" >${.TARGET}
+ echo "unitwidth `expr 7620000 / ${LJ4RES}`" >>${.TARGET}
+ cat ${.ALLSRC} >>${.TARGET}
+ if test "${PAGE}" = A4; then \
+ echo "papersize a4" >>${.TARGET}; \
+ else \
+ echo "papersize letter" >>${.TARGET}; \
+ fi
+ test -z '${LJ4PRINT}' || echo print '${LJ4PRINT}' >>${.TARGET}
+
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/font/devps/Makefile b/gnu/usr.bin/groff/font/devps/Makefile
new file mode 100644
index 0000000..0383d01
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devps/Makefile
@@ -0,0 +1,35 @@
+# $FreeBSD$
+
+DEV= ps
+DISTFILES= text.enc download \
+ S ZD ZDR SS AB ABI AI AR BMB BMBI BMI BMR \
+ CB CBI CI CR HB HBI HI HR HNB HNBI HNI HNR \
+ NB NBI NI NR PB PBI PI PR TB TBI TI TR ZCMI
+PSFILES= prologue symbolsl.pfa zapfdr.pfa
+DEVGENFILES= generate/Makefile generate/afmname generate/dingbats.map \
+ generate/dingbats.rmap generate/lgreekmap generate/symbol.sed \
+ generate/symbolchars generate/symbolsl.afm generate/textmap
+DEVFILES= DESC ${PSFILES} ${DISTFILES} ${DEVGENFILES}
+
+CLEANFILES+= DESC ${PSFILES}
+
+DESC: DESC.in
+ -rm -f DESC
+ cat ${DIST_DIR}/DESC.in >DESC
+ echo broken ${BROKEN_SPOOLER_FLAGS} >>DESC
+ if test "${PAGE}" = A4; then \
+ echo "paperlength 841890" >>DESC; \
+ else \
+ echo "paperlength 792000" >>DESC; \
+ fi
+ test -z '${PSPRINT}' || echo print '${PSPRINT}' >>DESC
+
+${PSFILES}:
+ -rm -f $@
+ sed -f ${DIST_DIR}/psstrip.sed $? >$@
+
+.include "../Makefile.dev"
+
+prologue: ${DIST_DIR}/prologue.ps
+zapfdr.pfa: ${DIST_DIR}/zapfdr.ps
+symbolsl.pfa: ${DIST_DIR}/symbolsl.ps
diff --git a/gnu/usr.bin/groff/font/devutf8/Makefile b/gnu/usr.bin/groff/font/devutf8/Makefile
new file mode 100644
index 0000000..bf5965e
--- /dev/null
+++ b/gnu/usr.bin/groff/font/devutf8/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+DEV= utf8
+
+.include "../Makefile.tty"
+.include "../Makefile.dev"
diff --git a/gnu/usr.bin/groff/man/Makefile b/gnu/usr.bin/groff/man/Makefile
new file mode 100644
index 0000000..9937f57
--- /dev/null
+++ b/gnu/usr.bin/groff/man/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+MAN= groff_font.5 groff_out.5
+MAN+= groff.7 groff_char.7 roff.7
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/Makefile b/gnu/usr.bin/groff/src/Makefile
new file mode 100644
index 0000000..7d2ca90
--- /dev/null
+++ b/gnu/usr.bin/groff/src/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= libs devices preproc roff utils
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/src/devices/Makefile b/gnu/usr.bin/groff/src/devices/Makefile
new file mode 100644
index 0000000..8af4ff8
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= grodvi grohtml grolbp grolj4 grops grotty
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/src/devices/Makefile.inc b/gnu/usr.bin/groff/src/devices/Makefile.inc
new file mode 100644
index 0000000..4619cbe
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+TOPREL= ../../..
+DIST_SUBDIR= src/devices/${.CURDIR:T}
+
+.include "../../Makefile.inc"
diff --git a/gnu/usr.bin/groff/src/devices/grodvi/Makefile b/gnu/usr.bin/groff/src/devices/grodvi/Makefile
new file mode 100644
index 0000000..9912a02
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/grodvi/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= grodvi
+SRCS= dvi.cc
+DPADD= ${LIBDRIVER} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBDRIVER} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/devices/grohtml/Makefile b/gnu/usr.bin/groff/src/devices/grohtml/Makefile
new file mode 100644
index 0000000..01b1aa1
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/grohtml/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= post-grohtml
+SRCS= post-html.cc html-text.cc output.cc
+DPADD= ${LIBDRIVER} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBDRIVER} ${LIBGROFF} -lm
+NOMAN= YES
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/devices/grolbp/Makefile b/gnu/usr.bin/groff/src/devices/grolbp/Makefile
new file mode 100644
index 0000000..64bcbad
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/grolbp/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= grolbp
+SRCS= lbp.cc
+DPADD= ${LIBDRIVER} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBDRIVER} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/devices/grolj4/Makefile b/gnu/usr.bin/groff/src/devices/grolj4/Makefile
new file mode 100644
index 0000000..13027f0
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/grolj4/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= grolj4
+SRCS= lj4.cc
+DPADD= ${LIBDRIVER} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBDRIVER} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/devices/grops/Makefile b/gnu/usr.bin/groff/src/devices/grops/Makefile
new file mode 100644
index 0000000..479898e
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/grops/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= grops
+SRCS= ps.cc psrm.cc
+DPADD= ${LIBDRIVER} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBDRIVER} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/devices/grotty/Makefile b/gnu/usr.bin/groff/src/devices/grotty/Makefile
new file mode 100644
index 0000000..15728bb
--- /dev/null
+++ b/gnu/usr.bin/groff/src/devices/grotty/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= grotty
+SRCS= tty.cc
+DPADD= ${LIBDRIVER} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBDRIVER} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/include/defs.h b/gnu/usr.bin/groff/src/include/defs.h
new file mode 100644
index 0000000..76bd117
--- /dev/null
+++ b/gnu/usr.bin/groff/src/include/defs.h
@@ -0,0 +1,12 @@
+/* $FreeBSD$ */
+
+#define PROG_PREFIX ""
+#define DEVICE "ps"
+#define BINPATH "/usr/bin"
+#define FONTPATH "/usr/share/groff_font"
+#define MACROPATH "/usr/share/tmac"
+#define INDEX_SUFFIX ".i"
+#define COMMON_WORDS_FILE "/usr/share/dict/eign"
+#define DEFAULT_INDEX_DIR "/usr/share/dict/papers"
+#define DEFAULT_INDEX_NAME "Ind"
+#define DEFAULT_INDEX "/usr/share/dict/papers/Ind"
diff --git a/gnu/usr.bin/groff/src/libs/Makefile b/gnu/usr.bin/groff/src/libs/Makefile
new file mode 100644
index 0000000..1461cda
--- /dev/null
+++ b/gnu/usr.bin/groff/src/libs/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= libgroff libdriver libbib
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/src/libs/Makefile.inc b/gnu/usr.bin/groff/src/libs/Makefile.inc
new file mode 100644
index 0000000..627553f
--- /dev/null
+++ b/gnu/usr.bin/groff/src/libs/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+TOPREL= ../../..
+DIST_SUBDIR= src/libs/${.CURDIR:T}
+
+.include "../../Makefile.inc"
diff --git a/gnu/usr.bin/groff/src/libs/libbib/Makefile b/gnu/usr.bin/groff/src/libs/libbib/Makefile
new file mode 100644
index 0000000..a4d3f23
--- /dev/null
+++ b/gnu/usr.bin/groff/src/libs/libbib/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+LIB= bib
+INTERNALLIB= YES
+SRCS= common.cc index.cc linear.cc search.cc map.c
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/groff/src/libs/libdriver/Makefile b/gnu/usr.bin/groff/src/libs/libdriver/Makefile
new file mode 100644
index 0000000..6eab241
--- /dev/null
+++ b/gnu/usr.bin/groff/src/libs/libdriver/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+LIB= driver
+INTERNALLIB= YES
+SRCS= input.cc printer.cc
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/groff/src/libs/libgroff/Makefile b/gnu/usr.bin/groff/src/libs/libgroff/Makefile
new file mode 100644
index 0000000..d309f19
--- /dev/null
+++ b/gnu/usr.bin/groff/src/libs/libgroff/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+LIB= groff
+INTERNALLIB= YES
+SRCS= assert.cc change_lf.cc cmap.cc cset.cc device.cc errarg.cc\
+ error.cc fatal.cc filename.cc font.cc fontfile.cc\
+ htmlindicate.cc lf.cc lineno.cc macropath.cc\
+ maxfilename.cc nametoindex.cc new.cc prime.cc\
+ progname.cc ptable.cc searchpath.cc string.cc strsave.cc\
+ tmpfile.cc illegal.cc version.cc
+SRCS+= getopt.c getopt1.c iftoa.c itoa.c matherr.c
+CLEANFILES= version.cc
+
+.include <bsd.lib.mk>
+
+version.cc: ${GROFF_DIST}/VERSION ${GROFF_DIST}/REVISION
+ @${ECHO} Making version.cc
+ @echo const char \*version_string = \"`cat ${GROFF_DIST}/VERSION`\"\; >$@
+ @echo const char \*revision_string = \"`cat ${GROFF_DIST}/REVISION`\"\; >>$@
+ @echo extern \"C\" const char \*Version_string = \"`cat ${GROFF_DIST}/VERSION`.`cat ${GROFF_DIST}/REVISION`\"\; | \
+ sed -e 's/\.0\"/\"/' >>$@
diff --git a/gnu/usr.bin/groff/src/preproc/Makefile b/gnu/usr.bin/groff/src/preproc/Makefile
new file mode 100644
index 0000000..680399c
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+SUBDIR= eqn grn html pic refer tbl
+
+# BSD already provides soelim(1)
+MISC= soelim
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/src/preproc/Makefile.inc b/gnu/usr.bin/groff/src/preproc/Makefile.inc
new file mode 100644
index 0000000..16c104a
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+TOPREL= ../../..
+DIST_SUBDIR= src/preproc/${.CURDIR:T}
+
+.include "../../Makefile.inc"
diff --git a/gnu/usr.bin/groff/src/preproc/eqn/Makefile b/gnu/usr.bin/groff/src/preproc/eqn/Makefile
new file mode 100644
index 0000000..fdae39f
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/eqn/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+PROG_CXX= eqn
+SRCS= eqn.cc eqn_tab.h main.cc lex.cc \
+ box.cc limit.cc list.cc over.cc text.cc \
+ script.cc mark.cc other.cc delim.cc sqrt.cc pile.cc special.cc
+CFLAGS+= -I${DIST_DIR} -I.
+DPADD= ${LIBGROFF}
+LDADD= ${LIBGROFF}
+SCRIPTS= neqn
+MAN= eqn.1 neqn.1
+CLEANFILES= eqn.cc eqn_tab.h ${SCRIPTS} ${MAN} y.tab.c y.tab.h
+
+eqn_tab.h: eqn.cc
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/preproc/grn/Makefile b/gnu/usr.bin/groff/src/preproc/grn/Makefile
new file mode 100644
index 0000000..2360254
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/grn/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= grn
+SRCS= hdb.cc hpoint.cc hgraph.cc main.cc
+DPADD= ${LIBGROFF} ${LIBM}
+LDADD= ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/preproc/html/Makefile b/gnu/usr.bin/groff/src/preproc/html/Makefile
new file mode 100644
index 0000000..2667405
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/html/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= pre-grohtml
+SRCS= pre-html.cc pushbackbuffer.cc
+DPADD= ${LIBGROFF}
+LDADD= ${LIBGROFF}
+NOMAN= YES
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/preproc/pic/Makefile b/gnu/usr.bin/groff/src/preproc/pic/Makefile
new file mode 100644
index 0000000..389016c
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/pic/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+PROG_CXX= pic
+SRCS= lex.cc main.cc object.cc pic.cc pic_tab.h \
+ common.cc troff.cc tex.cc
+CFLAGS+= -I${DIST_DIR} -I.
+DPADD= ${LIBGROFF} ${LIBM}
+LDADD= ${LIBGROFF} -lm
+CLEANFILES= ${MAN} pic.cc pic_tab.h y.tab.c y.tab.h
+
+pic_tab.h: pic.cc
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/preproc/refer/Makefile b/gnu/usr.bin/groff/src/preproc/refer/Makefile
new file mode 100644
index 0000000..0fc9f30
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/refer/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG_CXX= refer
+SRCS= command.cc label.cc ref.cc refer.cc token.cc
+CFLAGS+= -I${DIST_DIR}
+DPADD= ${LIBBIB} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBBIB} ${LIBGROFF} -lm
+CLEANFILES= label.cc label_tab.h ${MAN} y.tab.c y.tab.h
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/preproc/soelim/Makefile b/gnu/usr.bin/groff/src/preproc/soelim/Makefile
new file mode 100644
index 0000000..443d066
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/soelim/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+PROG_CXX= soelim
+DPADD= ${LIBGROFF}
+LDADD= ${LIBGROFF}
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/preproc/tbl/Makefile b/gnu/usr.bin/groff/src/preproc/tbl/Makefile
new file mode 100644
index 0000000..bc29521
--- /dev/null
+++ b/gnu/usr.bin/groff/src/preproc/tbl/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= tbl
+SRCS= main.cc table.cc
+DPADD= ${LIBGROFF} ${LIBM}
+LDADD= ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/roff/Makefile b/gnu/usr.bin/groff/src/roff/Makefile
new file mode 100644
index 0000000..543a990
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= groff grog nroff psroff troff
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/src/roff/Makefile.inc b/gnu/usr.bin/groff/src/roff/Makefile.inc
new file mode 100644
index 0000000..f893659
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+TOPREL= ../../..
+DIST_SUBDIR= src/roff/${.CURDIR:T}
+
+.include "../../Makefile.inc"
diff --git a/gnu/usr.bin/groff/src/roff/groff/Makefile b/gnu/usr.bin/groff/src/roff/groff/Makefile
new file mode 100644
index 0000000..d057d50
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/groff/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= groff
+SRCS= groff.cc pipeline.c
+DPADD= ${LIBGROFF} ${LIBM}
+LDADD= ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/roff/grog/Makefile b/gnu/usr.bin/groff/src/roff/grog/Makefile
new file mode 100644
index 0000000..718f0cf
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/grog/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SCRIPTS= grog
+MAN= grog.1
+CLEANFILES= ${SCRIPTS} ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/roff/nroff/Makefile b/gnu/usr.bin/groff/src/roff/nroff/Makefile
new file mode 100644
index 0000000..6971890
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/nroff/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SCRIPTS= nroff
+MAN= nroff.1
+CLEANFILES= ${SCRIPTS} ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/roff/psroff/Makefile b/gnu/usr.bin/groff/src/roff/psroff/Makefile
new file mode 100644
index 0000000..74bb4ad
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/psroff/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SCRIPTS= psroff.sh
+MAN= psroff.1
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/roff/psroff/psroff.1 b/gnu/usr.bin/groff/src/roff/psroff/psroff.1
new file mode 100644
index 0000000..e2291ba
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/psroff/psroff.1
@@ -0,0 +1,46 @@
+.\" Copyright (c) 1997 Wolfram Schneider <wosch@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd September 15, 1997
+.Dt PSROFF 1
+.Os
+.Sh NAME
+.Nm psroff
+.Nd "send troff to PostScript printer"
+.Sh SYNOPSIS
+.Nm
+.Op Ar "groff options"
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+program is actually just a shell script which invokes the
+.Xr groff 1
+command to print the troff files to a PostScript printer.
+.Sh SEE ALSO
+.Xr groff 1 ,
+.Xr lpr 1 ,
+.Xr vgrind 1 ,
+.Xr environ 7
diff --git a/gnu/usr.bin/groff/src/roff/psroff/psroff.sh b/gnu/usr.bin/groff/src/roff/psroff/psroff.sh
new file mode 100644
index 0000000..612fbcc
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/psroff/psroff.sh
@@ -0,0 +1,5 @@
+#! /bin/sh -
+#
+# $FreeBSD$
+
+exec groff -Tps -l -C ${1+"$@"}
diff --git a/gnu/usr.bin/groff/src/roff/troff/Makefile b/gnu/usr.bin/groff/src/roff/troff/Makefile
new file mode 100644
index 0000000..7b31e7d
--- /dev/null
+++ b/gnu/usr.bin/groff/src/roff/troff/Makefile
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+PROG_CXX= troff
+SRCS= env.cc node.cc input.cc div.cc symbol.cc dictionary.cc reg.cc \
+ number.cc majorminor.cc
+DPADD= ${LIBGROFF} ${LIBM}
+LDADD= ${LIBGROFF} -lm
+CLEANFILES= majorminor.cc ${MAN}
+
+.include <bsd.prog.mk>
+
+majorminor.cc: ${GROFF_DIST}/VERSION ${GROFF_DIST}/REVISION
+ @${ECHO} Making $@
+ @-rm -f $@
+ @echo const char \*major_version = \
+ \"`sed -e 's/^\([^.]*\)\..*$$/\1/' ${GROFF_DIST}/VERSION`\"\; >$@
+ @echo const char \*minor_version = \
+ \"`sed -e 's/^[^.]*\.\([0-9]*\).*$$/\1/' ${GROFF_DIST}/VERSION`\"\; >>$@
+ @echo const char \*revision = \"`cat ${GROFF_DIST}/REVISION`\"\; >>$@
diff --git a/gnu/usr.bin/groff/src/utils/Makefile b/gnu/usr.bin/groff/src/utils/Makefile
new file mode 100644
index 0000000..14953b9
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= addftinfo afmtodit hpftodit indxbib lkbib lookbib pfbtops tfmtodit
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/groff/src/utils/Makefile.inc b/gnu/usr.bin/groff/src/utils/Makefile.inc
new file mode 100644
index 0000000..68945ab
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+TOPREL= ../../..
+DIST_SUBDIR= src/utils/${.CURDIR:T}
+
+.include "../../Makefile.inc"
diff --git a/gnu/usr.bin/groff/src/utils/addftinfo/Makefile b/gnu/usr.bin/groff/src/utils/addftinfo/Makefile
new file mode 100644
index 0000000..164c7b3
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/addftinfo/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= addftinfo
+SRCS= addftinfo.cc guess.cc
+DPADD= ${LIBGROFF}
+LDADD= ${LIBGROFF}
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/utils/afmtodit/Makefile b/gnu/usr.bin/groff/src/utils/afmtodit/Makefile
new file mode 100644
index 0000000..00f88ad
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/afmtodit/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SCRIPTS= afmtodit
+MAN= afmtodit.1
+CLEANFILES= ${SCRIPTS} ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/utils/hpftodit/Makefile b/gnu/usr.bin/groff/src/utils/hpftodit/Makefile
new file mode 100644
index 0000000..f45bd17
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/hpftodit/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= hpftodit
+SRCS= hpftodit.cc
+DPADD= ${LIBGROFF} ${LIBM}
+LDADD= ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/utils/indxbib/Makefile b/gnu/usr.bin/groff/src/utils/indxbib/Makefile
new file mode 100644
index 0000000..eae694a
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/indxbib/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+PROG_CXX= indxbib
+SRCS= indxbib.cc signal.c
+DPADD= ${LIBBIB} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBBIB} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+beforeinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${NOBINMODE} \
+ ${DIST_DIR}/eign ${DESTDIR}${SHAREDIR}/dict/
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/utils/lkbib/Makefile b/gnu/usr.bin/groff/src/utils/lkbib/Makefile
new file mode 100644
index 0000000..d588dfa2
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/lkbib/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= lkbib
+SRCS= lkbib.cc
+DPADD= ${LIBBIB} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBBIB} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/utils/lookbib/Makefile b/gnu/usr.bin/groff/src/utils/lookbib/Makefile
new file mode 100644
index 0000000..525a66e
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/lookbib/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= lookbib
+SRCS= lookbib.cc
+DPADD= ${LIBBIB} ${LIBGROFF} ${LIBM}
+LDADD= ${LIBBIB} ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/utils/pfbtops/Makefile b/gnu/usr.bin/groff/src/utils/pfbtops/Makefile
new file mode 100644
index 0000000..4fa71b5
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/pfbtops/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+PROG= pfbtops
+DPADD= ${LIBGROFF}
+LDADD= ${LIBGROFF}
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/src/utils/tfmtodit/Makefile b/gnu/usr.bin/groff/src/utils/tfmtodit/Makefile
new file mode 100644
index 0000000..cc8333d
--- /dev/null
+++ b/gnu/usr.bin/groff/src/utils/tfmtodit/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+PROG_CXX= tfmtodit
+SRCS= tfmtodit.cc
+DPADD= ${LIBGROFF} ${LIBM}
+LDADD= ${LIBGROFF} -lm
+CLEANFILES= ${MAN}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/tmac/Makefile b/gnu/usr.bin/groff/tmac/Makefile
new file mode 100644
index 0000000..c384ed3
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/Makefile
@@ -0,0 +1,75 @@
+# $FreeBSD$
+
+TMACOWN?= ${BINOWN}
+TMACGRP?= ${BINGRP}
+TMACMODE?= ${NOBINMODE}
+TMACDIR?= ${SHAREDIR}/tmac
+MDOCDIR?= ${TMACDIR}/mdoc
+
+MAN= groff_tmac.5
+MLINKS+= groff_tmac.5 tmac.5
+MAN+= groff_ms.7 groff_man.7 groff_me.7 groff_mdoc.7 groff_mwww.7
+MLINKS+= groff_ms.7 ms.7
+MLINKS+= groff_man.7 man.7
+MLINKS+= groff_me.7 me.7
+MLINKS+= groff_mdoc.7 mdoc.7 groff_mdoc.7 mdoc.samples.7
+MLINKS+= groff_mwww.7 mwww.7
+
+CLEANFILES= ${MAN} ${MDOCFILES:S/$/-s/} ${STRIPFILES:S/$/-s/} ${SPECIALFILES:S/$/-s/}
+
+NORMALFILES= mandoc.tmac andoc.tmac an-old.tmac \
+ me.tmac \
+ mdoc.tmac \
+ pic.tmac \
+ a4.tmac \
+ safer.tmac \
+ trace.tmac \
+ ps.tmac psold.tmac pspic.tmac psatk.tmac \
+ dvi.tmac \
+ tty.tmac tty-char.tmac latin1.tmac \
+ X.tmac Xps.tmac \
+ lj4.tmac \
+ html.tmac mwww.tmac www.tmac \
+ eqnrc \
+ troffrc troffrc-end \
+ hyphen.us
+SPECIALFILES= an.tmac man.tmac s.tmac ms.tmac
+STRIPFILES= e.tmac doc.tmac mdoc.local
+MDOCFILES= doc-common doc-ditroff doc-nroff doc-syms koi8-r
+
+all: ${MDOCFILES:S/$/-s/} ${STRIPFILES:S/$/-s/} ${SPECIALFILES:S/$/-s/}
+
+.for f in ${MDOCFILES} ${STRIPFILES}
+$f-s: $f
+ sed -f ${DIST_DIR}/strip.sed ${.ALLSRC} > ${.TARGET}
+.endfor
+
+.for f in ${SPECIALFILES}
+$f-s: $f
+ sed -e "s;@TMAC_AN_PREFIX@;${tmac_an_prefix};g" \
+ -e "s;@TMAC_S_PREFIX@;${tmac_s_prefix};g" \
+ ${.ALLSRC} > ${.TARGET}
+.endfor
+
+beforeinstall:
+ cd ${DIST_DIR}; \
+ ${INSTALL} -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ ${NORMALFILES} ${DESTDIR}${TMACDIR}
+ cd ${.CURDIR}; \
+ ${INSTALL} ${COPY} -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ hyphen.us-ru ${DESTDIR}${TMACDIR}
+ cd ${.OBJDIR}
+.for f in ${STRIPFILES} ${SPECIALFILES}
+ ${INSTALL} ${COPY} -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ $f-s ${DESTDIR}${TMACDIR}/$f
+.endfor
+.for f in ${MDOCFILES}
+ ${INSTALL} ${COPY} -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ $f-s ${DESTDIR}${MDOCDIR}/$f
+.endfor
+.if !exists(${DESTDIR}${TMACDIR}/man.local)
+ ${INSTALL} -c -o ${TMACOWN} -g ${TMACGRP} -m ${TMACMODE} \
+ ${DIST_DIR}/man.local ${DESTDIR}${TMACDIR}
+.endif
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/groff/tmac/hyphen.us-ru b/gnu/usr.bin/groff/tmac/hyphen.us-ru
new file mode 100644
index 0000000..3ccef48
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/hyphen.us-ru
@@ -0,0 +1,4833 @@
+% Hyphenation patterns for US English and Russian (koi8-r).
+% These are the standard Plain TeX hyphenation patterns (in hyphen.tex).
+.ach4
+.ad4der
+.af1t
+.al3t
+.am5at
+.an5c
+.ang4
+.ani5m
+.ant4
+.an3te
+.anti5s
+.ar5s
+.ar4tie
+.ar4ty
+.as3c
+.as1p
+.as1s
+.aster5
+.atom5
+.au1d
+.av4i
+.awn4
+.ba4g
+.ba5na
+.bas4e
+.ber4
+.be5ra
+.be3sm
+.be5sto
+.bri2
+.but4ti
+.cam4pe
+.can5c
+.capa5b
+.car5ol
+.ca4t
+.ce4la
+.ch4
+.chill5i
+.ci2
+.cit5r
+.co3e
+.co4r
+.cor5ner
+.de4moi
+.de3o
+.de3ra
+.de3ri
+.des4c
+.dictio5
+.do4t
+.du4c
+.dumb5
+.earth5
+.eas3i
+.eb4
+.eer4
+.eg2
+.el5d
+.el3em
+.enam3
+.en3g
+.en3s
+.eq5ui5t
+.er4ri
+.es3
+.eu3
+.eye5
+.fes3
+.for5mer
+.ga2
+.ge2
+.gen3t4
+.ge5og
+.gi5a
+.gi4b
+.go4r
+.hand5i
+.han5k
+.he2
+.hero5i
+.hes3
+.het3
+.hi3b
+.hi3er
+.hon5ey
+.hon3o
+.hov5
+.id4l
+.idol3
+.im3m
+.im5pin
+.in1
+.in3ci
+.ine2
+.in2k
+.in3s
+.ir5r
+.is4i
+.ju3r
+.la4cy
+.la4m
+.lat5er
+.lath5
+.le2
+.leg5e
+.len4
+.lep5
+.lev1
+.li4g
+.lig5a
+.li2n
+.li3o
+.li4t
+.mag5a5
+.mal5o
+.man5a
+.mar5ti
+.me2
+.mer3c
+.me5ter
+.mis1
+.mist5i
+.mon3e
+.mo3ro
+.mu5ta
+.muta5b
+.ni4c
+.od2
+.odd5
+.of5te
+.or5ato
+.or3c
+.or1d
+.or3t
+.os3
+.os4tl
+.oth3
+.out3
+.ped5al
+.pe5te
+.pe5tit
+.pi4e
+.pio5n
+.pi2t
+.pre3m
+.ra4c
+.ran4t
+.ratio5na
+.ree2
+.re5mit
+.res2
+.re5stat
+.ri4g
+.rit5u
+.ro4q
+.ros5t
+.row5d
+.ru4d
+.sci3e
+.self5
+.sell5
+.se2n
+.se5rie
+.sh2
+.si2
+.sing4
+.st4
+.sta5bl
+.sy2
+.ta4
+.te4
+.ten5an
+.th2
+.ti2
+.til4
+.tim5o5
+.ting4
+.tin5k
+.ton4a
+.to4p
+.top5i
+.tou5s
+.trib5ut
+.un1a
+.un3ce
+.under5
+.un1e
+.un5k
+.un5o
+.un3u
+.up3
+.ure3
+.us5a
+.ven4de
+.ve5ra
+.wil5i
+.ye4
+4ab.
+a5bal
+a5ban
+abe2
+ab5erd
+abi5a
+ab5it5ab
+ab5lat
+ab5o5liz
+4abr
+ab5rog
+ab3ul
+a4car
+ac5ard
+ac5aro
+a5ceou
+ac1er
+a5chet
+4a2ci
+a3cie
+ac1in
+a3cio
+ac5rob
+act5if
+ac3ul
+ac4um
+a2d
+ad4din
+ad5er.
+2adi
+a3dia
+ad3ica
+adi4er
+a3dio
+a3dit
+a5diu
+ad4le
+ad3ow
+ad5ran
+ad4su
+4adu
+a3duc
+ad5um
+ae4r
+aeri4e
+a2f
+aff4
+a4gab
+aga4n
+ag5ell
+age4o
+4ageu
+ag1i
+4ag4l
+ag1n
+a2go
+3agog
+ag3oni
+a5guer
+ag5ul
+a4gy
+a3ha
+a3he
+ah4l
+a3ho
+ai2
+a5ia
+a3ic.
+ai5ly
+a4i4n
+ain5in
+ain5o
+ait5en
+a1j
+ak1en
+al5ab
+al3ad
+a4lar
+4aldi
+2ale
+al3end
+a4lenti
+a5le5o
+al1i
+al4ia.
+ali4e
+al5lev
+4allic
+4alm
+a5log.
+a4ly.
+4alys
+5a5lyst
+5alyt
+3alyz
+4ama
+am5ab
+am3ag
+ama5ra
+am5asc
+a4matis
+a4m5ato
+am5era
+am3ic
+am5if
+am5ily
+am1in
+ami4no
+a2mo
+a5mon
+amor5i
+amp5en
+a2n
+an3age
+3analy
+a3nar
+an3arc
+anar4i
+a3nati
+4and
+ande4s
+an3dis
+an1dl
+an4dow
+a5nee
+a3nen
+an5est.
+a3neu
+2ang
+ang5ie
+an1gl
+a4n1ic
+a3nies
+an3i3f
+an4ime
+a5nimi
+a5nine
+an3io
+a3nip
+an3ish
+an3it
+a3niu
+an4kli
+5anniz
+ano4
+an5ot
+anoth5
+an2sa
+an4sco
+an4sn
+an2sp
+ans3po
+an4st
+an4sur
+antal4
+an4tie
+4anto
+an2tr
+an4tw
+an3ua
+an3ul
+a5nur
+4ao
+apar4
+ap5at
+ap5ero
+a3pher
+4aphi
+a4pilla
+ap5illar
+ap3in
+ap3ita
+a3pitu
+a2pl
+apoc5
+ap5ola
+apor5i
+apos3t
+aps5es
+a3pu
+aque5
+2a2r
+ar3act
+a5rade
+ar5adis
+ar3al
+a5ramete
+aran4g
+ara3p
+ar4at
+a5ratio
+ar5ativ
+a5rau
+ar5av4
+araw4
+arbal4
+ar4chan
+ar5dine
+ar4dr
+ar5eas
+a3ree
+ar3ent
+a5ress
+ar4fi
+ar4fl
+ar1i
+ar5ial
+ar3ian
+a3riet
+ar4im
+ar5inat
+ar3io
+ar2iz
+ar2mi
+ar5o5d
+a5roni
+a3roo
+ar2p
+ar3q
+arre4
+ar4sa
+ar2sh
+4as.
+as4ab
+as3ant
+ashi4
+a5sia.
+a3sib
+a3sic
+5a5si4t
+ask3i
+as4l
+a4soc
+as5ph
+as4sh
+as3ten
+as1tr
+asur5a
+a2ta
+at3abl
+at5ac
+at3alo
+at5ap
+ate5c
+at5ech
+at3ego
+at3en.
+at3era
+ater5n
+a5terna
+at3est
+at5ev
+4ath
+ath5em
+a5then
+at4ho
+ath5om
+4ati.
+a5tia
+at5i5b
+at1ic
+at3if
+ation5ar
+at3itu
+a4tog
+a2tom
+at5omiz
+a4top
+a4tos
+a1tr
+at5rop
+at4sk
+at4tag
+at5te
+at4th
+a2tu
+at5ua
+at5ue
+at3ul
+at3ura
+a2ty
+au4b
+augh3
+au3gu
+au4l2
+aun5d
+au3r
+au5sib
+aut5en
+au1th
+a2va
+av3ag
+a5van
+ave4no
+av3era
+av5ern
+av5ery
+av1i
+avi4er
+av3ig
+av5oc
+a1vor
+3away
+aw3i
+aw4ly
+aws4
+ax4ic
+ax4id
+ay5al
+aye4
+ays4
+azi4er
+azz5i
+5ba.
+bad5ger
+ba4ge
+bal1a
+ban5dag
+ban4e
+ban3i
+barbi5
+bari4a
+bas4si
+1bat
+ba4z
+2b1b
+b2be
+b3ber
+bbi4na
+4b1d
+4be.
+beak4
+beat3
+4be2d
+be3da
+be3de
+be3di
+be3gi
+be5gu
+1bel
+be1li
+be3lo
+4be5m
+be5nig
+be5nu
+4bes4
+be3sp
+be5str
+3bet
+bet5iz
+be5tr
+be3tw
+be3w
+be5yo
+2bf
+4b3h
+bi2b
+bi4d
+3bie
+bi5en
+bi4er
+2b3if
+1bil
+bi3liz
+bina5r4
+bin4d
+bi5net
+bi3ogr
+bi5ou
+bi2t
+3bi3tio
+bi3tr
+3bit5ua
+b5itz
+b1j
+bk4
+b2l2
+blath5
+b4le.
+blen4
+5blesp
+b3lis
+b4lo
+blun4t
+4b1m
+4b3n
+bne5g
+3bod
+bod3i
+bo4e
+bol3ic
+bom4bi
+bon4a
+bon5at
+3boo
+5bor.
+4b1ora
+bor5d
+5bore
+5bori
+5bos4
+b5ota
+both5
+bo4to
+bound3
+4bp
+4brit
+broth3
+2b5s2
+bsor4
+2bt
+bt4l
+b4to
+b3tr
+buf4fer
+bu4ga
+bu3li
+bumi4
+bu4n
+bunt4i
+bu3re
+bus5ie
+buss4e
+5bust
+4buta
+3butio
+b5uto
+b1v
+4b5w
+5by.
+bys4
+1ca
+cab3in
+ca1bl
+cach4
+ca5den
+4cag4
+2c5ah
+ca3lat
+cal4la
+call5in
+4calo
+can5d
+can4e
+can4ic
+can5is
+can3iz
+can4ty
+cany4
+ca5per
+car5om
+cast5er
+cas5tig
+4casy
+ca4th
+4cativ
+cav5al
+c3c
+ccha5
+cci4a
+ccompa5
+ccon4
+ccou3t
+2ce.
+4ced.
+4ceden
+3cei
+5cel.
+3cell
+1cen
+3cenc
+2cen4e
+4ceni
+3cent
+3cep
+ce5ram
+4cesa
+3cessi
+ces5si5b
+ces5t
+cet4
+c5e4ta
+cew4
+2ch
+4ch.
+4ch3ab
+5chanic
+ch5a5nis
+che2
+cheap3
+4ched
+che5lo
+3chemi
+ch5ene
+ch3er.
+ch3ers
+4ch1in
+5chine.
+ch5iness
+5chini
+5chio
+3chit
+chi2z
+3cho2
+ch4ti
+1ci
+3cia
+ci2a5b
+cia5r
+ci5c
+4cier
+5cific.
+4cii
+ci4la
+3cili
+2cim
+2cin
+c4ina
+3cinat
+cin3em
+c1ing
+c5ing.
+5cino
+cion4
+4cipe
+ci3ph
+4cipic
+4cista
+4cisti
+2c1it
+cit3iz
+5ciz
+ck1
+ck3i
+1c4l4
+4clar
+c5laratio
+5clare
+cle4m
+4clic
+clim4
+cly4
+c5n
+1co
+co5ag
+coe2
+2cog
+co4gr
+coi4
+co3inc
+col5i
+5colo
+col3or
+com5er
+con4a
+c4one
+con3g
+con5t
+co3pa
+cop3ic
+co4pl
+4corb
+coro3n
+cos4e
+cov1
+cove4
+cow5a
+coz5e
+co5zi
+c1q
+cras5t
+5crat.
+5cratic
+cre3at
+5cred
+4c3reta
+cre4v
+cri2
+cri5f
+c4rin
+cris4
+5criti
+cro4pl
+crop5o
+cros4e
+cru4d
+4c3s2
+2c1t
+cta4b
+ct5ang
+c5tant
+c2te
+c3ter
+c4ticu
+ctim3i
+ctu4r
+c4tw
+cud5
+c4uf
+c4ui
+cu5ity
+5culi
+cul4tis
+3cultu
+cu2ma
+c3ume
+cu4mi
+3cun
+cu3pi
+cu5py
+cur5a4b
+cu5ria
+1cus
+cuss4i
+3c4ut
+cu4tie
+4c5utiv
+4cutr
+1cy
+cze4
+1d2a
+5da.
+2d3a4b
+dach4
+4daf
+2dag
+da2m2
+dan3g
+dard5
+dark5
+4dary
+3dat
+4dativ
+4dato
+5dav4
+dav5e
+5day
+d1b
+d5c
+d1d4
+2de.
+deaf5
+deb5it
+de4bon
+decan4
+de4cil
+de5com
+2d1ed
+4dee.
+de5if
+deli4e
+del5i5q
+de5lo
+d4em
+5dem.
+3demic
+dem5ic.
+de5mil
+de4mons
+demor5
+1den
+de4nar
+de3no
+denti5f
+de3nu
+de1p
+de3pa
+depi4
+de2pu
+d3eq
+d4erh
+5derm
+dern5iz
+der5s
+des2
+d2es.
+de1sc
+de2s5o
+des3ti
+de3str
+de4su
+de1t
+de2to
+de1v
+dev3il
+4dey
+4d1f
+d4ga
+d3ge4t
+dg1i
+d2gy
+d1h2
+5di.
+1d4i3a
+dia5b
+di4cam
+d4ice
+3dict
+3did
+5di3en
+d1if
+di3ge
+di4lato
+d1in
+1dina
+3dine.
+5dini
+di5niz
+1dio
+dio5g
+di4pl
+dir2
+di1re
+dirt5i
+dis1
+5disi
+d4is3t
+d2iti
+1di1v
+d1j
+d5k2
+4d5la
+3dle.
+3dled
+3dles.
+4dless
+2d3lo
+4d5lu
+2dly
+d1m
+4d1n4
+1do
+3do.
+do5de
+5doe
+2d5of
+d4og
+do4la
+doli4
+do5lor
+dom5iz
+do3nat
+doni4
+doo3d
+dop4p
+d4or
+3dos
+4d5out
+do4v
+3dox
+d1p
+1dr
+drag5on
+4drai
+dre4
+drea5r
+5dren
+dri4b
+dril4
+dro4p
+4drow
+5drupli
+4dry
+2d1s2
+ds4p
+d4sw
+d4sy
+d2th
+1du
+d1u1a
+du2c
+d1uca
+duc5er
+4duct.
+4ducts
+du5el
+du4g
+d3ule
+dum4be
+du4n
+4dup
+du4pe
+d1v
+d1w
+d2y
+5dyn
+dy4se
+dys5p
+e1a4b
+e3act
+ead1
+ead5ie
+ea4ge
+ea5ger
+ea4l
+eal5er
+eal3ou
+eam3er
+e5and
+ear3a
+ear4c
+ear5es
+ear4ic
+ear4il
+ear5k
+ear2t
+eart3e
+ea5sp
+e3ass
+east3
+ea2t
+eat5en
+eath3i
+e5atif
+e4a3tu
+ea2v
+eav3en
+eav5i
+eav5o
+2e1b
+e4bel.
+e4bels
+e4ben
+e4bit
+e3br
+e4cad
+ecan5c
+ecca5
+e1ce
+ec5essa
+ec2i
+e4cib
+ec5ificat
+ec5ifie
+ec5ify
+ec3im
+eci4t
+e5cite
+e4clam
+e4clus
+e2col
+e4comm
+e4compe
+e4conc
+e2cor
+ec3ora
+eco5ro
+e1cr
+e4crem
+ec4tan
+ec4te
+e1cu
+e4cul
+ec3ula
+2e2da
+4ed3d
+e4d1er
+ede4s
+4edi
+e3dia
+ed3ib
+ed3ica
+ed3im
+ed1it
+edi5z
+4edo
+e4dol
+edon2
+e4dri
+e4dul
+ed5ulo
+ee2c
+eed3i
+ee2f
+eel3i
+ee4ly
+ee2m
+ee4na
+ee4p1
+ee2s4
+eest4
+ee4ty
+e5ex
+e1f
+e4f3ere
+1eff
+e4fic
+5efici
+efil4
+e3fine
+ef5i5nite
+3efit
+efor5es
+e4fuse.
+4egal
+eger4
+eg5ib
+eg4ic
+eg5ing
+e5git5
+eg5n
+e4go.
+e4gos
+eg1ul
+e5gur
+5egy
+e1h4
+eher4
+ei2
+e5ic
+ei5d
+eig2
+ei5gl
+e3imb
+e3inf
+e1ing
+e5inst
+eir4d
+eit3e
+ei3th
+e5ity
+e1j
+e4jud
+ej5udi
+eki4n
+ek4la
+e1la
+e4la.
+e4lac
+elan4d
+el5ativ
+e4law
+elaxa4
+e3lea
+el5ebra
+5elec
+e4led
+el3ega
+e5len
+e4l1er
+e1les
+el2f
+el2i
+e3libe
+e4l5ic.
+el3ica
+e3lier
+el5igib
+e5lim
+e4l3ing
+e3lio
+e2lis
+el5ish
+e3liv3
+4ella
+el4lab
+ello4
+e5loc
+el5og
+el3op.
+el2sh
+el4ta
+e5lud
+el5ug
+e4mac
+e4mag
+e5man
+em5ana
+em5b
+e1me
+e2mel
+e4met
+em3ica
+emi4e
+em5igra
+em1in2
+em5ine
+em3i3ni
+e4mis
+em5ish
+e5miss
+em3iz
+5emniz
+emo4g
+emoni5o
+em3pi
+e4mul
+em5ula
+emu3n
+e3my
+en5amo
+e4nant
+ench4er
+en3dic
+e5nea
+e5nee
+en3em
+en5ero
+en5esi
+en5est
+en3etr
+e3new
+en5ics
+e5nie
+e5nil
+e3nio
+en3ish
+en3it
+e5niu
+5eniz
+4enn
+4eno
+eno4g
+e4nos
+en3ov
+en4sw
+ent5age
+4enthes
+en3ua
+en5uf
+e3ny.
+4en3z
+e5of
+eo2g
+e4oi4
+e3ol
+eop3ar
+e1or
+eo3re
+eo5rol
+eos4
+e4ot
+eo4to
+e5out
+e5ow
+e2pa
+e3pai
+ep5anc
+e5pel
+e3pent
+ep5etitio
+ephe4
+e4pli
+e1po
+e4prec
+ep5reca
+e4pred
+ep3reh
+e3pro
+e4prob
+ep4sh
+ep5ti5b
+e4put
+ep5uta
+e1q
+equi3l
+e4q3ui3s
+er1a
+era4b
+4erand
+er3ar
+4erati.
+2erb
+er4bl
+er3ch
+er4che
+2ere.
+e3real
+ere5co
+ere3in
+er5el.
+er3emo
+er5ena
+er5ence
+4erene
+er3ent
+ere4q
+er5ess
+er3est
+eret4
+er1h
+er1i
+e1ria4
+5erick
+e3rien
+eri4er
+er3ine
+e1rio
+4erit
+er4iu
+eri4v
+e4riva
+er3m4
+er4nis
+4ernit
+5erniz
+er3no
+2ero
+er5ob
+e5roc
+ero4r
+er1ou
+er1s
+er3set
+ert3er
+4ertl
+er3tw
+4eru
+eru4t
+5erwau
+e1s4a
+e4sage.
+e4sages
+es2c
+e2sca
+es5can
+e3scr
+es5cu
+e1s2e
+e2sec
+es5ecr
+es5enc
+e4sert.
+e4serts
+e4serva
+4esh
+e3sha
+esh5en
+e1si
+e2sic
+e2sid
+es5iden
+es5igna
+e2s5im
+es4i4n
+esis4te
+esi4u
+e5skin
+es4mi
+e2sol
+es3olu
+e2son
+es5ona
+e1sp
+es3per
+es5pira
+es4pre
+2ess
+es4si4b
+estan4
+es3tig
+es5tim
+4es2to
+e3ston
+2estr
+e5stro
+estruc5
+e2sur
+es5urr
+es4w
+eta4b
+eten4d
+e3teo
+ethod3
+et1ic
+e5tide
+etin4
+eti4no
+e5tir
+e5titio
+et5itiv
+4etn
+et5ona
+e3tra
+e3tre
+et3ric
+et5rif
+et3rog
+et5ros
+et3ua
+et5ym
+et5z
+4eu
+e5un
+e3up
+eu3ro
+eus4
+eute4
+euti5l
+eu5tr
+eva2p5
+e2vas
+ev5ast
+e5vea
+ev3ell
+evel3o
+e5veng
+even4i
+ev1er
+e5verb
+e1vi
+ev3id
+evi4l
+e4vin
+evi4v
+e5voc
+e5vu
+e1wa
+e4wag
+e5wee
+e3wh
+ewil5
+ew3ing
+e3wit
+1exp
+5eyc
+5eye.
+eys4
+1fa
+fa3bl
+fab3r
+fa4ce
+4fag
+fain4
+fall5e
+4fa4ma
+fam5is
+5far
+far5th
+fa3ta
+fa3the
+4fato
+fault5
+4f5b
+4fd
+4fe.
+feas4
+feath3
+fe4b
+4feca
+5fect
+2fed
+fe3li
+fe4mo
+fen2d
+fend5e
+fer1
+5ferr
+fev4
+4f1f
+f4fes
+f4fie
+f5fin.
+f2f5is
+f4fly
+f2fy
+4fh
+1fi
+fi3a
+2f3ic.
+4f3ical
+f3ican
+4ficate
+f3icen
+fi3cer
+fic4i
+5ficia
+5ficie
+4fics
+fi3cu
+fi5del
+fight5
+fil5i
+fill5in
+4fily
+2fin
+5fina
+fin2d5
+fi2ne
+f1in3g
+fin4n
+fis4ti
+f4l2
+f5less
+flin4
+flo3re
+f2ly5
+4fm
+4fn
+1fo
+5fon
+fon4de
+fon4t
+fo2r
+fo5rat
+for5ay
+fore5t
+for4i
+fort5a
+fos5
+4f5p
+fra4t
+f5rea
+fres5c
+fri2
+fril4
+frol5
+2f3s
+2ft
+f4to
+f2ty
+3fu
+fu5el
+4fug
+fu4min
+fu5ne
+fu3ri
+fusi4
+fus4s
+4futa
+1fy
+1ga
+gaf4
+5gal.
+3gali
+ga3lo
+2gam
+ga5met
+g5amo
+gan5is
+ga3niz
+gani5za
+4gano
+gar5n4
+gass4
+gath3
+4gativ
+4gaz
+g3b
+gd4
+2ge.
+2ged
+geez4
+gel4in
+ge5lis
+ge5liz
+4gely
+1gen
+ge4nat
+ge5niz
+4geno
+4geny
+1geo
+ge3om
+g4ery
+5gesi
+geth5
+4geto
+ge4ty
+ge4v
+4g1g2
+g2ge
+g3ger
+gglu5
+ggo4
+gh3in
+gh5out
+gh4to
+5gi.
+1gi4a
+gia5r
+g1ic
+5gicia
+g4ico
+gien5
+5gies.
+gil4
+g3imen
+3g4in.
+gin5ge
+5g4ins
+5gio
+3gir
+gir4l
+g3isl
+gi4u
+5giv
+3giz
+gl2
+gla4
+glad5i
+5glas
+1gle
+gli4b
+g3lig
+3glo
+glo3r
+g1m
+g4my
+gn4a
+g4na.
+gnet4t
+g1ni
+g2nin
+g4nio
+g1no
+g4non
+1go
+3go.
+gob5
+5goe
+3g4o4g
+go3is
+gon2
+4g3o3na
+gondo5
+go3ni
+5goo
+go5riz
+gor5ou
+5gos.
+gov1
+g3p
+1gr
+4grada
+g4rai
+gran2
+5graph.
+g5rapher
+5graphic
+4graphy
+4gray
+gre4n
+4gress.
+4grit
+g4ro
+gruf4
+gs2
+g5ste
+gth3
+gu4a
+3guard
+2gue
+5gui5t
+3gun
+3gus
+4gu4t
+g3w
+1gy
+2g5y3n
+gy5ra
+h3ab4l
+hach4
+hae4m
+hae4t
+h5agu
+ha3la
+hala3m
+ha4m
+han4ci
+han4cy
+5hand.
+han4g
+hang5er
+hang5o
+h5a5niz
+han4k
+han4te
+hap3l
+hap5t
+ha3ran
+ha5ras
+har2d
+hard3e
+har4le
+harp5en
+har5ter
+has5s
+haun4
+5haz
+haz3a
+h1b
+1head
+3hear
+he4can
+h5ecat
+h4ed
+he5do5
+he3l4i
+hel4lis
+hel4ly
+h5elo
+hem4p
+he2n
+hena4
+hen5at
+heo5r
+hep5
+h4era
+hera3p
+her4ba
+here5a
+h3ern
+h5erou
+h3ery
+h1es
+he2s5p
+he4t
+het4ed
+heu4
+h1f
+h1h
+hi5an
+hi4co
+high5
+h4il2
+himer4
+h4ina
+hion4e
+hi4p
+hir4l
+hi3ro
+hir4p
+hir4r
+his3el
+his4s
+hith5er
+hi2v
+4hk
+4h1l4
+hlan4
+h2lo
+hlo3ri
+4h1m
+hmet4
+2h1n
+h5odiz
+h5ods
+ho4g
+hoge4
+hol5ar
+3hol4e
+ho4ma
+home3
+hon4a
+ho5ny
+3hood
+hoon4
+hor5at
+ho5ris
+hort3e
+ho5ru
+hos4e
+ho5sen
+hos1p
+1hous
+house3
+hov5el
+4h5p
+4hr4
+hree5
+hro5niz
+hro3po
+4h1s2
+h4sh
+h4tar
+ht1en
+ht5es
+h4ty
+hu4g
+hu4min
+hun5ke
+hun4t
+hus3t4
+hu4t
+h1w
+h4wart
+hy3pe
+hy3ph
+hy2s
+2i1a
+i2al
+iam4
+iam5ete
+i2an
+4ianc
+ian3i
+4ian4t
+ia5pe
+iass4
+i4ativ
+ia4tric
+i4atu
+ibe4
+ib3era
+ib5ert
+ib5ia
+ib3in
+ib5it.
+ib5ite
+i1bl
+ib3li
+i5bo
+i1br
+i2b5ri
+i5bun
+4icam
+5icap
+4icar
+i4car.
+i4cara
+icas5
+i4cay
+iccu4
+4iceo
+4ich
+2ici
+i5cid
+ic5ina
+i2cip
+ic3ipa
+i4cly
+i2c5oc
+4i1cr
+5icra
+i4cry
+ic4te
+ictu2
+ic4t3ua
+ic3ula
+ic4um
+ic5uo
+i3cur
+2id
+i4dai
+id5anc
+id5d
+ide3al
+ide4s
+i2di
+id5ian
+idi4ar
+i5die
+id3io
+idi5ou
+id1it
+id5iu
+i3dle
+i4dom
+id3ow
+i4dr
+i2du
+id5uo
+2ie4
+ied4e
+5ie5ga
+ield3
+ien5a4
+ien4e
+i5enn
+i3enti
+i1er.
+i3esc
+i1est
+i3et
+4if.
+if5ero
+iff5en
+if4fr
+4ific.
+i3fie
+i3fl
+4ift
+2ig
+iga5b
+ig3era
+ight3i
+4igi
+i3gib
+ig3il
+ig3in
+ig3it
+i4g4l
+i2go
+ig3or
+ig5ot
+i5gre
+igu5i
+ig1ur
+i3h
+4i5i4
+i3j
+4ik
+i1la
+il3a4b
+i4lade
+i2l5am
+ila5ra
+i3leg
+il1er
+ilev4
+il5f
+il1i
+il3ia
+il2ib
+il3io
+il4ist
+2ilit
+il2iz
+ill5ab
+4iln
+il3oq
+il4ty
+il5ur
+il3v
+i4mag
+im3age
+ima5ry
+imenta5r
+4imet
+im1i
+im5ida
+imi5le
+i5mini
+4imit
+im4ni
+i3mon
+i2mu
+im3ula
+2in.
+i4n3au
+4inav
+incel4
+in3cer
+4ind
+in5dling
+2ine
+i3nee
+iner4ar
+i5ness
+4inga
+4inge
+in5gen
+4ingi
+in5gling
+4ingo
+4ingu
+2ini
+i5ni.
+i4nia
+in3io
+in1is
+i5nite.
+5initio
+in3ity
+4ink
+4inl
+2inn
+2i1no
+i4no4c
+ino4s
+i4not
+2ins
+in3se
+insur5a
+2int.
+2in4th
+in1u
+i5nus
+4iny
+2io
+4io.
+ioge4
+io2gr
+i1ol
+io4m
+ion3at
+ion4ery
+ion3i
+io5ph
+ior3i
+i4os
+io5th
+i5oti
+io4to
+i4our
+2ip
+ipe4
+iphras4
+ip3i
+ip4ic
+ip4re4
+ip3ul
+i3qua
+iq5uef
+iq3uid
+iq3ui3t
+4ir
+i1ra
+ira4b
+i4rac
+ird5e
+ire4de
+i4ref
+i4rel4
+i4res
+ir5gi
+ir1i
+iri5de
+ir4is
+iri3tu
+5i5r2iz
+ir4min
+iro4g
+5iron.
+ir5ul
+2is.
+is5ag
+is3ar
+isas5
+2is1c
+is3ch
+4ise
+is3er
+3isf
+is5han
+is3hon
+ish5op
+is3ib
+isi4d
+i5sis
+is5itiv
+4is4k
+islan4
+4isms
+i2so
+iso5mer
+is1p
+is2pi
+is4py
+4is1s
+is4sal
+issen4
+is4ses
+is4ta.
+is1te
+is1ti
+ist4ly
+4istral
+i2su
+is5us
+4ita.
+ita4bi
+i4tag
+4ita5m
+i3tan
+i3tat
+2ite
+it3era
+i5teri
+it4es
+2ith
+i1ti
+4itia
+4i2tic
+it3ica
+5i5tick
+it3ig
+it5ill
+i2tim
+2itio
+4itis
+i4tism
+i2t5o5m
+4iton
+i4tram
+it5ry
+4itt
+it3uat
+i5tud
+it3ul
+4itz.
+i1u
+2iv
+iv3ell
+iv3en.
+i4v3er.
+i4vers.
+iv5il.
+iv5io
+iv1it
+i5vore
+iv3o3ro
+i4v3ot
+4i5w
+ix4o
+4iy
+4izar
+izi4
+5izont
+5ja
+jac4q
+ja4p
+1je
+jer5s
+4jestie
+4jesty
+jew3
+jo4p
+5judg
+3ka.
+k3ab
+k5ag
+kais4
+kal4
+k1b
+k2ed
+1kee
+ke4g
+ke5li
+k3en4d
+k1er
+kes4
+k3est.
+ke4ty
+k3f
+kh4
+k1i
+5ki.
+5k2ic
+k4ill
+kilo5
+k4im
+k4in.
+kin4de
+k5iness
+kin4g
+ki4p
+kis4
+k5ish
+kk4
+k1l
+4kley
+4kly
+k1m
+k5nes
+1k2no
+ko5r
+kosh4
+k3ou
+kro5n
+4k1s2
+k4sc
+ks4l
+k4sy
+k5t
+k1w
+lab3ic
+l4abo
+laci4
+l4ade
+la3dy
+lag4n
+lam3o
+3land
+lan4dl
+lan5et
+lan4te
+lar4g
+lar3i
+las4e
+la5tan
+4lateli
+4lativ
+4lav
+la4v4a
+2l1b
+lbin4
+4l1c2
+lce4
+l3ci
+2ld
+l2de
+ld4ere
+ld4eri
+ldi4
+ld5is
+l3dr
+l4dri
+le2a
+le4bi
+left5
+5leg.
+5legg
+le4mat
+lem5atic
+4len.
+3lenc
+5lene.
+1lent
+le3ph
+le4pr
+lera5b
+ler4e
+3lerg
+3l4eri
+l4ero
+les2
+le5sco
+5lesq
+3less
+5less.
+l3eva
+lev4er.
+lev4era
+lev4ers
+3ley
+4leye
+2lf
+l5fr
+4l1g4
+l5ga
+lgar3
+l4ges
+lgo3
+2l3h
+li4ag
+li2am
+liar5iz
+li4as
+li4ato
+li5bi
+5licio
+li4cor
+4lics
+4lict.
+l4icu
+l3icy
+l3ida
+lid5er
+3lidi
+lif3er
+l4iff
+li4fl
+5ligate
+3ligh
+li4gra
+3lik
+4l4i4l
+lim4bl
+lim3i
+li4mo
+l4im4p
+l4ina
+1l4ine
+lin3ea
+lin3i
+link5er
+li5og
+4l4iq
+lis4p
+l1it
+l2it.
+5litica
+l5i5tics
+liv3er
+l1iz
+4lj
+lka3
+l3kal
+lka4t
+l1l
+l4law
+l2le
+l5lea
+l3lec
+l3leg
+l3lel
+l3le4n
+l3le4t
+ll2i
+l2lin4
+l5lina
+ll4o
+lloqui5
+ll5out
+l5low
+2lm
+l5met
+lm3ing
+l4mod
+lmon4
+2l1n2
+3lo.
+lob5al
+lo4ci
+4lof
+3logic
+l5ogo
+3logu
+lom3er
+5long
+lon4i
+l3o3niz
+lood5
+5lope.
+lop3i
+l3opm
+lora4
+lo4rato
+lo5rie
+lor5ou
+5los.
+los5et
+5losophiz
+5losophy
+los4t
+lo4ta
+loun5d
+2lout
+4lov
+2lp
+lpa5b
+l3pha
+l5phi
+lp5ing
+l3pit
+l4pl
+l5pr
+4l1r
+2l1s2
+l4sc
+l2se
+l4sie
+4lt
+lt5ag
+ltane5
+l1te
+lten4
+ltera4
+lth3i
+l5ties.
+ltis4
+l1tr
+ltu2
+ltur3a
+lu5a
+lu3br
+luch4
+lu3ci
+lu3en
+luf4
+lu5id
+lu4ma
+5lumi
+l5umn.
+5lumnia
+lu3o
+luo3r
+4lup
+luss4
+lus3te
+1lut
+l5ven
+l5vet4
+2l1w
+1ly
+4lya
+4lyb
+ly5me
+ly3no
+2lys4
+l5yse
+1ma
+2mab
+ma2ca
+ma5chine
+ma4cl
+mag5in
+5magn
+2mah
+maid5
+4mald
+ma3lig
+ma5lin
+mal4li
+mal4ty
+5mania
+man5is
+man3iz
+4map
+ma5rine.
+ma5riz
+mar4ly
+mar3v
+ma5sce
+mas4e
+mas1t
+5mate
+math3
+ma3tis
+4matiza
+4m1b
+mba4t5
+m5bil
+m4b3ing
+mbi4v
+4m5c
+4me.
+2med
+4med.
+5media
+me3die
+m5e5dy
+me2g
+mel5on
+mel4t
+me2m
+mem1o3
+1men
+men4a
+men5ac
+men4de
+4mene
+men4i
+mens4
+mensu5
+3ment
+men4te
+me5on
+m5ersa
+2mes
+3mesti
+me4ta
+met3al
+me1te
+me5thi
+m4etr
+5metric
+me5trie
+me3try
+me4v
+4m1f
+2mh
+5mi.
+mi3a
+mid4a
+mid4g
+mig4
+3milia
+m5i5lie
+m4ill
+min4a
+3mind
+m5inee
+m4ingl
+min5gli
+m5ingly
+min4t
+m4inu
+miot4
+m2is
+mis4er.
+mis5l
+mis4ti
+m5istry
+4mith
+m2iz
+4mk
+4m1l
+m1m
+mma5ry
+4m1n
+mn4a
+m4nin
+mn4o
+1mo
+4mocr
+5mocratiz
+mo2d1
+mo4go
+mois2
+moi5se
+4mok
+mo5lest
+mo3me
+mon5et
+mon5ge
+moni3a
+mon4ism
+mon4ist
+mo3niz
+monol4
+mo3ny.
+mo2r
+4mora.
+mos2
+mo5sey
+mo3sp
+moth3
+m5ouf
+3mous
+mo2v
+4m1p
+mpara5
+mpa5rab
+mpar5i
+m3pet
+mphas4
+m2pi
+mpi4a
+mp5ies
+m4p1in
+m5pir
+mp5is
+mpo3ri
+mpos5ite
+m4pous
+mpov5
+mp4tr
+m2py
+4m3r
+4m1s2
+m4sh
+m5si
+4mt
+1mu
+mula5r4
+5mult
+multi3
+3mum
+mun2
+4mup
+mu4u
+4mw
+1na
+2n1a2b
+n4abu
+4nac.
+na4ca
+n5act
+nag5er.
+nak4
+na4li
+na5lia
+4nalt
+na5mit
+n2an
+nanci4
+nan4it
+nank4
+nar3c
+4nare
+nar3i
+nar4l
+n5arm
+n4as
+nas4c
+nas5ti
+n2at
+na3tal
+nato5miz
+n2au
+nau3se
+3naut
+nav4e
+4n1b4
+ncar5
+n4ces.
+n3cha
+n5cheo
+n5chil
+n3chis
+nc1in
+nc4it
+ncour5a
+n1cr
+n1cu
+n4dai
+n5dan
+n1de
+nd5est.
+ndi4b
+n5d2if
+n1dit
+n3diz
+n5duc
+ndu4r
+nd2we
+2ne.
+n3ear
+ne2b
+neb3u
+ne2c
+5neck
+2ned
+ne4gat
+neg5ativ
+5nege
+ne4la
+nel5iz
+ne5mi
+ne4mo
+1nen
+4nene
+3neo
+ne4po
+ne2q
+n1er
+nera5b
+n4erar
+n2ere
+n4er5i
+ner4r
+1nes
+2nes.
+4nesp
+2nest
+4nesw
+3netic
+ne4v
+n5eve
+ne4w
+n3f
+n4gab
+n3gel
+nge4n4e
+n5gere
+n3geri
+ng5ha
+n3gib
+ng1in
+n5git
+n4gla
+ngov4
+ng5sh
+n1gu
+n4gum
+n2gy
+4n1h4
+nha4
+nhab3
+nhe4
+3n4ia
+ni3an
+ni4ap
+ni3ba
+ni4bl
+ni4d
+ni5di
+ni4er
+ni2fi
+ni5ficat
+n5igr
+nik4
+n1im
+ni3miz
+n1in
+5nine.
+nin4g
+ni4o
+5nis.
+nis4ta
+n2it
+n4ith
+3nitio
+n3itor
+ni3tr
+n1j
+4nk2
+n5kero
+n3ket
+nk3in
+n1kl
+4n1l
+n5m
+nme4
+nmet4
+4n1n2
+nne4
+nni3al
+nni4v
+nob4l
+no3ble
+n5ocl
+4n3o2d
+3noe
+4nog
+noge4
+nois5i
+no5l4i
+5nologis
+3nomic
+n5o5miz
+no4mo
+no3my
+no4n
+non4ag
+non5i
+n5oniz
+4nop
+5nop5o5li
+nor5ab
+no4rary
+4nosc
+nos4e
+nos5t
+no5ta
+1nou
+3noun
+nov3el3
+nowl3
+n1p4
+npi4
+npre4c
+n1q
+n1r
+nru4
+2n1s2
+ns5ab
+nsati4
+ns4c
+n2se
+n4s3es
+nsid1
+nsig4
+n2sl
+ns3m
+n4soc
+ns4pe
+n5spi
+nsta5bl
+n1t
+nta4b
+nter3s
+nt2i
+n5tib
+nti4er
+nti2f
+n3tine
+n4t3ing
+nti4p
+ntrol5li
+nt4s
+ntu3me
+nu1a
+nu4d
+nu5en
+nuf4fe
+n3uin
+3nu3it
+n4um
+nu1me
+n5umi
+3nu4n
+n3uo
+nu3tr
+n1v2
+n1w4
+nym4
+nyp4
+4nz
+n3za
+4oa
+oad3
+o5a5les
+oard3
+oas4e
+oast5e
+oat5i
+ob3a3b
+o5bar
+obe4l
+o1bi
+o2bin
+ob5ing
+o3br
+ob3ul
+o1ce
+och4
+o3chet
+ocif3
+o4cil
+o4clam
+o4cod
+oc3rac
+oc5ratiz
+ocre3
+5ocrit
+octor5a
+oc3ula
+o5cure
+od5ded
+od3ic
+odi3o
+o2do4
+odor3
+od5uct.
+od5ucts
+o4el
+o5eng
+o3er
+oe4ta
+o3ev
+o2fi
+of5ite
+ofit4t
+o2g5a5r
+og5ativ
+o4gato
+o1ge
+o5gene
+o5geo
+o4ger
+o3gie
+1o1gis
+og3it
+o4gl
+o5g2ly
+3ogniz
+o4gro
+ogu5i
+1ogy
+2ogyn
+o1h2
+ohab5
+oi2
+oic3es
+oi3der
+oiff4
+oig4
+oi5let
+o3ing
+oint5er
+o5ism
+oi5son
+oist5en
+oi3ter
+o5j
+2ok
+o3ken
+ok5ie
+o1la
+o4lan
+olass4
+ol2d
+old1e
+ol3er
+o3lesc
+o3let
+ol4fi
+ol2i
+o3lia
+o3lice
+ol5id.
+o3li4f
+o5lil
+ol3ing
+o5lio
+o5lis.
+ol3ish
+o5lite
+o5litio
+o5liv
+olli4e
+ol5ogiz
+olo4r
+ol5pl
+ol2t
+ol3ub
+ol3ume
+ol3un
+o5lus
+ol2v
+o2ly
+om5ah
+oma5l
+om5atiz
+om2be
+om4bl
+o2me
+om3ena
+om5erse
+o4met
+om5etry
+o3mia
+om3ic.
+om3ica
+o5mid
+om1in
+o5mini
+5ommend
+omo4ge
+o4mon
+om3pi
+ompro5
+o2n
+on1a
+on4ac
+o3nan
+on1c
+3oncil
+2ond
+on5do
+o3nen
+on5est
+on4gu
+on1ic
+o3nio
+on1is
+o5niu
+on3key
+on4odi
+on3omy
+on3s
+onspi4
+onspir5a
+onsu4
+onten4
+on3t4i
+ontif5
+on5um
+onva5
+oo2
+ood5e
+ood5i
+oo4k
+oop3i
+o3ord
+oost5
+o2pa
+ope5d
+op1er
+3opera
+4operag
+2oph
+o5phan
+o5pher
+op3ing
+o3pit
+o5pon
+o4posi
+o1pr
+op1u
+opy5
+o1q
+o1ra
+o5ra.
+o4r3ag
+or5aliz
+or5ange
+ore5a
+o5real
+or3ei
+ore5sh
+or5est.
+orew4
+or4gu
+4o5ria
+or3ica
+o5ril
+or1in
+o1rio
+or3ity
+o3riu
+or2mi
+orn2e
+o5rof
+or3oug
+or5pe
+3orrh
+or4se
+ors5en
+orst4
+or3thi
+or3thy
+or4ty
+o5rum
+o1ry
+os3al
+os2c
+os4ce
+o3scop
+4oscopi
+o5scr
+os4i4e
+os5itiv
+os3ito
+os3ity
+osi4u
+os4l
+o2so
+os4pa
+os4po
+os2ta
+o5stati
+os5til
+os5tit
+o4tan
+otele4g
+ot3er.
+ot5ers
+o4tes
+4oth
+oth5esi
+oth3i4
+ot3ic.
+ot5ica
+o3tice
+o3tif
+o3tis
+oto5s
+ou2
+ou3bl
+ouch5i
+ou5et
+ou4l
+ounc5er
+oun2d
+ou5v
+ov4en
+over4ne
+over3s
+ov4ert
+o3vis
+oviti4
+o5v4ol
+ow3der
+ow3el
+ow5est
+ow1i
+own5i
+o4wo
+oy1a
+1pa
+pa4ca
+pa4ce
+pac4t
+p4ad
+5pagan
+p3agat
+p4ai
+pain4
+p4al
+pan4a
+pan3el
+pan4ty
+pa3ny
+pa1p
+pa4pu
+para5bl
+par5age
+par5di
+3pare
+par5el
+p4a4ri
+par4is
+pa2te
+pa5ter
+5pathic
+pa5thy
+pa4tric
+pav4
+3pay
+4p1b
+pd4
+4pe.
+3pe4a
+pear4l
+pe2c
+2p2ed
+3pede
+3pedi
+pedia4
+ped4ic
+p4ee
+pee4d
+pek4
+pe4la
+peli4e
+pe4nan
+p4enc
+pen4th
+pe5on
+p4era.
+pera5bl
+p4erag
+p4eri
+peri5st
+per4mal
+perme5
+p4ern
+per3o
+per3ti
+pe5ru
+per1v
+pe2t
+pe5ten
+pe5tiz
+4pf
+4pg
+4ph.
+phar5i
+phe3no
+ph4er
+ph4es.
+ph1ic
+5phie
+ph5ing
+5phisti
+3phiz
+ph2l
+3phob
+3phone
+5phoni
+pho4r
+4phs
+ph3t
+5phu
+1phy
+pi3a
+pian4
+pi4cie
+pi4cy
+p4id
+p5ida
+pi3de
+5pidi
+3piec
+pi3en
+pi4grap
+pi3lo
+pi2n
+p4in.
+pind4
+p4ino
+3pi1o
+pion4
+p3ith
+pi5tha
+pi2tu
+2p3k2
+1p2l2
+3plan
+plas5t
+pli3a
+pli5er
+4plig
+pli4n
+ploi4
+plu4m
+plum4b
+4p1m
+2p3n
+po4c
+5pod.
+po5em
+po3et5
+5po4g
+poin2
+5point
+poly5t
+po4ni
+po4p
+1p4or
+po4ry
+1pos
+pos1s
+p4ot
+po4ta
+5poun
+4p1p
+ppa5ra
+p2pe
+p4ped
+p5pel
+p3pen
+p3per
+p3pet
+ppo5site
+pr2
+pray4e
+5preci
+pre5co
+pre3em
+pref5ac
+pre4la
+pre3r
+p3rese
+3press
+pre5ten
+pre3v
+5pri4e
+prin4t3
+pri4s
+pris3o
+p3roca
+prof5it
+pro3l
+pros3e
+pro1t
+2p1s2
+p2se
+ps4h
+p4sib
+2p1t
+pt5a4b
+p2te
+p2th
+pti3m
+ptu4r
+p4tw
+pub3
+pue4
+puf4
+pul3c
+pu4m
+pu2n
+pur4r
+5pus
+pu2t
+5pute
+put3er
+pu3tr
+put4ted
+put4tin
+p3w
+qu2
+qua5v
+2que.
+3quer
+3quet
+2rab
+ra3bi
+rach4e
+r5acl
+raf5fi
+raf4t
+r2ai
+ra4lo
+ram3et
+r2ami
+rane5o
+ran4ge
+r4ani
+ra5no
+rap3er
+3raphy
+rar5c
+rare4
+rar5ef
+4raril
+r2as
+ration4
+rau4t
+ra5vai
+rav3el
+ra5zie
+r1b
+r4bab
+r4bag
+rbi2
+rbi4f
+r2bin
+r5bine
+rb5ing.
+rb4o
+r1c
+r2ce
+rcen4
+r3cha
+rch4er
+r4ci4b
+rc4it
+rcum3
+r4dal
+rd2i
+rdi4a
+rdi4er
+rdin4
+rd3ing
+2re.
+re1al
+re3an
+re5arr
+5reav
+re4aw
+r5ebrat
+rec5oll
+rec5ompe
+re4cre
+2r2ed
+re1de
+re3dis
+red5it
+re4fac
+re2fe
+re5fer.
+re3fi
+re4fy
+reg3is
+re5it
+re1li
+re5lu
+r4en4ta
+ren4te
+re1o
+re5pin
+re4posi
+re1pu
+r1er4
+r4eri
+rero4
+re5ru
+r4es.
+re4spi
+ress5ib
+res2t
+re5stal
+re3str
+re4ter
+re4ti4z
+re3tri
+reu2
+re5uti
+rev2
+re4val
+rev3el
+r5ev5er.
+re5vers
+re5vert
+re5vil
+rev5olu
+re4wh
+r1f
+rfu4
+r4fy
+rg2
+rg3er
+r3get
+r3gic
+rgi4n
+rg3ing
+r5gis
+r5git
+r1gl
+rgo4n
+r3gu
+rh4
+4rh.
+4rhal
+ri3a
+ria4b
+ri4ag
+r4ib
+rib3a
+ric5as
+r4ice
+4rici
+5ricid
+ri4cie
+r4ico
+rid5er
+ri3enc
+ri3ent
+ri1er
+ri5et
+rig5an
+5rigi
+ril3iz
+5riman
+rim5i
+3rimo
+rim4pe
+r2ina
+5rina.
+rin4d
+rin4e
+rin4g
+ri1o
+5riph
+riph5e
+ri2pl
+rip5lic
+r4iq
+r2is
+r4is.
+ris4c
+r3ish
+ris4p
+ri3ta3b
+r5ited.
+rit5er.
+rit5ers
+rit3ic
+ri2tu
+rit5ur
+riv5el
+riv3et
+riv3i
+r3j
+r3ket
+rk4le
+rk4lin
+r1l
+rle4
+r2led
+r4lig
+r4lis
+rl5ish
+r3lo4
+r1m
+rma5c
+r2me
+r3men
+rm5ers
+rm3ing
+r4ming.
+r4mio
+r3mit
+r4my
+r4nar
+r3nel
+r4ner
+r5net
+r3ney
+r5nic
+r1nis4
+r3nit
+r3niv
+rno4
+r4nou
+r3nu
+rob3l
+r2oc
+ro3cr
+ro4e
+ro1fe
+ro5fil
+rok2
+ro5ker
+5role.
+rom5ete
+rom4i
+rom4p
+ron4al
+ron4e
+ro5n4is
+ron4ta
+1room
+5root
+ro3pel
+rop3ic
+ror3i
+ro5ro
+ros5per
+ros4s
+ro4the
+ro4ty
+ro4va
+rov5el
+rox5
+r1p
+r4pea
+r5pent
+rp5er.
+r3pet
+rp4h4
+rp3ing
+r3po
+r1r4
+rre4c
+rre4f
+r4reo
+rre4st
+rri4o
+rri4v
+rron4
+rros4
+rrys4
+4rs2
+r1sa
+rsa5ti
+rs4c
+r2se
+r3sec
+rse4cr
+rs5er.
+rs3es
+rse5v2
+r1sh
+r5sha
+r1si
+r4si4b
+rson3
+r1sp
+r5sw
+rtach4
+r4tag
+r3teb
+rten4d
+rte5o
+r1ti
+rt5ib
+rti4d
+r4tier
+r3tig
+rtil3i
+rtil4l
+r4tily
+r4tist
+r4tiv
+r3tri
+rtroph4
+rt4sh
+ru3a
+ru3e4l
+ru3en
+ru4gl
+ru3in
+rum3pl
+ru2n
+runk5
+run4ty
+r5usc
+ruti5n
+rv4e
+rvel4i
+r3ven
+rv5er.
+r5vest
+r3vey
+r3vic
+rvi4v
+r3vo
+r1w
+ry4c
+5rynge
+ry3t
+sa2
+2s1ab
+5sack
+sac3ri
+s3act
+5sai
+salar4
+sal4m
+sa5lo
+sal4t
+3sanc
+san4de
+s1ap
+sa5ta
+5sa3tio
+sat3u
+sau4
+sa5vor
+5saw
+4s5b
+scan4t5
+sca4p
+scav5
+s4ced
+4scei
+s4ces
+sch2
+s4cho
+3s4cie
+5scin4d
+scle5
+s4cli
+scof4
+4scopy
+scour5a
+s1cu
+4s5d
+4se.
+se4a
+seas4
+sea5w
+se2c3o
+3sect
+4s4ed
+se4d4e
+s5edl
+se2g
+seg3r
+5sei
+se1le
+5self
+5selv
+4seme
+se4mol
+sen5at
+4senc
+sen4d
+s5ened
+sen5g
+s5enin
+4sentd
+4sentl
+sep3a3
+4s1er.
+s4erl
+ser4o
+4servo
+s1e4s
+se5sh
+ses5t
+5se5um
+5sev
+sev3en
+sew4i
+5sex
+4s3f
+2s3g
+s2h
+2sh.
+sh1er
+5shev
+sh1in
+sh3io
+3ship
+shiv5
+sho4
+sh5old
+shon3
+shor4
+short5
+4shw
+si1b
+s5icc
+3side.
+5sides
+5sidi
+si5diz
+4signa
+sil4e
+4sily
+2s1in
+s2ina
+5sine.
+s3ing
+1sio
+5sion
+sion5a
+si2r
+sir5a
+1sis
+3sitio
+5siu
+1siv
+5siz
+sk2
+4ske
+s3ket
+sk5ine
+sk5ing
+s1l2
+s3lat
+s2le
+slith5
+2s1m
+s3ma
+small3
+sman3
+smel4
+s5men
+5smith
+smol5d4
+s1n4
+1so
+so4ce
+soft3
+so4lab
+sol3d2
+so3lic
+5solv
+3som
+3s4on.
+sona4
+son4g
+s4op
+5sophic
+s5ophiz
+s5ophy
+sor5c
+sor5d
+4sov
+so5vi
+2spa
+5spai
+spa4n
+spen4d
+2s5peo
+2sper
+s2phe
+3spher
+spho5
+spil4
+sp5ing
+4spio
+s4ply
+s4pon
+spor4
+4spot
+squal4l
+s1r
+2ss
+s1sa
+ssas3
+s2s5c
+s3sel
+s5seng
+s4ses.
+s5set
+s1si
+s4sie
+ssi4er
+ss5ily
+s4sl
+ss4li
+s4sn
+sspend4
+ss2t
+ssur5a
+ss5w
+2st.
+s2tag
+s2tal
+stam4i
+5stand
+s4ta4p
+5stat.
+s4ted
+stern5i
+s5tero
+ste2w
+stew5a
+s3the
+st2i
+s4ti.
+s5tia
+s1tic
+5stick
+s4tie
+s3tif
+st3ing
+5stir
+s1tle
+5stock
+stom3a
+5stone
+s4top
+3store
+st4r
+s4trad
+5stratu
+s4tray
+s4trid
+4stry
+4st3w
+s2ty
+1su
+su1al
+su4b3
+su2g3
+su5is
+suit3
+s4ul
+su2m
+sum3i
+su2n
+su2r
+4sv
+sw2
+4swo
+s4y
+4syc
+3syl
+syn5o
+sy5rin
+1ta
+3ta.
+2tab
+ta5bles
+5taboliz
+4taci
+ta5do
+4taf4
+tai5lo
+ta2l
+ta5la
+tal5en
+tal3i
+4talk
+tal4lis
+ta5log
+ta5mo
+tan4de
+tanta3
+ta5per
+ta5pl
+tar4a
+4tarc
+4tare
+ta3riz
+tas4e
+ta5sy
+4tatic
+ta4tur
+taun4
+tav4
+2taw
+tax4is
+2t1b
+4tc
+t4ch
+tch5et
+4t1d
+4te.
+tead4i
+4teat
+tece4
+5tect
+2t1ed
+te5di
+1tee
+teg4
+te5ger
+te5gi
+3tel.
+teli4
+5tels
+te2ma2
+tem3at
+3tenan
+3tenc
+3tend
+4tenes
+1tent
+ten4tag
+1teo
+te4p
+te5pe
+ter3c
+5ter3d
+1teri
+ter5ies
+ter3is
+teri5za
+5ternit
+ter5v
+4tes.
+4tess
+t3ess.
+teth5e
+3teu
+3tex
+4tey
+2t1f
+4t1g
+2th.
+than4
+th2e
+4thea
+th3eas
+the5at
+the3is
+3thet
+th5ic.
+th5ica
+4thil
+5think
+4thl
+th5ode
+5thodic
+4thoo
+thor5it
+tho5riz
+2ths
+1tia
+ti4ab
+ti4ato
+2ti2b
+4tick
+t4ico
+t4ic1u
+5tidi
+3tien
+tif2
+ti5fy
+2tig
+5tigu
+till5in
+1tim
+4timp
+tim5ul
+2t1in
+t2ina
+3tine.
+3tini
+1tio
+ti5oc
+tion5ee
+5tiq
+ti3sa
+3tise
+tis4m
+ti5so
+tis4p
+5tistica
+ti3tl
+ti4u
+1tiv
+tiv4a
+1tiz
+ti3za
+ti3zen
+2tl
+t5la
+tlan4
+3tle.
+3tled
+3tles.
+t5let.
+t5lo
+4t1m
+tme4
+2t1n2
+1to
+to3b
+to5crat
+4todo
+2tof
+to2gr
+to5ic
+to2ma
+tom4b
+to3my
+ton4ali
+to3nat
+4tono
+4tony
+to2ra
+to3rie
+tor5iz
+tos2
+5tour
+4tout
+to3war
+4t1p
+1tra
+tra3b
+tra5ch
+traci4
+trac4it
+trac4te
+tras4
+tra5ven
+trav5es5
+tre5f
+tre4m
+trem5i
+5tria
+tri5ces
+5tricia
+4trics
+2trim
+tri4v
+tro5mi
+tron5i
+4trony
+tro5phe
+tro3sp
+tro3v
+tru5i
+trus4
+4t1s2
+t4sc
+tsh4
+t4sw
+4t3t2
+t4tes
+t5to
+ttu4
+1tu
+tu1a
+tu3ar
+tu4bi
+tud2
+4tue
+4tuf4
+5tu3i
+3tum
+tu4nis
+2t3up.
+3ture
+5turi
+tur3is
+tur5o
+tu5ry
+3tus
+4tv
+tw4
+4t1wa
+twis4
+4two
+1ty
+4tya
+2tyl
+type3
+ty5ph
+4tz
+tz4e
+4uab
+uac4
+ua5na
+uan4i
+uar5ant
+uar2d
+uar3i
+uar3t
+u1at
+uav4
+ub4e
+u4bel
+u3ber
+u4bero
+u1b4i
+u4b5ing
+u3ble.
+u3ca
+uci4b
+uc4it
+ucle3
+u3cr
+u3cu
+u4cy
+ud5d
+ud3er
+ud5est
+udev4
+u1dic
+ud3ied
+ud3ies
+ud5is
+u5dit
+u4don
+ud4si
+u4du
+u4ene
+uens4
+uen4te
+uer4il
+3ufa
+u3fl
+ugh3en
+ug5in
+2ui2
+uil5iz
+ui4n
+u1ing
+uir4m
+uita4
+uiv3
+uiv4er.
+u5j
+4uk
+u1la
+ula5b
+u5lati
+ulch4
+5ulche
+ul3der
+ul4e
+u1len
+ul4gi
+ul2i
+u5lia
+ul3ing
+ul5ish
+ul4lar
+ul4li4b
+ul4lis
+4ul3m
+u1l4o
+4uls
+uls5es
+ul1ti
+ultra3
+4ultu
+u3lu
+ul5ul
+ul5v
+um5ab
+um4bi
+um4bly
+u1mi
+u4m3ing
+umor5o
+um2p
+unat4
+u2ne
+un4er
+u1ni
+un4im
+u2nin
+un5ish
+uni3v
+un3s4
+un4sw
+unt3ab
+un4ter.
+un4tes
+unu4
+un5y
+un5z
+u4ors
+u5os
+u1ou
+u1pe
+uper5s
+u5pia
+up3ing
+u3pl
+up3p
+upport5
+upt5ib
+uptu4
+u1ra
+4ura.
+u4rag
+u4ras
+ur4be
+urc4
+ur1d
+ure5at
+ur4fer
+ur4fr
+u3rif
+uri4fic
+ur1in
+u3rio
+u1rit
+ur3iz
+ur2l
+url5ing.
+ur4no
+uros4
+ur4pe
+ur4pi
+urs5er
+ur5tes
+ur3the
+urti4
+ur4tie
+u3ru
+2us
+u5sad
+u5san
+us4ap
+usc2
+us3ci
+use5a
+u5sia
+u3sic
+us4lin
+us1p
+us5sl
+us5tere
+us1tr
+u2su
+usur4
+uta4b
+u3tat
+4ute.
+4utel
+4uten
+uten4i
+4u1t2i
+uti5liz
+u3tine
+ut3ing
+ution5a
+u4tis
+5u5tiz
+u4t1l
+ut5of
+uto5g
+uto5matic
+u5ton
+u4tou
+uts4
+u3u
+uu4m
+u1v2
+uxu3
+uz4e
+1va
+5va.
+2v1a4b
+vac5il
+vac3u
+vag4
+va4ge
+va5lie
+val5o
+val1u
+va5mo
+va5niz
+va5pi
+var5ied
+3vat
+4ve.
+4ved
+veg3
+v3el.
+vel3li
+ve4lo
+v4ely
+ven3om
+v5enue
+v4erd
+5vere.
+v4erel
+v3eren
+ver5enc
+v4eres
+ver3ie
+vermi4n
+3verse
+ver3th
+v4e2s
+4ves.
+ves4te
+ve4te
+vet3er
+ve4ty
+vi5ali
+5vian
+5vide.
+5vided
+4v3iden
+5vides
+5vidi
+v3if
+vi5gn
+vik4
+2vil
+5vilit
+v3i3liz
+v1in
+4vi4na
+v2inc
+vin5d
+4ving
+vio3l
+v3io4r
+vi1ou
+vi4p
+vi5ro
+vis3it
+vi3so
+vi3su
+4viti
+vit3r
+4vity
+3viv
+5vo.
+voi4
+3vok
+vo4la
+v5ole
+5volt
+3volv
+vom5i
+vor5ab
+vori4
+vo4ry
+vo4ta
+4votee
+4vv4
+v4y
+w5abl
+2wac
+wa5ger
+wag5o
+wait5
+w5al.
+wam4
+war4t
+was4t
+wa1te
+wa5ver
+w1b
+wea5rie
+weath3
+wed4n
+weet3
+wee5v
+wel4l
+w1er
+west3
+w3ev
+whi4
+wi2
+wil2
+will5in
+win4de
+win4g
+wir4
+3wise
+with3
+wiz5
+w4k
+wl4es
+wl3in
+w4no
+1wo2
+wom1
+wo5ven
+w5p
+wra4
+wri4
+writa4
+w3sh
+ws4l
+ws4pe
+w5s4t
+4wt
+wy4
+x1a
+xac5e
+x4ago
+xam3
+x4ap
+xas5
+x3c2
+x1e
+xe4cuto
+x2ed
+xer4i
+xe5ro
+x1h
+xhi2
+xhil5
+xhu4
+x3i
+xi5a
+xi5c
+xi5di
+x4ime
+xi5miz
+x3o
+x4ob
+x3p
+xpan4d
+xpecto5
+xpe3d
+x1t2
+x3ti
+x1u
+xu3a
+xx4
+y5ac
+3yar4
+y5at
+y1b
+y1c
+y2ce
+yc5er
+y3ch
+ych4e
+ycom4
+ycot4
+y1d
+y5ee
+y1er
+y4erf
+yes4
+ye4t
+y5gi
+4y3h
+y1i
+y3la
+ylla5bl
+y3lo
+y5lu
+ymbol5
+yme4
+ympa3
+yn3chr
+yn5d
+yn5g
+yn5ic
+5ynx
+y1o4
+yo5d
+y4o5g
+yom4
+yo5net
+y4ons
+y4os
+y4ped
+yper5
+yp3i
+y3po
+y4poc
+yp2ta
+y5pu
+yra5m
+yr5ia
+y3ro
+yr4r
+ys4c
+y3s2e
+ys3ica
+ys3io
+3ysis
+y4so
+yss4
+ys1t
+ys3ta
+ysur4
+y3thin
+yt3ic
+y1w
+za1
+z5a2b
+zar2
+4zb
+2ze
+ze4n
+ze4p
+z1er
+ze3ro
+zet4
+2z1i
+z4il
+z4is
+5zl
+4zm
+1zo
+zo4m
+zo5ol
+zte4
+4z1z2
+z4zy
+Á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Õ
+Ï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Á
+À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
+.×ÐÌ2
+.×ÐÒ2
+.×Ò2
+.×Ó2
+.×ÓË2
+.×ÓËÒ2
+.×ÓÌ2
+.×ÓÍ2
+.×ÓÐ2
+.×ÓÐÌ2
+.×ÓÐÒ2
+.×ÓÔ2
+.×ÓÔÒ2
+.×ÓÈ2
+.×ÓÈÌ2
+.×Ô2
+.×ÔÒ2
+.×È2
+.×Ã2
+.×Þ2
+.×Ø2
+.Ç×2
+.ÇÄ2
+.ÇÌ2
+.ÇÎ2
+.ÇÒ2
+.Ä×2
+.ÄÌ2
+.ÄÎ2
+.ÄÒ2
+.ÄØ2
+.Ö×2
+.ÖÇ2
+.ÖÇÌ2
+.ÖÄ2
+.ÖÖ2
+.ÖÒ2
+.Ú×2
+.ÚÄ2
+.ÚÄÒ2
+.ÚÌ2
+.ÚÍ2
+.ÚÎ2
+.ÚÒ2
+.Ë×2
+.ËÌ2
+.ËÎ2
+.ËÒ2
+.ËÓÔ2
+.ËÔ2
+.ÌÂ2
+.ÌÇ2
+.ÌÖ2
+.ÌØ2
+.ÌØ×2
+.ÍÇÌ2
+.ÍÇÎ2
+.ÍÌ2
+.ÍÎ2
+.ÍÒ2
+.ÍÓÔ2
+.ÍÈ2
+.ÍÞ2
+.ÍÝ2
+.ÎÒ2
+.ÐÌ2
+.ÐÎ2
+.ÐÒ2
+.ÐÓ2
+.ÐÔ2
+.ÐÈ2
+.ÐÞ2
+.ÐÛ2
+.ÐØ2
+.Ò×2
+.ÒÖ2
+.ÒÔ2
+.ÓÂ2
+.ÓÂÌ2
+.ÓÂÒ2
+.Ó×2
+.Ó×ÓÔ2
+.ÓÇ2
+.ÓÇÎ2
+.ÓÇÒ2
+.ÓÄ2
+.ÓÄ×2
+.ÓÄÒ2
+.ÓÖ2
+.ÓÚ2
+.ÓË2
+.ÓË×2
+.ÓËÌ2
+.ÓËÒ2
+.ÓÌ2
+.ÓÍ2
+.ÓÎ2
+.ÓÐ2
+.ÓÐÌ2
+.ÓÐÒ2
+.ÓÒ2
+.ÓÓ2
+.ÓÔ2
+.ÓÔ×2
+.ÓÔÌ2
+.ÓÔÒ2
+.ÓÆ2
+.ÓÈ2
+.ÓÈ×2
+.ÓÈÌ2
+.ÓÞ2
+.ÓÛ2
+.Óß2
+.Ô×2
+.ÔË2
+.ÔËÎ2
+.ÔÌ2
+.ÔÒ2
+.ÔÝ2
+.ÔØÍ2
+.ÔØÆ2
+.ÆÌ2
+.ÆÒ2
+.È×2
+.ÈÌ2
+.ÈÍ2
+.ÈÎ2
+.ÈÒ2
+.Ã×2
+.ÞÌ2
+.ÞÒ2
+.ÞÔ2
+.ÞØ2
+.Û×2
+.ÛË2
+.ÛË×2
+.ÛÌ2
+.ÛÎ2
+.ÛÐ2
+.ÛÒ2
+.ÛÔ2
+.ÛÔÒ2
+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ÖÕ
+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ÎÏ
+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ÔÙ
+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ÝÉ
+1ÝÏ
diff --git a/gnu/usr.bin/groff/tmac/koi8-r b/gnu/usr.bin/groff/tmac/koi8-r
new file mode 100644
index 0000000..8244049
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/koi8-r
@@ -0,0 +1,126 @@
+.\" Copyright (c) 2001 Ruslan Ermilov <ru@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.\" %beginstrip%
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Dt
+.ds doc-volume-ds-1 óÐÒÁ×ÏÞÎÉË ÏÓÎÏ×ÎÙÈ ËÏÍÁÎÄ
+.ds doc-volume-ds-2 óÐÒÁ×ÏÞÎÉË ÓÉÓÔÅÍÎÙÈ ×ÙÚÏ×Ï×
+.ds doc-volume-ds-3 óÐÒÁ×ÏÞÎÉË ÂÉÂÌÉÏÔÅÞÎÙÈ ÆÕÎËÃÉÊ
+.ds doc-volume-ds-4 óÐÒÁ×ÏÞÎÉË ÉÎÔÅÒÆÅÊÓÏ× ÑÄÒÁ
+.ds doc-volume-ds-5 óÐÒÁ×ÏÞÎÉË ÆÏÒÍÁÔÏ× ÆÁÊÌÏ×
+.ds doc-volume-ds-6 óÐÒÁ×ÏÞÎÉË ÉÇÒ
+.ds doc-volume-ds-7 óÐÒÁ×ÏÞÎÉË ÒÁÚÎÏÊ ÉÎÆÏÒÍÁÃÉÉ
+.ds doc-volume-ds-8 óÐÒÁ×ÏÞÎÉË ÓÉÓÔÅÍÎÏÇÏ ÁÄÍÉÎÉÓÔÒÁÔÏÒÁ
+.ds doc-volume-ds-9 óÐÒÁ×ÏÞÎÉË ÒÁÚÒÁÂÏÔÞÉËÁ ÑÄÒÁ
+.
+.ds doc-volume-ds-USD äÏÐÏÌÎÉÔÅÌØÎÙÅ ÄÏËÕÍÅÎÔÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ
+.ds doc-volume-ds-PS1 äÏÐÏÌÎÉÔÅÌØÎÙÅ ÄÏËÕÍÅÎÔÙ ÄÌÑ ÐÒÏÇÒÁÍÍÉÓÔÁ
+.ds doc-volume-ds-AMD äÏËÕÍÅÎÔÙ ÕÎÁÓÌÅÄÏ×ÁÎÎÏÇÏ ÓÐÒÁ×ÏÞÎÉËÁ
+.ds doc-volume-ds-SMM òÕËÏ×ÏÄÓÔ×Ï ÓÉÓÔÅÍÎÏÇÏ ÁÄÍÉÎÉÓÔÒÁÔÏÒÁ
+.ds doc-volume-ds-URM óÐÒÁ×ÏÞÎÏÅ ÒÕËÏ×ÏÄÓÔ×Ï
+.ds doc-volume-ds-PRM òÕËÏ×ÏÄÓÔ×Ï ÐÒÏÇÒÁÍÍÉÓÔÁ
+.ds doc-volume-ds-KM òÕËÏ×ÏÄÓÔ×Ï ÐÏ ÑÄÒÕ
+.ds doc-volume-ds-IND ïÓÎÏ×ÎÏÊ ÐÒÅÄÍÅÔÎÙÊ ÕËÁÚÁÔÅÌØ ÓÐÒÁ×ÏÞÎÉËÁ
+.ds doc-volume-ds-LOCAL ìÏËÁÌØÎÙÊ ÓÐÒÁ×ÏÞÎÉË
+.ds doc-volume-ds-CON óÐÒÁ×ÏÞÎÉË ÐÏ ÄÏÐÏÌÎÉÔÅÌØÎÏÍÕ ðï
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Os
+.ds doc-operating-system-ATT-7 7Ñ\~ÒÅÄÁËÃÉÑ
+.ds doc-operating-system-BSD-3 3Ê\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4 4Ê\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.1 4.1\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.2 4.2\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.3 4.3\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.3T 4.3-Tahoe ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.3R 4.3-Reno ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Sh
+.ds doc-section-name îáú÷áîéå
+.ds doc-section-synopsis óéîôáëóéó
+.ds doc-section-description ïðéóáîéå
+.ds doc-section-see-also óíïôòé
+.ds doc-section-files æáêìù
+.ds doc-section-authors á÷ôïòù
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Lb (XXX)
+.ds doc-str-Lb-libarm32 âÉÂÌÉÏÔÅËÁ ÁÒÈÉÔÅËÔÕÒÙ ARM32 (libarm32, \-larm32)
+.ds doc-str-Lb-libc óÔÁÎÄÁÒÔÎÁÑ ÂÉÂÌÉÏÔÅËÁ\~C (libc, \-lc)
+.ds doc-str-Lb-libc_r òÅÅÎÔÅÒÁÂÅÌØÎÁÑ ÂÉÂÌÉÏÔÅËÁ\~C (libc_r, \-lc_r)
+.ds doc-str-Lb-libcalendar âÉÂÌÉÏÔÅËÁ ËÁÌÅÎÄÁÒÎÏÊ ÁÒÉÆÍÅÔÉËÉ (libcalendar, \-lcalendar)
+.ds doc-str-Lb-libcam ðÏÌØÚÏ×ÁÔÅÌØÓËÁÑ ÂÉÂÌÉÏÔÅËÁ CAM (libcam, \-lcam)
+.ds doc-str-Lb-libcipher âÉÂÌÉÏÔÅËÁ ËÒÉÐÔÏÇÒÁÆÉÉ FreeSec (libcipher, \-lcipher)
+.ds doc-str-Lb-libcompat âÉÂÌÉÏÔÅËÁ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ (libcompat, \-lcompat)
+.ds doc-str-Lb-libcrypt âÉÂÌÉÏÔÅËÁ ËÒÉÐÔÏÇÒÁÆÉÉ (libcrypt, \-lcrypt)
+.ds doc-str-Lb-libcurses Curses Library (libcurses, \-lcurses)
+.ds doc-str-Lb-libdevstat âÉÂÌÉÏÔÅËÁ ÓÔÁÔÉÓÔÉËÉ ÕÓÔÒÏÊÓÔ× (libdevstat, \-ldevstat)
+.ds doc-str-Lb-libdisk Interface to Slice and Partition Labels Library (libdisk, \-ldisk)
+.ds doc-str-Lb-libedit âÉÂÌÉÏÔÅËÁ ÒÅÄÁËÔÏÒÁ ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ (libedit, \-ledit)
+.ds doc-str-Lb-libfetch âÉÂÌÉÏÔÅËÁ ÆÁÊÌÏ×ÏÊ ÐÅÒÅÄÁÞÉ (libfetch, \-lfetch)
+.ds doc-str-Lb-libi386 âÉÂÌÉÏÔÅËÁ ÁÒÈÉÔÅËÔÕÒÙ i386 (libi386, \-li386)
+.ds doc-str-Lb-libipsec âÉÂÌÉÏÔÅËÁ ÕÐÒÁ×ÌÅÎÉÑ IPsec Policy (libipsec, \-lipsec)
+.ds doc-str-Lb-libipx âÉÂÌÉÏÔÅËÁ ÐÏÄÄÅÒÖËÉ ËÏÎ×ÅÒÓÉÉ ÁÄÒÅÓÏ× IPX (libipx, \-lipx)
+.ds doc-str-Lb-libkvm âÉÂÌÉÏÔÅËÁ ÄÏÓÔÕÐÁ Ë ÄÁÎÎÙÍ ÑÄÒÁ (libkvm, \-lkvm)
+.ds doc-str-Lb-libm âÉÂÌÉÏÔÅËÁ ÍÁÔÅÍÁÔÉÞÅÓËÉÈ ÆÕÎËÃÉÊ (libm, \-lm)
+.ds doc-str-Lb-libmd Message Digest (MD4, MD5, É Ô.Ä.) Support Library (libmd, \-lmd)
+.ds doc-str-Lb-libmenu Curses Menu Library (libmenu, \-lmenu)
+.ds doc-str-Lb-libnetgraph ðÏÌØÚÏ×ÁÔÅÌØÓËÁÑ ÂÉÂÌÉÏÔÅËÁ Netgraph (libnetgraph, \-lnetgraph)
+.ds doc-str-Lb-libossaudio âÉÂÌÉÏÔÅËÁ ÜÍÕÌÑÃÉÉ OSS Audio (libossaudio, \-lossaudio)
+.ds doc-str-Lb-libpam âÉÂÌÉÏÔÅËÁ PAM (libpam, \-lpam)
+.ds doc-str-Lb-libposix âÉÂÌÉÏÔÅËÁ \*[Px]\-ÓÏ×ÍÅÓÔÉÍÏÓÔÉ (libposix, \-lposix)
+.ds doc-str-Lb-libresolv DNS Resolver Library (libresolv, \-lresolv)
+.ds doc-str-Lb-librpcsvc âÉÂÌÉÏÔÅËÁ ÓÌÕÖ RPC (librpcsvc, \-lrpcsvc)
+.ds doc-str-Lb-libskey S/Key Password Control Table Access Library (libskey, \-lskey)
+.ds doc-str-Lb-libtermcap âÉÂÌÉÏÔÅËÁ ÄÏÓÔÕÐÁ Ë termcap (libtermcap, \-ltermcap)
+.ds doc-str-Lb-libusb âÉÂÌÉÏÔÅËÁ ÆÕÎËÃÉÊ ÄÏÓÔÕÐÁ Ë USB HID (libusb, \-lusb)
+.ds doc-str-Lb-libutil âÉÂÌÉÏÔÅËÁ ÓÉÓÔÅÍÎÙÈ ÕÔÉÌÉÔ (libutil, \-lutil)
+.ds doc-str-Lb-libvgl âÉÂÌÉÏÔÅËÁ ×ÉÄÅÏ-ÇÒÁÆÉËÉ (libvgl, \-lvgl)
+.ds doc-str-Lb-libz âÉÂÌÉÏÔÅËÁ ËÏÍÐÒÅÓÓÉÉ (libz, \-lz)
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Rv
+.ds doc-str-Rv-std-prefix "æÕÎËÃÉÑ
+.ds doc-str-Rv-std-suffix "×ÏÚ×ÒÁÝÁÅÔ\~0 × ÓÌÕÞÁÅ ÕÓÐÅÛÎÏÇÏ ÚÁ×ÅÒÛÅÎÉÑ;
+.as doc-str-Rv-std-suffix " × ÐÒÏÔÉ×ÎÏÍ ÓÌÕÞÁÅ ÏÎÁ ×ÏÚ×ÒÁÝÁÅÔ\~-1,
+.as doc-str-Rv-std-suffix " Á ËÏÄ ÏÛÉÂËÉ ÓÏÈÒÁÎÑÅÔÓÑ × ÇÌÏÂÁÌØÎÏÊ
+.as doc-str-Rv-std-suffix " ÐÅÒÅÍÅÎÎÏÊ \*[doc-Va-font]errno\f[P].
+.
+.ds doc-str-Rv-stds-prefix "æÕÎËÃÉÉ
+.ds doc-str-Rv-stds-and "É
+.ds doc-str-Rv-stds-suffix "×ÏÚ×ÒÁÝÁÀÔ\~0 × ÓÌÕÞÁÅ ÕÓÐÅÛÎÏÇÏ ÚÁ×ÅÒÛÅÎÉÑ;
+.as doc-str-Rv-stds-suffix " × ÐÒÏÔÉ×ÎÏÍ ÓÌÕÞÁÅ ÏÎÉ ×ÏÚ×ÒÁÝÁÀÔ\~-1,
+.as doc-str-Rv-stds-suffix " Á ËÏÄ ÏÛÉÂËÉ ÓÏÈÒÁÎÑÅÔÓÑ × ÇÌÏÂÁÌØÎÏÊ
+.as doc-str-Rv-stds-suffix " ÐÅÒÅÍÅÎÎÏÊ \*[doc-Va-font]errno\f[P].
+.
+.ds doc-str-Rv-std0 "÷ ÓÌÕÞÁÅ ÕÓÐÅÛÎÏÇÏ ÚÁ×ÅÒÛÅÎÉÑ ×ÏÚ×ÒÁÝÁÅÔÓÑ\~0;
+.as doc-str-Rv-std0 " × ÐÒÏÔÉ×ÎÏÍ ÓÌÕÞÁÅ ×ÏÚ×ÒÁÝÁÅÔÓÑ\~-1,
+.as doc-str-Rv-std0 " Á ËÏÄ ÏÛÉÂËÉ ÓÏÈÒÁÎÑÅÔÓÑ × ÇÌÏÂÁÌØÎÏÊ
+.as doc-str-Rv-std0 " ÐÅÒÅÍÅÎÎÏÊ \*[doc-Va-font]errno\f[P].
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Ar
+.ds doc-str-Ar-default "ÆÁÊÌ\ .\|.\|.
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .%A
+.ds doc-str-dpra "É
diff --git a/gnu/usr.bin/groff/tmac/mdoc.local b/gnu/usr.bin/groff/tmac/mdoc.local
new file mode 100644
index 0000000..db9abb7
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/mdoc.local
@@ -0,0 +1,65 @@
+.\" Copyright (c) 2001 Ruslan Ermilov <ru@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.\" %beginstrip%
+.
+.eo
+.
+.
+.ds doc-volume-operating-system FreeBSD
+.
+.\" FreeBSD .Lb values
+.ds doc-str-Lb-libc_r Reentrant C\~Library (libc_r, \-lc_r)
+.ds doc-str-Lb-libcalendar Calendar Arithmetic Library (libcalendar, \-lcalendar)
+.ds doc-str-Lb-libcam Common Access Method User Library (libcam, \-lcam)
+.ds doc-str-Lb-libcipher FreeSec Crypt Library (libcipher, \-lcipher)
+.ds doc-str-Lb-libdevinfo Device and Resource Information Utility Library (libdevinfo, \-ldevinfo)
+.ds doc-str-Lb-libdevstat Device Statistics Library (libdevstat, \-ldevstat)
+.ds doc-str-Lb-libdisk Interface to Slice and Partition Labels Library (libdisk, \-ldisk)
+.ds doc-str-Lb-libedit Line Editor and History Library (libedit, \-ledit)
+.ds doc-str-Lb-libfetch File Transfer Library (libfetch, \-lfetch)
+.ds doc-str-Lb-libipx IPX Address Conversion Support Library (libipx, \-lipx)
+.ds doc-str-Lb-libmd Message Digest (MD4, MD5, etc.) Support Library (libmd, \-lmd)
+.ds doc-str-Lb-libnetgraph Netgraph User Library (libnetgraph, \-lnetgraph)
+.ds doc-str-Lb-libpam PAM Library (libpam, \-lpam)
+.ds doc-str-Lb-librpcsvc RPC Service Library (librpcsvc, \-lrpcsvc)
+.ds doc-str-Lb-libskey S/Key Password Control Table Access Library (libskey, \-lskey)
+.ds doc-str-Lb-libusbhid USB HID access routines library (libusbhid, \-lusbhid)
+.ds doc-str-Lb-libvgl Video Graphics Library (libvgl, \-lvgl)
+.
+.\" Default .Os value
+.ds doc-operating-system FreeBSD\~5.0
+.
+.\" FreeBSD releases not found in doc-common
+.ds doc-operating-system-FreeBSD-4.7 4.7
+.ds doc-operating-system-FreeBSD-4.8 4.8
+.
+.ec
+.
+.\" Locale support
+.if d doc-lang \{\
+. if "\*[doc-lang]"ru.KOI8-R" .mso mdoc/koi8-r
+.\}
diff --git a/gnu/usr.bin/groff/tmac/ru.KOI8-R b/gnu/usr.bin/groff/tmac/ru.KOI8-R
new file mode 100644
index 0000000..8244049
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/ru.KOI8-R
@@ -0,0 +1,126 @@
+.\" Copyright (c) 2001 Ruslan Ermilov <ru@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.\" %beginstrip%
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Dt
+.ds doc-volume-ds-1 óÐÒÁ×ÏÞÎÉË ÏÓÎÏ×ÎÙÈ ËÏÍÁÎÄ
+.ds doc-volume-ds-2 óÐÒÁ×ÏÞÎÉË ÓÉÓÔÅÍÎÙÈ ×ÙÚÏ×Ï×
+.ds doc-volume-ds-3 óÐÒÁ×ÏÞÎÉË ÂÉÂÌÉÏÔÅÞÎÙÈ ÆÕÎËÃÉÊ
+.ds doc-volume-ds-4 óÐÒÁ×ÏÞÎÉË ÉÎÔÅÒÆÅÊÓÏ× ÑÄÒÁ
+.ds doc-volume-ds-5 óÐÒÁ×ÏÞÎÉË ÆÏÒÍÁÔÏ× ÆÁÊÌÏ×
+.ds doc-volume-ds-6 óÐÒÁ×ÏÞÎÉË ÉÇÒ
+.ds doc-volume-ds-7 óÐÒÁ×ÏÞÎÉË ÒÁÚÎÏÊ ÉÎÆÏÒÍÁÃÉÉ
+.ds doc-volume-ds-8 óÐÒÁ×ÏÞÎÉË ÓÉÓÔÅÍÎÏÇÏ ÁÄÍÉÎÉÓÔÒÁÔÏÒÁ
+.ds doc-volume-ds-9 óÐÒÁ×ÏÞÎÉË ÒÁÚÒÁÂÏÔÞÉËÁ ÑÄÒÁ
+.
+.ds doc-volume-ds-USD äÏÐÏÌÎÉÔÅÌØÎÙÅ ÄÏËÕÍÅÎÔÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ
+.ds doc-volume-ds-PS1 äÏÐÏÌÎÉÔÅÌØÎÙÅ ÄÏËÕÍÅÎÔÙ ÄÌÑ ÐÒÏÇÒÁÍÍÉÓÔÁ
+.ds doc-volume-ds-AMD äÏËÕÍÅÎÔÙ ÕÎÁÓÌÅÄÏ×ÁÎÎÏÇÏ ÓÐÒÁ×ÏÞÎÉËÁ
+.ds doc-volume-ds-SMM òÕËÏ×ÏÄÓÔ×Ï ÓÉÓÔÅÍÎÏÇÏ ÁÄÍÉÎÉÓÔÒÁÔÏÒÁ
+.ds doc-volume-ds-URM óÐÒÁ×ÏÞÎÏÅ ÒÕËÏ×ÏÄÓÔ×Ï
+.ds doc-volume-ds-PRM òÕËÏ×ÏÄÓÔ×Ï ÐÒÏÇÒÁÍÍÉÓÔÁ
+.ds doc-volume-ds-KM òÕËÏ×ÏÄÓÔ×Ï ÐÏ ÑÄÒÕ
+.ds doc-volume-ds-IND ïÓÎÏ×ÎÏÊ ÐÒÅÄÍÅÔÎÙÊ ÕËÁÚÁÔÅÌØ ÓÐÒÁ×ÏÞÎÉËÁ
+.ds doc-volume-ds-LOCAL ìÏËÁÌØÎÙÊ ÓÐÒÁ×ÏÞÎÉË
+.ds doc-volume-ds-CON óÐÒÁ×ÏÞÎÉË ÐÏ ÄÏÐÏÌÎÉÔÅÌØÎÏÍÕ ðï
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Os
+.ds doc-operating-system-ATT-7 7Ñ\~ÒÅÄÁËÃÉÑ
+.ds doc-operating-system-BSD-3 3Ê\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4 4Ê\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.1 4.1\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.2 4.2\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.3 4.3\~ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.3T 4.3-Tahoe ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.ds doc-operating-system-BSD-4.3R 4.3-Reno ÄÉÓÔÒÉÂÕÔÉ× âÅÒËÌÉ
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Sh
+.ds doc-section-name îáú÷áîéå
+.ds doc-section-synopsis óéîôáëóéó
+.ds doc-section-description ïðéóáîéå
+.ds doc-section-see-also óíïôòé
+.ds doc-section-files æáêìù
+.ds doc-section-authors á÷ôïòù
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Lb (XXX)
+.ds doc-str-Lb-libarm32 âÉÂÌÉÏÔÅËÁ ÁÒÈÉÔÅËÔÕÒÙ ARM32 (libarm32, \-larm32)
+.ds doc-str-Lb-libc óÔÁÎÄÁÒÔÎÁÑ ÂÉÂÌÉÏÔÅËÁ\~C (libc, \-lc)
+.ds doc-str-Lb-libc_r òÅÅÎÔÅÒÁÂÅÌØÎÁÑ ÂÉÂÌÉÏÔÅËÁ\~C (libc_r, \-lc_r)
+.ds doc-str-Lb-libcalendar âÉÂÌÉÏÔÅËÁ ËÁÌÅÎÄÁÒÎÏÊ ÁÒÉÆÍÅÔÉËÉ (libcalendar, \-lcalendar)
+.ds doc-str-Lb-libcam ðÏÌØÚÏ×ÁÔÅÌØÓËÁÑ ÂÉÂÌÉÏÔÅËÁ CAM (libcam, \-lcam)
+.ds doc-str-Lb-libcipher âÉÂÌÉÏÔÅËÁ ËÒÉÐÔÏÇÒÁÆÉÉ FreeSec (libcipher, \-lcipher)
+.ds doc-str-Lb-libcompat âÉÂÌÉÏÔÅËÁ ÓÏ×ÍÅÓÔÉÍÏÓÔÉ (libcompat, \-lcompat)
+.ds doc-str-Lb-libcrypt âÉÂÌÉÏÔÅËÁ ËÒÉÐÔÏÇÒÁÆÉÉ (libcrypt, \-lcrypt)
+.ds doc-str-Lb-libcurses Curses Library (libcurses, \-lcurses)
+.ds doc-str-Lb-libdevstat âÉÂÌÉÏÔÅËÁ ÓÔÁÔÉÓÔÉËÉ ÕÓÔÒÏÊÓÔ× (libdevstat, \-ldevstat)
+.ds doc-str-Lb-libdisk Interface to Slice and Partition Labels Library (libdisk, \-ldisk)
+.ds doc-str-Lb-libedit âÉÂÌÉÏÔÅËÁ ÒÅÄÁËÔÏÒÁ ËÏÍÁÎÄÎÏÊ ÓÔÒÏËÉ (libedit, \-ledit)
+.ds doc-str-Lb-libfetch âÉÂÌÉÏÔÅËÁ ÆÁÊÌÏ×ÏÊ ÐÅÒÅÄÁÞÉ (libfetch, \-lfetch)
+.ds doc-str-Lb-libi386 âÉÂÌÉÏÔÅËÁ ÁÒÈÉÔÅËÔÕÒÙ i386 (libi386, \-li386)
+.ds doc-str-Lb-libipsec âÉÂÌÉÏÔÅËÁ ÕÐÒÁ×ÌÅÎÉÑ IPsec Policy (libipsec, \-lipsec)
+.ds doc-str-Lb-libipx âÉÂÌÉÏÔÅËÁ ÐÏÄÄÅÒÖËÉ ËÏÎ×ÅÒÓÉÉ ÁÄÒÅÓÏ× IPX (libipx, \-lipx)
+.ds doc-str-Lb-libkvm âÉÂÌÉÏÔÅËÁ ÄÏÓÔÕÐÁ Ë ÄÁÎÎÙÍ ÑÄÒÁ (libkvm, \-lkvm)
+.ds doc-str-Lb-libm âÉÂÌÉÏÔÅËÁ ÍÁÔÅÍÁÔÉÞÅÓËÉÈ ÆÕÎËÃÉÊ (libm, \-lm)
+.ds doc-str-Lb-libmd Message Digest (MD4, MD5, É Ô.Ä.) Support Library (libmd, \-lmd)
+.ds doc-str-Lb-libmenu Curses Menu Library (libmenu, \-lmenu)
+.ds doc-str-Lb-libnetgraph ðÏÌØÚÏ×ÁÔÅÌØÓËÁÑ ÂÉÂÌÉÏÔÅËÁ Netgraph (libnetgraph, \-lnetgraph)
+.ds doc-str-Lb-libossaudio âÉÂÌÉÏÔÅËÁ ÜÍÕÌÑÃÉÉ OSS Audio (libossaudio, \-lossaudio)
+.ds doc-str-Lb-libpam âÉÂÌÉÏÔÅËÁ PAM (libpam, \-lpam)
+.ds doc-str-Lb-libposix âÉÂÌÉÏÔÅËÁ \*[Px]\-ÓÏ×ÍÅÓÔÉÍÏÓÔÉ (libposix, \-lposix)
+.ds doc-str-Lb-libresolv DNS Resolver Library (libresolv, \-lresolv)
+.ds doc-str-Lb-librpcsvc âÉÂÌÉÏÔÅËÁ ÓÌÕÖ RPC (librpcsvc, \-lrpcsvc)
+.ds doc-str-Lb-libskey S/Key Password Control Table Access Library (libskey, \-lskey)
+.ds doc-str-Lb-libtermcap âÉÂÌÉÏÔÅËÁ ÄÏÓÔÕÐÁ Ë termcap (libtermcap, \-ltermcap)
+.ds doc-str-Lb-libusb âÉÂÌÉÏÔÅËÁ ÆÕÎËÃÉÊ ÄÏÓÔÕÐÁ Ë USB HID (libusb, \-lusb)
+.ds doc-str-Lb-libutil âÉÂÌÉÏÔÅËÁ ÓÉÓÔÅÍÎÙÈ ÕÔÉÌÉÔ (libutil, \-lutil)
+.ds doc-str-Lb-libvgl âÉÂÌÉÏÔÅËÁ ×ÉÄÅÏ-ÇÒÁÆÉËÉ (libvgl, \-lvgl)
+.ds doc-str-Lb-libz âÉÂÌÉÏÔÅËÁ ËÏÍÐÒÅÓÓÉÉ (libz, \-lz)
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Rv
+.ds doc-str-Rv-std-prefix "æÕÎËÃÉÑ
+.ds doc-str-Rv-std-suffix "×ÏÚ×ÒÁÝÁÅÔ\~0 × ÓÌÕÞÁÅ ÕÓÐÅÛÎÏÇÏ ÚÁ×ÅÒÛÅÎÉÑ;
+.as doc-str-Rv-std-suffix " × ÐÒÏÔÉ×ÎÏÍ ÓÌÕÞÁÅ ÏÎÁ ×ÏÚ×ÒÁÝÁÅÔ\~-1,
+.as doc-str-Rv-std-suffix " Á ËÏÄ ÏÛÉÂËÉ ÓÏÈÒÁÎÑÅÔÓÑ × ÇÌÏÂÁÌØÎÏÊ
+.as doc-str-Rv-std-suffix " ÐÅÒÅÍÅÎÎÏÊ \*[doc-Va-font]errno\f[P].
+.
+.ds doc-str-Rv-stds-prefix "æÕÎËÃÉÉ
+.ds doc-str-Rv-stds-and "É
+.ds doc-str-Rv-stds-suffix "×ÏÚ×ÒÁÝÁÀÔ\~0 × ÓÌÕÞÁÅ ÕÓÐÅÛÎÏÇÏ ÚÁ×ÅÒÛÅÎÉÑ;
+.as doc-str-Rv-stds-suffix " × ÐÒÏÔÉ×ÎÏÍ ÓÌÕÞÁÅ ÏÎÉ ×ÏÚ×ÒÁÝÁÀÔ\~-1,
+.as doc-str-Rv-stds-suffix " Á ËÏÄ ÏÛÉÂËÉ ÓÏÈÒÁÎÑÅÔÓÑ × ÇÌÏÂÁÌØÎÏÊ
+.as doc-str-Rv-stds-suffix " ÐÅÒÅÍÅÎÎÏÊ \*[doc-Va-font]errno\f[P].
+.
+.ds doc-str-Rv-std0 "÷ ÓÌÕÞÁÅ ÕÓÐÅÛÎÏÇÏ ÚÁ×ÅÒÛÅÎÉÑ ×ÏÚ×ÒÁÝÁÅÔÓÑ\~0;
+.as doc-str-Rv-std0 " × ÐÒÏÔÉ×ÎÏÍ ÓÌÕÞÁÅ ×ÏÚ×ÒÁÝÁÅÔÓÑ\~-1,
+.as doc-str-Rv-std0 " Á ËÏÄ ÏÛÉÂËÉ ÓÏÈÒÁÎÑÅÔÓÑ × ÇÌÏÂÁÌØÎÏÊ
+.as doc-str-Rv-std0 " ÐÅÒÅÍÅÎÎÏÊ \*[doc-Va-font]errno\f[P].
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .Ar
+.ds doc-str-Ar-default "ÆÁÊÌ\ .\|.\|.
+.
+.\" ÌÏËÁÌÉÚÁÃÉÑ .%A
+.ds doc-str-dpra "É
diff --git a/gnu/usr.bin/gzip/COPYING b/gnu/usr.bin/gzip/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/gnu/usr.bin/gzip/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/gzip/ChangeLog b/gnu/usr.bin/gzip/ChangeLog
new file mode 100644
index 0000000..7dd0f86
--- /dev/null
+++ b/gnu/usr.bin/gzip/ChangeLog
@@ -0,0 +1,587 @@
+Wed Aug 18 09:34:23 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.2.4
+ By default, do not restore file name and timestamp from those saved
+ inside the .gz file (behave as 'compress'). Added the --name option
+ to force name and timestamp restoration.
+ Accept - as synonym for stdin.
+ Use manlinks=so or ln to support either hard links or .so in man pages
+ Accept foo.gz~ in zdiff.
+ Added support for Windows NT
+ Handle ENAMETOOLONG for strict Posix systems
+ Use --recursive instead of --recurse to comply with Webster and
+ the GNU stdandard.
+ Allow installation of shell scripts with a g prefix: make G=g install
+ Install by default zcat as gzcat if gzcat already exists in path.
+ Let zmore behave as more when invoked without parameters (give help)
+ Let gzip --list reject files not in gzip format even with --force.
+ Don't complain about non gzip files for options -rt or -rl.
+ Added advice in INSTALL for several systems.
+ Added makefile entries for NeXTstep 3.1 (if configure fails)
+ Avoid problem with memcpy on Pyramid (gave crc error on some files)
+ Support the -r option when compiled with Borland C++ on msdos.
+ Force lower case file names only for FAT file systems (not HPFS)
+ Rewrite one expression in inflate.c to avoid cc bug on Solaris x86.
+ In the msdos makefiles, get match.asm from the msdos subdirectory.
+ Catch SIGTERM and SIGHUP only if they are not ignored.
+ getopt.c: on Amiga, "#if !defined(const)" does not compile.
+ Use register parameters on Amiga.
+ Do not force names to lower case on Amiga.
+ Fix support of Atari TOS (Makefile.st and tailor.h)
+ In unlzw.c, do not suggest using zcat if zcat already used.
+ In INSTALL, suggest using bsdinst for HPUX.
+ Document Turbo C++ 1.0 bug in INSTALL.
+ Improved the documentation relative to the --no-name option.
+ Avoid signed/unsigned warnings in several files.
+ Added pointer to jka-compr19.el in README.
+ Added pointer to OS/2 executables in README.
+ Added --block-compress in tar -z example (gzip.1 and gzip.texi).
+ Don't keep rcsid in executable (avoid compilation warnings).
+ Check also the correctness of the first byte of an .Z file.
+ Return non zero status for an invalid option.
+ Remove "NEWFILES" from os2/gzip.def for Borland C++ on OS/2.
+ Remove "time stamp restored" message (just obey the -N request).
+
+Thu Jun 24 10:27:57 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.2.3
+ Don't display the output name when decompressing except with --verbose.
+ Remove usage of alloca in getopt.c and all makefiles.
+ Use ASCPP instead of CPP to avoid breaking AC_HEADER_CHECK on RiscOS.
+ Added the zfile shell script in subdirectory sample.
+ Moved the list of compiler bugs from README to INSTALL.
+ Added vms/Readme.vms.
+ Fix DIST_BUFSIZE check in unlzh.c for 16 bit machines.
+ Fix REGSIGTYP macro in configure.in.
+ Use 'define' instead of == in vms/gzip.hlp.
+ Avoid warnings in unlzh.c
+ Allow separate installation of binaries and man pages.
+ Simplified handling of file names with spaces in zgrep and znew.
+ Fix dependencies and remove rule for trees.c in amiga/Makefile.sasc
+ Add missing quote in gzexe.
+
+Thu Jun 17 13:47:05 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.2.2
+ Fix a compilation error in gzip.c on Sun with cc (worked with gcc).
+
+Wed Jun 16 11:20:27 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.2.1
+ Let zmore act as more if the data is not gzipped.
+ By default, display output name only when name was actually truncated.
+ Use absolute path names in gzexe'd programs for better security.
+ In gzexe, use chmod 700 instead of 755 and don't gzexe tail,rm,etc...
+ Update vms/gzip.hlp.
+ Added a note about the fast options (-1 to -3) in algorithm.doc.
+ Improved man page for zgrep.
+ Minor fixes to gzip.texi.
+ Always set LC_ALL and LANG in configure (for tr on HPUX)
+
+Mon Jun 14 10:03:24 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.2
+ Added the --list option to display the file characteristics.
+ Added the --no-name option: do not save or restore original filename
+ Save the original name by default.
+ Allow gunzip --suffix "" to attempt decompression on any file
+ regardless of its extension if an original name is present.
+ Add support for the SCO compress -H format.
+ gzip --fast now compresses faster (speed close to that of compress)
+ with degraded compression ratio (but still better than compress).
+ Default level changed to -6 (acts exactly as previous level -5) to
+ be a better indication of its placement in the speed/ratio range.
+ Use smart name truncation: 123456789012.c -> 123456789.c.gz
+ instead of 12345678901.gz
+ With --force, let zcat pass non gzip'ed data unchanged (zcat == cat)
+ Added the zgrep shell script.
+ Made sub.c useful for 16 bit sound, 24 bit images, etc..
+ Supress warnings about suffix for gunzip -r, except with --verbose.
+ Moved the sample programs to a subdirectory sample.
+ On MSDOS, use .gz extension when possible (files without extension)
+ Added a "Special targets" section in INSTALL.
+ Use stty -g correctly in zmore.in.
+ Use cheaper test for gzipness in zforce.in.
+ Remove space before $ in match.S (no longer accepted by gas 2.x)
+ For the shell scripts, do not assume that gzip is in the path.
+ Fix syntax error and define lnk$library in vms/Makefile.mms
+ REGSIGTYPE is void on the Amiga.
+ Do not write empty line when decompressing stdin with --verbose.
+ Fix the 1.1.2 fix for VMS (bug in get_suffix)
+ Added warning in README about compiler bug on Solaris 2.1 for x86.
+ Added warning about 'rehash' in INSTALL.
+ Removed default value of read_buf in bits.c (supermax doesn't like).
+ In tailor.h, added support for Borland C and Zortech C on OS/2.
+ Added warning in gzexe about Ultrix buggy sh (use /bin/sh5 instead).
+ Added warning in zdiff about AIX buggy sh (use /bin/ksh instead).
+ In configure.in, do not try the asm code if DEFS contains NO_ASM
+
+Fri Jun 4 09:49:33 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.1.2
+ Fix serious bug for VMS (-gz not removed when decompressing).
+ Allow suffix other than .gz in znew.
+ Do not display compression ratio when decompressing stdin.
+ In zmore.in, work around brain damaged stty -g (Ultrix).
+ Display a correct compression ratio for .Z files.
+ Added .z to .gz renaming script in INTALL.
+ Allow setting CFLAGS in configure.
+ Add warning in README about bug in Concentrix cc compiler.
+ Avoid || in Makefile.in (at least one make doesn't support this).
+ Disable useless --ascii option for the Amiga.
+ Add a pointer to the Primos executable in README.
+ Added description of extra field in algorithm.doc.
+ Do not redefine NULL in alloca.c.
+ Added check for unsupported compression methods.
+ Avoid getopt redeclaration on OSF/1.
+
+Tue Jun 1 09:07:15 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.1.1
+ Fix serious bug in vms.c (== instead of =).
+ Added --ascii option.
+ Add workaround in configure.in for Ultrix (quote eval argument)
+ Do not use unset in znew (not supported on Ultrix)
+ Use tar.gz instead of tar.z for the distribution of gzip.
+ Add missing menu item in gzip.texi.
+ Use size_t instead of unsigned, add AC_SIZE_T in configure.in.
+
+Fri May 28 11:40:01 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.1
+ Use .gz suffix by default, add --suffix option.
+ Let gunzip accept a "_z" suffix (used by one 'compress' on Vax/VMS).
+ Quit when reading garbage from stdin instead of reporting an error.
+ Added sub.c and add.c for compression of 8 bit images.
+ Added makefile for VAX/MMS and support for wildcards on VMS.
+ Added support for MSC under OS/2.
+ Added support for Prime/PRIMOS.
+ Display compression ratio also when decompressing.
+ Quit after --version (GNU standard)
+ Use --force to bypass isatty() check.
+ Accept --silent as synonym for --quiet (see longopts.table)
+ Accept --to-stdout as synonym for --stdout (see longopts.table)
+ Accept -H and -? in addition to -h and --help.
+ Added comparison of zip and gzip in the readme file.
+ Return an error code in all main compression/decompression functions.
+ Continue processing other files in case of recoverable error.
+ Add description of -f in znew.1.
+ Do not keep uncompressed version for znew -t if .gz already exists.
+ On Unix, use only st_ino and st_dev in same_file().
+ Use S_IRUSR and S_IWUSR if they exist.
+ "test $1 = -d" -> "test x$1 = x-d" in gzexe.
+ In match.S, use symbol sysV68 to detect the Motorola Delta.
+ Do not include memory.h with gcc (conflicting declarations on Sun).
+ Fix more typos.
+ On VMS, define unlink as delete also for gcc.
+ In "make check", unset LANG because "wc -c" fails on Kanji.
+ Renamed shdir as scriptdir.
+ Use the 68020 code instead of 68000 code on the NeXT.
+ Documented --uncompress as synonym for --decompress.
+ Include the standard header files before gzip.h (needed on Bull).
+ Do not assume that _POSIX_VERSION implies dirent.h present.
+ Removed gzip-tar.patch since tar 1.11.2 handles gzip directly.
+ Use less memory when compiled with -DSMALL_MEM (for MSDOS).
+ Optimized updcrc().
+ Don't complain if cc -E does not work correctly.
+ Do not attempt reading 64K bytes on 16 bit Unix systems.
+ Do not use the variable name 'overhead' which is reserved on Lynx!
+ One BULL compiler does not like *p++ in inflate.c => *p, p++.
+ Use casts on free and memcmp to avoid warnings.
+ Remove the "off by more than one minute" time stamp kludge, but
+ document how to avoid saving the time stamp on pipes if desired.
+ Include crypt.h in inflate.c (one system predefines the CRYPT symbol).
+ Add links to gunzip and (g)zcat in the default make rule.
+ Create installation directories if they do not exist.
+ Clarified --prefix option in INSTALL.
+ Use symbol mc68k in match.S for the DIAB DS90.
+ Guard against zero length _match.s in configure.in.
+ In zmore, restore all tty options using stty -g.
+ Added support for MacOS
+ Simplified makecrc.c.
+ Avoid warnings in getopt.c, util.c, unlzw.c.
+ Use autoconf 1.4, in particular for INSTALL and AC_HAVE_POUNDBANG
+ Use .so instead of hard links for zcat.1, gunzip.1 and zcmp.1.
+ Fixed declration of sig_type.
+ Make consistency check in fcfree.
+ Added ztouch.
+ Do not complain if utime fails on a directory (for OS/2).
+
+Thu Mar 18 18:56:43 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0.7
+ Allow zmore to read from standard input (like more).
+ Support the 68000 (Atari ST) in match.S.
+ Retry partial writes (required on Linux when gzip is suspended in
+ a pipe).
+ Allow full pathnames and renamings in gzexe.
+ Don't let gzexe compress setuid executables or gzip itself.
+ Added vms/Makefile.gcc for gcc on the Vax.
+ Give a pointer to Solaris and VMS executables of gzip in README.
+ Allow installation of binaries and shell scripts in different dirs.
+ Do not use alloca on the Cray.
+ Provide strspn and strcspn if string.h does not exist.
+ Define O_CREAT and O_EXCL from FCREAT and FEXCL if necessary.
+ Remove gzip.doc in make realclean.
+ Fixed many typos. (Corrections to my English are welcome.)
+ Put "make manext=l install" at the correct place in INSTALL.
+ Fix incorrect examples in INSTALL and give more examples.
+ Include zdiff.1 for install and uninstall.
+ Allows complex PAGER variable in zmore (e.g.: PAGER="col -x | more")
+ Avoid warning on unused indfound in getopt.c.
+ Cast memset arg to void* (required by some buggy compilers).
+ Include sys/types.h before dirent.h in acgeneral.m4.
+ Fix acgeneral.m4 AC_COMPILE_CHECK to avoid warnings.
+ Don't use alloca.c with gcc. (One NeXT user did not have alloca.h).
+ Change all error messages according to GNU standards.
+ Restore time stamp only if off by more than one minute.
+ Allow installation of zcat as gzcat.
+ Suppress help message and send compressed data to the terminal when
+ gzip is invoked without parameters and without redirection.
+ (Explicit request from Noah Friedman.)
+ Add compile option GNU_STANDARD to respect the GNU coding standards:
+ with -DGNU_STANDARD, behave as gzip even if invoked under the
+ name gunzip. (Complaints to /dev/null or the FSF, not to me!)
+
+Fri Mar 10 13:27:18 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0.6
+ Let gzexe detect executables that are already gzexe'd.
+ Don't try restoring record format on VMS (the simple 1.0.5 code
+ worked correctly only on fixed-512 files). Suppress text_mode.
+ Added asm version for 68000 in amiga/match.a.
+ Use asm version for Atari TT.
+ Fix "make clean" in vms/Makefile.vms.
+ For OS/2, assume HPFS by default, add flag OS2FAT if necessary.
+ Fixed some bugs in zdiff and define zcmp as a link to zdiff.
+ Added zdiff.1
+ Remove configure hack for NeXT; add general fix to autoconf instead
+ Do not strip a ".z" extension if this results in an empty name.
+ Avoid array overflow in get_prefix() for extensions > 10 chars.
+ Accept either q or e to quit zmore.
+ In zmore, try restoring tty mode in all cases.
+ Use Motorola style for match.S on the NeXT.
+ configure.in: unsetenv *hangs* with the Siemens csh...
+ Update vms/gzip.hlp.
+
+Thu Mar 4 14:13:34 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0.5
+ For VMS, restore the file type for variable record format, otherwise
+ extract in fixed length format (not perfect, but better than
+ forcing all files to be in stream_LF format).
+ Use "-z" suffix for VMS.
+ Use only .z, .*-z, .tgz, .taz as valid gzip extensions; update
+ zforce accordingly.
+ Allow a version number in input file names for VMS.
+ Added sample program zread.c.
+ Fix "make check" for some implementations of /bin/sh.
+ Don't rely on stat() for filenames with extension > 3 chars
+ on MSDOS, OS2 and Atari.
+ Garbage collect files in /tmp created by gzexe.
+ Quote $opt in znew.
+ Use TOUCH env variable in znew if it exists.
+ Better error message for gunzip on empty or truncated file.
+ Allow prototypes in getopt.h when __STDC__ defined but 0.
+ Added "make clean" in vms/Makefile.vms.
+ Removed -g from default CFLAGS (with Noah's permission!)
+ Avoid too many HAVE_xxx_H for most systems; use common defaults.
+ Moved default Atari flags into tailor.h for consistency.
+ Use memzero() to clear the hash table.
+ Update vms/gzip.hlp to reflect the VMS behavior.
+ Fix OS_CODE (to fit in a byte).
+ Add utime.h for the Amiga.
+ Add gcc support for the Amiga.
+ Work around incorrect dirent.h for NeXT 2.0.
+ Added Makefile entry for Coherent.
+
+Fri Feb 22 11:20:49 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0.4
+ Added optimized asm version for 68020.
+ Add support for DJGPP.
+ Add support for the Atari ST.
+ Added zforce to rename gzip'ed files with truncated names.
+ Do not install with name uncompress (some systems rely on the
+ absence of any check in the old uncompress).
+ Added missing function (fcfree) in msdos/tailor.c
+ Let gunzip handle .tgz files, and let gzip skip them.
+ Added 'stty min 1' in zmore for SysV and fixed trap code.
+ Suppress .PHONY in Makefile.in, which breaks old makes.
+ Added documentation about pcat and unpack in INSTALL.
+ Add cast to getenv for systems without stdlib.h.
+ Use VAXC instead of VMS to avoid confusion for gcc.
+ Add -K to znew.1.
+ Add gzexe.1.
+ Try preserving file permissions in gzexe.
+ Added -d option for gzexe.
+ Guard against spaces in file names in gzexe.
+ Use CMP env. variable in zcmp.
+ Return a warning exit status for gzip of file with .z suffix.
+ Suppress usage of d_ino which is not portable to all systems.
+ Use #ifdef instead of #if for consistency.
+ For VMS, use "cc util.c" instead of "cc util" (pb with logical names)
+ Added utime() for Amiga.
+ Renamed gzcat.1 as zcat.1.
+ Include fcntl.h for Amiga (for read and write).
+ For VMS, add definition of symbols and links in the makefiles.
+ Give a VMS look to vms/gzip.hlp.
+ Save the original name only when necessary.
+ Add a mode parameter for open in read mode (required by VMS).
+ For VMS, remove the version suffix from the original name.
+ Accept both / and \ as path separator for MSDOS.
+ Let gunzip extract stored .zip files correctly.
+ Added warning about VFC format in vms/gzip.hlp.
+ In znew, skip a bad file but process the others.
+ Cleanup tailor.h.
+ Use GZIP_OPT for VMS to avoid conflict with program name.
+ Added description of GZIP variable in gzip.texi.
+
+Thu Feb 11 17:21:32 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0.3
+ Add -K option for znew to keep old .Z files if smaller.
+ Add -q option (quiet) to cancel -v in GZIP env variable.
+ For Turbo C, normalize pointers before freeing them.
+ Add more safety checks in add_envopt().
+ Add do_exit() for uniform exit path (always free memory).
+ Reduce MAX_PATH_LEN for MSDOS.
+ Include sys/types.h before signal.h
+ Avoid strdup, the NeXT does not have it.
+ Made gzexe safer on systems with filename limitation to 14 chars.
+
+Fri Feb 10 09:45:49 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0.2
+ Added env variable GZIP for default options.
+ Added support for the Amiga.
+ znew now keeps the old .Z if it is smaller than the .z file.
+ Added gzexe to compress rarely used executables.
+ Reduce memory usage when using static allocation (no DYN_ALLOC).
+ Better separation of warning and error return codes.
+ Fix unlzw.c to make DYN_ALLOC and MAXSEG_64K independent options.
+ Allow INBUFSIZ to be >= 32K in unlzw (don't use sign of rsize)
+ Generate tar file in old format to avoid problems with old systems.
+ Preserve time stamp in znew -P if touch -r works.
+ Use ${PAGER-more} instead of ${PAGER:-more} in zmore.
+ Do not use unsigned instead of mode_t.
+ Better error message for trailing garbage in .z file; ignore this
+ garbage on VMS.
+ In zmore, use icanon instead of -cbreak on SYSV.
+ Add trap handler in zmore.
+ Use char* instead of void* for non STDC compilers.
+ Added makefile entry for Xenix on 286.
+ Return an error code when existing file was not overwritten.
+ Use prototype of lzw.h for lzw.c.
+ Fix znew with -P option alone.
+ Give warning for directories even without -v.
+ Close output file before unlink() in case of error.
+ Suppress all target dependent ifdef from the portable files.
+ Free all dynamically allocated variables upon exit.
+
+Thu Feb 4 18:23:56 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0.1
+ Fixed some trivial errors in msdos/Makefile.bor
+
+Thu Feb 4 10:00:59 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * version 1.0
+ gzip now runs on Vax/VMS (Amiga support will come in next version).
+ Do not overwrite files without -f when using /bin/sh.
+ Support the test option -t for compressed (.Z) files.
+ Flush output for bad compressed files. Add warning in README.
+ Added makefiles for MSDOS.
+ Don't rely on presence of csh in configure
+ Added gunzip.1 and gzcat.1.
+ Updated znew.1.
+ Check reserved flags in unlzw().
+ Return dummy value in main to avoid lint warning.
+ Define OF in lzw.h for lint.
+ Allow both "znew -v -t" and "znew -vt".
+ Don't overwrite the output file name for multiple parts.
+ Echo just a warning if configure is out of date.
+ Use ; instead of , in trees.c (confuses the SAS Amiga compiler).
+ In INSTALL, document "DEFS='-DM_XENIX' ./configure".
+ Use OTHER_PATH_SEP for more portability (DOS, OS2, VMS, AMIGA).
+ Make all directories world writable for broken versions of tar.
+ Use gzip -cd instead of zcat in zmore, zcmp, zdiff.
+ Don't use GNU tar for distributions, some systems can't untar.
+ Do not exit() for gzip --version.
+
+Mon Jan 26 10:26:42 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.8.2
+ Avoid 'far' declarations for MSDOS.
+ Use test -f instead of test -x in configure.in (for Ultrix)
+ Add empty else part to if in Makefile.in for broken shells.
+ Use NO_UNDERLINE instead of UNDERLINE (pb with Linux cpp)
+ Accept continuation files with -ff (for damage recovery)
+ Small patch to Makefile.os2
+ Use memzero instead of bzero to avoid potential conflicts
+ Document restriction on extraction of zip files.
+ Fix quoting in ACL_HAVE_SHELL_HACK.
+ Do not check file size on MSDOS because of bug in DIET.
+ Allow zcat on a file with multiple links.
+ Add fix in inflate.c for compatibility with pkzip 2.04c.
+ Release gzip in tar.z and tar format. (No tar.Z).
+
+Fri Jan 22 10:04:13 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.8.1
+ Fixed Makefile.os2
+ Fixed #if directives that TurboC does not like.
+ Don't rely on uncompress in znew, use gzip -d.
+ Add the pipe option -P in znew.
+ Add some more ideas in TODO.
+ Support both NDIR and SYSNDIR.
+
+Sat Jan 21 15:46:38 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.8
+ Support unpack.
+ Check for _match.o in configure.in in addition to return status.
+ Include <sys/types.h> in zip.c
+ Define local variables and functions as local.
+ Accept more alternative names for the program (pcat, gzcat, ...).
+ Accept .exe as well as .EXE.
+ Uncompress files with multiple links only with -f.
+ Better error message for gunzip of non-existent file.z.
+ Fix the entry for /etc/magic in INSTALL.
+ Use AC_HAVE_HEADERS uniformly instead of special macros.
+ Install the man pages as .1 by default instead of .l.
+ Document crypt++.el in README.
+ Fix for unlzw() on 16-bit machines (bitmask must be unsigned).
+ Complain if input and output files are identical.
+ Create a correct output name for files of exactly 13 chars.
+ Do not overwrite CPP if set
+ Check for i386 before trying to assemble match.s
+ Check for underline in external name before assembling
+ Add patch for tar 1.11.1.
+
+Mon Jan 5 10:16:24 1993 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.7
+ Use "make check" instead of "make test".
+ Do not rely on dirname in znew.
+ Keep time stamp and pass options to gzip in znew.
+ Rename .l files back to .1 to avoid conflict with lex
+ Do not create .z.z files with gzip -r.
+ Use nice_match in match.asm
+ Unroll loops in deflate.c
+ Do not attempt matches beyond the window end
+ Allow again gunzip .zip files (was working in 0.5)
+ Allow again compilation with TurboC 2.0 (was working in 0.4)
+
+Tue Dec 30 20:00:19 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.6
+ The .z extension is used by pack, not compact (README, gzip.1)
+ Accept gzcat in addition to zcat.
+ Use PAGER in zmore if defined.
+ Man pages for /usr/local/man/manl should have extension .l.
+ Don't redefine bzero on the NeXT
+ Allow incomplete Huffman table if there is only one code.
+ Don't lookahead more than 7 bits (caused premature EOF).
+ Added "make test" to check for compiler bugs.
+ Don't rely on `i386`; try to assemble directly
+ Change magic header to avoid conflict with freeze 1.x.
+ Added entry for /etc/magic in INSTALL.
+ Do not destroy an input .zip file with more than one member.
+ Display "untested" instead of "OK" for gzip -t foo.Z
+ With -t, skip stdin in .Z format
+ Allow multiple compressed members in an input file.
+ Ignore a zero time stamp.
+ Made znew safer.
+
+Tue Dec 29 10:00:19 1992 Noah Friedman (friedman@gnu.ai.mit.edu)
+
+ Added test for #!/bin/sh in configure.in.
+ Fix some references to $srcdir in Makefile.in
+
+Mon Dec 21 17:33:35 1992 Jean-Loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.5
+ Put RCS ids in all files.
+ Added znew to recompress old .Z files with gzip.
+ Avoid "already .z suffix" messages for -r and no -v.
+ Put back check for d_ino in treat_dir().
+ Use HAVE_STRING_H instead of USG.
+ Added os2/Makefile.os2
+ Use SYSUTIME on OS/2.
+ Info dir is $(prefix)/info, not $(prefix)/lib/info.
+ Support long options, added getopt and alloca
+ Support -V and -t
+ Reorder configure.in according to suggestions in autoconf.info
+ Allow links when not removing original file
+ Allow either .z or .Z in zdiff
+
+Wed Nov 25 11:40:04 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.4.1
+ Save only the original base name, don't include any directory prefix.
+ Don't use HAVE_LONG_FILE_NAMES (support multiple file system types).
+ Fix declaration of abort_gzip in gzip.h.
+ Include unistd.h when it exists to avoid warnings with gcc -Wall.
+
+Mon Nov 23 12:39:01 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.4
+ Lots of cleanup
+ Use autoconf generated 'configure'
+ Fixed the NO_MULTIPLE_DOTS code
+ Fixed the save_orig_name code
+ Support for MSDOS (Turbo C)
+
+Thu Nov 19 15:18:22 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Beta version 0.3
+ Added auto configuration. Just type "make" now.
+ Don't overwrite compress by default in "make install". Use
+ "make install_compress" to overwrite.
+ Add match.s for 386 boxes.
+ Added documentation in texinfo format.
+ Provide help for "gunzip" invoked without redirected input.
+ Save original file name when necessary.
+ Support OS/2 (Kai-Uwe Rommel).
+
+Tue Nov 17 14:32:53 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Alpha version 0.2.4
+ Return 0 in get_istat() when ok (caused error with zcat).
+ Don't update crc on compressed data (caused crc errors on
+ large files).
+
+Fri Nov 13 15:04:12 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Alpha version 0.2.3
+ Initialize rsize in unlzw.c
+ Initialize ofd for zcat.
+ Do not use volatile ifname as argument of treat_dir.
+ Add -1 to -9 in gzip.1.
+
+Sat Oct 31 18:30:00 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Alpha version 0.2.2.
+ Fix error messages.
+ Accept gunzip on zip files.
+
+Sat Oct 31 17:15:00 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Alpha version 0.2.1
+ Use ctype.h in util.c (problem on SysV).
+ Create BINDIR if it does not exist.
+ Use cc by default.
+ Added zcmp, zmore, zdiff.
+ Fixed the man page gzip.1.
+
+Sat Oct 31 17:00:00 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Alpha version 0.2
+ Fixed compilation problems with gcc
+
+Sat Oct 31 12:46:00 1992 Jean-loup Gailly (jloup@chorus.fr)
+
+ * Alpha version 0.1 released (under time pressure), so it's not
+ much tested, sorry.
+
diff --git a/gnu/usr.bin/gzip/Makefile b/gnu/usr.bin/gzip/Makefile
new file mode 100644
index 0000000..4088b2c
--- /dev/null
+++ b/gnu/usr.bin/gzip/Makefile
@@ -0,0 +1,39 @@
+# @(#)Makefile 5.3 (Berkeley) 5/12/90
+# $FreeBSD$
+
+PROG= gzip
+SRCS= gzip.c zip.c deflate.c trees.c bits.c unzip.c inflate.c util.c \
+ crypt.c lzw.c unlzw.c unlzh.c unpack.c getopt.c
+CFLAGS+=-DSTDC_HEADERS=1 -DHAVE_UNISTD_H=1 -DDIRENT=1
+.if ${MACHINE_ARCH} == "i386"
+SRCS+= match.S
+CFLAGS+=-DASMV
+.endif
+SCRIPTS=gzexe zdiff zforce zmore znew
+MAN= gzexe.1 gzip.1 zdiff.1 zforce.1 zmore.1 znew.1
+
+NOSHARED?=yes
+
+LINKS+= ${BINDIR}/gzip ${BINDIR}/gunzip
+LINKS+= ${BINDIR}/gzip ${BINDIR}/gzcat
+LINKS+= ${BINDIR}/gzip ${BINDIR}/zcat
+LINKS+= ${BINDIR}/zdiff ${BINDIR}/zcmp
+MLINKS= gzip.1 gunzip.1 gzip.1 zcat.1 gzip.1 gzcat.1
+MLINKS+= zdiff.1 zcmp.1
+
+GREP_LIBZ?= YES
+.if defined(GREP_LIBZ) && empty(GREP_LIBZ)
+SCRIPTS+=zgrep.getopt
+MAN+= zgrep.1
+LINKS+= ${BINDIR}/zgrep ${BINDIR}/zegrep
+LINKS+= ${BINDIR}/zgrep ${BINDIR}/zfgrep
+MLINKS+= zgrep.1 zfgrep.1 zgrep.1 zegrep.1
+.endif
+
+match.o: ${.CURDIR}/match.S
+ $(CC) -E -traditional ${.CURDIR}/match.S >_match.s
+ $(CC) -c _match.s
+ mv -f _match.o match.o
+ rm -f _match.s
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/gzip/NEWS b/gnu/usr.bin/gzip/NEWS
new file mode 100644
index 0000000..ef5f833
--- /dev/null
+++ b/gnu/usr.bin/gzip/NEWS
@@ -0,0 +1,221 @@
+Current Version: 1.2.4.
+See the file ChangeLog for the details of all changes.
+
+Major changes from 1.2.3 to 1.2.4
+* By default, do not restore file name and timestamp from those saved
+ inside the .gz file (behave as 'compress'). Added the --name option
+ to force name and timestamp restoration.
+* Accept - as synonym for stdin.
+* Use manlinks=so or ln to support either hard links or .so in man pages
+* Accept foo.gz~ in zdiff.
+* Added support for Windows NT
+* Handle ENAMETOOLONG for strict Posix systems
+* Use --recursive instead of --recurse to comply with Webster and
+ the GNU stdandard.
+* Allow installation of shell scripts with a g prefix: make G=g install
+* Install by default zcat as gzcat if gzcat already exists in path.
+* Let zmore behave as more when invoked without parameters (give help)
+* Let gzip --list reject files not in gzip format even with --force.
+* Don't complain about non gzip files for options -rt or -rl.
+* Added advice in INSTALL for several systems.
+
+Major changes from 1.2.2 to 1.2.3
+* Don't display the output name when decompressing except with --verbose.
+* Remove usage of alloca in getopt.c and all makefiles.
+* Added the zfile shell script in subdirectory sample.
+* Moved the list of compiler bugs from README to INSTALL.
+* Added vms/Readme.vms.
+
+Major changes from 1.2.1 to 1.2.2
+* Fix a compilation error on Sun with cc (worked with gcc).
+
+Major changes from 1.2 to 1.2.1
+* Let zmore act as more if the data is not gzipped.
+* made gzexe more secure (don't rely on PATH).
+* By default, display output name only when the name was actually truncated.
+
+Major changes from 1.1.2 to 1.2
+* Added the --list option to display the file characteristics.
+* Added the --no-name option: do not save or restore original filename
+ Save the original name by default.
+* Allow gunzip --suffix "" to attempt decompression on any file
+ regardless of its extension if an original name is present.
+* Add support for the SCO compress -H format.
+* gzip --fast now compresses faster (speed close to that of compress)
+ with degraded compression ratio (but still better than compress).
+ Default level changed to -6 (acts exactly as previous level -5) to
+ be a better indication of its placement in the speed/ratio range.
+* Use smart name truncation: 123456789012.c -> 123456789.c.gz
+ instead of 12345678901.gz
+* With --force, let zcat pass non gzip'ed data unchanged (zcat == cat)
+* Added the zgrep shell script.
+* Made sub.c useful for 16 bit sound, 24 bit images, etc..
+* Supress warnings about suffix for gunzip -r, except with --verbose.
+* On MSDOS, use .gz extension when possible (files without extension)
+* Moved the sample programs to a subdirectory sample.
+* Added a "Special targets" section in INSTALL.
+
+Major changes from 1.1.1 to 1.1.2.
+* Fix serious bug for VMS (-gz not removed when decompressing).
+* Allow suffix other than .gz in znew.
+* Do not display compression ratio when decompressing stdin.
+* In zmore.in, work around brain damaged stty -g (Ultrix).
+* Display a correct compression ratio for .Z files.
+* Added .z to .gz renaming script in INTALL.
+* Allow setting CFLAGS in configure.
+
+Major changes from 1.1 to 1.1.1.
+* Fix serious bug in vms.c (affects Vax/VMS only).
+* Added --ascii option.
+* Add workaround in configure.in for Ultrix (quote eval argument)
+
+Major changes from 1.0.7 to 1.1.
+* Use .gz suffix by default, add --suffix option.
+* Let gunzip accept a "_z" suffix (used by one 'compress' on Vax/VMS).
+* Quit when reading garbage from stdin instead of reporting an error.
+* Added makefile for VAX/MMS and support for wildcards on VMS.
+* Added support for MSC under OS/2.
+* Added support for Prime/PRIMOS.
+* Display compression ratio also when decompressing (with --verbose).
+* Quit after --version (GNU standard)
+* Use --force to bypass isatty() check
+* Continue processing other files in case of recoverable error.
+* Added comparison of zip and gzip in the readme file.
+* Added small sample programs (ztouch, sub, add)
+* Use less memory when compiled with -DSMALL_MEM (for MSDOS).
+* Remove the "off by more than one minute" time stamp kludge
+
+Major changes from 1.0.6 to 1.0.7.
+* Allow zmore to read from standard input (like more).
+* Support the 68000 (Atari ST) in match.S.
+* Retry partial writes (required on Linux when gzip is suspended in a pipe).
+* Allow full pathnames and renamings in gzexe.
+* Don't let gzexe compress setuid executables or gzip itself.
+* Added vms/Makefile.gcc for gcc on the Vax.
+* Allow installation of binaries and shell scripts in different dirs.
+* Allows complex PAGER variable in zmore (e.g.: PAGER="col -x | more")
+* Allow installation of zcat as gzcat.
+* Several small changes for portability to old or weird systems.
+* Suppress help message and send compressed data to the terminal when
+ gzip is invoked without parameters and without redirection.
+* Add compile option GNU_STANDARD to respect the GNU coding standards:
+ with -DGNU_STANDARD, behave as gzip even if invoked under the name gunzip.
+(I don't like the last two changes, which were requested by the FSF.)
+
+Major changes from 1.0.5 to 1.0.6.
+* Let gzexe detect executables that are already gzexe'd.
+* Keep file attributes in znew and gzexe if cpmod is available.
+* Don't try restoring record format on VMS (1.0.5 did not work correctly)
+* Added asm version for 68000 in amiga/match.a.
+ Use asm version for Atari TT and NeXT.
+* For OS/2, assume HPFS by default, add flag OS2FAT if necessary.
+* Fixed some bugs in zdiff and define zcmp as a link to zdiff.
+
+
+Major changes from 1.0.4 to 1.0.5.
+* For VMS, restore the file type for variable record format, otherwise
+ extract in fixed length format (not perfect, but better than
+ forcing all files to be in stream_LF format).
+* For VMS, use "-z" default suffix and accept a version number in file names.
+* For Unix, allow compression of files with name ending in 'z'. Use only
+ .z, .*-z, .tgz, .taz as valid gzip extensions. In the last two cases,
+ extract to .tar by default.
+* On some versions of MSDOS, files with a 3 character extension could not
+ be compressed.
+* Garbage collect files in /tmp created by gzexe.
+* Fix the 'OS code' byte in the gzip header.
+* For the Amiga, add the missing utime.h and add support for gcc.
+
+
+Major changes from 1.0.3 to 1.0.4.
+* Added optimized asm version for 68020.
+* Add support for DJGPP.
+
+* Add support for the Atari ST.
+* Added zforce to rename gzip'ed files with truncated names.
+* Do not install with name uncompress (some systems rely on the
+ absence of any check in the old uncompress).
+* Added missing function (fcfree) in msdos/tailor.c
+* Let gunzip handle .tgz files, and let gzip skip them.
+* Added -d option (decompress) for gzexe and try preserving file permissions.
+* Suppress all warnings with -q.
+* Use GZIP_OPT for VMS to avoid conflict with program name.
+* ... and many other small changes (see ChangeLog)
+
+
+Major changes from 1.0.2 to 1.0.3
+* Added -K option for znew to keep old .Z files if smaller
+* Added -q option (quiet) to cancel -v in GZIP env variable.
+* Made gzexe safer on systems with filename limitation to 14 chars.
+* Fixed bugs in handling of GZIP env variable and incorrect free with Turbo C.
+
+
+Major changes from 1.0.1 to 1.0.2
+* Added env variable GZIP for default options. Example:
+ for sh: GZIP="-8 -v"; export GZIP
+ for csh: setenv GZIP "-8 -v"
+* Added support for the Amiga.
+* znew now keeps the old .Z if it is smaller than the .z file.
+ This can happen for some large and very redundant files.
+* Do not complain about trailing garbage for record oriented IO (Vax/VMS).
+ This implies however that multi-part gzip files are not supported
+ on such systems.
+* Added gzexe to compress rarely used executables.
+* Reduce memory usage (required for MSDOS and useful on all systems).
+* Preserve time stamp in znew -P (pipe option) if touch -r works.
+
+
+Major changes from 1.0 to 1.0.1
+* fix trivial errors in the Borland makefile (msdos/Makefile.bor)
+
+
+Major changes from 0.8.2 to 1.0
+* gzip now runs on Vax/VMS
+* gzip will not not overwrite files without -f when using /bin/sh in
+ background.
+* Support the test option -t for compressed (.Z) files.
+ Allow some data recovery for bad .Z files.
+* Added makefiles for MSDOS (Only tested for MSC, not Borland).
+* still more changes to configure for several systems
+
+
+Major changes from 0.8.1 to 0.8.2:
+* yet more changes to configure for Linux and other systems
+* Allow zcat on a file with multiple links.
+
+
+Major changes from 0.8 to 0.8.1:
+* znew has now a pipe option -P to reduce the disk space requirements,
+ but this option does not preserve timestamps.
+* Fixed some #if directives for compilation with TurboC.
+
+
+Major changes from 0.7 to 0.8:
+* gzip can now extract .z files created by 'pack'.
+* configure should no longer believe that every machine is a 386
+* Fix the entry for /etc/magic in INSTALL.
+* Add patch for GNU tar 1.11.1 and a pointer to crypt++.el
+* Uncompress files with multiple links only with -f.
+* Fix for uncompress of .Z files on 16-bit machines
+* Create a correct output name for file names of exactly N-1 chars when
+ the system has a limit of N chars.
+
+
+Major changes from 0.6 to 0.7:
+* Use "make check" instead of "make test".
+* Keep time stamp and pass options to gzip in znew.
+* Do not create .z.z files with gzip -r.
+* Allow again gunzip .zip files (was working in 0.5)
+* Allow again compilation with TurboC 2.0 (was working in 0.4)
+
+
+Major changes form 0.5 to 0.6:
+* gunzip reported an error when extracting certain .z files. The .z files
+ produced by gzip 0.5 are correct and can be read by gunzip 0.6.
+* gunzip now supports multiple compressed members within a single .z file.
+* Fix the check for i386 in configure.
+* Added "make test" to check for compiler bugs. (gcc -finline-functions
+ is broken at least on the NeXT.)
+* Use environment variable PAGER in zmore if it is defined.
+* Accept gzcat in addition to zcat for people having /usr/bin before
+ /usr/local/bin in their path.
diff --git a/gnu/usr.bin/gzip/README b/gnu/usr.bin/gzip/README
new file mode 100644
index 0000000..fdd7311
--- /dev/null
+++ b/gnu/usr.bin/gzip/README
@@ -0,0 +1,144 @@
+This is the file README for the gzip distribution, version 1.2.4.
+
+gzip (GNU zip) is a compression utility designed to be a replacement
+for 'compress'. Its main advantages over compress are much better
+compression and freedom from patented algorithms. The GNU Project
+uses it as the standard compression program for its system.
+
+gzip currently uses by default the LZ77 algorithm used in zip 1.9 (the
+portable pkzip compatible archiver). The gzip format was however
+designed to accommodate several compression algorithms. See below
+for a comparison of zip and gzip.
+
+gunzip can currently decompress files created by gzip, compress or
+pack. The detection of the input format is automatic. For the
+gzip format, gunzip checks a 32 bit CRC. For pack, gunzip checks the
+uncompressed length. The 'compress' format was not designed to allow
+consistency checks. However gunzip is sometimes able to detect a bad
+.Z file because there is some redundancy in the .Z compression format.
+If you get an error when uncompressing a .Z file, do not assume that
+the .Z file is correct simply because the standard uncompress does not
+complain. This generally means that the standard uncompress does not
+check its input, and happily generates garbage output.
+
+gzip produces files with a .gz extension. Previous versions of gzip
+used the .z extension, which was already used by the 'pack'
+Huffman encoder. gunzip is able to decompress .z files (packed
+or gzip'ed).
+
+Several planned features are not yet supported (see the file TODO).
+See the file NEWS for a summary of changes since 0.5. See the file
+INSTALL for installation instructions. Some answers to frequently
+asked questions are given in the file INSTALL, please read it. (In
+particular, please don't ask me once more for an /etc/magic entry.)
+
+WARNING: on several systems, compiler bugs cause gzip to fail, in
+particular when optimization options are on. See the section "Special
+targets" at the end of the INSTALL file for a list of known problems.
+For all machines, use "make check" to check that gzip was compiled
+correctly. Try compiling gzip without any optimization if you have a
+problem.
+
+Please send all comments and bug reports by electronic mail to:
+ Jean-loup Gailly <jloup@chorus.fr>
+
+or, if this fails, to bug-gnu-utils@prep.ai.mit.edu.
+Bug reports should ideally include:
+
+ * The complete output of "gzip -V" (or the contents of revision.h
+ if you can't get gzip to compile)
+ * The hardware and operating system (try "uname -a")
+ * The compiler used to compile (if it is gcc, use "gcc -v")
+ * A description of the bug behavior
+ * The input to gzip, that triggered the bug
+
+If you send me patches for machines I don't have access to, please test them
+very carefully. gzip is used for backups, it must be extremely reliable.
+
+The package crypt++.el is highly recommended to manipulate gzip'ed
+file from emacs. It recognizes automatically encrypted and compressed
+files when they are first visited or written. It is available via
+anonymous ftp to roebling.poly.edu [128.238.5.31] in /pub/crypt++.el.
+The same directory contains also patches to dired, ange-ftp and info.
+GNU tar 1.11.2 has a -z option to invoke directly gzip, so you don't have to
+patch it. The package ftp.uu.net:/languages/emacs-lisp/misc/jka-compr19.el.Z
+also supports gzip'ed files.
+
+The znew and gzexe shell scripts provided with gzip benefit from
+(but do not require) the cpmod utility to transfer file attributes.
+It is available by anonymous ftp on gatekeeper.dec.com in
+/.0/usenet/comp.sources.unix/volume11/cpmod.Z.
+
+The sample programs zread.c, sub.c and add.c in subdirectory sample
+are provided as examples of useful complements to gzip. Read the
+comments inside each source file. The perl script ztouch is also
+provided as example (not installed by default since it relies on perl).
+
+
+gzip is free software, you can redistribute it and/or modify it under
+the terms of the GNU General Public License, a copy of which is
+provided under the name COPYING. The latest version of gzip are always
+available by ftp in prep.ai.mit.edu:/pub/gnu, or in any of the prep
+mirror sites:
+
+- sources in gzip-*.tar (or .shar or .tar.gz).
+- Solaris 2 executables in sparc-sun-solaris2/gzip-binaries-*.tar
+- MSDOS lha self-extracting exe in gzip-msdos-*.exe. Once extracted,
+ copy gzip.exe to gunzip.exe and zcat.exe, or use "gzip -d" to decompress.
+ gzip386.exe runs much faster but only on 386 and above; it is compiled with
+ djgpp 1.10 available in directory omnigate.clarkson.edu:/pub/msdos/djgpp.
+
+A VMS executable is available in ftp.spc.edu:[.macro32.savesets]gzip-1-*.zip
+(use [.macro32]unzip.exe to extract). A PRIMOS executable is available
+in ftp.lysator.liu.se:/pub/primos/run/gzip.run.
+OS/2 executables (16 and 32 bits versions) are available in
+ftp.tu-muenchen.de:/pub/comp/os/os2/archiver/gz*-[16,32].zip
+
+Some ftp servers can automatically make a tar.Z from a tar file. If
+you are getting gzip for the first time, you can ask for a tar.Z file
+instead of the much larger tar file.
+
+Many thanks to those who provided me with bug reports and feedback.
+See the files THANKS and ChangeLog for more details.
+
+
+ Note about zip vs. gzip:
+
+The name 'gzip' was a very unfortunate choice, because zip and gzip
+are two really different programs, although the actual compression and
+decompression sources were written by the same persons. A different
+name should have been used for gzip, but it is too late to change now.
+
+zip is an archiver: it compresses several files into a single archive
+file. gzip is a simple compressor: each file is compressed separately.
+Both share the same compression and decompression code for the
+'deflate' method. unzip can also decompress old zip archives
+(implode, shrink and reduce methods). gunzip can also decompress files
+created by compress and pack. zip 1.9 and gzip do not support
+compression methods other than deflation. (zip 1.0 supports shrink and
+implode). Better compression methods may be added in future versions
+of gzip. zip will always stick to absolute compatibility with pkzip,
+it is thus constrained by PKWare, which is a commercial company. The
+gzip header format is deliberately different from that of pkzip to
+avoid such a constraint.
+
+On Unix, gzip is mostly useful in combination with tar. GNU tar
+1.11.2 has a -z option to invoke gzip automatically. "tar -z"
+compresses better than zip, since gzip can then take advantage of
+redundancy between distinct files. The drawback is that you must
+scan the whole tar.gz file in order to extract a single file near
+the end; unzip can directly seek to the end of the zip file. There
+is no overhead when you extract the whole archive anyway.
+If a member of a .zip archive is damaged, other files can still
+be recovered. If a .tar.gz file is damaged, files beyond the failure
+point cannot be recovered. (Future versions of gzip will have
+error recovery features.)
+
+gzip and gunzip are distributed as a single program. zip and unzip
+are, for historical reasons, two separate programs, although the
+authors of these two programs work closely together in the info-zip
+team. zip and unzip are not associated with the GNU project.
+The sources are available by ftp in
+
+ oak.oakland.edu:/pub/misc/unix/zip19p1.zip
+ oak.oakland.edu:/pub/misc/unix/unz50p1.tar-z
diff --git a/gnu/usr.bin/gzip/THANKS b/gnu/usr.bin/gzip/THANKS
new file mode 100644
index 0000000..6a545cb
--- /dev/null
+++ b/gnu/usr.bin/gzip/THANKS
@@ -0,0 +1,276 @@
+gzip was written by Jean-loup Gailly <jloup@chorus.fr>, with portions
+written by Mark Adler (inflate.c), Peter Jannesen (unlzw.c) and
+Haruhiko Okumura (unlzh.c). The zip deflate format was defined by Phil Katz.
+Thanks to those who reported problems and suggested various
+improvements. Here is a partial list of them:
+
+Robert Abramovitz bromo@cougar.tandem.com
+Jay Adams jka@ece.cmu.edu
+Mark Adler madler@cco.caltech.edu
+Edwin Allum edwin@csri.toronto.edu
+Joseph Arceneaux jla@gnu.ai.mit.edu
+Tim Auckland tda10@cus.cam.ac.uk
+Ken-ichiro Aoki aoki@madonna.physics.ucla.edu
+David Ascher da@marlowe.cog.brown.edu
+Eric Backus ericb@lsid.hp.com
+Becky A. Badgett badgett@cs.utexas.edu
+Bo Nygaard Bai bai@iesd.auc.dk
+Dave Barber dbarber@apocalypse.bbn.com
+Rene Beaulieu reneb@distri.hydro.qc.ca
+Neal Becker neal@ctd.comsat.com
+Dieter Becker becker@med-in.uni-sb.de
+Nelson H. F. Beebe beebe@geronimo.math.utah.edu
+Jeff Beadles jeff@onion.rain.com
+David J. N. Begley dbegley@st.nepean.uws.edu.au
+Bob Beresh rberesh@rd.hydro.on.ca
+Jim Bernard jbernard@iola.mines.colorado.edu
+Karl Berry karl@cs.umb.edu
+James W. Birdsall jwbirdsa@picarefy.picarefy.com
+Scott Bolte scott@craycos.com
+Wayne E. Bouchard web@paladine.hacks.arizona.edu
+Marc Boucher marc@cam.org
+Ola Brahammar pt90ob@pt.hk-r.se
+Dave Brennan brennan@hal.com
+Alan Brown dogbowl@dogbox.acme.gen.nz
+Michael L. Brown brown@wi.extrel.com
+Rodney Brown rdb@mel.cocam.oz.au
+Bruce bde@runx.oz.au
+Bill Bumgarner bbum@stone.com
+Leila Burrell-Davis leilabd@syma.sussex.ac.uk
+Roger Butenuth butenuth@ira.uka.de
+Jon Cargille jcargill@cs.wisc.edu
+Bud Carlson bud@isle.pegasus.com
+Lim Fung Chai fclim@i1sin.daq.semi.harris.com
+Wes Chalfant wes@kofax.com
+Andrew A. Chernov ache@astral.msk.su
+Paul Close pdc@lunch.wpd.sgi.com
+Jeff Coffler coffler@jac.enet.dec.com
+Will Colley wcc3@occs.cs.oberlin.edu
+Roger Cornelius sherpa!rac@uunet.uu.net
+Kevin Cosgrove kevinc@tekig6.pen.tek.com
+Stephen J Cowley s.j.cowley@amtp.cam.ac.uk
+Ron Cox roncox@indirect.com
+Frank Crawford frank@photon.ansto.gov.au
+James R. Crawford qralston@cislabs.pitt.edu
+Lawrence Crowl crowl@research.cs.orst.edu
+Klaus Dahlenburg kdburg@incoahe.hanse.de
+William E Davidsen davidsen@ariel.crd.ge.com
+John M. DeDourek dedourek@aixive2.cs.unb.ca
+Jeff Deifik jdeifik@isi.edu
+Vince DeMarco vince@whatnxt.cuc.ab.ca
+Michael De La Rue p91152@cplab.physics.edinburgh.ac.uk
+Jeff Delinck delinck@pa621a.inland.com
+John DeRoo deroo@grout.adv.shr.dec.com
+Jim Diamond zsd@axe.drea.dnd.ca
+Stefano Diomedi sd@teculx.tecsiel.it
+Lawrence R. Dodd dodd@roebling.poly.edu
+Matthew Donadio donadio@mxd120.rh.psu.edu
+Andy Dougherty andy@crystal.phys.lafayette.edu
+Darrell Duane dduane@mason1.gmu.edu
+John Eaton jwe@che.utexas.edu
+Will Edgington wedgingt@ptolemy.arc.nasa.gov
+Brian Edmonds edmonds@edmonds.home.cs.ubc.ca
+Paul Eggert eggert@twinsun.com
+Enami enami@sys.ptg.sony.co.jp
+Kristoffer Eriksson ske@pkmab.se
+Daniel Eriksson m91der@bellatrix.tdb.uu.se
+Rik Faith faith@cs.unc.edu
+Larry Fahnoe fahnoe@c1mpls.mn.org
+Cristian Ferretti cfs@poincare.mat.puc.cl
+Karl-Jose Filler pla_jfi@pki-nbg.philips.de
+Valery Fine fine@vxcern.cern.ch
+Bob Fischer bobf@milne.geology.yale.edu
+Per Foreby perf@efd.lth.se
+Alexander Fraser alex@cs.umb.edu
+Noah Friedman friedman@gnu.ai.mit.edu
+Bob Friesenhahn bfriesen@iphase.com
+Gerhard Friesland-Koepke frieslan@rzdspc3.informatik.uni-hamburg.de
+Andy Fyfe andy@scp.caltech.edu
+Geoff geoff@frs.faxon.com
+Arnd Gerns gerns@informatik.uni-hildesheim.de
+Kaveh R. Ghazi ghazi@staccato.rutgers.edu
+Torbjorn Granlund tege@sics.se
+Carl Greco cgreco@parrot.creighton.edu
+Bruno Haible haible@ma2s2.mathematik.uni-karlsruhe.de
+Junio Hamano junio@shadow.twinsun.com
+Harald Hanche-Olsen hanche@ams.sunysb.edu
+Darrel R. Hankerson hankedr@mail.auburn.edu
+Mark Hanning-Lee markhl@romeo.caltech.edu
+Lars Hecking st000002@hrz1.hrz.th-darmstadt.de
+Ruediger Helsch ruediger@ramz.ing.tu-bs.de
+Mark C. Henderson mch@sqwest.wimsey.bc.ca
+Karl Heuer karl@kelp.boston.ma.us
+Jarkko Hietaniemi jhi@dol-guldur.hut.fi
+Thomas Hiller hiller@fzi.de
+Eiji Hirai hirai@cc.swarthmore.edu
+Kjetil Torgrim Homme kjetilho@ifi.uio.no
+Robert D. Houk rdh@sli.com
+Jim Howard jim_howard@mentorg.com
+Preston Hunt gt5708a@prism.gatech.edu
+Shane C Hutchins sch@nymph.msel.unh.edu
+Hutch hutchinson@wrair-emh1.army.mil
+Lester Ingber ingber@alumni.caltech.edu
+Ken Ishii ishii@sni-usa.com
+Per Steinar Iversen iversen@vsfys1.fi.uib.no
+Chris Jacobsen jacobsen@xray1.physics.sunysb.edu
+Michal Jaegermann ntomczak@vm.ucs.ualberta.ca
+Brian Jones brianj@skat.usc.edu
+Denny de Jonge witaddj@dutrex.tudelft.nl
+Arne H. Juul arnej@lise.unit.no
+Dana Jacobsen jacobsd@solar.cor2.epa.gov
+Peter Jannesen peter@ncs.nl
+Brian D. Johnston johnstonb@med.ge.com
+Walter W. Jones wwj@candela.cfr.nist.gov
+Tom Judson judson@scf.usc.edu
+Henry G. Juengst juengst@saph2.physik.uni-bonn.de
+Sarantos Kapidakis sarantos%manteion@ics.forth.gr
+Amir J. Katz amir@matis.ingr.com
+Steve Kelem kelem@castor.xilinx.com
+Steven Kimball kimball@shrew.sanders.lockheed.com
+Randy Kirchhof rkk@posms.aus.tx.us
+Ned Kittlitz kittlitz@seagoon.sw.stratus.com
+Sakai Kiyotaka ksakai@mtl.t.u-tokyo.ac.jp
+Philip C Kizer pckizer@gonzo.tamu.edu
+Pete Klammer pklammer@ouray.denver.colorado.edu
+Fritz Kleemann kleemann@informatik.uni-wuerzburg.dbp.de
+Wilhelm B. Kloke wb@ifado.arb-phys.uni-dortmund.de
+Tom Kloos tk@sequent.com
+Carsten Koch carsten.koch@icem.de
+Winfried Koenig win@in.rhein-main.de
+Mathias Koerber mathias@solomon.technet.sg
+Steph Konigsdorfer s.konigsdorfer@frmy.bull.fr
+Leif Kornstaedt leif@rumtifsl.ruessel.sub.org
+Michael D. Lawler mdlawler@bsu-cs.bsu.edu
+Kevin Layer layer@franz.com
+Howard D. Leadmon howardl@wb3ffv.ampr.org
+Alexander Lehmann alex@hal.rhein-main.de
+Simon Leinen simon@lia.di.epfl.ch
+Burt Leland burt@molecular.com
+Tony Leneis tony@plaza.adp.ds.com
+Hugues Leroy hugues.leroy@irisa.fr
+Marty Leisner leisner@eso.mc.xerox.com
+Charles Levert charles@aramis.comm.polymtl.ca
+Richard Levitte levitte@e.kth.se
+Torbj|rn Lindh toobii@elixir.e.kth.se
+David R. Linn drl@vuse.vanderbilt.edu
+Antonio Lioy cat@athena.polito.it
+Jamie Lokier u90jl@ecs.oxford.ac.uk
+Richard Lloyd R.K.Lloyd@csc.liv.ac.uk
+David J. MacKenzie djm@eng.umd.edu
+John R MacMillan john@chance.gts.org
+Ron Male male@eso.mc.xerox.com
+Don R. Maszle maze@bea.lbl.gov
+Jaye Mathisen osyjm@cs.montana.edu
+Telly Mavroidis mavroidi@acf2.nyu.edu
+Imed Eddine Mbarki mbarki@pacific.cmpe.psu.edu
+Steeve McCauley steeve@pooh.geophys.mcgill.ca
+Tom McConnell tmcconne@sedona.intel.com
+Tod McQuillin mcquill@ccit05.duq.edu
+Tye McQueen tye@spillman.com
+Bernd Melchers melchers@chemie.fu-berlin.de
+Jason Merrill jason@jarthur.claremont.edu
+Dean S. Messing deanm@medulla.labs.tek.com
+M. Mesturino mesturino@cselt.stet.it
+Luke Mewburn zak@rmit.edu.au
+Jim Meyering meyering@cs.utexas.edu
+Dragan Milicic milicic@math.utah.edu
+Frederic Miserey none.fred@applelink.apple.com
+Marcel J.E. Mol marcel@duteca.et.tudelft.nl
+Soren Juul Moller sjm@dde.dk
+Chris Moore moore@src.bae.co.uk
+Dan Mosedale mosedale@genome.stanford.edu
+Helmut Muelner hmuelner@fiicmds04.tu-graz.ac.at
+Urban D Mueller umueller@amiga.physik.unizh.ch
+Ulrich Mueller ulm@vsnhdb.cern.ch
+Timothy Murphy tim@maths.tcd.ie
+Greg Naber greg@squally.halcyon.com
+Jay Nayegandhi jayng@bbiv02.enet.dec.com
+Paul K. Neville II pkn2@idsi.com
+Karl L. Noell noell@informatik.fh-wiesbaden.dbp.de
+Demizu Noritoshi nori-d@is.aist-nara.ac.jp
+Todd Ogasawara todd@protege.pegasus.com
+Helge Oldach helge.oldach@stollmann.de
+Arthur David Olson ado@elsie.nci.nih.gov
+Piet van Oostrum piet@cs.ruu.nl
+Rafael R. Pappalardo rafapa@obelix.cica.es
+Mike Pearlman canuck@masc38.rice.edu
+Yves Perrenoud pyves@nuga.alphanet.ch
+Hal Peterson hrp@pecan.cray.com
+Pascal Petit petit@cadillac.ibp.fr
+Bruno Pillard bp@chorus.fr
+Franc,ois Pinard pinard@iro.umontreal.ca
+Jay Pinkos pinkos@butyng.bu.edu
+Thomas Plass thomas@cogsci.ed.ac.uk
+Mike Polo mikep@cfsmo.honeywell.com
+Francesco Potorti pot@fly.cnuce.cnr.it
+Will Priest bpriest@lobby.ti.com
+David Purves purves@apogee.com
+Andreas Raab ar@nvmr.robin.de
+Eric S. Raymond esr@snark.thyrsus.com
+Klaus Reimann kr@cip.physik.uni-stuttgart.de
+Michael Rendell michael@mercury.cs.mun.ca
+Hal Render render@massive.uccs.edu
+Julian F. Reschke julian@math.uni-muenster.de
+Phil Richards Phil.Richards@prg.oxford.ac.uk
+Roland B Roberts roberts@nsrl31.nsrl.rochester.edu
+Arnold Robbins arnold@cc.gatech.edu
+Kevin Rodgers kevin@rolling-stone.den.mmc.com
+Kai Uwe Rommel rommel@informatik.tu-muenchen.de
+Paul Rubin phr@america.telebit.com
+Wolfgang Rupprecht wolfgang@wsrcc.com
+Jonathan Ryshpan jon@amito.hitachi.com
+Paul A Sand pas@unh.edu
+Tony Sanders sanders@bsdi.com
+Mike Sangrey mike@sojurn.lns.pa.us
+Niimi Satoshi a01309@cfi.waseda.ac.jp
+Marc Schaefer sysadm@alphanet.ch
+Andreas Schwab schwab@lamothe.informatik.uni-dortmund.de
+Eric Schenk schenk@cs.toronto.edu
+Eric P. Scott eps@cs.sfsu.edu
+Olaf Seibert rhialto@mbfys.kun.nl
+Sunando Sen sens@fasecon.econ.nyu.edu
+Harry Shamansky hts@hertz.eng.ohio-state.edu
+Amos Shapira amoss@cs.huji.ac.il
+Rick Sladkey jrs@world.std.com
+Daniel L Smith dls@autodesk.com
+Fred Smith fredex%fcshome@merk.merk.com
+Stephen Soliday soliday@ncat.edu
+Paul Southworth pauls@css.itd.umich.edu
+Rob Spencer robbie@winkle.bhpese.oz.au
+Richard Stallman rms@gnu.ai.mit.edu
+Carsten Steger carsten.steger@informatik.tu-muenchen.de
+David Sundstrom sunds@anon.asic.sc.ti.com
+Ed Sznyter ews@babel.babel.com
+Hideaki Tanabe arctanx@iyeyasu.ynl.t.u-tokyo.ac.jp
+Andrew Telford ajt@peregrin.resmel.bhp.com.au
+Glenn E. Thobe thobe@getunx.info.com
+Kei Thomsen kt@keihh.hanse.de
+Karsten Thygesen karthy@dannug.dk
+Mark Towfiq towfiq@microdyne.com
+Jeff Treece treece@sabbagh.com
+Oliver Trepte oliver@ikaros.fysik4.kth.se
+Stephane Tsacas slt@is21.isoft.fr
+Stephen Tweedie sct@dcs.ed.ac.uk
+John R. Vanderpool fish@daacdev1.stx.com
+Sotiris Vassilopoulos vassilopoulos@virginia.edu
+Pedro A. M. Vazquez vazquez@iqm.unicamp.br
+Arjan de Vet devet@win.tue.nl
+Larry W. Virden lvirden@cas.org
+Vadim V. Vlasov vvlasov@inucres.msk.su
+Eduard Vopicka eduard.vopicka@vse.cs
+Theo Vosse vosse@ruls41.leidenuniv.nl
+Darin Wayrynen darin@pcg.uucp
+Marcel Waldvogel marcel@nice.usergroup.ethz.ch
+Stephen J. Walick steve@nshore.org
+Gray Watson gray@antaire.com
+David Watt dmwatt@smersh.cambridge.ma.us
+Scott Weikart scott@igc.apc.org
+Ivo Welch iwelch@agsm.ucla.edu
+Jochen Wiedmann zrawi01@zmcipdec1.zdv.uni-tuebingen.de
+Gijsb. Wiesenekker wiesenecker@sara.nl
+Wietze van Winden wietze@swi.psy.uva.nl
+Frank Wuebbeling wuebbel@math.uni-muenster.de
+Larry W. Virden lwv26@cas.org
+Bill Wohler wohler@sap-ag.de
+Jamie Zawinski jwz@lucid.com
+Christos Zoulas christos@deshaw.com
diff --git a/gnu/usr.bin/gzip/TODO b/gnu/usr.bin/gzip/TODO
new file mode 100644
index 0000000..865be92
--- /dev/null
+++ b/gnu/usr.bin/gzip/TODO
@@ -0,0 +1,58 @@
+TODO file for gzip.
+
+Some of the planned features include:
+
+- Structure the sources so that the compression and decompression code
+ form a library usable by any program, and write both gzip and zip on
+ top of this library. This would ideally be a reentrant (thread safe)
+ library, but this would degrade performance. In the meantime, you can
+ look at the sample program zread.c.
+
+ The library should have one mode in which compressed data is sent
+ as soon as input is available, instead of waiting for complete
+ blocks. This can be useful for sending compressed data to/from interactive
+ programs.
+
+- Make it convenient to define alternative user interfaces (in
+ particular for windowing environments).
+
+- Support in-memory compression for arbitrarily large amounts of data
+ (zip currently supports in-memory compression only for a single buffer.)
+
+- Map files in memory when possible, this is generally much faster
+ than read/write. (zip currently maps entire files at once, this
+ should be done in chunks to reduce memory usage.)
+
+- Add a super-fast compression method, suitable for implementing
+ file systems with transparent compression. One problem is that the
+ best candidate (lzrw1) is patented twice (Waterworth 4,701,745
+ and Gibson & Graybill 5,049,881). The lzrw series of algorithms
+ are available by ftp in ftp.adelaide.edu.au:/pub/compression/lzrw*.
+
+- Add a super-tight (but slow) compression method, suitable for long
+ term archives. One problem is that the best versions of arithmetic
+ coding are patented (4,286,256 4,295,125 4,463,342 4,467,317
+ 4,633,490 4,652,856 4,891,643 4,905,297 4,935,882 4,973,961
+ 5,023,611 5,025,258).
+
+ Note: I will introduce new compression methods only if they are
+ significantly better in either speed or compression ratio than the
+ existing method(s). So the total number of different methods should
+ reasonably not exceed 3. (The current 9 compression levels are just
+ tuning parameters for a single method, deflation.)
+
+- Add optional error correction. One problem is that the current version
+ of ecc cannot recover from inserted or missing bytes. It would be
+ nice to recover from the most common error (transfer of a binary
+ file in ascii mode).
+
+- Add a block size (-b) option to improve error recovery in case of
+ failure of a complete sector. Each block could be extracted
+ independently, but this reduces the compression ratio.
+
+- Use a larger window size to deal with some large redundant files that
+ 'compress' currently handles better than gzip.
+
+- Implement the -e (encrypt) option.
+
+Send comments to Jean-loup Gailly <jloup@chorus.fr>.
diff --git a/gnu/usr.bin/gzip/algorithm.doc b/gnu/usr.bin/gzip/algorithm.doc
new file mode 100644
index 0000000..596faac
--- /dev/null
+++ b/gnu/usr.bin/gzip/algorithm.doc
@@ -0,0 +1,164 @@
+1. Algorithm
+
+The deflation algorithm used by zip and gzip is a variation of LZ77
+(Lempel-Ziv 1977, see reference below). It finds duplicated strings in
+the input data. The second occurrence of a string is replaced by a
+pointer to the previous string, in the form of a pair (distance,
+length). Distances are limited to 32K bytes, and lengths are limited
+to 258 bytes. When a string does not occur anywhere in the previous
+32K bytes, it is emitted as a sequence of literal bytes. (In this
+description, 'string' must be taken as an arbitrary sequence of bytes,
+and is not restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when zip determines that it
+would be useful to start another block with fresh trees. (This is
+somewhat similar to compress.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (zip -1
+to -9). So zip does not always find the longest possible match but
+generally finds a match which is long enough.
+
+zip also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, zip searches for a
+longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the longer match is emitted afterwards. Otherwise,
+the original match is kept, and the next match search is attempted only
+N steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, zip reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, zip attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (speed options -1 to -3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+
+2. gzip file format
+
+The pkzip format imposes a lot of overhead in various headers, which
+are useful for an archiver but not necessary when only one file is
+compressed. gzip uses a much simpler structure. Numbers are in little
+endian format, and bit 0 is the least significant bit.
+A gzip file is a sequence of compressed members. Each member has the
+following structure:
+
+2 bytes magic header 0x1f, 0x8b (\037 \213)
+1 byte compression method (0..7 reserved, 8 = deflate)
+1 byte flags
+ bit 0 set: file probably ascii text
+ bit 1 set: continuation of multi-part gzip file
+ bit 2 set: extra field present
+ bit 3 set: original file name present
+ bit 4 set: file comment present
+ bit 5 set: file is encrypted
+ bit 6,7: reserved
+4 bytes file modification time in Unix format
+1 byte extra flags (depend on compression method)
+1 byte operating system on which compression took place
+
+2 bytes optional part number (second part=1)
+2 bytes optional extra field length
+? bytes optional extra field
+? bytes optional original file name, zero terminated
+? bytes optional file comment, zero terminated
+12 bytes optional encryption header
+? bytes compressed data
+4 bytes crc32
+4 bytes uncompressed input size modulo 2^32
+
+The format was designed to allow single pass compression without any
+backwards seek, and without a priori knowledge of the uncompressed
+input size or the available size on the output media. If input does
+not come from a regular disk file, the file modification time is set
+to the time at which compression started.
+
+The time stamp is useful mainly when one gzip file is transferred over
+a network. In this case it would not help to keep ownership
+attributes. In the local case, the ownership attributes are preserved
+by gzip when compressing/decompressing the file. A time stamp of zero
+is ignored.
+
+Bit 0 in the flags is only an optional indication, which can be set by
+a small lookahead in the input data. In case of doubt, the flag is
+cleared indicating binary data. For systems which have different
+file formats for ascii text and binary data, the decompressor can
+use the flag to choose the appropriate format.
+
+The extra field, if present, must consist of one or more subfields,
+each with the following format:
+
+ subfield id : 2 bytes
+ subfield size : 2 bytes (little-endian format)
+ subfield data
+
+The subfield id can consist of two letters with some mnemonic value.
+Please send any such id to jloup@chorus.fr. Ids with a zero second
+byte are reserved for future use. The following ids are defined:
+
+ Ap (0x41, 0x70) : Apollo file type information
+
+The subfield size is the size of the subfield data and does not
+include the id and the size itself. The field 'extra field length' is
+the total size of the extra field, including subfield ids and sizes.
+
+It must be possible to detect the end of the compressed data with any
+compression format, regardless of the actual size of the compressed
+data. If the compressed data cannot fit in one file (in particular for
+diskettes), each part starts with a header as described above, but
+only the last part has the crc32 and uncompressed size. A decompressor
+may prompt for additional data for multipart compressed files. It is
+desirable but not mandatory that multiple parts be extractable
+independently so that partial data can be recovered if one of the
+parts is damaged. This is possible only if no compression state is
+kept from one part to the other. The compression-type dependent flags
+can indicate this.
+
+If the file being compressed is on a file system with case insensitive
+names, the original name field must be forced to lower case. There is
+no original file name if the data was compressed from standard input.
+
+Compression is always performed, even if the compressed file is
+slightly larger than the original. The worst case expansion is
+a few bytes for the gzip file header, plus 5 bytes every 32K block,
+or an expansion ratio of 0.015% for large files. Note that the actual
+number of used disk blocks almost never increases.
+
+The encryption is that of zip 1.9. For the encryption check, the
+last byte of the decoded encryption header must be zero. The time
+stamp of an encrypted file might be set to zero to avoid giving a clue
+about the construction of the random header.
+
+Jean-loup Gailly
+jloup@chorus.fr
+
+References:
+
+[LZ77] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
+Compression", IEEE Transactions on Information Theory", Vol. 23, No. 3,
+pp. 337-343.
+
+APPNOTE.TXT documentation file in PKZIP 1.93a. It is available by
+ftp in ftp.cso.uiuc.edu:/pc/exec-pc/pkz193a.exe [128.174.5.59]
+Use "unzip pkz193a.exe APPNOTE.TXT" to extract.
diff --git a/gnu/usr.bin/gzip/bits.c b/gnu/usr.bin/gzip/bits.c
new file mode 100644
index 0000000..efce391
--- /dev/null
+++ b/gnu/usr.bin/gzip/bits.c
@@ -0,0 +1,205 @@
+/* bits.c -- output variable-length bit strings
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+
+/*
+ * PURPOSE
+ *
+ * Output variable-length bit strings. Compression can be done
+ * to a file or to memory. (The latter is not supported in this version.)
+ *
+ * DISCUSSION
+ *
+ * The PKZIP "deflate" file format interprets compressed file data
+ * as a sequence of bits. Multi-bit strings in the file may cross
+ * byte boundaries without restriction.
+ *
+ * The first bit of each byte is the low-order bit.
+ *
+ * The routines in this file allow a variable-length bit value to
+ * be output right-to-left (useful for literal values). For
+ * left-to-right output (useful for code strings from the tree routines),
+ * the bits must have been reversed first with bi_reverse().
+ *
+ * For in-memory compression, the compressed bit stream goes directly
+ * into the requested output buffer. The input data is read in blocks
+ * by the mem_read() function. The buffer is limited to 64K on 16 bit
+ * machines.
+ *
+ * INTERFACE
+ *
+ * void bi_init (FILE *zipfile)
+ * Initialize the bit string routines.
+ *
+ * void send_bits (int value, int length)
+ * Write out a bit string, taking the source bits right to
+ * left.
+ *
+ * int bi_reverse (int value, int length)
+ * Reverse the bits of a bit string, taking the source bits left to
+ * right and emitting them right to left.
+ *
+ * void bi_windup (void)
+ * Write out any remaining bits in an incomplete byte.
+ *
+ * void copy_block(char *buf, unsigned len, int header)
+ * Copy a stored block to the zip file, storing first the length and
+ * its one's complement if requested.
+ *
+ */
+
+#include "tailor.h"
+#include "gzip.h"
+#include "crypt.h"
+
+#ifdef DEBUG
+# include <stdio.h>
+#endif
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+/* ===========================================================================
+ * Local data used by the "bit string" routines.
+ */
+
+local file_t zfile; /* output gzip file */
+
+local unsigned short bi_buf;
+/* Output buffer. bits are inserted starting at the bottom (least significant
+ * bits).
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+local int bi_valid;
+/* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+int (*read_buf) OF((char *buf, unsigned size));
+/* Current input function. Set to mem_read for in-memory compression */
+
+#ifdef DEBUG
+ ulg bits_sent; /* bit length of the compressed data */
+#endif
+
+/* ===========================================================================
+ * Initialize the bit string routines.
+ */
+void bi_init (zipfile)
+ file_t zipfile; /* output zip file, NO_FILE for in-memory compression */
+{
+ zfile = zipfile;
+ bi_buf = 0;
+ bi_valid = 0;
+#ifdef DEBUG
+ bits_sent = 0L;
+#endif
+
+ /* Set the defaults for file compression. They are set by memcompress
+ * for in-memory compression.
+ */
+ if (zfile != NO_FILE) {
+ read_buf = file_read;
+ }
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+void send_bits(value, length)
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+#ifdef DEBUG
+ Tracev((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ bits_sent += (ulg)length;
+#endif
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (bi_valid > (int)Buf_size - length) {
+ bi_buf |= (value << bi_valid);
+ put_short(bi_buf);
+ bi_buf = (ush)value >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ } else {
+ bi_buf |= value << bi_valid;
+ bi_valid += length;
+ }
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Write out any remaining bits in an incomplete byte.
+ */
+void bi_windup()
+{
+ if (bi_valid > 8) {
+ put_short(bi_buf);
+ } else if (bi_valid > 0) {
+ put_byte(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+#ifdef DEBUG
+ bits_sent = (bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block to the zip file, storing first the length and its
+ * one's complement if requested.
+ */
+void copy_block(buf, len, header)
+ char *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(); /* align on byte boundary */
+
+ if (header) {
+ put_short((ush)len);
+ put_short((ush)~len);
+#ifdef DEBUG
+ bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+#ifdef CRYPT
+ int t;
+ if (key) zencode(*buf, t);
+#endif
+ put_byte(*buf++);
+ }
+}
diff --git a/gnu/usr.bin/gzip/crypt.c b/gnu/usr.bin/gzip/crypt.c
new file mode 100644
index 0000000..cdbd812
--- /dev/null
+++ b/gnu/usr.bin/gzip/crypt.c
@@ -0,0 +1,6 @@
+/* crypt.c (dummy version) -- do not perform encryption
+ * Hardly worth copyrighting :-)
+ */
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
diff --git a/gnu/usr.bin/gzip/crypt.h b/gnu/usr.bin/gzip/crypt.h
new file mode 100644
index 0000000..2a4c203
--- /dev/null
+++ b/gnu/usr.bin/gzip/crypt.h
@@ -0,0 +1,12 @@
+/* crypt.h (dummy version) -- do not perform encryption
+ * Hardly worth copyrighting :-)
+ */
+
+#ifdef CRYPT
+# undef CRYPT /* dummy version */
+#endif
+
+#define RAND_HEAD_LEN 12 /* length of encryption random header */
+
+#define zencode
+#define zdecode
diff --git a/gnu/usr.bin/gzip/deflate.c b/gnu/usr.bin/gzip/deflate.c
new file mode 100644
index 0000000..cbc4884
--- /dev/null
+++ b/gnu/usr.bin/gzip/deflate.c
@@ -0,0 +1,763 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/*
+ * PURPOSE
+ *
+ * Identify new text as repetitions of old text within a fixed-
+ * length sliding window trailing behind the new text.
+ *
+ * DISCUSSION
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many info-zippers for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ * INTERFACE
+ *
+ * void lm_init (int pack_level, ush *flags)
+ * Initialize the "longest match" routines for a new file
+ *
+ * ulg deflate (void)
+ * Processes a new input file and return its compressed length. Sets
+ * the compressed length, crc, deflate flags and internal file
+ * attributes.
+ */
+
+#include <stdio.h>
+
+#include "tailor.h"
+#include "gzip.h"
+#include "lzw.h" /* just for consistency checking */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+/* ===========================================================================
+ * Configuration parameters
+ */
+
+/* Compile with MEDIUM_MEM to reduce the memory requirements or
+ * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
+ * entire input file can be held in memory (not possible on 16 bit systems).
+ * Warning: defining these symbols affects HASH_BITS (see below) and thus
+ * affects the compression ratio. The compressed output
+ * is still correct, and might even be smaller in some cases.
+ */
+
+#ifdef SMALL_MEM
+# define HASH_BITS 13 /* Number of bits used to hash strings */
+#endif
+#ifdef MEDIUM_MEM
+# define HASH_BITS 14
+#endif
+#ifndef HASH_BITS
+# define HASH_BITS 15
+ /* For portability to 16 bit machines, do not use values above 15. */
+#endif
+
+/* To save space (see unlzw.c), we overlay prev+head with tab_prefix and
+ * window with tab_suffix. Check that we can do this:
+ */
+#if (WSIZE<<1) > (1<<BITS)
+ error: cannot overlay window with tab_suffix and prev with tab_prefix0
+#endif
+#if HASH_BITS > BITS-1
+ error: cannot overlay head with tab_prefix1
+#endif
+
+#define HASH_SIZE (unsigned)(1<<HASH_BITS)
+#define HASH_MASK (HASH_SIZE-1)
+#define WMASK (WSIZE-1)
+/* HASH_SIZE and WSIZE must be powers of two */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#define FAST 4
+#define SLOW 2
+/* speed options for the general purpose bit flag */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+/* ===========================================================================
+ * Local data used by the "longest match" routines.
+ */
+
+typedef ush Pos;
+typedef unsigned IPos;
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+/* DECLARE(uch, window, 2L*WSIZE); */
+/* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least WSIZE
+ * bytes. With this organization, matches are limited to a distance of
+ * WSIZE-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: limit the window size to WSIZE+BSZ if SMALL_MEM (the code would
+ * be less efficient).
+ */
+
+/* DECLARE(Pos, prev, WSIZE); */
+/* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+/* DECLARE(Pos, head, 1<<HASH_BITS); */
+/* Heads of the hash chains or NIL. */
+
+ulg window_size = (ulg)2*WSIZE;
+/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
+ * input file length plus MIN_LOOKAHEAD.
+ */
+
+long block_start;
+/* window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+local unsigned ins_h; /* hash index of string to be inserted */
+
+#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
+/* Number of bits by which ins_h and del_h must be shifted at each
+ * input step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * H_SHIFT * MIN_MATCH >= HASH_BITS
+ */
+
+unsigned int near prev_length;
+/* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ unsigned near strstart; /* start of string to insert */
+ unsigned near match_start; /* start of matching string */
+local int eofile; /* flag set at end of input file */
+local unsigned lookahead; /* number of valid bytes ahead in window */
+
+unsigned near max_chain_length;
+/* To speed up deflation, hash chains are never searched beyond this length.
+ * A higher limit improves compression ratio but degrades the speed.
+ */
+
+local unsigned int max_lazy_match;
+/* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+#define max_insert_length max_lazy_match
+/* Insert new strings in the hash table only if the match length
+ * is not greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+local int compr_level;
+/* compression level (1..9) */
+
+unsigned near good_match;
+/* Use a faster search when the previous match is longer than this */
+
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+
+typedef struct config {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+} config;
+
+#ifdef FULL_SEARCH
+# define nice_match MAX_MATCH
+#else
+ int near nice_match; /* Stop searching when current match exceeds this */
+#endif
+
+local config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0}, /* store only */
+/* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8},
+/* 3 */ {4, 6, 32, 32},
+
+/* 4 */ {4, 4, 16, 16}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32},
+/* 6 */ {8, 16, 128, 128},
+/* 7 */ {8, 32, 128, 256},
+/* 8 */ {32, 128, 258, 1024},
+/* 9 */ {32, 258, 258, 4096}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ * Prototypes for local functions.
+ */
+local void fill_window OF((void));
+local ulg deflate_fast OF((void));
+
+ int longest_match OF((IPos cur_match));
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+#endif
+
+#ifdef DEBUG
+local void check_match OF((IPos start, IPos match, int length));
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
+
+/* ===========================================================================
+ * Insert string s in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of s are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#define INSERT_STRING(s, match_head) \
+ (UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \
+ prev[(s) & WMASK] = match_head = head[ins_h], \
+ head[ins_h] = (s))
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new file
+ */
+void lm_init (pack_level, flags)
+ int pack_level; /* 0: store, 1: best speed, 9: best compression */
+ ush *flags; /* general purpose bit flag */
+{
+ register unsigned j;
+
+ if (pack_level < 1 || pack_level > 9) error("bad pack level");
+ compr_level = pack_level;
+
+ /* Initialize the hash table. */
+#if defined(MAXSEG_64K) && HASH_BITS == 15
+ for (j = 0; j < HASH_SIZE; j++) head[j] = NIL;
+#else
+ memzero((char*)head, HASH_SIZE*sizeof(*head));
+#endif
+ /* prev will be initialized on the fly */
+
+ /* Set the default configuration parameters:
+ */
+ max_lazy_match = configuration_table[pack_level].max_lazy;
+ good_match = configuration_table[pack_level].good_length;
+#ifndef FULL_SEARCH
+ nice_match = configuration_table[pack_level].nice_length;
+#endif
+ max_chain_length = configuration_table[pack_level].max_chain;
+ if (pack_level == 1) {
+ *flags |= FAST;
+ } else if (pack_level == 9) {
+ *flags |= SLOW;
+ }
+ /* ??? reduce max_chain_length for binary files */
+
+ strstart = 0;
+ block_start = 0L;
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+
+ lookahead = read_buf((char*)window,
+ sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE);
+
+ if (lookahead == 0 || lookahead == (unsigned)EOF) {
+ eofile = 1, lookahead = 0;
+ return;
+ }
+ eofile = 0;
+ /* Make sure that we always have enough lookahead. This is important
+ * if input comes from a device such as a tty.
+ */
+ while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
+
+ ins_h = 0;
+ for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]);
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
+ * not important since only literal bytes will be emitted.
+ */
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+#ifndef ASMV
+/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or
+ * match.s. The code is functionally equivalent, so you can use the C version
+ * if desired.
+ */
+int longest_match(cur_match)
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = max_chain_length; /* max hash chain length */
+ register uch *scan = window + strstart; /* current string */
+ register uch *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = prev_length; /* best match length so far */
+ IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+
+/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+#if HASH_BITS < 8 || MAX_MATCH != 258
+ error: Code too clever
+#endif
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register uch *strend = window + strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ush*)scan;
+ register ush scan_end = *(ush*)(scan+best_len-1);
+#else
+ register uch *strend = window + strstart + MAX_MATCH;
+ register uch scan_end1 = scan[best_len-1];
+ register uch scan_end = scan[best_len];
+#endif
+
+ /* Do not waste too much time if we already have a good match: */
+ if (prev_length >= good_match) {
+ chain_length >>= 2;
+ }
+ Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead");
+
+ do {
+ Assert(cur_match < strstart, "no future");
+ match = window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2:
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ush*)(match+best_len-1) != scan_end ||
+ *(ush*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ scan++, match++;
+ do {
+ } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ush*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & WMASK]) > limit
+ && --chain_length != 0);
+
+ return best_len;
+}
+#endif /* ASMV */
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(start, match, length)
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (memcmp((char*)window + match,
+ (char*)window + start, length) != EQUAL) {
+ fprintf(stderr,
+ " start %d, match %d, length %d\n",
+ start, match, length);
+ error("invalid match");
+ }
+ if (verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead, and sets eofile if end of input file.
+ * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
+ * OUT assertions: at least one byte has been read, or eofile is set;
+ * file reads are performed for at least two bytes (required for the
+ * translate_eol option).
+ */
+local void fill_window()
+{
+ register unsigned n, m;
+ unsigned more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart);
+ /* Amount of free space at the end of the window. */
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (more == (unsigned)EOF) {
+ /* Very unlikely, but possible on 16 bit machine if strstart == 0
+ * and lookahead == 1 (input done one byte at time)
+ */
+ more--;
+ } else if (strstart >= WSIZE+MAX_DIST) {
+ /* By the IN assertion, the window is not empty so we can't confuse
+ * more == 0 with more == 64K on a 16 bit machine.
+ */
+ Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM");
+
+ memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);
+ match_start -= WSIZE;
+ strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
+
+ block_start -= (long) WSIZE;
+
+ for (n = 0; n < HASH_SIZE; n++) {
+ m = head[n];
+ head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
+ }
+ for (n = 0; n < WSIZE; n++) {
+ m = prev[n];
+ prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ }
+ more += WSIZE;
+ }
+ /* At this point, more >= 2 */
+ if (!eofile) {
+ n = read_buf((char*)window+strstart+lookahead, more);
+ if (n == 0 || n == (unsigned)EOF) {
+ eofile = 1;
+ } else {
+ lookahead += n;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK(eof) \
+ flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
+ (char*)NULL, (long)strstart - block_start, (eof))
+
+/* ===========================================================================
+ * Processes a new input file and return its compressed length. This
+ * function does not perform lazy evaluationof matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local ulg deflate_fast()
+{
+ IPos hash_head; /* head of the hash chain */
+ int flush; /* set if current block must be flushed */
+ unsigned match_length = 0; /* length of best match */
+
+ prev_length = MIN_MATCH-1;
+ while (lookahead != 0) {
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ INSERT_STRING(strstart, hash_head);
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && strstart - hash_head <= MAX_DIST) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ match_length = longest_match (hash_head);
+ /* longest_match() sets match_start */
+ if (match_length > lookahead) match_length = lookahead;
+ }
+ if (match_length >= MIN_MATCH) {
+ check_match(strstart, match_start, match_length);
+
+ flush = ct_tally(strstart-match_start, match_length - MIN_MATCH);
+
+ lookahead -= match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+ if (match_length <= max_insert_length) {
+ match_length--; /* string at strstart already in hash table */
+ do {
+ strstart++;
+ INSERT_STRING(strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
+ * these bytes are garbage, but it does not matter since
+ * the next lookahead bytes will be emitted as literals.
+ */
+ } while (--match_length != 0);
+ strstart++;
+ } else {
+ strstart += match_length;
+ match_length = 0;
+ ins_h = window[strstart];
+ UPDATE_HASH(ins_h, window[strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c",window[strstart]));
+ flush = ct_tally (0, window[strstart]);
+ lookahead--;
+ strstart++;
+ }
+ if (flush) FLUSH_BLOCK(0), block_start = strstart;
+
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
+
+ }
+ return FLUSH_BLOCK(1); /* eof */
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+ulg deflate()
+{
+ IPos hash_head; /* head of hash chain */
+ IPos prev_match; /* previous match */
+ int flush; /* set if current block must be flushed */
+ int match_available = 0; /* set if previous match exists */
+ register unsigned match_length = MIN_MATCH-1; /* length of best match */
+#ifdef DEBUG
+ extern long isize; /* byte length of input file, for debug only */
+#endif
+
+ if (compr_level <= 3) return deflate_fast(); /* optimized for speed */
+
+ /* Process the input block. */
+ while (lookahead != 0) {
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ INSERT_STRING(strstart, hash_head);
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ prev_length = match_length, prev_match = match_start;
+ match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && prev_length < max_lazy_match &&
+ strstart - hash_head <= MAX_DIST) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ match_length = longest_match (hash_head);
+ /* longest_match() sets match_start */
+ if (match_length > lookahead) match_length = lookahead;
+
+ /* Ignore a length 3 match if it is too distant: */
+ if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ match_length--;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (prev_length >= MIN_MATCH && match_length <= prev_length) {
+
+ check_match(strstart-1, prev_match, prev_length);
+
+ flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted.
+ */
+ lookahead -= prev_length-1;
+ prev_length -= 2;
+ do {
+ strstart++;
+ INSERT_STRING(strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
+ * these bytes are garbage, but it does not matter since the
+ * next lookahead bytes will always be emitted as literals.
+ */
+ } while (--prev_length != 0);
+ match_available = 0;
+ match_length = MIN_MATCH-1;
+ strstart++;
+ if (flush) FLUSH_BLOCK(0), block_start = strstart;
+
+ } else if (match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c",window[strstart-1]));
+ if (ct_tally (0, window[strstart-1])) {
+ FLUSH_BLOCK(0), block_start = strstart;
+ }
+ strstart++;
+ lookahead--;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ match_available = 1;
+ strstart++;
+ lookahead--;
+ }
+ Assert (strstart <= isize && lookahead <= isize, "a bit too far");
+
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
+ }
+ if (match_available) ct_tally (0, window[strstart-1]);
+
+ return FLUSH_BLOCK(1); /* eof */
+}
diff --git a/gnu/usr.bin/gzip/getopt.c b/gnu/usr.bin/gzip/getopt.c
new file mode 100644
index 0000000..55fad84
--- /dev/null
+++ b/gnu/usr.bin/gzip/getopt.c
@@ -0,0 +1,755 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef __STDC__
+# ifndef const
+# define const
+# endif
+#endif
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#include <stdio.h>
+#include "tailor.h"
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+ long-named option. Because this is not POSIX.2 compliant, it is
+ being phased out. */
+/* #define GETOPT_COMPAT */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = 0;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+#define BAD_OPTION '\0'
+int optopt = BAD_OPTION;
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#define my_strlen strlen
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+#if __STDC__ || defined(PROTO)
+extern char *getenv(const char *name);
+extern int strcmp (const char *s1, const char *s2);
+extern int strncmp(const char *s1, const char *s2, int n);
+
+static int my_strlen(const char *s);
+static char *my_index (const char *str, int chr);
+#else
+extern char *getenv ();
+#endif
+
+static int
+my_strlen (str)
+ const char *str;
+{
+ int n = 0;
+ while (*str++)
+ n++;
+ return n;
+}
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+#endif /* GNU C library. */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved.
+
+ To perform the swap, we first reverse the order of all elements. So
+ all options now come before all non options, but they are in the
+ wrong order. So we put back the options and non options in original
+ order by reversing them again. For example:
+ original input: a b c -x -y
+ reverse all: -y -x c b a
+ reverse options: -x -y c b a
+ reverse non options: -x -y a b c
+*/
+
+#if __STDC__ || defined(PROTO)
+static void exchange (char **argv);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ char *temp, **first, **last;
+
+ /* Reverse all the elements [first_nonopt, optind) */
+ first = &argv[first_nonopt];
+ last = &argv[optind-1];
+ while (first < last) {
+ temp = *first; *first = *last; *last = temp; first++; last--;
+ }
+ /* Put back the options in order */
+ first = &argv[first_nonopt];
+ first_nonopt += (optind - last_nonopt);
+ last = &argv[first_nonopt - 1];
+ while (first < last) {
+ temp = *first; *first = *last; *last = temp; first++; last--;
+ }
+
+ /* Put back the non options in order */
+ first = &argv[first_nonopt];
+ last_nonopt = optind;
+ last = &argv[last_nonopt-1];
+ while (first < last) {
+ temp = *first; *first = *last; *last = temp; first++; last--;
+ }
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return BAD_OPTION after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return BAD_OPTION.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int option_index;
+
+ optarg = 0;
+
+ /* Initialize the internal data when the first call is made.
+ Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ if (optind == 0)
+ {
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (getenv ("POSIXLY_CORRECT") != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+ }
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Now skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* Special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Start decoding its characters. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ if (longopts != NULL
+ && ((argv[optind][0] == '-'
+ && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ ))
+ {
+ const struct option *p;
+ char *s = nextchar;
+ int exact = 0;
+ int ambig = 0;
+ const struct option *pfound = NULL;
+ int indfound = 0;
+
+ while (*s && *s != '=')
+ s++;
+
+ /* Test all options for either exact match or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name;
+ p++, option_index++)
+ if (!strncmp (p->name, nextchar, s - nextchar))
+ {
+ if (s - nextchar == my_strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += my_strlen (nextchar);
+ optind++;
+ return BAD_OPTION;
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*s)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = s + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += my_strlen (nextchar);
+ return BAD_OPTION;
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += my_strlen (nextchar);
+ return optstring[0] == ':' ? ':' : BAD_OPTION;
+ }
+ }
+ nextchar += my_strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return BAD_OPTION;
+ }
+ }
+
+ /* Look at and handle the next option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+#if 0
+ if (c < 040 || c >= 0177)
+ fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+ argv[0], c);
+ else
+ fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+#else
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+#endif
+ }
+ optopt = c;
+ return BAD_OPTION;
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = 0;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+#if 0
+ fprintf (stderr, "%s: option `-%c' requires an argument\n",
+ argv[0], c);
+#else
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+#endif
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = BAD_OPTION;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case BAD_OPTION:
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/gzip/getopt.h b/gnu/usr.bin/gzip/getopt.h
new file mode 100644
index 0000000..0abce6e
--- /dev/null
+++ b/gnu/usr.bin/gzip/getopt.h
@@ -0,0 +1,127 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if __STDC__ || defined(PROTO)
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/gnu/usr.bin/gzip/gzexe b/gnu/usr.bin/gzip/gzexe
new file mode 100644
index 0000000..8cce647
--- /dev/null
+++ b/gnu/usr.bin/gzip/gzexe
@@ -0,0 +1,158 @@
+#!/bin/sh
+# gzexe: compressor for Unix executables.
+# Use this only for binaries that you do not use frequently.
+#
+# The compressed version is a shell script which decompresses itself after
+# skipping $skip lines of shell commands. We try invoking the compressed
+# executable with the original name (for programs looking at their name).
+# We also try to retain the original file permissions on the compressed file.
+# For safety reasons, gzexe will not create setuid or setgid shell scripts.
+
+# WARNING: the first line of this file must be either : or #!/bin/sh
+# The : is required for some old versions of csh.
+# On Ultrix, /bin/sh is too buggy, change the first line to: #!/bin/sh5
+#
+# $FreeBSD$
+
+x=`basename $0`
+if test $# = 0; then
+ echo compress executables. original file foo is renamed to foo~
+ echo usage: ${x} [-d] files...
+ echo " -d decompress the executables"
+ exit 1
+fi
+
+tmp=`/usr/bin/mktemp -t gz` || exit 1
+trap "rm -f $tmp; exit 1" 1 2 3 5 10 13 15
+
+decomp=0
+res=0
+test "$x" = "ungzexe" && decomp=1
+if test "x$1" = "x-d"; then
+ decomp=1
+ shift
+fi
+
+zfoo1=`/usr/bin/mktemp -t zfoo1` || exit 1
+zfoo2=`/usr/bin/mktemp -t zfoo2` || exit 1
+echo hi > $zfoo1
+echo hi > $zfoo2
+if test -z "`(${CPMOD-cpmod} $zfoo1 $zfoo2) 2>&1`"; then
+ cpmod=${CPMOD-cpmod}
+fi
+rm -f $zfoo1 $zfoo2
+
+tail=""
+IFS="${IFS= }"; saveifs="$IFS"; IFS="${IFS}:"
+for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/tail; then
+ tail="$dir/tail"
+ break
+ fi
+done
+IFS="$saveifs"
+if test -z "$tail"; then
+ echo cannot find tail
+ exit 1
+fi
+
+for i do
+ if test ! -f "$i" ; then
+ echo ${x}: $i not a file
+ res=1
+ continue
+ fi
+ if test $decomp -eq 0; then
+ if sed -e 1d -e 2q "$i" | grep "^skip=[0-9]*$" >/dev/null; then
+ echo "${x}: $i is already gzexe'd"
+ continue
+ fi
+ fi
+ if ls -l "$i" | grep '^...[sS]' > /dev/null; then
+ echo "${x}: $i has setuid permission, unchanged"
+ continue
+ fi
+ if ls -l "$i" | grep '^......[sS]' > /dev/null; then
+ echo "${x}: $i has setgid permission, unchanged"
+ continue
+ fi
+ case "`basename $i`" in
+ sh | gzip | tail | chmod | ln | sleep | rm | mktemp)
+ echo "${x}: $i would depend on itself"; continue ;;
+ esac
+ if test -z "$cpmod"; then
+ cp -p "$i" $tmp 2>/dev/null || cp "$i" $tmp
+ if test -w $tmp 2>/dev/null; then
+ writable=1
+ else
+ writable=0
+ chmod u+w $tmp 2>/dev/null
+ fi
+ fi
+ if test $decomp -eq 0; then
+ sed 1q $0 > $tmp
+ sed "s|^if tail|if $tail|" >> $tmp <<'EOF'
+skip=22
+gztmp=`/usr/bin/mktemp -t gztmp` || exit 1
+if tail +$skip $0 | gzip -cd > $gztmp; then
+ chmod 700 $gztmp
+ prog="`echo $0 | sed 's|^.*/||'`"
+ progtmp=`/usr/bin/mktemp -t ${prog}` || exit 1
+ if /bin/ln $gztmp $progtmp 2>/dev/null; then
+ trap '/bin/rm -f $gztmp $progtmp; exit $res' 0
+ (/bin/sleep 5; /bin/rm -f $gztmp $progtmp) 2>/dev/null &
+ /tmp/"$prog" ${1+"$@"}; res=$?
+ else
+ trap '/bin/rm -f $progtmp $gztmp exit $res' 0
+ (/bin/sleep 5; /bin/rm -f $progtmp $gztmp) 2>/dev/null &
+ $gztmp ${1+"$@"}; res=$?
+ fi
+else
+ echo Cannot decompress $0
+ rm -f $gztmp
+ exit 1
+fi; exit $res
+EOF
+ gzip -cv9 "$i" >> $tmp || {
+ /bin/rm -f $tmp
+ echo ${x}: compression not possible for $i, file unchanged.
+ res=1
+ continue
+ }
+
+ else
+ # decompression
+ skip=18
+ if sed -e 1d -e 2q "$i" | grep "^skip=[0-9]*$" >/dev/null; then
+ eval `sed -e 1d -e 2q "$i"`
+ fi
+ if tail +$skip "$i" | gzip -cd > $tmp; then
+ :
+ else
+ echo ${x}: $i probably not in gzexe format, file unchanged.
+ res=1
+ continue
+ fi
+ fi
+ rm -f "$i~"
+ mv "$i" "$i~" || {
+ echo ${x}: cannot backup $i as $i~
+ rm -f $tmp
+ res=1
+ continue
+ }
+ mv $tmp "$i" || cp -p $tmp "$i" 2>/dev/null || cp $tmp "$i" || {
+ echo ${x}: cannot create $i
+ rm -f $tmp
+ res=1
+ continue
+ }
+ rm -f $tmp
+ if test -n "$cpmod"; then
+ $cpmod "$i~" "$i" 2>/dev/null
+ elif test $writable -eq 0; then
+ chmod u-w $i 2>/dev/null
+ fi
+done
+exit $res
diff --git a/gnu/usr.bin/gzip/gzexe.1 b/gnu/usr.bin/gzip/gzexe.1
new file mode 100644
index 0000000..8b62cd6
--- /dev/null
+++ b/gnu/usr.bin/gzip/gzexe.1
@@ -0,0 +1,43 @@
+.TH GZEXE 1
+.SH NAME
+gzexe \- compress executable files in place
+.SH SYNOPSIS
+.B gzexe
+[ name ... ]
+.SH DESCRIPTION
+The
+.I gzexe
+utility allows you to compress executables in place and have them
+automatically uncompress and execute when you run them (at a penalty
+in performance). For example if you execute ``gzexe /bin/cat'' it
+will create the following two files:
+.nf
+.br
+ -r-xr-xr-x 1 root bin 9644 Feb 11 11:16 /bin/cat
+ -r-xr-xr-x 1 bin bin 24576 Nov 23 13:21 /bin/cat~
+.fi
+/bin/cat~ is the original file and /bin/cat is the self-uncompressing
+executable file. You can remove /bin/cat~ once you are sure that
+/bin/cat works properly.
+.PP
+This utility is most useful on systems with very small disks.
+.SH OPTIONS
+.TP
+.B \-d
+Decompress the given executables instead of compressing them.
+.SH "SEE ALSO"
+gzip(1), znew(1), zmore(1), zcmp(1), zforce(1)
+.SH CAVEATS
+The compressed executable is a shell script. This may create some
+security holes. In particular, the compressed executable relies
+on the PATH environment variable to find
+.I gzip
+and some other utilities
+.I (tail, chmod, ln, sleep).
+.SH "BUGS"
+.I gzexe
+attempts to retain the original file attributes on the compressed executable,
+but you may have to fix them manually in some cases, using
+.I chmod
+or
+.I chown.
diff --git a/gnu/usr.bin/gzip/gzip.1 b/gnu/usr.bin/gzip/gzip.1
new file mode 100644
index 0000000..795e47f
--- /dev/null
+++ b/gnu/usr.bin/gzip/gzip.1
@@ -0,0 +1,479 @@
+.\" $FreeBSD$
+.\"
+.PU
+.TH GZIP 1
+.SH NAME
+gzip, gunzip, zcat \- compress or expand files
+.SH SYNOPSIS
+.ll +8
+.B gzip
+.RB [ " \-acdfhlLnNrtvV19 " ]
+.RB [ \-S\ suffix ]
+[
+.I "name \&..."
+]
+.ll -8
+.br
+.B gunzip
+.RB [ " \-acfhlLnNrtvV " ]
+.RB [ \-S\ suffix ]
+[
+.I "name \&..."
+]
+.br
+.B zcat
+.RB [ " \-fhLV " ]
+[
+.I "name \&..."
+]
+.SH DESCRIPTION
+.I Gzip
+reduces the size of the named files using Lempel-Ziv coding (LZ77).
+Whenever possible,
+each file is replaced by one with the extension
+.B "\&.gz,"
+while keeping the same ownership modes, access and modification times.
+(The default extension is
+.B "\-gz"
+for VMS,
+.B "z"
+for MSDOS, OS/2 FAT, Windows NT FAT and Atari.)
+If no files are specified, or if a file name is "-", the standard input is
+compressed to the standard output.
+.I Gzip
+will only attempt to compress regular files.
+In particular, it will ignore symbolic links.
+.PP
+If the compressed file name is too long for its file system,
+.I gzip
+truncates it.
+.I Gzip
+attempts to truncate only the parts of the file name longer than 3 characters.
+(A part is delimited by dots.) If the name consists of small parts only,
+the longest parts are truncated. For example, if file names are limited
+to 14 characters, gzip.msdos.exe is compressed to gzi.msd.exe.gz.
+Names are not truncated on systems which do not have a limit on file name
+length.
+.PP
+By default,
+.I gzip
+keeps the original file name and timestamp in the compressed file. These
+are used when decompressing the file with the
+.B \-N
+option. This is useful when the compressed file name was truncated or
+when the time stamp was not preserved after a file transfer.
+.PP
+Compressed files can be restored to their original form using
+.I gzip -d
+or
+.I gunzip
+or
+.I zcat.
+If the original name saved in the compressed file is not suitable for its
+file system, a new name is constructed from the original one to make it
+legal.
+.PP
+.I gunzip
+takes a list of files on its command line and replaces each
+file whose name ends with .gz, -gz, .z, -z, _z or .Z
+and which begins with the correct magic number with an uncompressed
+file without the original extension.
+.I gunzip
+also recognizes the special extensions
+.B "\&.tgz"
+and
+.B "\&.taz"
+as shorthands for
+.B "\&.tar.gz"
+and
+.B "\&.tar.Z"
+respectively.
+When compressing,
+.I gzip
+uses the
+.B "\&.tgz"
+extension if necessary instead of truncating a file with a
+.B "\&.tar"
+extension.
+.PP
+.I gunzip
+can currently decompress files created by
+.I gzip, zip, compress, compress -H
+or
+.I pack.
+The detection of the input format is automatic. When using
+the first two formats,
+.I gunzip
+checks a 32 bit CRC. For
+.I pack, gunzip
+checks the uncompressed length. The standard
+.I compress
+format was not designed to allow consistency checks. However
+.I gunzip
+is sometimes able to detect a bad .Z file. If you get an error
+when uncompressing a .Z file, do not assume that the .Z file is
+correct simply because the standard
+.I uncompress
+does not complain. This generally means that the standard
+.I uncompress
+does not check its input, and happily generates garbage output.
+The SCO compress -H format (lzh compression method) does not include a CRC
+but also allows some consistency checks.
+.PP
+Files created by
+.I zip
+can be uncompressed by gzip only if they have a single member compressed
+with the 'deflation' method. This feature is only intended to help
+conversion of tar.zip files to the tar.gz format. To extract zip files
+with several members, use
+.I unzip
+instead of
+.I gunzip.
+.PP
+.I zcat
+is identical to
+.I gunzip
+.B \-c.
+(On some systems,
+.I zcat
+may be installed as
+.I gzcat
+to preserve the original link to
+.I compress.)
+.I zcat
+uncompresses either a list of files on the command line or its
+standard input and writes the uncompressed data on standard output.
+.I zcat
+will uncompress files that have the correct magic number whether
+they have a
+.B "\&.gz"
+suffix or not.
+.PP
+.I Gzip
+uses the Lempel-Ziv algorithm used in
+.I zip
+and PKZIP.
+The amount of compression obtained depends on the size of the
+input and the distribution of common substrings.
+Typically, text such as source code or English
+is reduced by 60\-70%.
+Compression is generally much better than that achieved by
+LZW (as used in
+.IR compress ),
+Huffman coding (as used in
+.IR pack ),
+or adaptive Huffman coding
+.RI ( compact ).
+.PP
+Compression is always performed, even if the compressed file is
+slightly larger than the original. The worst case expansion is
+a few bytes for the gzip file header, plus 5 bytes every 32K block,
+or an expansion ratio of 0.015% for large files. Note that the actual
+number of used disk blocks almost never increases.
+.I gzip
+preserves the mode, ownership and timestamps of files when compressing
+or decompressing.
+
+.SH OPTIONS
+.TP
+.B \-a --ascii
+ASCII text mode: convert end-of-lines using local conventions. This option
+is supported only on some non-Unix systems. For MSDOS, CR LF is converted
+to LF when compressing, and LF is converted to CR LF when decompressing.
+.TP
+.B \-c --stdout --to-stdout
+Write output on standard output; keep original files unchanged.
+If there are several input files, the output consists of a sequence of
+independently compressed members. To obtain better compression,
+concatenate all input files before compressing them.
+.TP
+.B \-d --decompress --uncompress
+Decompress.
+.TP
+.B \-f --force
+Force compression or decompression even if the file has multiple links
+or the corresponding file already exists, or if the compressed data
+is read from or written to a terminal. If the input data is not in
+a format recognized by
+.I gzip,
+and if the option --stdout is also given, copy the input data without change
+to the standard output: let
+.I zcat
+behave as
+.I cat.
+If
+.B \-f
+is not given,
+and when not running in the background,
+.I gzip
+prompts to verify whether an existing file should be overwritten.
+.TP
+.B \-h --help
+Display a help screen and quit.
+.TP
+.B \-l --list
+For each compressed file, list the following fields:
+
+ compressed size: size of the compressed file
+ uncompressed size: size of the uncompressed file
+ ratio: compression ratio (0.0% if unknown)
+ uncompressed_name: name of the uncompressed file
+
+The uncompressed size is given as -1 for files not in gzip format,
+such as compressed .Z files. To get the uncompressed size for such a file,
+you can use:
+
+ zcat file.Z | wc -c
+
+In combination with the --verbose option, the following fields are also
+displayed:
+
+ method: compression method
+ crc: the 32-bit CRC of the uncompressed data
+ date & time: time stamp for the uncompressed file
+
+The compression methods currently supported are deflate, compress, lzh
+(SCO compress -H) and pack. The crc is given as ffffffff for a file
+not in gzip format.
+
+With --name, the uncompressed name, date and time are
+those stored within the compress file if present.
+
+With --verbose, the size totals and compression ratio for all files
+is also displayed, unless some sizes are unknown. With --quiet,
+the title and totals lines are not displayed.
+.TP
+.B \-L --license
+Display the
+.I gzip
+license and quit.
+.TP
+.B \-n --no-name
+When compressing, do not save the original file name and time stamp by
+default. (The original name is always saved if the name had to be
+truncated.) When decompressing, do not restore the original file name
+if present (remove only the
+.I gzip
+suffix from the compressed file name) and do not restore the original
+time stamp if present (copy it from the compressed file). This option
+is the default when decompressing.
+.TP
+.B \-N --name
+When compressing, always save the original file name and time stamp; this
+is the default. When decompressing, restore the original file name and
+time stamp if present. This option is useful on systems which have
+a limit on file name length or when the time stamp has been lost after
+a file transfer.
+.TP
+.B \-q --quiet
+Suppress all warnings.
+.TP
+.B \-r --recursive
+Travel the directory structure recursively. If any of the file names
+specified on the command line are directories,
+.I gzip
+will descend into the directory and compress all the files it finds there
+(or decompress them in the case of
+.I gunzip
+).
+.TP
+.B \-S .suf --suffix .suf
+Use suffix .suf instead of .gz. Any suffix can be given, but suffixes
+other than .z and .gz should be avoided to avoid confusion when files
+are transferred to other systems. A null suffix forces gunzip to try
+decompression on all given files regardless of suffix, as in:
+
+ gunzip -S "" * (*.* for MSDOS)
+
+Previous versions of gzip used
+the .z suffix. This was changed to avoid a conflict with
+.IR pack "(1)".
+.TP
+.B \-t --test
+Test. Check the compressed file integrity.
+.TP
+.B \-v --verbose
+Verbose. Display the name and percentage reduction for each file compressed
+or decompressed.
+.TP
+.B \-V --version
+Version. Display the version number and compilation options then quit.
+.TP
+.B \-# --fast --best
+Regulate the speed of compression using the specified digit
+.IR # ,
+where
+.B \-1
+or
+.B \-\-fast
+indicates the fastest compression method (less compression)
+and
+.B \-9
+or
+.B \-\-best
+indicates the slowest compression method (best compression).
+The default compression level is
+.BR \-6
+(that is, biased towards high compression at expense of speed).
+.SH "ADVANCED USAGE"
+Multiple compressed files can be concatenated. In this case,
+.I gunzip
+will extract all members at once. For example:
+
+ gzip -c file1 > foo.gz
+ gzip -c file2 >> foo.gz
+
+Then
+ gunzip -c foo
+
+is equivalent to
+
+ cat file1 file2
+
+In case of damage to one member of a .gz file, other members can
+still be recovered (if the damaged member is removed). However,
+you can get better compression by compressing all members at once:
+
+ cat file1 file2 | gzip > foo.gz
+
+compresses better than
+
+ gzip -c file1 file2 > foo.gz
+
+If you want to recompress concatenated files to get better compression, do:
+
+ gzip -cd old.gz | gzip > new.gz
+
+If a compressed file consists of several members, the uncompressed
+size and CRC reported by the --list option applies to the last member
+only. If you need the uncompressed size for all members, you can use:
+
+ gzip -cd file.gz | wc -c
+
+If you wish to create a single archive file with multiple members so
+that members can later be extracted independently, use an archiver
+such as tar or zip. GNU tar supports the -z option to invoke gzip
+transparently. gzip is designed as a complement to tar, not as a
+replacement.
+.SH "ENVIRONMENT"
+The environment variable
+.B GZIP
+can hold a set of default options for
+.I gzip.
+These options are interpreted first and can be overwritten by
+explicit command line parameters. For example:
+ for sh: GZIP="-8v --name"; export GZIP
+ for csh: setenv GZIP "-8v --name"
+ for MSDOS: set GZIP=-8v --name
+
+On Vax/VMS, the name of the environment variable is GZIP_OPT, to
+avoid a conflict with the symbol set for invocation of the program.
+.SH "SEE ALSO"
+znew(1), zcmp(1), zmore(1), zforce(1), gzexe(1), compress(1)
+.SH "DIAGNOSTICS"
+Exit status is normally 0;
+if an error occurs, exit status is 1. If a warning occurs, exit status is 2.
+.PP
+Usage: gzip [-cdfhlLnNrtvV19] [-S suffix] [file ...]
+.in +8
+Invalid options were specified on the command line.
+.in -8
+.IR file :
+not in gzip format
+.in +8
+The file specified to
+.I gunzip
+has not been compressed.
+.in -8
+.IR file:
+Corrupt input. Use zcat to recover some data.
+.in +8
+The compressed file has been damaged. The data up to the point of failure
+can be recovered using
+.in +8
+zcat file > recover
+.in -16
+.IR file :
+compressed with
+.I xx
+bits, can only handle
+.I yy
+bits
+.in +8
+.I File
+was compressed (using LZW) by a program that could deal with
+more
+.I bits
+than the decompress code on this machine.
+Recompress the file with gzip, which compresses better and uses
+less memory.
+.in -8
+.IR file :
+already has .gz suffix -- no change
+.in +8
+The file is assumed to be already compressed.
+Rename the file and try again.
+.in -8
+.I file
+already exists; do you wish to overwrite (y or n)?
+.in +8
+Respond "y" if you want the output file to be replaced; "n" if not.
+.in -8
+gunzip: corrupt input
+.in +8
+A SIGSEGV violation was detected which usually means that the input file has
+been corrupted.
+.in -8
+.I "xx.x%"
+.in +8
+Percentage of the input saved by compression.
+(Relevant only for
+.BR \-v
+and
+.BR \-l \.)
+.in -8
+-- not a regular file or directory: ignored
+.in +8
+When the input file is not a regular file or directory,
+(e.g. a symbolic link, socket, FIFO, device file), it is
+left unaltered.
+.in -8
+-- has
+.I xx
+other links: unchanged
+.in +8
+The input file has links; it is left unchanged. See
+.IR ln "(1)"
+for more information. Use the
+.B \-f
+flag to force compression of multiply-linked files.
+.in -8
+.SH CAVEATS
+When writing compressed data to a tape, it is generally necessary to
+pad the output with zeroes up to a block boundary. When the data is
+read and the whole block is passed to
+.I gunzip
+for decompression,
+.I gunzip
+detects that there is extra trailing garbage after the compressed data
+and emits a warning by default. You have to use the --quiet option to
+suppress the warning. This option can be set in the
+.B GZIP
+environment variable as in:
+ for sh: GZIP="-q" tar -xfz --block-compress /dev/rst0
+ for csh: (setenv GZIP -q; tar -xfz --block-compr /dev/rst0
+
+In the above example, gzip is invoked implicitly by the -z option of
+GNU tar. Make sure that the same block size (-b option of tar) is used
+for reading and writing compressed data on tapes. (This example
+assumes you are using the GNU version of tar.)
+.SH BUGS
+The --list option reports incorrect sizes if they exceed 2 gigabytes.
+The --list option reports sizes as -1 and crc as ffffffff if the
+compressed file is on a non seekable media.
+
+In some rare cases, the --best option gives worse compression than
+the default compression level (-6). On some highly redundant files,
+.I compress
+compresses better than
+.I gzip.
diff --git a/gnu/usr.bin/gzip/gzip.c b/gnu/usr.bin/gzip/gzip.c
new file mode 100644
index 0000000..b59b4d1
--- /dev/null
+++ b/gnu/usr.bin/gzip/gzip.c
@@ -0,0 +1,1755 @@
+/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * The unzip code was written and put in the public domain by Mark Adler.
+ * Portions of the lzw code are derived from the public domain 'compress'
+ * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
+ * Ken Turkowski, Dave Mack and Peter Jannesen.
+ *
+ * See the license_msg below and the file COPYING for the software license.
+ * See the file algorithm.doc for the compression algorithms and file formats.
+ */
+
+static char *license_msg[] = {
+" Copyright (C) 1992-1993 Jean-loup Gailly",
+" This program is free software; you can redistribute 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.",
+0};
+
+/* Compress files with zip algorithm and 'compress' interface.
+ * See usage() and help() functions below for all options.
+ * Outputs:
+ * file.gz: compressed file with same mode, owner, and utimes
+ * or stdout with -c option or if stdin used as input.
+ * If the output file name had to be truncated, the original name is kept
+ * in the compressed file.
+ * On MSDOS, file.tmp -> file.tmz. On VMS, file.tmp -> file.tmp-gz.
+ *
+ * Using gz on MSDOS would create too many file name conflicts. For
+ * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for
+ * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz.
+ * I also considered 12345678.txt -> 12345txt.gz but this truncates the name
+ * too heavily. There is no ideal solution given the MSDOS 8+3 limitation.
+ *
+ * For the meaning of all compilation flags, see comments in Makefile.in.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "tailor.h"
+#include "gzip.h"
+#include "lzw.h"
+#include "revision.h"
+#include "getopt.h"
+
+ /* configuration */
+
+#ifdef NO_TIME_H
+# include <sys/time.h>
+#else
+# include <time.h>
+#endif
+
+#ifndef NO_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
+# include <stdlib.h>
+#else
+ extern int errno;
+#endif
+
+#if defined(DIRENT)
+# include <dirent.h>
+ typedef struct dirent dir_type;
+# define NLENGTH(dirent) ((int)strlen((dirent)->d_name))
+# define DIR_OPT "DIRENT"
+#else
+# define NLENGTH(dirent) ((dirent)->d_namlen)
+# ifdef SYSDIR
+# include <sys/dir.h>
+ typedef struct direct dir_type;
+# define DIR_OPT "SYSDIR"
+# else
+# ifdef SYSNDIR
+# include <sys/ndir.h>
+ typedef struct direct dir_type;
+# define DIR_OPT "SYSNDIR"
+# else
+# ifdef NDIR
+# include <ndir.h>
+ typedef struct direct dir_type;
+# define DIR_OPT "NDIR"
+# else
+# define NO_DIR
+# define DIR_OPT "NO_DIR"
+# endif
+# endif
+# endif
+#endif
+
+#ifndef NO_UTIME
+# ifndef NO_UTIME_H
+# include <utime.h>
+# define TIME_OPT "UTIME"
+# else
+# ifdef HAVE_SYS_UTIME_H
+# include <sys/utime.h>
+# define TIME_OPT "SYS_UTIME"
+# else
+ struct utimbuf {
+ time_t actime;
+ time_t modtime;
+ };
+# define TIME_OPT ""
+# endif
+# endif
+#else
+# define TIME_OPT "NO_UTIME"
+#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
+
+typedef RETSIGTYPE (*sig_type) OF((int));
+
+#ifndef O_BINARY
+# define O_BINARY 0 /* creation mode for open() */
+#endif
+
+#ifndef O_CREAT
+ /* Pure BSD system? */
+# include <sys/file.h>
+# ifndef O_CREAT
+# define O_CREAT FCREAT
+# endif
+# ifndef O_EXCL
+# define O_EXCL FEXCL
+# endif
+#endif
+
+#ifndef S_IRUSR
+# define S_IRUSR 0400
+#endif
+#ifndef S_IWUSR
+# define S_IWUSR 0200
+#endif
+#define RW_USER (S_IRUSR | S_IWUSR) /* creation mode for open() */
+
+#ifndef MAX_PATH_LEN
+# define MAX_PATH_LEN 1024 /* max pathname length */
+#endif
+
+#ifndef SEEK_END
+# define SEEK_END 2
+#endif
+
+#ifdef NO_OFF_T
+ typedef long off_t;
+ off_t lseek OF((int fd, off_t offset, int whence));
+#endif
+
+/* Separator for file name parts (see shorten_name()) */
+#ifdef NO_MULTIPLE_DOTS
+# define PART_SEP "-"
+#else
+# define PART_SEP "."
+#endif
+
+ /* global buffers */
+
+DECLARE(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
+DECLARE(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
+DECLARE(ush, d_buf, DIST_BUFSIZE);
+DECLARE(uch, window, 2L*WSIZE);
+#ifndef MAXSEG_64K
+ DECLARE(ush, tab_prefix, 1L<<BITS);
+#else
+ DECLARE(ush, tab_prefix0, 1L<<(BITS-1));
+ DECLARE(ush, tab_prefix1, 1L<<(BITS-1));
+#endif
+
+ /* local variables */
+
+int ascii = 0; /* convert end-of-lines to local OS conventions */
+int to_stdout = 0; /* output to stdout (-c) */
+int decompress = 0; /* decompress (-d) */
+int force = 0; /* don't ask questions, compress links (-f) */
+int no_name = -1; /* don't save or restore the original file name */
+int no_time = -1; /* don't save or restore the original file time */
+int recursive = 0; /* recurse through directories (-r) */
+int list = 0; /* list the file contents (-l) */
+int verbose = 0; /* be verbose (-v) */
+int quiet = 0; /* be very quiet (-q) */
+int do_lzw = 0; /* generate output compatible with old compress (-Z) */
+int test = 0; /* test .gz file integrity */
+int foreground; /* set if program run in foreground */
+char *progname; /* program name */
+int maxbits = BITS; /* max bits per code for LZW */
+int method = DEFLATED;/* compression method */
+int level = 6; /* compression level */
+int exit_code = OK; /* program exit code */
+int save_orig_name; /* set if original name must be saved */
+int last_member; /* set for .zip and .Z files */
+int part_nb; /* number of parts in .gz file */
+long time_stamp; /* original time stamp (modification time) */
+long ifile_size; /* input file size, -1 for devices (debug only) */
+char *env; /* contents of GZIP env variable */
+char **args = NULL; /* argv pointer if GZIP env variable defined */
+char z_suffix[MAX_SUFFIX+1]; /* default suffix (can be set with --suffix) */
+int z_len; /* strlen(z_suffix) */
+
+long bytes_in; /* number of input bytes */
+long bytes_out; /* number of output bytes */
+long total_in = 0; /* input bytes for all files */
+long total_out = 0; /* output bytes for all files */
+char ifname[MAX_PATH_LEN]; /* input file name */
+char ofname[MAX_PATH_LEN]; /* output file name */
+int remove_ofname = 0; /* remove output file on error */
+struct stat istat; /* status for input file */
+int ifd; /* input file descriptor */
+int ofd; /* output file descriptor */
+unsigned insize; /* valid bytes in inbuf */
+unsigned inptr; /* index of next byte to be processed in inbuf */
+unsigned outcnt; /* bytes in output buffer */
+
+struct option longopts[] =
+{
+ /* { name has_arg *flag val } */
+ {"ascii", 0, 0, 'a'}, /* ascii text mode */
+ {"to-stdout", 0, 0, 'c'}, /* write output on standard output */
+ {"stdout", 0, 0, 'c'}, /* write output on standard output */
+ {"decompress", 0, 0, 'd'}, /* decompress */
+ {"uncompress", 0, 0, 'd'}, /* decompress */
+ /* {"encrypt", 0, 0, 'e'}, encrypt */
+ {"force", 0, 0, 'f'}, /* force overwrite of output file */
+ {"help", 0, 0, 'h'}, /* give help */
+ /* {"pkzip", 0, 0, 'k'}, force output in pkzip format */
+ {"list", 0, 0, 'l'}, /* list .gz file contents */
+ {"license", 0, 0, 'L'}, /* display software license */
+ {"no-name", 0, 0, 'n'}, /* don't save or restore original name & time */
+ {"name", 0, 0, 'N'}, /* save or restore original name & time */
+ {"quiet", 0, 0, 'q'}, /* quiet mode */
+ {"silent", 0, 0, 'q'}, /* quiet mode */
+ {"recursive", 0, 0, 'r'}, /* recurse through directories */
+ {"suffix", 1, 0, 'S'}, /* use given suffix instead of .gz */
+ {"test", 0, 0, 't'}, /* test compressed file integrity */
+ {"no-time", 0, 0, 'T'}, /* don't save or restore the time stamp */
+ {"verbose", 0, 0, 'v'}, /* verbose mode */
+ {"version", 0, 0, 'V'}, /* display version number */
+ {"fast", 0, 0, '1'}, /* compress faster */
+ {"best", 0, 0, '9'}, /* compress better */
+ {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */
+ {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */
+ { 0, 0, 0, 0 }
+};
+
+/* local functions */
+
+local void usage OF((void));
+local void help OF((void));
+local void license OF((void));
+local void version OF((void));
+local void treat_stdin OF((void));
+local void treat_file OF((char *iname));
+local int create_outfile OF((void));
+local int do_stat OF((char *name, struct stat *sbuf));
+local char *get_suffix OF((char *name));
+local int get_istat OF((char *iname, struct stat *sbuf));
+local int make_ofname OF((void));
+local int same_file OF((struct stat *stat1, struct stat *stat2));
+local int name_too_long OF((char *name, struct stat *statb));
+local void shorten_name OF((char *name));
+local int get_method OF((int in));
+local void do_list OF((int ifd, int method));
+local int check_ofname OF((void));
+local void copy_stat OF((struct stat *ifstat));
+local void do_exit OF((int exitcode));
+ int main OF((int argc, char **argv));
+int (*work) OF((int infile, int outfile)) = zip; /* function to call */
+
+#ifndef NO_DIR
+local void treat_dir OF((char *dir));
+#endif
+#ifndef NO_UTIME
+local void reset_times OF((char *name, struct stat *statb));
+#endif
+
+#define strequ(s1, s2) (strcmp((s1),(s2)) == 0)
+
+/* ======================================================================== */
+local void usage()
+{
+ fprintf(stderr, "usage: %s [-%scdfhlLnN%stvV19] [-S suffix] [file ...]\n",
+ progname,
+#if O_BINARY
+ "a",
+#else
+ "",
+#endif
+#ifdef NO_DIR
+ ""
+#else
+ "r"
+#endif
+ );
+}
+
+/* ======================================================================== */
+local void help()
+{
+ static char *help_msg[] = {
+#if O_BINARY
+ " -a --ascii ascii text; convert end-of-lines using local conventions",
+#endif
+ " -c --stdout write on standard output, keep original files unchanged",
+ " -d --decompress decompress",
+/* -e --encrypt encrypt */
+ " -f --force force overwrite of output file and compress links",
+ " -h --help give this help",
+/* -k --pkzip force output in pkzip format */
+ " -l --list list compressed file contents",
+ " -L --license display software license",
+#ifdef UNDOCUMENTED
+ " -m --no-time do not save or restore the original modification time",
+ " -M --time save or restore the original modification time",
+#endif
+ " -n --no-name do not save or restore the original name and time stamp",
+ " -N --name save or restore the original name and time stamp",
+ " -q --quiet suppress all warnings",
+#ifndef NO_DIR
+ " -r --recursive operate recursively on directories",
+#endif
+ " -S .suf --suffix .suf use suffix .suf on compressed files",
+ " -t --test test compressed file integrity",
+ " -v --verbose verbose mode",
+ " -V --version display version number",
+ " -1 --fast compress faster",
+ " -9 --best compress better",
+#ifdef LZW
+ " -Z --lzw produce output compatible with old compress",
+ " -b --bits maxbits max number of bits per code (implies -Z)",
+#endif
+ " file... files to (de)compress. If none given, use standard input.",
+ 0};
+ char **p = help_msg;
+
+ fprintf(stderr,"%s %s (%s)\n", progname, VERSION, REVDATE);
+ usage();
+ while (*p) fprintf(stderr, "%s\n", *p++);
+}
+
+/* ======================================================================== */
+local void license()
+{
+ char **p = license_msg;
+
+ fprintf(stderr,"%s %s (%s)\n", progname, VERSION, REVDATE);
+ while (*p) fprintf(stderr, "%s\n", *p++);
+}
+
+/* ======================================================================== */
+local void version()
+{
+ fprintf(stderr,"%s %s (%s)\n", progname, VERSION, REVDATE);
+
+ fprintf(stderr, "Compilation options:\n%s %s ", DIR_OPT, TIME_OPT);
+#ifdef STDC_HEADERS
+ fprintf(stderr, "STDC_HEADERS ");
+#endif
+#ifdef HAVE_UNISTD_H
+ fprintf(stderr, "HAVE_UNISTD_H ");
+#endif
+#ifdef NO_MEMORY_H
+ fprintf(stderr, "NO_MEMORY_H ");
+#endif
+#ifdef NO_STRING_H
+ fprintf(stderr, "NO_STRING_H ");
+#endif
+#ifdef NO_SYMLINK
+ fprintf(stderr, "NO_SYMLINK ");
+#endif
+#ifdef NO_MULTIPLE_DOTS
+ fprintf(stderr, "NO_MULTIPLE_DOTS ");
+#endif
+#ifdef NO_CHOWN
+ fprintf(stderr, "NO_CHOWN ");
+#endif
+#ifdef PROTO
+ fprintf(stderr, "PROTO ");
+#endif
+#ifdef ASMV
+ fprintf(stderr, "ASMV ");
+#endif
+#ifdef DEBUG
+ fprintf(stderr, "DEBUG ");
+#endif
+#ifdef DYN_ALLOC
+ fprintf(stderr, "DYN_ALLOC ");
+#endif
+#ifdef MAXSEG_64K
+ fprintf(stderr, "MAXSEG_64K");
+#endif
+ fprintf(stderr, "\n");
+}
+
+/* ======================================================================== */
+int main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int file_count; /* number of files to precess */
+ int proglen; /* length of progname */
+ int optc; /* current option */
+
+ EXPAND(argc, argv); /* wild card expansion if necessary */
+
+ progname = basename(argv[0]);
+ proglen = strlen(progname);
+
+ /* Suppress .exe for MSDOS, OS/2 and VMS: */
+ if (proglen > 4 && strequ(progname+proglen-4, ".exe")) {
+ progname[proglen-4] = '\0';
+ }
+
+ /* Add options in GZIP environment variable if there is one */
+ env = add_envopt(&argc, &argv, OPTIONS_VAR);
+ if (env != NULL) args = argv;
+
+ foreground = signal(SIGINT, SIG_IGN) != SIG_IGN;
+ if (foreground) {
+ (void) signal (SIGINT, (sig_type)abort_gzip);
+ }
+#ifdef SIGTERM
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGTERM, (sig_type)abort_gzip);
+ }
+#endif
+#ifdef SIGHUP
+ if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGHUP, (sig_type)abort_gzip);
+ }
+#endif
+
+#ifndef GNU_STANDARD
+ /* For compatibility with old compress, use program name as an option.
+ * If you compile with -DGNU_STANDARD, this program will behave as
+ * gzip even if it is invoked under the name gunzip or zcat.
+ *
+ * Systems which do not support links can still use -d or -dc.
+ * Ignore an .exe extension for MSDOS, OS/2 and VMS.
+ */
+ if ( strncmp(progname, "un", 2) == 0 /* ungzip, uncompress */
+ || strncmp(progname, "gun", 3) == 0) { /* gunzip */
+ decompress = 1;
+ } else if (strequ(progname+1, "cat") /* zcat, pcat, gcat */
+ || strequ(progname, "gzcat")) { /* gzcat */
+ decompress = to_stdout = 1;
+ }
+#endif
+
+ strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix)-1);
+ z_len = strlen(z_suffix);
+
+ while ((optc = getopt_long (argc, argv, "ab:cdfhH?lLmMnNqrS:tvVZ123456789",
+ longopts, (int *)0)) != EOF) {
+ switch (optc) {
+ case 'a':
+ ascii = 1; break;
+ case 'b':
+ maxbits = atoi(optarg);
+ break;
+ case 'c':
+ to_stdout = 1; break;
+ case 'd':
+ decompress = 1; break;
+ case 'f':
+ force++; break;
+ case 'h': case 'H': case '?':
+ help(); do_exit(OK); break;
+ case 'l':
+ list = decompress = to_stdout = 1; break;
+ case 'L':
+ license(); do_exit(OK); break;
+ case 'm': /* undocumented, may change later */
+ no_time = 1; break;
+ case 'M': /* undocumented, may change later */
+ no_time = 0; break;
+ case 'n':
+ no_name = no_time = 1; break;
+ case 'N':
+ no_name = no_time = 0; break;
+ case 'q':
+ quiet = 1; verbose = 0; break;
+ case 'r':
+#ifdef NO_DIR
+ fprintf(stderr, "%s: -r not supported on this system\n", progname);
+ usage();
+ do_exit(ERROR); break;
+#else
+ recursive = 1; break;
+#endif
+ case 'S':
+#ifdef NO_MULTIPLE_DOTS
+ if (*optarg == '.') optarg++;
+#endif
+ z_len = strlen(optarg);
+ if (z_len > sizeof(z_suffix)-1) {
+ fprintf(stderr, "%s: -S suffix too long\n", progname);
+ usage();
+ do_exit(ERROR);
+ }
+ strncpy(z_suffix, optarg, sizeof z_suffix-1);
+ z_suffix[sizeof z_suffix-1] = '\0';
+ break;
+ case 't':
+ test = decompress = to_stdout = 1;
+ break;
+ case 'v':
+ verbose++; quiet = 0; break;
+ case 'V':
+ version(); do_exit(OK); break;
+ case 'Z':
+#ifdef LZW
+ do_lzw = 1; break;
+#else
+ fprintf(stderr, "%s: -Z not supported in this version\n",
+ progname);
+ usage();
+ do_exit(ERROR); break;
+#endif
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ level = optc - '0';
+ break;
+ default:
+ /* Error message already emitted by getopt_long. */
+ usage();
+ do_exit(ERROR);
+ }
+ } /* loop on all arguments */
+
+ /* By default, save name and timestamp on compression but do not
+ * restore them on decompression.
+ */
+ if (no_time < 0) no_time = decompress;
+ if (no_name < 0) no_name = decompress;
+
+ file_count = argc - optind;
+
+#if O_BINARY
+#else
+ if (ascii && !quiet) {
+ fprintf(stderr, "%s: option --ascii ignored on this system\n",
+ progname);
+ }
+#endif
+ if ((z_len == 0 && !decompress) || z_len > MAX_SUFFIX) {
+ fprintf(stderr, "%s: incorrect suffix '%s'\n",
+ progname, optarg);
+ do_exit(ERROR);
+ }
+ if (do_lzw && !decompress) work = lzw;
+
+ /* Allocate all global buffers (for DYN_ALLOC option) */
+ ALLOC(uch, inbuf, INBUFSIZ +INBUF_EXTRA);
+ ALLOC(uch, outbuf, OUTBUFSIZ+OUTBUF_EXTRA);
+ ALLOC(ush, d_buf, DIST_BUFSIZE);
+ ALLOC(uch, window, 2L*WSIZE);
+#ifndef MAXSEG_64K
+ ALLOC(ush, tab_prefix, 1L<<BITS);
+#else
+ ALLOC(ush, tab_prefix0, 1L<<(BITS-1));
+ ALLOC(ush, tab_prefix1, 1L<<(BITS-1));
+#endif
+
+ /* And get to work */
+ if (file_count != 0) {
+ if (to_stdout && !test && !list && (!decompress || !ascii)) {
+ SET_BINARY_MODE(fileno(stdout));
+ }
+ while (optind < argc) {
+ treat_file(argv[optind++]);
+ }
+ } else { /* Standard input */
+ treat_stdin();
+ }
+ if (list && !quiet && file_count > 1) {
+ do_list(-1, -1); /* print totals */
+ }
+ do_exit(exit_code);
+ return exit_code; /* just to avoid lint warning */
+}
+
+/* ========================================================================
+ * Compress or decompress stdin
+ */
+local void treat_stdin()
+{
+ if (!force && !list &&
+ isatty(fileno((FILE *)(decompress ? stdin : stdout)))) {
+ /* Do not send compressed data to the terminal or read it from
+ * the terminal. We get here when user invoked the program
+ * without parameters, so be helpful. According to the GNU standards:
+ *
+ * If there is one behavior you think is most useful when the output
+ * is to a terminal, and another that you think is most useful when
+ * the output is a file or a pipe, then it is usually best to make
+ * the default behavior the one that is useful with output to a
+ * terminal, and have an option for the other behavior.
+ *
+ * Here we use the --force option to get the other behavior.
+ */
+ fprintf(stderr,
+ "%s: compressed data not %s a terminal. Use -f to force %scompression.\n",
+ progname, decompress ? "read from" : "written to",
+ decompress ? "de" : "");
+ fprintf(stderr,"For help, type: %s -h\n", progname);
+ do_exit(ERROR);
+ }
+
+ if (decompress || !ascii) {
+ SET_BINARY_MODE(fileno(stdin));
+ }
+ if (!test && !list && (!decompress || !ascii)) {
+ SET_BINARY_MODE(fileno(stdout));
+ }
+ strcpy(ifname, "stdin");
+ strcpy(ofname, "stdout");
+
+ /* Get the time stamp on the input file. */
+ time_stamp = 0; /* time unknown by default */
+
+#ifndef NO_STDIN_FSTAT
+ if (list || !no_time) {
+ if (fstat(fileno(stdin), &istat) != 0) {
+ error("fstat(stdin)");
+ }
+# ifdef NO_PIPE_TIMESTAMP
+ if (S_ISREG(istat.st_mode))
+# endif
+ time_stamp = istat.st_mtime;
+#endif /* NO_STDIN_FSTAT */
+ }
+ ifile_size = -1L; /* convention for unknown size */
+
+ clear_bufs(); /* clear input and output buffers */
+ to_stdout = 1;
+ part_nb = 0;
+
+ if (decompress) {
+ method = get_method(ifd);
+ if (method < 0) {
+ do_exit(exit_code); /* error message already emitted */
+ }
+ }
+ if (list) {
+ do_list(ifd, method);
+ return;
+ }
+
+ /* Actually do the compression/decompression. Loop over zipped members.
+ */
+ for (;;) {
+ if ((*work)(fileno(stdin), fileno(stdout)) != OK) return;
+
+ if (!decompress || last_member || inptr == insize) break;
+ /* end of file */
+
+ method = get_method(ifd);
+ if (method < 0) return; /* error message already emitted */
+ bytes_out = 0; /* required for length check */
+ }
+
+ if (verbose) {
+ if (test) {
+ fprintf(stderr, " OK\n");
+
+ } else if (!decompress) {
+ display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
+ fprintf(stderr, "\n");
+#ifdef DISPLAY_STDIN_RATIO
+ } else {
+ display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
+ fprintf(stderr, "\n");
+#endif
+ }
+ }
+}
+
+/* ========================================================================
+ * Compress or decompress the given file
+ */
+local void treat_file(iname)
+ char *iname;
+{
+ /* Accept "-" as synonym for stdin */
+ if (strequ(iname, "-")) {
+ int cflag = to_stdout;
+ treat_stdin();
+ to_stdout = cflag;
+ return;
+ }
+
+ /* Check if the input file is present, set ifname and istat: */
+ if (get_istat(iname, &istat) != OK) return;
+
+ /* If the input name is that of a directory, recurse or ignore: */
+ if (S_ISDIR(istat.st_mode)) {
+#ifndef NO_DIR
+ if (recursive) {
+ struct stat st;
+ st = istat;
+ treat_dir(iname);
+ /* Warning: ifname is now garbage */
+# ifndef NO_UTIME
+ reset_times (iname, &st);
+# endif
+ } else
+#endif
+ WARN((stderr,"%s: %s is a directory -- ignored\n", progname, ifname));
+ return;
+ }
+ if (!S_ISREG(istat.st_mode)) {
+ WARN((stderr,
+ "%s: %s is not a directory or a regular file - ignored\n",
+ progname, ifname));
+ return;
+ }
+ if (istat.st_nlink > 1 && !to_stdout && !force) {
+ WARN((stderr, "%s: %s has %d other link%c -- unchanged\n",
+ progname, ifname,
+ (int)istat.st_nlink - 1, istat.st_nlink > 2 ? 's' : ' '));
+ return;
+ }
+
+ ifile_size = istat.st_size;
+ time_stamp = no_time && !list ? 0 : istat.st_mtime;
+
+ /* Generate output file name. For -r and (-t or -l), skip files
+ * without a valid gzip suffix (check done in make_ofname).
+ */
+ if (to_stdout && !list && !test) {
+ strcpy(ofname, "stdout");
+
+ } else if (make_ofname() != OK) {
+ return;
+ }
+
+ /* Open the input file and determine compression method. The mode
+ * parameter is ignored but required by some systems (VMS) and forbidden
+ * on other systems (MacOS).
+ */
+ ifd = OPEN(ifname, ascii && !decompress ? O_RDONLY : O_RDONLY | O_BINARY,
+ RW_USER);
+ if (ifd == -1) {
+ fprintf(stderr, "%s: ", progname);
+ perror(ifname);
+ exit_code = ERROR;
+ return;
+ }
+ clear_bufs(); /* clear input and output buffers */
+ part_nb = 0;
+
+ if (decompress) {
+ method = get_method(ifd); /* updates ofname if original given */
+ if (method < 0) {
+ close(ifd);
+ return; /* error message already emitted */
+ }
+ }
+ if (list) {
+ do_list(ifd, method);
+ close(ifd);
+ return;
+ }
+
+ /* If compressing to a file, check if ofname is not ambiguous
+ * because the operating system truncates names. Otherwise, generate
+ * a new ofname and save the original name in the compressed file.
+ */
+ if (to_stdout) {
+ ofd = fileno(stdout);
+ /* keep remove_ofname as zero */
+ } else {
+ if (create_outfile() != OK) return;
+
+ if (!decompress && save_orig_name && !verbose && !quiet) {
+ fprintf(stderr, "%s: %s compressed to %s\n",
+ progname, ifname, ofname);
+ }
+ }
+ /* Keep the name even if not truncated except with --no-name: */
+ if (!save_orig_name) save_orig_name = !no_name;
+
+ if (verbose) {
+ fprintf(stderr, "%s:\t%s", ifname, (int)strlen(ifname) >= 15 ?
+ "" : ((int)strlen(ifname) >= 7 ? "\t" : "\t\t"));
+ }
+
+ /* Actually do the compression/decompression. Loop over zipped members.
+ */
+ for (;;) {
+ if ((*work)(ifd, ofd) != OK) {
+ method = -1; /* force cleanup */
+ break;
+ }
+ if (!decompress || last_member || inptr == insize) break;
+ /* end of file */
+
+ method = get_method(ifd);
+ if (method < 0) break; /* error message already emitted */
+ bytes_out = 0; /* required for length check */
+ }
+
+ close(ifd);
+ if (!to_stdout && close(ofd)) {
+ write_error();
+ }
+ if (method == -1) {
+ if (!to_stdout) unlink (ofname);
+ return;
+ }
+ /* Display statistics */
+ if(verbose) {
+ if (test) {
+ fprintf(stderr, " OK");
+ } else if (decompress) {
+ display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr);
+ } else {
+ display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
+ }
+ if (!test && !to_stdout) {
+ fprintf(stderr, " -- replaced with %s", ofname);
+ }
+ fprintf(stderr, "\n");
+ }
+ /* Copy modes, times, ownership, and remove the input file */
+ if (!to_stdout) {
+ copy_stat(&istat);
+ }
+}
+
+/* ========================================================================
+ * Create the output file. Return OK or ERROR.
+ * Try several times if necessary to avoid truncating the z_suffix. For
+ * example, do not create a compressed file of name "1234567890123."
+ * Sets save_orig_name to true if the file name has been truncated.
+ * IN assertions: the input file has already been open (ifd is set) and
+ * ofname has already been updated if there was an original name.
+ * OUT assertions: ifd and ofd are closed in case of error.
+ */
+local int create_outfile()
+{
+ struct stat ostat; /* stat for ofname */
+ int flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY;
+
+ if (ascii && decompress) {
+ flags &= ~O_BINARY; /* force ascii text mode */
+ }
+ for (;;) {
+ /* Make sure that ofname is not an existing file */
+ if (check_ofname() != OK) {
+ close(ifd);
+ return ERROR;
+ }
+ /* Create the output file */
+ remove_ofname = 1;
+ ofd = OPEN(ofname, flags, RW_USER);
+ if (ofd == -1) {
+ perror(ofname);
+ close(ifd);
+ exit_code = ERROR;
+ return ERROR;
+ }
+
+ /* Check for name truncation on new file (1234567890123.gz) */
+#ifdef NO_FSTAT
+ if (stat(ofname, &ostat) != 0) {
+#else
+ if (fstat(ofd, &ostat) != 0) {
+#endif
+ fprintf(stderr, "%s: ", progname);
+ perror(ofname);
+ close(ifd); close(ofd);
+ unlink(ofname);
+ exit_code = ERROR;
+ return ERROR;
+ }
+ if (!name_too_long(ofname, &ostat)) return OK;
+
+ if (decompress) {
+ /* name might be too long if an original name was saved */
+ WARN((stderr, "%s: %s: warning, name truncated\n",
+ progname, ofname));
+ return OK;
+ }
+ close(ofd);
+ unlink(ofname);
+#ifdef NO_MULTIPLE_DOTS
+ /* Should never happen, see check_ofname() */
+ fprintf(stderr, "%s: %s: name too long\n", progname, ofname);
+ do_exit(ERROR);
+#endif
+ shorten_name(ofname);
+ }
+}
+
+/* ========================================================================
+ * Use lstat if available, except for -c or -f. Use stat otherwise.
+ * This allows links when not removing the original file.
+ */
+local int do_stat(name, sbuf)
+ char *name;
+ struct stat *sbuf;
+{
+ errno = 0;
+#if (defined(S_IFLNK) || defined (S_ISLNK)) && !defined(NO_SYMLINK)
+ if (!to_stdout && !force) {
+ return lstat(name, sbuf);
+ }
+#endif
+ return stat(name, sbuf);
+}
+
+/* ========================================================================
+ * Return a pointer to the 'z' suffix of a file name, or NULL. For all
+ * systems, ".gz", ".z", ".Z", ".taz", ".tgz", "-gz", "-z" and "_z" are
+ * accepted suffixes, in addition to the value of the --suffix option.
+ * ".tgz" is a useful convention for tar.z files on systems limited
+ * to 3 characters extensions. On such systems, ".?z" and ".??z" are
+ * also accepted suffixes. For Unix, we do not want to accept any
+ * .??z suffix as indicating a compressed file; some people use .xyz
+ * to denote volume data.
+ * On systems allowing multiple versions of the same file (such as VMS),
+ * this function removes any version suffix in the given name.
+ */
+local char *get_suffix(name)
+ char *name;
+{
+ int nlen, slen;
+ char suffix[MAX_SUFFIX+3]; /* last chars of name, forced to lower case */
+ static char *known_suffixes[] =
+ {z_suffix, ".gz", ".z", ".taz", ".tgz", "-gz", "-z", "_z",
+#ifdef MAX_EXT_CHARS
+ "z",
+#endif
+ NULL};
+ char **suf = known_suffixes;
+
+ if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */
+
+#ifdef SUFFIX_SEP
+ /* strip a version number from the file name */
+ {
+ char *v = strrchr(name, SUFFIX_SEP);
+ if (v != NULL) *v = '\0';
+ }
+#endif
+ nlen = strlen(name);
+ if (nlen <= MAX_SUFFIX+2) {
+ strcpy(suffix, name);
+ } else {
+ strcpy(suffix, name+nlen-MAX_SUFFIX-2);
+ }
+ strlwr(suffix);
+ slen = strlen(suffix);
+ do {
+ int s = strlen(*suf);
+ if (slen > s && suffix[slen-s-1] != PATH_SEP
+ && strequ(suffix + slen - s, *suf)) {
+ return name+nlen-s;
+ }
+ } while (*++suf != NULL);
+
+ return NULL;
+}
+
+
+/* ========================================================================
+ * Set ifname to the input file name (with a suffix appended if necessary)
+ * and istat to its stats. For decompression, if no file exists with the
+ * original name, try adding successively z_suffix, .gz, .z, -z and .Z.
+ * For MSDOS, we try only z_suffix and z.
+ * Return OK or ERROR.
+ */
+local int get_istat(iname, sbuf)
+ char *iname;
+ struct stat *sbuf;
+{
+ int ilen; /* strlen(ifname) */
+ static char *suffixes[] = {z_suffix, ".gz", ".z", "-z", ".Z", NULL};
+ char **suf = suffixes;
+ char *s;
+#ifdef NO_MULTIPLE_DOTS
+ char *dot; /* pointer to ifname extension, or NULL */
+#endif
+
+ if (strlen(iname) >= sizeof(ifname) - 3) {
+ errno = ENAMETOOLONG;
+ perror(iname);
+ exit_code = ERROR;
+ return ERROR;
+ }
+
+ strcpy(ifname, iname);
+
+ /* If input file exists, return OK. */
+ if (do_stat(ifname, sbuf) == 0) return OK;
+
+ if (!decompress || errno != ENOENT) {
+ perror(ifname);
+ exit_code = ERROR;
+ return ERROR;
+ }
+ /* file.ext doesn't exist, try adding a suffix (after removing any
+ * version number for VMS).
+ */
+ s = get_suffix(ifname);
+ if (s != NULL) {
+ perror(ifname); /* ifname already has z suffix and does not exist */
+ exit_code = ERROR;
+ return ERROR;
+ }
+#ifdef NO_MULTIPLE_DOTS
+ dot = strrchr(ifname, '.');
+ if (dot == NULL) {
+ strcat(ifname, ".");
+ dot = strrchr(ifname, '.');
+ }
+#endif
+ ilen = strlen(ifname);
+ if (strequ(z_suffix, ".gz")) suf++;
+
+ /* Search for all suffixes */
+ do {
+ s = *suf;
+#ifdef NO_MULTIPLE_DOTS
+ if (*s == '.') s++;
+#endif
+#ifdef MAX_EXT_CHARS
+ strcpy(ifname, iname);
+ /* Needed if the suffixes are not sorted by increasing length */
+
+ if (*dot == '\0') strcpy(dot, ".");
+ dot[MAX_EXT_CHARS+1-strlen(s)] = '\0';
+#endif
+ strcat(ifname, s);
+ if (do_stat(ifname, sbuf) == 0) return OK;
+ ifname[ilen] = '\0';
+ } while (*++suf != NULL);
+
+ /* No suffix found, complain using z_suffix: */
+#ifdef MAX_EXT_CHARS
+ strcpy(ifname, iname);
+ if (*dot == '\0') strcpy(dot, ".");
+ dot[MAX_EXT_CHARS+1-z_len] = '\0';
+#endif
+ strcat(ifname, z_suffix);
+ perror(ifname);
+ exit_code = ERROR;
+ return ERROR;
+}
+
+/* ========================================================================
+ * Generate ofname given ifname. Return OK, or WARNING if file must be skipped.
+ * Sets save_orig_name to true if the file name has been truncated.
+ */
+local int make_ofname()
+{
+ char *suff; /* ofname z suffix */
+
+ strcpy(ofname, ifname);
+ /* strip a version number if any and get the gzip suffix if present: */
+ suff = get_suffix(ofname);
+
+ if (decompress) {
+ if (suff == NULL) {
+ /* Whith -t or -l, try all files (even without .gz suffix)
+ * except with -r (behave as with just -dr).
+ */
+ if (!recursive && (list || test)) return OK;
+
+ /* Avoid annoying messages with -r */
+ if (verbose || (!recursive && !quiet)) {
+ WARN((stderr,"%s: %s: unknown suffix -- ignored\n",
+ progname, ifname));
+ }
+ return WARNING;
+ }
+ /* Make a special case for .tgz and .taz: */
+ strlwr(suff);
+ if (strequ(suff, ".tgz") || strequ(suff, ".taz")) {
+ strcpy(suff, ".tar");
+ } else {
+ *suff = '\0'; /* strip the z suffix */
+ }
+ /* ofname might be changed later if infile contains an original name */
+
+ } else if (suff != NULL) {
+ /* Avoid annoying messages with -r (see treat_dir()) */
+ if (verbose || (!recursive && !quiet)) {
+ fprintf(stderr, "%s: %s already has %s suffix -- unchanged\n",
+ progname, ifname, suff);
+ }
+ if (exit_code == OK) exit_code = WARNING;
+ return WARNING;
+ } else {
+ save_orig_name = 0;
+
+#ifdef NO_MULTIPLE_DOTS
+ suff = strrchr(ofname, '.');
+ if (suff == NULL) {
+ strcat(ofname, ".");
+# ifdef MAX_EXT_CHARS
+ if (strequ(z_suffix, "z")) {
+ strcat(ofname, "gz"); /* enough room */
+ return OK;
+ }
+ /* On the Atari and some versions of MSDOS, name_too_long()
+ * does not work correctly because of a bug in stat(). So we
+ * must truncate here.
+ */
+ } else if (strlen(suff)-1 + z_len > MAX_SUFFIX) {
+ suff[MAX_SUFFIX+1-z_len] = '\0';
+ save_orig_name = 1;
+# endif
+ }
+#endif /* NO_MULTIPLE_DOTS */
+ strcat(ofname, z_suffix);
+
+ } /* decompress ? */
+ return OK;
+}
+
+
+/* ========================================================================
+ * Check the magic number of the input file and update ofname if an
+ * original name was given and to_stdout is not set.
+ * Return the compression method, -1 for error, -2 for warning.
+ * Set inptr to the offset of the next byte to be processed.
+ * Updates time_stamp if there is one and --no-time is not used.
+ * This function may be called repeatedly for an input file consisting
+ * of several contiguous gzip'ed members.
+ * IN assertions: there is at least one remaining compressed member.
+ * If the member is a zip file, it must be the only one.
+ */
+local int get_method(in)
+ int in; /* input file descriptor */
+{
+ uch flags; /* compression flags */
+ char magic[2]; /* magic header */
+ ulg stamp; /* time stamp */
+
+ /* If --force and --stdout, zcat == cat, so do not complain about
+ * premature end of file: use try_byte instead of get_byte.
+ */
+ if (force && to_stdout) {
+ magic[0] = (char)try_byte();
+ magic[1] = (char)try_byte();
+ /* If try_byte returned EOF, magic[1] == 0xff */
+ } else {
+ magic[0] = (char)get_byte();
+ magic[1] = (char)get_byte();
+ }
+ method = -1; /* unknown yet */
+ part_nb++; /* number of parts in gzip file */
+ header_bytes = 0;
+ last_member = RECORD_IO;
+ /* assume multiple members in gzip file except for record oriented I/O */
+
+ if (memcmp(magic, GZIP_MAGIC, 2) == 0
+ || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) {
+
+ method = (int)get_byte();
+ if (method != DEFLATED) {
+ fprintf(stderr,
+ "%s: %s: unknown method %d -- get newer version of gzip\n",
+ progname, ifname, method);
+ exit_code = ERROR;
+ return -1;
+ }
+ work = unzip;
+ flags = (uch)get_byte();
+
+ if ((flags & ENCRYPTED) != 0) {
+ fprintf(stderr,
+ "%s: %s is encrypted -- get newer version of gzip\n",
+ progname, ifname);
+ exit_code = ERROR;
+ return -1;
+ }
+ if ((flags & CONTINUATION) != 0) {
+ fprintf(stderr,
+ "%s: %s is a a multi-part gzip file -- get newer version of gzip\n",
+ progname, ifname);
+ exit_code = ERROR;
+ if (force <= 1) return -1;
+ }
+ if ((flags & RESERVED) != 0) {
+ fprintf(stderr,
+ "%s: %s has flags 0x%x -- get newer version of gzip\n",
+ progname, ifname, flags);
+ exit_code = ERROR;
+ if (force <= 1) return -1;
+ }
+ stamp = (ulg)get_byte();
+ stamp |= ((ulg)get_byte()) << 8;
+ stamp |= ((ulg)get_byte()) << 16;
+ stamp |= ((ulg)get_byte()) << 24;
+ if (stamp != 0 && !no_time) time_stamp = stamp;
+
+ (void)get_byte(); /* Ignore extra flags for the moment */
+ (void)get_byte(); /* Ignore OS type for the moment */
+
+ if ((flags & CONTINUATION) != 0) {
+ unsigned part = (unsigned)get_byte();
+ part |= ((unsigned)get_byte())<<8;
+ if (verbose) {
+ fprintf(stderr,"%s: %s: part number %u\n",
+ progname, ifname, part);
+ }
+ }
+ if ((flags & EXTRA_FIELD) != 0) {
+ unsigned len = (unsigned)get_byte();
+ len |= ((unsigned)get_byte())<<8;
+ if (verbose) {
+ fprintf(stderr,"%s: %s: extra field of %u bytes ignored\n",
+ progname, ifname, len);
+ }
+ while (len--) (void)get_byte();
+ }
+
+ /* Get original file name if it was truncated */
+ if ((flags & ORIG_NAME) != 0) {
+ if (no_name || (to_stdout && !list) || part_nb > 1) {
+ /* Discard the old name */
+ char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */
+ do {c=get_byte();} while (c != 0);
+ } else {
+ /* Copy the base name. Keep a directory prefix intact. */
+ char *p = basename(ofname);
+ char *base = p;
+ for (;;) {
+ *p = (char)get_char();
+ if (*p++ == '\0') break;
+ if (p >= ofname+sizeof(ofname)) {
+ error("corrupted input -- file name too large");
+ }
+ }
+ /* If necessary, adapt the name to local OS conventions: */
+ if (!list) {
+ MAKE_LEGAL_NAME(base);
+ if (base) list=0; /* avoid warning about unused variable */
+ }
+ } /* no_name || to_stdout */
+ } /* ORIG_NAME */
+
+ /* Discard file comment if any */
+ if ((flags & COMMENT) != 0) {
+ while (get_char() != 0) /* null */ ;
+ }
+ if (part_nb == 1) {
+ header_bytes = inptr + 2*sizeof(long); /* include crc and size */
+ }
+
+ } else if (memcmp(magic, PKZIP_MAGIC, 2) == 0 && inptr == 2
+ && memcmp((char*)inbuf, PKZIP_MAGIC, 4) == 0) {
+ /* To simplify the code, we support a zip file when alone only.
+ * We are thus guaranteed that the entire local header fits in inbuf.
+ */
+ inptr = 0;
+ work = unzip;
+ if (check_zipfile(in) != OK) return -1;
+ /* check_zipfile may get ofname from the local header */
+ last_member = 1;
+
+ } else if (memcmp(magic, PACK_MAGIC, 2) == 0) {
+ work = unpack;
+ method = PACKED;
+
+ } else if (memcmp(magic, LZW_MAGIC, 2) == 0) {
+ work = unlzw;
+ method = COMPRESSED;
+ last_member = 1;
+
+ } else if (memcmp(magic, LZH_MAGIC, 2) == 0) {
+ work = unlzh;
+ method = LZHED;
+ last_member = 1;
+
+ } else if (force && to_stdout && !list) { /* pass input unchanged */
+ method = STORED;
+ work = copy;
+ inptr = 0;
+ last_member = 1;
+ }
+ if (method >= 0) return method;
+
+ if (part_nb == 1) {
+ fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname);
+ exit_code = ERROR;
+ return -1;
+ } else {
+ WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n",
+ progname, ifname));
+ return -2;
+ }
+}
+
+/* ========================================================================
+ * Display the characteristics of the compressed file.
+ * If the given method is < 0, display the accumulated totals.
+ * IN assertions: time_stamp, header_bytes and ifile_size are initialized.
+ */
+local void do_list(ifd, method)
+ int ifd; /* input file descriptor */
+ int method; /* compression method */
+{
+ ulg crc; /* original crc */
+ static int first_time = 1;
+ static char* methods[MAX_METHODS] = {
+ "store", /* 0 */
+ "compr", /* 1 */
+ "pack ", /* 2 */
+ "lzh ", /* 3 */
+ "", "", "", "", /* 4 to 7 reserved */
+ "defla"}; /* 8 */
+ char *date;
+
+ if (first_time && method >= 0) {
+ first_time = 0;
+ if (verbose) {
+ printf("method crc date time ");
+ }
+ if (!quiet) {
+ printf("compressed uncompr. ratio uncompressed_name\n");
+ }
+ } else if (method < 0) {
+ if (total_in <= 0 || total_out <= 0) return;
+ if (verbose) {
+ printf(" %9lu %9lu ",
+ total_in, total_out);
+ } else if (!quiet) {
+ printf("%9ld %9ld ", total_in, total_out);
+ }
+ display_ratio(total_out-(total_in-header_bytes), total_out, stdout);
+ /* header_bytes is not meaningful but used to ensure the same
+ * ratio if there is a single file.
+ */
+ printf(" (totals)\n");
+ return;
+ }
+ crc = (ulg)~0; /* unknown */
+ bytes_out = -1L;
+ bytes_in = ifile_size;
+
+#if RECORD_IO == 0
+ if (method == DEFLATED && !last_member) {
+ /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
+ * If the lseek fails, we could use read() to get to the end, but
+ * --list is used to get quick results.
+ * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if
+ * you are not concerned about speed.
+ */
+ bytes_in = (long)lseek(ifd, (off_t)(-8), SEEK_END);
+ if (bytes_in != -1L) {
+ uch buf[8];
+ bytes_in += 8L;
+ if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {
+ read_error();
+ }
+ crc = LG(buf);
+ bytes_out = LG(buf+4);
+ }
+ }
+#endif /* RECORD_IO */
+ date = ctime((time_t*)&time_stamp) + 4; /* skip the day of the week */
+ date[12] = '\0'; /* suppress the 1/100sec and the year */
+ if (verbose) {
+ printf("%5s %08lx %11s ", methods[method], crc, date);
+ }
+ printf("%9ld %9ld ", bytes_in, bytes_out);
+ if (bytes_in == -1L) {
+ total_in = -1L;
+ bytes_in = bytes_out = header_bytes = 0;
+ } else if (total_in >= 0) {
+ total_in += bytes_in;
+ }
+ if (bytes_out == -1L) {
+ total_out = -1L;
+ bytes_in = bytes_out = header_bytes = 0;
+ } else if (total_out >= 0) {
+ total_out += bytes_out;
+ }
+ display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout);
+ printf(" %s\n", ofname);
+}
+
+/* ========================================================================
+ * Return true if the two stat structures correspond to the same file.
+ */
+local int same_file(stat1, stat2)
+ struct stat *stat1;
+ struct stat *stat2;
+{
+ return stat1->st_ino == stat2->st_ino
+ && stat1->st_dev == stat2->st_dev
+#ifdef NO_ST_INO
+ /* Can't rely on st_ino and st_dev, use other fields: */
+ && stat1->st_mode == stat2->st_mode
+ && stat1->st_uid == stat2->st_uid
+ && stat1->st_gid == stat2->st_gid
+ && stat1->st_size == stat2->st_size
+ && stat1->st_atime == stat2->st_atime
+ && stat1->st_mtime == stat2->st_mtime
+ && stat1->st_ctime == stat2->st_ctime
+#endif
+ ;
+}
+
+/* ========================================================================
+ * Return true if a file name is ambiguous because the operating system
+ * truncates file names.
+ */
+local int name_too_long(name, statb)
+ char *name; /* file name to check */
+ struct stat *statb; /* stat buf for this file name */
+{
+ int s = strlen(name);
+ char c = name[s-1];
+ struct stat tstat; /* stat for truncated name */
+ int res;
+
+ tstat = *statb; /* Just in case OS does not fill all fields */
+ name[s-1] = '\0';
+ res = stat(name, &tstat) == 0 && same_file(statb, &tstat);
+ name[s-1] = c;
+ Trace((stderr, " too_long(%s) => %d\n", name, res));
+ return res;
+}
+
+/* ========================================================================
+ * Shorten the given name by one character, or replace a .tar extension
+ * with .tgz. Truncate the last part of the name which is longer than
+ * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name
+ * has only parts shorter than MIN_PART truncate the longest part.
+ * For decompression, just remove the last character of the name.
+ *
+ * IN assertion: for compression, the suffix of the given name is z_suffix.
+ */
+local void shorten_name(name)
+ char *name;
+{
+ int len; /* length of name without z_suffix */
+ char *trunc = NULL; /* character to be truncated */
+ int plen; /* current part length */
+ int min_part = MIN_PART; /* current minimum part length */
+ char *p;
+
+ len = strlen(name);
+ if (decompress) {
+ if (len <= 1) error("name too short");
+ name[len-1] = '\0';
+ return;
+ }
+ p = get_suffix(name);
+ if (p == NULL) error("can't recover suffix\n");
+ *p = '\0';
+ save_orig_name = 1;
+
+ /* compress 1234567890.tar to 1234567890.tgz */
+ if (len > 4 && strequ(p-4, ".tar")) {
+ strcpy(p-4, ".tgz");
+ return;
+ }
+ /* Try keeping short extensions intact:
+ * 1234.678.012.gz -> 123.678.012.gz
+ */
+ do {
+ p = strrchr(name, PATH_SEP);
+ p = p ? p+1 : name;
+ while (*p) {
+ plen = strcspn(p, PART_SEP);
+ p += plen;
+ if (plen > min_part) trunc = p-1;
+ if (*p) p++;
+ }
+ } while (trunc == NULL && --min_part != 0);
+
+ if (trunc != NULL) {
+ do {
+ trunc[0] = trunc[1];
+ } while (*trunc++);
+ trunc--;
+ } else {
+ trunc = strrchr(name, PART_SEP[0]);
+ if (trunc == NULL) error("internal error in shorten_name");
+ if (trunc[1] == '\0') trunc--; /* force truncation */
+ }
+ strcpy(trunc, z_suffix);
+}
+
+/* ========================================================================
+ * If compressing to a file, check if ofname is not ambiguous
+ * because the operating system truncates names. Otherwise, generate
+ * a new ofname and save the original name in the compressed file.
+ * If the compressed file already exists, ask for confirmation.
+ * The check for name truncation is made dynamically, because different
+ * file systems on the same OS might use different truncation rules (on SVR4
+ * s5 truncates to 14 chars and ufs does not truncate).
+ * This function returns -1 if the file must be skipped, and
+ * updates save_orig_name if necessary.
+ * IN assertions: save_orig_name is already set if ofname has been
+ * already truncated because of NO_MULTIPLE_DOTS. The input file has
+ * already been open and istat is set.
+ */
+local int check_ofname()
+{
+ struct stat ostat; /* stat for ofname */
+
+#ifdef ENAMETOOLONG
+ /* Check for strictly conforming Posix systems (which return ENAMETOOLONG
+ * instead of silently truncating filenames).
+ */
+ errno = 0;
+ while (stat(ofname, &ostat) != 0) {
+ if (errno != ENAMETOOLONG) return 0; /* ofname does not exist */
+ shorten_name(ofname);
+ }
+#else
+ if (stat(ofname, &ostat) != 0) return 0;
+#endif
+ /* Check for name truncation on existing file. Do this even on systems
+ * defining ENAMETOOLONG, because on most systems the strict Posix
+ * behavior is disabled by default (silent name truncation allowed).
+ */
+ if (!decompress && name_too_long(ofname, &ostat)) {
+ shorten_name(ofname);
+ if (stat(ofname, &ostat) != 0) return 0;
+ }
+
+ /* Check that the input and output files are different (could be
+ * the same by name truncation or links).
+ */
+ if (same_file(&istat, &ostat)) {
+ if (strequ(ifname, ofname)) {
+ fprintf(stderr, "%s: %s: cannot %scompress onto itself\n",
+ progname, ifname, decompress ? "de" : "");
+ } else {
+ fprintf(stderr, "%s: %s and %s are the same file\n",
+ progname, ifname, ofname);
+ }
+ exit_code = ERROR;
+ return ERROR;
+ }
+ /* Ask permission to overwrite the existing file */
+ if (!force) {
+ char response[80];
+ strcpy(response,"n");
+ fprintf(stderr, "%s: %s already exists;", progname, ofname);
+ if (foreground && isatty(fileno(stdin))) {
+ fprintf(stderr, " do you wish to overwrite (y or n)? ");
+ fflush(stderr);
+ (void)fgets(response, sizeof(response)-1, stdin);
+ }
+ if (tolow(*response) != 'y') {
+ fprintf(stderr, "\tnot overwritten\n");
+ if (exit_code == OK) exit_code = WARNING;
+ return ERROR;
+ }
+ }
+ if (unlink(ofname)) {
+ fprintf(stderr, "%s: ", progname);
+ perror(ofname);
+ exit_code = ERROR;
+ return ERROR;
+ }
+ return OK;
+}
+
+
+#ifndef NO_UTIME
+/* ========================================================================
+ * Set the access and modification times from the given stat buffer.
+ */
+local void reset_times (name, statb)
+ char *name;
+ struct stat *statb;
+{
+ struct utimbuf timep;
+
+ /* Copy the time stamp */
+ timep.actime = statb->st_atime;
+ timep.modtime = statb->st_mtime;
+
+ /* Some systems (at least OS/2) do not support utime on directories */
+ if (utime(name, &timep) && !S_ISDIR(statb->st_mode)) {
+ WARN((stderr, "%s: ", progname));
+ if (!quiet) perror(ofname);
+ }
+}
+#endif
+
+
+/* ========================================================================
+ * Copy modes, times, ownership from input file to output file.
+ * IN assertion: to_stdout is false.
+ */
+local void copy_stat(ifstat)
+ struct stat *ifstat;
+{
+#ifndef NO_UTIME
+ if (decompress && time_stamp != 0 && ifstat->st_mtime != time_stamp) {
+ ifstat->st_mtime = time_stamp;
+ if (verbose > 1) {
+ fprintf(stderr, "%s: time stamp restored\n", ofname);
+ }
+ }
+ reset_times(ofname, ifstat);
+#endif
+ /* Copy the protection modes */
+ if (chmod(ofname, ifstat->st_mode & 07777)) {
+ WARN((stderr, "%s: ", progname));
+ if (!quiet) perror(ofname);
+ }
+#ifndef NO_CHOWN
+ chown(ofname, ifstat->st_uid, ifstat->st_gid); /* Copy ownership */
+#endif
+ remove_ofname = 0;
+ /* It's now safe to remove the input file: */
+ if (unlink(ifname)) {
+ WARN((stderr, "%s: ", progname));
+ if (!quiet) perror(ifname);
+ }
+}
+
+#ifndef NO_DIR
+
+/* ========================================================================
+ * Recurse through the given directory. This code is taken from ncompress.
+ */
+local void treat_dir(dir)
+ char *dir;
+{
+ dir_type *dp;
+ DIR *dirp;
+ char nbuf[MAX_PATH_LEN];
+ int len;
+
+ dirp = opendir(dir);
+
+ if (dirp == NULL) {
+ fprintf(stderr, "%s: %s unreadable\n", progname, dir);
+ exit_code = ERROR;
+ return ;
+ }
+ /*
+ ** WARNING: the following algorithm could occasionally cause
+ ** compress to produce error warnings of the form "<filename>.gz
+ ** already has .gz suffix - ignored". This occurs when the
+ ** .gz output file is inserted into the directory below
+ ** readdir's current pointer.
+ ** These warnings are harmless but annoying, so they are suppressed
+ ** with option -r (except when -v is on). An alternative
+ ** to allowing this would be to store the entire directory
+ ** list in memory, then compress the entries in the stored
+ ** list. Given the depth-first recursive algorithm used here,
+ ** this could use up a tremendous amount of memory. I don't
+ ** think it's worth it. -- Dave Mack
+ ** (An other alternative might be two passes to avoid depth-first.)
+ */
+
+ while ((dp = readdir(dirp)) != NULL) {
+
+ if (strequ(dp->d_name,".") || strequ(dp->d_name,"..")) {
+ continue;
+ }
+ len = strlen(dir);
+ if (len + NLENGTH(dp) + 1 < MAX_PATH_LEN - 1) {
+ strcpy(nbuf,dir);
+ if (len != 0 /* dir = "" means current dir on Amiga */
+#ifdef PATH_SEP2
+ && dir[len-1] != PATH_SEP2
+#endif
+#ifdef PATH_SEP3
+ && dir[len-1] != PATH_SEP3
+#endif
+ ) {
+ nbuf[len++] = PATH_SEP;
+ }
+ strcpy(nbuf+len, dp->d_name);
+ treat_file(nbuf);
+ } else {
+ fprintf(stderr,"%s: %s/%s: pathname too long\n",
+ progname, dir, dp->d_name);
+ exit_code = ERROR;
+ }
+ }
+ closedir(dirp);
+}
+#endif /* ? NO_DIR */
+
+/* ========================================================================
+ * Free all dynamically allocated variables and exit with the given code.
+ */
+local void do_exit(exitcode)
+ int exitcode;
+{
+ static int in_exit = 0;
+
+ if (in_exit) exit(exitcode);
+ in_exit = 1;
+ if (env != NULL) free(env), env = NULL;
+ if (args != NULL) free((char*)args), args = NULL;
+ FREE(inbuf);
+ FREE(outbuf);
+ FREE(d_buf);
+ FREE(window);
+#ifndef MAXSEG_64K
+ FREE(tab_prefix);
+#else
+ FREE(tab_prefix0);
+ FREE(tab_prefix1);
+#endif
+ exit(exitcode);
+}
+
+/* ========================================================================
+ * Signal and error handler.
+ */
+RETSIGTYPE abort_gzip()
+{
+ if (remove_ofname) {
+ close(ofd);
+ unlink (ofname);
+ }
+ do_exit(ERROR);
+}
diff --git a/gnu/usr.bin/gzip/gzip.h b/gnu/usr.bin/gzip/gzip.h
new file mode 100644
index 0000000..1ec96cb
--- /dev/null
+++ b/gnu/usr.bin/gzip/gzip.h
@@ -0,0 +1,315 @@
+/* gzip.h -- common declarations for all gzip modules
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if defined(__STDC__) || defined(PROTO)
+# define OF(args) args
+#else
+# define OF(args) ()
+#endif
+
+#ifdef __STDC__
+ typedef void *voidp;
+#else
+ typedef char *voidp;
+#endif
+
+/* I don't like nested includes, but the string and io functions are used
+ * too often
+ */
+#include <stdio.h>
+#if !defined(NO_STRING_H) || defined(STDC_HEADERS)
+# include <string.h>
+# if !defined(STDC_HEADERS) && !defined(NO_MEMORY_H) && !defined(__GNUC__)
+# include <memory.h>
+# endif
+# define memzero(s, n) memset ((voidp)(s), 0, (n))
+#else
+# include <strings.h>
+# define strchr index
+# define strrchr rindex
+# define memcpy(d, s, n) bcopy((s), (d), (n))
+# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
+# define memzero(s, n) bzero((s), (n))
+#endif
+
+#ifndef RETSIGTYPE
+# define RETSIGTYPE void
+#endif
+
+#define local static
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+/* Return codes from gzip */
+#define OK 0
+#define ERROR 1
+#define WARNING 2
+
+/* Compression methods (see algorithm.doc) */
+#define STORED 0
+#define COMPRESSED 1
+#define PACKED 2
+#define LZHED 3
+/* methods 4 to 7 reserved */
+#define DEFLATED 8
+#define MAX_METHODS 9
+extern int method; /* compression method */
+
+/* To save memory for 16 bit systems, some arrays are overlaid between
+ * the various modules:
+ * deflate: prev+head window d_buf l_buf outbuf
+ * unlzw: tab_prefix tab_suffix stack inbuf outbuf
+ * inflate: window inbuf
+ * unpack: window inbuf prefix_len
+ * unlzh: left+right window c_table inbuf c_len
+ * For compression, input is done in window[]. For decompression, output
+ * is done in window except for unlzw.
+ */
+
+#ifndef INBUFSIZ
+# ifdef SMALL_MEM
+# define INBUFSIZ 0x2000 /* input buffer size */
+# else
+# define INBUFSIZ 0x8000 /* input buffer size */
+# endif
+#endif
+#define INBUF_EXTRA 64 /* required by unlzw() */
+
+#ifndef OUTBUFSIZ
+# ifdef SMALL_MEM
+# define OUTBUFSIZ 8192 /* output buffer size */
+# else
+# define OUTBUFSIZ 16384 /* output buffer size */
+# endif
+#endif
+#define OUTBUF_EXTRA 2048 /* required by unlzw() */
+
+#ifndef DIST_BUFSIZE
+# ifdef SMALL_MEM
+# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
+# else
+# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
+# endif
+#endif
+
+#ifdef DYN_ALLOC
+# define EXTERN(type, array) extern type * near array
+# define DECLARE(type, array, size) type * near array
+# define ALLOC(type, array, size) { \
+ array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
+ if (array == NULL) error("insufficient memory"); \
+ }
+# define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
+#else
+# define EXTERN(type, array) extern type array[]
+# define DECLARE(type, array, size) type array[size]
+# define ALLOC(type, array, size)
+# define FREE(array)
+#endif
+
+EXTERN(uch, inbuf); /* input buffer */
+EXTERN(uch, outbuf); /* output buffer */
+EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
+EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
+#define tab_suffix window
+#ifndef MAXSEG_64K
+# define tab_prefix prev /* hash link (see deflate.c) */
+# define head (prev+WSIZE) /* hash head (see deflate.c) */
+ EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
+#else
+# define tab_prefix0 prev
+# define head tab_prefix1
+ EXTERN(ush, tab_prefix0); /* prefix for even codes */
+ EXTERN(ush, tab_prefix1); /* prefix for odd codes */
+#endif
+
+extern unsigned insize; /* valid bytes in inbuf */
+extern unsigned inptr; /* index of next byte to be processed in inbuf */
+extern unsigned outcnt; /* bytes in output buffer */
+
+extern long bytes_in; /* number of input bytes */
+extern long bytes_out; /* number of output bytes */
+extern long header_bytes;/* number of bytes in gzip header */
+
+#define isize bytes_in
+/* for compatibility with old zip sources (to be cleaned) */
+
+extern int ifd; /* input file descriptor */
+extern int ofd; /* output file descriptor */
+extern char ifname[]; /* input file name or "stdin" */
+extern char ofname[]; /* output file name or "stdout" */
+extern char *progname; /* program name */
+
+extern long time_stamp; /* original time stamp (modification time) */
+extern long ifile_size; /* input file size, -1 for devices (debug only) */
+
+typedef int file_t; /* Do not use stdio */
+#define NO_FILE (-1) /* in memory compression */
+
+
+#define PACK_MAGIC "\037\036" /* Magic header for packed files */
+#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */
+#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */
+#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files*/
+#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
+#define RESERVED 0xC0 /* bit 6,7: reserved */
+
+/* internal file attribute */
+#define UNKNOWN 0xffff
+#define BINARY 0
+#define ASCII 1
+
+#ifndef WSIZE
+# define WSIZE 0x8000 /* window size--must be a power of two, and */
+#endif /* at least 32K for zip's deflate method */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+extern int decrypt; /* flag to turn on decryption */
+extern int exit_code; /* program exit code */
+extern int verbose; /* be verbose (-v) */
+extern int quiet; /* be quiet (-q) */
+extern int level; /* compression level */
+extern int test; /* check .z file integrity */
+extern int to_stdout; /* output to stdout (-c) */
+extern int save_orig_name; /* set if original name must be saved */
+
+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0))
+#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1))
+
+/* put_byte is used for the compressed output, put_ubyte for the
+ * uncompressed output. However unlzw() uses window for its
+ * suffix table instead of its output buffer, so it does not use put_ubyte
+ * (to be cleaned up).
+ */
+#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
+ flush_outbuf();}
+#define put_ubyte(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
+ flush_window();}
+
+/* Output a 16 bit value, lsb first */
+#define put_short(w) \
+{ if (outcnt < OUTBUFSIZ-2) { \
+ outbuf[outcnt++] = (uch) ((w) & 0xff); \
+ outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
+ } else { \
+ put_byte((uch)((w) & 0xff)); \
+ put_byte((uch)((ush)(w) >> 8)); \
+ } \
+}
+
+/* Output a 32 bit value to the bit stream, lsb first */
+#define put_long(n) { \
+ put_short((n) & 0xffff); \
+ put_short(((ulg)(n)) >> 16); \
+}
+
+#define seekable() 0 /* force sequential output */
+#define translate_eol 0 /* no option -a yet */
+
+#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
+
+/* Macros for getting two-byte and four-byte header values */
+#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
+#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# define Assert(cond,msg) {if(!(cond)) error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+#define WARN(msg) {if (!quiet) fprintf msg ; \
+ if (exit_code == OK) exit_code = WARNING;}
+
+ /* in zip.c: */
+extern int zip OF((int in, int out));
+extern int file_read OF((char *buf, unsigned size));
+
+ /* in unzip.c */
+extern int unzip OF((int in, int out));
+extern int check_zipfile OF((int in));
+
+ /* in unpack.c */
+extern int unpack OF((int in, int out));
+
+ /* in unlzh.c */
+extern int unlzh OF((int in, int out));
+
+ /* in gzip.c */
+RETSIGTYPE abort_gzip OF((void));
+
+ /* in deflate.c */
+void lm_init OF((int pack_level, ush *flags));
+ulg deflate OF((void));
+
+ /* in trees.c */
+void ct_init OF((ush *attr, int *method));
+int ct_tally OF((int dist, int lc));
+ulg flush_block OF((char *buf, ulg stored_len, int eof));
+
+ /* in bits.c */
+void bi_init OF((file_t zipfile));
+void send_bits OF((int value, int length));
+unsigned bi_reverse OF((unsigned value, int length));
+void bi_windup OF((void));
+void copy_block OF((char *buf, unsigned len, int header));
+extern int (*read_buf) OF((char *buf, unsigned size));
+
+ /* in util.c: */
+extern int copy OF((int in, int out));
+extern ulg updcrc OF((uch *s, unsigned n));
+extern void clear_bufs OF((void));
+extern int fill_inbuf OF((int eof_ok));
+extern void flush_outbuf OF((void));
+extern void flush_window OF((void));
+extern void write_buf OF((int fd, voidp buf, unsigned cnt));
+extern char *strlwr OF((char *s));
+extern char *basename OF((char *fname));
+extern void make_simple_name OF((char *name));
+extern char *add_envopt OF((int *argcp, char ***argvp, char *env));
+extern void error OF((char *m));
+extern void warn OF((char *a, char *b));
+extern void read_error OF((void));
+extern void write_error OF((void));
+extern void display_ratio OF((long num, long den, FILE *file));
+extern voidp xmalloc OF((unsigned int size));
+
+ /* in inflate.c */
+extern int inflate OF((void));
diff --git a/gnu/usr.bin/gzip/inflate.c b/gnu/usr.bin/gzip/inflate.c
new file mode 100644
index 0000000..c9b250b
--- /dev/null
+++ b/gnu/usr.bin/gzip/inflate.c
@@ -0,0 +1,956 @@
+/* inflate.c -- Not copyrighted 1992 by Mark Adler
+ version c10p1, 10 January 1993 */
+
+/* You can do whatever you like with this source file, though I would
+ prefer that if you modify it and redistribute it that you include
+ comments to that effect with your name and the date. Thank you.
+ [The history has been moved to the file ChangeLog.]
+ */
+
+/*
+ Inflate deflated (PKZIP's method 8 compressed) data. The compression
+ method searches for as much of the current string of bytes (up to a
+ length of 258) in the previous 32K bytes. If it doesn't find any
+ matches (of at least length 3), it codes the next byte. Otherwise, it
+ codes the length of the matched string and its distance backwards from
+ the current position. There is a single Huffman code that codes both
+ single bytes (called "literals") and match lengths. A second Huffman
+ code codes the distance information, which follows a length code. Each
+ length or distance code actually represents a base value and a number
+ of "extra" (sometimes zero) bits to get to add to the base value. At
+ the end of each deflated block is a special end-of-block (EOB) literal/
+ length code. The decoding process is basically: get a literal/length
+ code; if EOB then done; if a literal, emit the decoded byte; if a
+ length then get the distance and emit the referred-to bytes from the
+ sliding window of previously emitted data.
+
+ There are (currently) three kinds of inflate blocks: stored, fixed, and
+ dynamic. The compressor deals with some chunk of data at a time, and
+ decides which method to use on a chunk-by-chunk basis. A chunk might
+ typically be 32K or 64K. If the chunk is uncompressible, then the
+ "stored" method is used. In this case, the bytes are simply stored as
+ is, eight bits per byte, with none of the above coding. The bytes are
+ preceded by a count, since there is no longer an EOB code.
+
+ If the data is compressible, then either the fixed or dynamic methods
+ are used. In the dynamic method, the compressed data is preceded by
+ an encoding of the literal/length and distance Huffman codes that are
+ to be used to decode this block. The representation is itself Huffman
+ coded, and so is preceded by a description of that code. These code
+ descriptions take up a little space, and so for small blocks, there is
+ a predefined set of codes, called the fixed codes. The fixed method is
+ used if the block codes up smaller that way (usually for quite small
+ chunks), otherwise the dynamic method is used. In the latter case, the
+ codes are customized to the probabilities in the current block, and so
+ can code it much better than the pre-determined fixed codes.
+
+ The Huffman codes themselves are decoded using a mutli-level table
+ lookup, in order to maximize the speed of decoding plus the speed of
+ building the decoding tables. See the comments below that precede the
+ lbits and dbits tuning parameters.
+ */
+
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarly, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <sys/types.h>
+
+#include "tailor.h"
+
+#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
+# include <stdlib.h>
+#endif
+
+#include "gzip.h"
+#define slide window
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model).
+ Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
+ means that v is a literal, 16 < e < 32 means that v is a pointer to
+ the next table, which codes e - 16 bits, and lastly e == 99 indicates
+ an unused code. If a code with e == 99 is looked up, this implies an
+ error in the data. */
+struct huft {
+ uch e; /* number of extra bits or operation */
+ uch b; /* number of bits in this code or subcode */
+ union {
+ ush n; /* literal, length base, or distance base */
+ struct huft *t; /* pointer to next level of table */
+ } v;
+};
+
+
+/* Function prototypes */
+int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
+ struct huft **, int *));
+int huft_free OF((struct huft *));
+int inflate_codes OF((struct huft *, struct huft *, int, int));
+int inflate_stored OF((void));
+int inflate_fixed OF((void));
+int inflate_dynamic OF((void));
+int inflate_block OF((int *));
+int inflate OF((void));
+
+
+/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
+ stream to find repeated byte strings. This is implemented here as a
+ circular buffer. The index is updated simply by incrementing and then
+ and'ing with 0x7fff (32K-1). */
+/* It is left to other modules to supply the 32K area. It is assumed
+ to be usable as if it were declared "uch slide[32768];" or as just
+ "uch *slide;" and then malloc'ed in the latter case. The definition
+ must be in unzip.h, included above. */
+/* unsigned wp; current position in slide */
+#define wp outcnt
+#define flush_output(w) (wp=(w),flush_window())
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static unsigned border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* note: see note #13 above about the 258 in this list. */
+static ush cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
+static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+static ush cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask_bits[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed, and are initialized at the beginning of a
+ routine that uses these macros from a global bit buffer and count.
+
+ If we assume that EOB will be the longest code, then we will never
+ ask for bits with NEEDBITS that are beyond the end of the stream.
+ So, NEEDBITS should not read any more bytes than are needed to
+ meet the request. Then no bytes need to be "returned" to the buffer
+ at the end of the last block.
+
+ However, this assumption is not true for fixed blocks--the EOB code
+ is 7 bits, but the other literal/length codes can be 8 or 9 bits.
+ (The EOB code is shorter than other codes because fixed blocks are
+ generally short. So, while a block always has an EOB, many other
+ literal/length codes have a significantly lower probability of
+ showing up at all.) However, by making the first table have a
+ lookup of seven bits, the EOB code will be found in that first
+ lookup, and so will not require that too many bits be pulled from
+ the stream.
+ */
+
+ulg bb; /* bit buffer */
+unsigned bk; /* bits in bit buffer */
+
+ush mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+#ifdef CRYPT
+ uch cc;
+# define NEXTBYTE() \
+ (decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
+#else
+# define NEXTBYTE() (uch)get_byte()
+#endif
+#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+int lbits = 9; /* bits in base literal/length lookup table */
+int dbits = 6; /* bits in base distance lookup table */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+
+unsigned hufts; /* track memory usage */
+
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
+unsigned n; /* number of codes (assumed <= N_MAX) */
+unsigned s; /* number of simple-valued codes (0..s-1) */
+ush *d; /* list of base values for non-simple codes */
+ush *e; /* list of extra bits for non-simple codes */
+struct huft **t; /* result: starting table */
+int *m; /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return zero on success, one if
+ the given code set is incomplete (the tables are still built in this
+ case), two if the input is invalid (all zero length codes or an
+ oversubscribed set of lengths), and three if not enough memory. */
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX+1]; /* bit length count table */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register unsigned i; /* counter, current code */
+ register unsigned j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register unsigned *p; /* pointer into c[], b[], or v[] */
+ register struct huft *q; /* points to current table */
+ struct huft r; /* table entry for structure assignment */
+ struct huft *u[BMAX]; /* table stack */
+ unsigned v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ unsigned x[BMAX+1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ memzero(c, sizeof(c));
+ p = b; i = n;
+ do {
+ Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"),
+ n-i, *p));
+ c[*p]++; /* assume all entries <= BMAX */
+ p++; /* Can't combine with above line (Solaris bug) */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (struct huft *)NULL;
+ *m = 0;
+ return 0;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((unsigned)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((unsigned)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return 2; /* bad input: more codes than bits */
+ if ((y -= c[i]) < 0)
+ return 2;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
+ q = (struct huft *)NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+ (struct huft *)NULL)
+ {
+ if (h)
+ huft_free(u[0]);
+ return 3; /* not enough memory */
+ }
+ hufts += z + 1; /* track memory usage */
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->v.t)) = (struct huft *)NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.b = (uch)l; /* bits to dump before this table */
+ r.e = (uch)(16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.b = (uch)(k - w);
+ if (p >= v + n)
+ r.e = 99; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
+ r.v.n = (ush)(*p); /* simple code is just the value */
+ p++; /* one compiler does not like *p++ */
+ }
+ else
+ {
+ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+
+int huft_free(t)
+struct huft *t; /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register struct huft *p, *q;
+
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != (struct huft *)NULL)
+ {
+ q = (--p)->v.t;
+ free((char*)p);
+ p = q;
+ }
+ return 0;
+}
+
+
+int inflate_codes(tl, td, bl, bd)
+struct huft *tl, *td; /* literal/length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* inflate (decompress) the codes in a deflated (compressed) block.
+ Return an error code or zero if it all goes ok. */
+{
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+ /* inflate the coded data */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ for (;;) /* do until end of block */
+ {
+ NEEDBITS((unsigned)bl)
+ if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ if (e == 16) /* then it's a literal */
+ {
+ slide[w++] = (uch)t->v.n;
+ Tracevv((stderr, "%c", slide[w-1]));
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ }
+ else /* it's an EOB or a length */
+ {
+ /* exit if end of block */
+ if (e == 15)
+ break;
+
+ /* get length of block to copy */
+ NEEDBITS(e)
+ n = t->v.n + ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e);
+
+ /* decode distance of block to copy */
+ NEEDBITS((unsigned)bd)
+ if ((e = (t = td + ((unsigned)b & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ NEEDBITS(e)
+ d = w - t->v.n - ((unsigned)b & mask_bits[e]);
+ DUMPBITS(e)
+ Tracevv((stderr,"\\[%d,%d]", w-d, n));
+
+ /* do the copy */
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+#if !defined(NOMEMCPY) && !defined(DEBUG)
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ Tracevv((stderr, "%c", slide[w-1]));
+ } while (--e);
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ } while (n);
+ }
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+
+ /* done */
+ return 0;
+}
+
+
+
+int inflate_stored()
+/* "decompress" an inflated type 0 (stored) block. */
+{
+ unsigned n; /* number of bytes in block */
+ unsigned w; /* current window position */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local copies of globals */
+ b = bb; /* initialize bit buffer */
+ k = bk;
+ w = wp; /* initialize window position */
+
+
+ /* go to byte boundary */
+ n = k & 7;
+ DUMPBITS(n);
+
+
+ /* get the length and its complement */
+ NEEDBITS(16)
+ n = ((unsigned)b & 0xffff);
+ DUMPBITS(16)
+ NEEDBITS(16)
+ if (n != (unsigned)((~b) & 0xffff))
+ return 1; /* error in compressed data */
+ DUMPBITS(16)
+
+
+ /* read and output the compressed data */
+ while (n--)
+ {
+ NEEDBITS(8)
+ slide[w++] = (uch)b;
+ if (w == WSIZE)
+ {
+ flush_output(w);
+ w = 0;
+ }
+ DUMPBITS(8)
+ }
+
+
+ /* restore the globals from the locals */
+ wp = w; /* restore global window pointer */
+ bb = b; /* restore global bit buffer */
+ bk = k;
+ return 0;
+}
+
+
+
+int inflate_fixed()
+/* decompress an inflated type 1 (fixed Huffman codes) block. We should
+ either replace this with a custom decoder, or at least precompute the
+ Huffman tables. */
+{
+ int i; /* temporary variable */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned l[288]; /* length list for huft_build */
+
+
+ /* set up literal table */
+ for (i = 0; i < 144; i++)
+ l[i] = 8;
+ for (; i < 256; i++)
+ l[i] = 9;
+ for (; i < 280; i++)
+ l[i] = 7;
+ for (; i < 288; i++) /* make a complete, but wrong code set */
+ l[i] = 8;
+ bl = 7;
+ if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
+ return i;
+
+
+ /* set up distance table */
+ for (i = 0; i < 30; i++) /* make an incomplete code set */
+ l[i] = 5;
+ bd = 5;
+ if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
+ {
+ huft_free(tl);
+ return i;
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+int inflate_dynamic()
+/* decompress an inflated type 2 (dynamic Huffman codes) block. */
+{
+ int i; /* temporary variables */
+ unsigned j;
+ unsigned l; /* last length */
+ unsigned m; /* mask for bit lengths table */
+ unsigned n; /* number of lengths to get */
+ struct huft *tl; /* literal/length code table */
+ struct huft *td; /* distance code table */
+ int bl; /* lookup bits for tl */
+ int bd; /* lookup bits for td */
+ unsigned nb; /* number of bit length codes */
+ unsigned nl; /* number of literal/length codes */
+ unsigned nd; /* number of distance codes */
+#ifdef PKZIP_BUG_WORKAROUND
+ unsigned ll[288+32]; /* literal/length and distance code lengths */
+#else
+ unsigned ll[286+30]; /* literal/length and distance code lengths */
+#endif
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in table lengths */
+ NEEDBITS(5)
+ nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
+ DUMPBITS(5)
+ NEEDBITS(5)
+ nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
+ DUMPBITS(5)
+ NEEDBITS(4)
+ nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
+ DUMPBITS(4)
+#ifdef PKZIP_BUG_WORKAROUND
+ if (nl > 288 || nd > 32)
+#else
+ if (nl > 286 || nd > 30)
+#endif
+ return 1; /* bad lengths */
+
+
+ /* read in bit-length-code lengths */
+ for (j = 0; j < nb; j++)
+ {
+ NEEDBITS(3)
+ ll[border[j]] = (unsigned)b & 7;
+ DUMPBITS(3)
+ }
+ for (; j < 19; j++)
+ ll[border[j]] = 0;
+
+
+ /* build decoding table for trees--single level, 7 bit lookup */
+ bl = 7;
+ if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
+ {
+ if (i == 1)
+ huft_free(tl);
+ return i; /* incomplete code set */
+ }
+
+ if (tl == NULL) /* Grrrhhh */
+ return 2;
+
+ /* read in literal and distance code lengths */
+ n = nl + nd;
+ m = mask_bits[bl];
+ i = l = 0;
+ while ((unsigned)i < n)
+ {
+ NEEDBITS((unsigned)bl)
+ j = (td = tl + ((unsigned)b & m))->b;
+ DUMPBITS(j)
+ j = td->v.n;
+ if (j < 16) /* length of code in bits (0..15) */
+ ll[i++] = l = j; /* save last length in l */
+ else if (j == 16) /* repeat last length 3 to 6 times */
+ {
+ NEEDBITS(2)
+ j = 3 + ((unsigned)b & 3);
+ DUMPBITS(2)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = l;
+ }
+ else if (j == 17) /* 3 to 10 zero length codes */
+ {
+ NEEDBITS(3)
+ j = 3 + ((unsigned)b & 7);
+ DUMPBITS(3)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ else /* j == 18: 11 to 138 zero length codes */
+ {
+ NEEDBITS(7)
+ j = 11 + ((unsigned)b & 0x7f);
+ DUMPBITS(7)
+ if ((unsigned)i + j > n)
+ return 1;
+ while (j--)
+ ll[i++] = 0;
+ l = 0;
+ }
+ }
+
+
+ /* free decoding table for trees */
+ huft_free(tl);
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* build the decoding tables for literal/length and distance codes */
+ bl = lbits;
+ if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
+ {
+ if (i == 1) {
+ fprintf(stderr, " incomplete literal tree\n");
+ huft_free(tl);
+ }
+ return i; /* incomplete code set */
+ }
+ bd = dbits;
+ if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
+ {
+ if (i == 1) {
+ fprintf(stderr, " incomplete distance tree\n");
+#ifdef PKZIP_BUG_WORKAROUND
+ i = 0;
+ }
+#else
+ huft_free(td);
+ }
+ huft_free(tl);
+ return i; /* incomplete code set */
+#endif
+ }
+
+
+ /* decompress until an end-of-block code */
+ if (inflate_codes(tl, td, bl, bd))
+ return 1;
+
+
+ /* free the decoding tables, return */
+ huft_free(tl);
+ huft_free(td);
+ return 0;
+}
+
+
+
+int inflate_block(e)
+int *e; /* last block flag */
+/* decompress an inflated block */
+{
+ unsigned t; /* block type */
+ register ulg b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+
+
+ /* make local bit buffer */
+ b = bb;
+ k = bk;
+
+
+ /* read in last block bit */
+ NEEDBITS(1)
+ *e = (int)b & 1;
+ DUMPBITS(1)
+
+
+ /* read in block type */
+ NEEDBITS(2)
+ t = (unsigned)b & 3;
+ DUMPBITS(2)
+
+
+ /* restore the global bit buffer */
+ bb = b;
+ bk = k;
+
+
+ /* inflate that block type */
+ if (t == 2)
+ return inflate_dynamic();
+ if (t == 0)
+ return inflate_stored();
+ if (t == 1)
+ return inflate_fixed();
+
+
+ /* bad block type */
+ return 2;
+}
+
+
+
+int inflate()
+/* decompress an inflated entry */
+{
+ int e; /* last block flag */
+ int r; /* result code */
+ unsigned h; /* maximum struct huft's malloc'ed */
+
+
+ /* initialize window, bit buffer */
+ wp = 0;
+ bk = 0;
+ bb = 0;
+
+
+ /* decompress until the last block */
+ h = 0;
+ do {
+ hufts = 0;
+ if ((r = inflate_block(&e)) != 0)
+ return r;
+ if (hufts > h)
+ h = hufts;
+ } while (!e);
+
+ /* Undo too much lookahead. The next read will be byte aligned so we
+ * can discard unused bits in the last meaningful byte.
+ */
+ while (bk >= 8) {
+ bk -= 8;
+ inptr--;
+ }
+
+ /* flush out slide */
+ flush_output(wp);
+
+
+ /* return success */
+#ifdef DEBUG
+ fprintf(stderr, "<%u> ", h);
+#endif /* DEBUG */
+ return 0;
+}
diff --git a/gnu/usr.bin/gzip/lzw.c b/gnu/usr.bin/gzip/lzw.c
new file mode 100644
index 0000000..934a8d9
--- /dev/null
+++ b/gnu/usr.bin/gzip/lzw.c
@@ -0,0 +1,26 @@
+/* lzw.c -- compress files in LZW format.
+ * This is a dummy version avoiding patent problems.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "tailor.h"
+#include "gzip.h"
+#include "lzw.h"
+
+static int msg_done = 0;
+
+/* Compress in to out with lzw method. */
+int lzw(in, out)
+ int in, out;
+{
+ if (msg_done) return ERROR;
+ msg_done = 1;
+ fprintf(stderr,"output in compress .Z format not supported\n");
+ if (in != out) { /* avoid warnings on unused variables */
+ exit_code = ERROR;
+ }
+ return ERROR;
+}
diff --git a/gnu/usr.bin/gzip/lzw.h b/gnu/usr.bin/gzip/lzw.h
new file mode 100644
index 0000000..4b7ac86
--- /dev/null
+++ b/gnu/usr.bin/gzip/lzw.h
@@ -0,0 +1,42 @@
+/* lzw.h -- define the lzw functions.
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#if !defined(OF) && defined(lint)
+# include "gzip.h"
+#endif
+
+#ifndef BITS
+# define BITS 16
+#endif
+#define INIT_BITS 9 /* Initial number of bits per code */
+
+#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */
+
+#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
+/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
+ * It's a pity that old uncompress does not check bit 0x20. That makes
+ * extension of the format actually undesirable because old compress
+ * would just crash on the new format instead of giving a meaningful
+ * error message. It does check the number of bits, but it's more
+ * helpful to say "unsupported format, get a new version" than
+ * "can only handle 16 bits".
+ */
+
+#define BLOCK_MODE 0x80
+/* Block compression: if table is full and compression rate is dropping,
+ * clear the dictionary.
+ */
+
+#define LZW_RESERVED 0x60 /* reserved bits */
+
+#define CLEAR 256 /* flush the dictionary */
+#define FIRST (CLEAR+1) /* first free entry */
+
+extern int maxbits; /* max bits per code for LZW */
+extern int block_mode; /* block compress mode -C compatible with 2.0 */
+
+extern int lzw OF((int in, int out));
+extern int unlzw OF((int in, int out));
diff --git a/gnu/usr.bin/gzip/match.S b/gnu/usr.bin/gzip/match.S
new file mode 100644
index 0000000..2eb114f
--- /dev/null
+++ b/gnu/usr.bin/gzip/match.S
@@ -0,0 +1,379 @@
+/* match.s -- optional optimized asm version of longest match in deflate.c
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ *
+ * The 68020 version has been written by Francesco Potorti` <pot@cnuce.cnr.it>
+ * with adaptations by Carsten Steger <stegerc@informatik.tu-muenchen.de>,
+ * Andreas Schwab <schwab@lamothe.informatik.uni-dortmund.de> and
+ * Kristoffer Eriksson <ske@pkmab.se>
+ */
+
+/* $FreeBSD$ */
+
+/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
+ * external symbols with an underline character '_'.
+ */
+#ifdef __ELF__ /* NO_UNDERLINE */
+# define _prev prev
+# define _window window
+# define _match_start match_start
+# define _prev_length prev_length
+# define _good_match good_match
+# define _nice_match nice_match
+# define _strstart strstart
+# define _max_chain_length max_chain_length
+
+# define _match_init match_init
+# define _longest_match longest_match
+#endif
+
+#ifdef DYN_ALLOC
+ error: DYN_ALLOC not yet supported in match.s
+#endif
+
+#if defined(i386) || defined(_I386) || defined(__i386__)
+
+/* This version is for 386 Unix or OS/2 in 32 bit mode.
+ * Warning: it uses the AT&T syntax: mov source,dest
+ * This file is only optional. If you want to force the C version,
+ * add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string.
+ * If you have reduced WSIZE in gzip.h, then change its value below.
+ * This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
+ */
+
+ .file "match.S"
+
+#define MAX_MATCH 258
+#define MAX_MATCH2 $128 /* MAX_MATCH/2-1 */
+#define MIN_MATCH 3
+#define WSIZE $32768
+#define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1
+
+ .globl _match_init
+ .globl _longest_match
+
+ .text
+
+_match_init:
+ ret
+
+/*-----------------------------------------------------------------------
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+
+_longest_match: /* int longest_match(cur_match) */
+
+#define cur_match 20(%esp)
+ /* return address */ /* esp+16 */
+ push %ebp /* esp+12 */
+ push %edi /* esp+8 */
+ push %esi /* esp+4 */
+ push %ebx /* esp */
+
+/*
+ * match equ esi
+ * scan equ edi
+ * chain_length equ ebp
+ * best_len equ ebx
+ * limit equ edx
+ */
+ mov cur_match,%esi
+ mov _max_chain_length,%ebp /* chain_length = max_chain_length */
+ mov _strstart,%edi
+ mov %edi,%edx
+ sub MAX_DIST,%edx /* limit = strstart-MAX_DIST */
+ jae limit_ok
+ sub %edx,%edx /* limit = NIL */
+limit_ok:
+ add $2+_window,%edi /* edi = offset(window+strstart+2) */
+ mov _prev_length,%ebx /* best_len = prev_length */
+ movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */
+ movw -2(%edi),%cx /* cx = scan[0..1] */
+ cmp _good_match,%ebx /* do we have a good match already? */
+ jb do_scan
+ shr $2,%ebp /* chain_length >>= 2 */
+ jmp do_scan
+
+ .align 4
+long_loop:
+/* at this point, edi == scan+2, esi == cur_match */
+ movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */
+ movw -2(%edi),%cx /* cx = scan[0..1] */
+short_loop:
+/*
+ * at this point, di == scan+2, si == cur_match,
+ * ax = scan[best_len-1..best_len] and cx = scan[0..1]
+ */
+ and WSIZE-1, %esi
+ movw _prev(%esi,%esi),%si /* cur_match = prev[cur_match] */
+ /* top word of esi is still 0 */
+ cmp %edx,%esi /* cur_match <= limit ? */
+ jbe the_end
+ dec %ebp /* --chain_length */
+ jz the_end
+do_scan:
+ cmpw _window-1(%ebx,%esi),%ax/* check match at best_len-1 */
+ jne short_loop
+ cmpw _window(%esi),%cx /* check min_match_length match */
+ jne short_loop
+
+ lea _window+2(%esi),%esi /* si = match */
+ mov %edi,%eax /* ax = scan+2 */
+ mov MAX_MATCH2,%ecx /* scan for at most MAX_MATCH bytes */
+ rep; cmpsw /* loop until mismatch */
+ je maxmatch /* match of length MAX_MATCH? */
+mismatch:
+ movb -2(%edi),%cl /* mismatch on first or second byte? */
+ subb -2(%esi),%cl /* cl = 0 if first bytes equal */
+ xchg %edi,%eax /* edi = scan+2, eax = end of scan */
+ sub %edi,%eax /* eax = len */
+ sub %eax,%esi /* esi = cur_match + 2 + offset(window) */
+ sub $2+_window,%esi /* esi = cur_match */
+ subb $1,%cl /* set carry if cl == 0 (cannot use DEC) */
+ adc $0,%eax /* eax = carry ? len+1 : len */
+ cmp %ebx,%eax /* len > best_len ? */
+ jle long_loop
+ mov %esi,_match_start /* match_start = cur_match */
+ mov %eax,%ebx /* ebx = best_len = len */
+ cmp _nice_match,%eax /* len >= nice_match ? */
+ jl long_loop
+the_end:
+ mov %ebx,%eax /* result = eax = best_len */
+ pop %ebx
+ pop %esi
+ pop %edi
+ pop %ebp
+ ret
+maxmatch:
+ cmpsb
+ jmp mismatch
+
+#else
+
+/* ======================== 680x0 version ================================= */
+
+#if defined(m68k)||defined(mc68k)||defined(__mc68000__)||defined(__MC68000__)
+# ifndef mc68000
+# define mc68000
+# endif
+#endif
+
+#if defined(__mc68020__) || defined(__MC68020__) || defined(sysV68)
+# ifndef mc68020
+# define mc68020
+# endif
+#endif
+
+#if defined(mc68020) || defined(mc68000)
+
+#if (defined(mc68020) || defined(NeXT)) && !defined(UNALIGNED_OK)
+# define UNALIGNED_OK
+#endif
+
+#ifdef sysV68 /* Try Motorola Delta style */
+
+# define GLOBAL(symbol) global symbol
+# define TEXT text
+# define FILE(filename) file filename
+# define invert_maybe(src,dst) dst,src
+# define imm(data) &data
+# define reg(register) %register
+
+# define addl add.l
+# define addql addq.l
+# define blos blo.b
+# define bhis bhi.b
+# define bras bra.b
+# define clrl clr.l
+# define cmpmb cmpm.b
+# define cmpw cmp.w
+# define cmpl cmp.l
+# define lslw lsl.w
+# define lsrl lsr.l
+# define movel move.l
+# define movew move.w
+# define moveb move.b
+# define moveml movem.l
+# define subl sub.l
+# define subw sub.w
+# define subql subq.l
+
+# define IndBase(bd,An) (bd,An)
+# define IndBaseNdxl(bd,An,Xn) (bd,An,Xn.l)
+# define IndBaseNdxw(bd,An,Xn) (bd,An,Xn.w)
+# define predec(An) -(An)
+# define postinc(An) (An)+
+
+#else /* default style (Sun 3, NeXT, Amiga, Atari) */
+
+# define GLOBAL(symbol) .globl symbol
+# define TEXT .text
+# define FILE(filename) .even
+# define invert_maybe(src,dst) src,dst
+# if defined(sun) || defined(mc68k)
+# define imm(data) #data
+# else
+# define imm(data) \#data
+# endif
+# define reg(register) register
+
+# define blos bcss
+# if defined(sun) || defined(mc68k)
+# define movel movl
+# define movew movw
+# define moveb movb
+# endif
+# define IndBase(bd,An) An@(bd)
+# define IndBaseNdxl(bd,An,Xn) An@(bd,Xn:l)
+# define IndBaseNdxw(bd,An,Xn) An@(bd,Xn:w)
+# define predec(An) An@-
+# define postinc(An) An@+
+
+#endif /* styles */
+
+#define Best_Len reg(d0) /* unsigned */
+#define Cur_Match reg(d1) /* Ipos */
+#define Loop_Counter reg(d2) /* int */
+#define Scan_Start reg(d3) /* unsigned short */
+#define Scan_End reg(d4) /* unsigned short */
+#define Limit reg(d5) /* IPos */
+#define Chain_Length reg(d6) /* unsigned */
+#define Scan_Test reg(d7)
+#define Scan reg(a0) /* *uch */
+#define Match reg(a1) /* *uch */
+#define Prev_Address reg(a2) /* *Pos */
+#define Scan_Ini reg(a3) /* *uch */
+#define Match_Ini reg(a4) /* *uch */
+#define Stack_Pointer reg(sp)
+
+#define MAX_MATCH 258
+#define MIN_MATCH 3
+#define WSIZE 32768
+#define MAX_DIST (WSIZE - MAX_MATCH - MIN_MATCH - 1)
+
+ GLOBAL (_match_init)
+ GLOBAL (_longest_match)
+
+ TEXT
+
+ FILE ("match.S")
+
+_match_init:
+ rts
+
+/*-----------------------------------------------------------------------
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ */
+
+/* int longest_match (cur_match) */
+
+#ifdef UNALIGNED_OK
+# define pushreg 15928 /* d2-d6/a2-a4 */
+# define popreg 7292
+#else
+# define pushreg 16184 /* d2-d7/a2-a4 */
+# define popreg 7420
+#endif
+
+_longest_match:
+ movel IndBase(4,Stack_Pointer),Cur_Match
+ moveml imm(pushreg),predec(Stack_Pointer)
+ movel _max_chain_length,Chain_Length
+ movel _prev_length,Best_Len
+ movel imm(_prev),Prev_Address
+ movel imm(_window+MIN_MATCH),Match_Ini
+ movel _strstart,Limit
+ movel Match_Ini,Scan_Ini
+ addl Limit,Scan_Ini
+ subw imm(MAX_DIST),Limit
+ bhis L__limit_ok
+ clrl Limit
+L__limit_ok:
+ cmpl invert_maybe(_good_match,Best_Len)
+ blos L__length_ok
+ lsrl imm(2),Chain_Length
+L__length_ok:
+ subql imm(1),Chain_Length
+#ifdef UNALIGNED_OK
+ movew IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
+ movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+#else
+ moveb IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
+ lslw imm(8),Scan_Start
+ moveb IndBase(-MIN_MATCH+1,Scan_Ini),Scan_Start
+ moveb IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+ lslw imm(8),Scan_End
+ moveb IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
+#endif
+ bras L__do_scan
+
+L__long_loop:
+#ifdef UNALIGNED_OK
+ movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+#else
+ moveb IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
+ lslw imm(8),Scan_End
+ moveb IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
+#endif
+
+L__short_loop:
+ lslw imm(1),Cur_Match
+ movew IndBaseNdxl(0,Prev_Address,Cur_Match),Cur_Match
+ cmpw invert_maybe(Limit,Cur_Match)
+ dbls Chain_Length,L__do_scan
+ bras L__return
+
+L__do_scan:
+ movel Match_Ini,Match
+ addl Cur_Match,Match
+#ifdef UNALIGNED_OK
+ cmpw invert_maybe(IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_End)
+ bne L__short_loop
+ cmpw invert_maybe(IndBase(-MIN_MATCH,Match),Scan_Start)
+ bne L__short_loop
+#else
+ moveb IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_Test
+ lslw imm(8),Scan_Test
+ moveb IndBaseNdxw(-MIN_MATCH,Match,Best_Len),Scan_Test
+ cmpw invert_maybe(Scan_Test,Scan_End)
+ bne L__short_loop
+ moveb IndBase(-MIN_MATCH,Match),Scan_Test
+ lslw imm(8),Scan_Test
+ moveb IndBase(-MIN_MATCH+1,Match),Scan_Test
+ cmpw invert_maybe(Scan_Test,Scan_Start)
+ bne L__short_loop
+#endif
+
+ movew imm((MAX_MATCH-MIN_MATCH+1)-1),Loop_Counter
+ movel Scan_Ini,Scan
+L__scan_loop:
+ cmpmb postinc(Match),postinc(Scan)
+ dbne Loop_Counter,L__scan_loop
+
+ subl Scan_Ini,Scan
+ addql imm(MIN_MATCH-1),Scan
+ cmpl invert_maybe(Best_Len,Scan)
+ bls L__short_loop
+ movel Scan,Best_Len
+ movel Cur_Match,_match_start
+ cmpl invert_maybe(_nice_match,Best_Len)
+ blos L__long_loop
+L__return:
+ moveml postinc(Stack_Pointer),imm(popreg)
+ rts
+
+#else
+ error: this asm version is for 386 or 680x0 only
+#endif /* mc68000 || mc68020 */
+#endif /* i386 || _I386 */
diff --git a/gnu/usr.bin/gzip/revision.h b/gnu/usr.bin/gzip/revision.h
new file mode 100644
index 0000000..43b0885
--- /dev/null
+++ b/gnu/usr.bin/gzip/revision.h
@@ -0,0 +1,16 @@
+/* revision.h -- define the version number
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#define VERSION "1.2.4"
+#define PATCHLEVEL 0
+#define REVDATE "18 Aug 93"
+
+/* This version does not support compression into old compress format: */
+#ifdef LZW
+# undef LZW
+#endif
+
+/* $FreeBSD$ */
diff --git a/gnu/usr.bin/gzip/tailor.h b/gnu/usr.bin/gzip/tailor.h
new file mode 100644
index 0000000..abdde17
--- /dev/null
+++ b/gnu/usr.bin/gzip/tailor.h
@@ -0,0 +1,328 @@
+/* tailor.h -- target dependent definitions
+ * Copyright (C) 1992-1993 Jean-loup Gailly.
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/* The target dependent definitions should be defined here only.
+ * The target dependent functions should be defined in tailor.c.
+ */
+
+/* $FreeBSD$ */
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+
+#if defined(__OS2__) && !defined(OS2)
+# define OS2
+#endif
+
+#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */
+# undef MSDOS
+#endif
+
+#ifdef MSDOS
+# ifdef __GNUC__
+ /* DJGPP version 1.09+ on MS-DOS.
+ * The DJGPP 1.09 stat() function must be upgraded before gzip will
+ * fully work.
+ * No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which
+ * implies DIRENT.
+ */
+# define near
+# else
+# define MAXSEG_64K
+# ifdef __TURBOC__
+# define NO_OFF_T
+# ifdef __BORLANDC__
+# define DIRENT
+# else
+# define NO_UTIME
+# endif
+# else /* MSC */
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# endif
+# endif
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 128
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define NO_CHOWN
+# define PROTO
+# define STDC_HEADERS
+# define NO_SIZE_CHECK
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# include <io.h>
+# define OS_CODE 0x00
+# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+# if !defined(NO_ASM) && !defined(ASMV)
+# define ASMV
+# endif
+#else
+# define near
+#endif
+
+#ifdef OS2
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 260
+# ifdef OS2FAT
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define casemap(c) tolow(c)
+# endif
+# define NO_CHOWN
+# define PROTO
+# define STDC_HEADERS
+# include <io.h>
+# define OS_CODE 0x06
+# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+# ifdef _MSC_VER
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# define MAXSEG_64K
+# undef near
+# define near _near
+# endif
+# ifdef __EMX__
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# define DIRENT
+# define EXPAND(argc,argv) \
+ {_response(&argc, &argv); _wildcard(&argc, &argv);}
+# endif
+# ifdef __BORLANDC__
+# define DIRENT
+# endif
+# ifdef __ZTC__
+# define NO_DIR
+# define NO_UTIME_H
+# include <dos.h>
+# define EXPAND(argc,argv) \
+ {response_expand(&argc, &argv);}
+# endif
+#endif
+
+#ifdef WIN32 /* Windows NT */
+# define HAVE_SYS_UTIME_H
+# define NO_UTIME_H
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 260
+# define NO_CHOWN
+# define PROTO
+# define STDC_HEADERS
+# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
+# include <io.h>
+# include <malloc.h>
+# ifdef NTFAT
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# endif
+# define OS_CODE 0x0b
+#endif
+
+#ifdef MSDOS
+# ifdef __TURBOC__
+# include <alloc.h>
+# define DYN_ALLOC
+ /* Turbo C 2.0 does not accept static allocations of large arrays */
+ void * fcalloc (unsigned items, unsigned size);
+ void fcfree (void *ptr);
+# else /* MSC */
+# include <malloc.h>
+# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
+# define fcfree(ptr) hfree(ptr)
+# endif
+#else
+# ifdef MAXSEG_64K
+# define fcalloc(items,size) calloc((items),(size))
+# else
+# define fcalloc(items,size) malloc((size_t)(items)*(size_t)(size))
+# endif
+# define fcfree(ptr) free(ptr)
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define PATH_SEP ']'
+# define PATH_SEP2 ':'
+# define SUFFIX_SEP ';'
+# define NO_MULTIPLE_DOTS
+# define Z_SUFFIX "-gz"
+# define RECORD_IO 1
+# define casemap(c) tolow(c)
+# define OS_CODE 0x02
+# define OPTIONS_VAR "GZIP_OPT"
+# define STDC_HEADERS
+# define NO_UTIME
+# define EXPAND(argc,argv) vms_expand_args(&argc,&argv);
+# include <file.h>
+# define unlink delete
+# ifdef VAXC
+# define NO_FCNTL_H
+# include <unixio.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define PATH_SEP2 ':'
+# define STDC_HEADERS
+# define OS_CODE 0x01
+# define ASMV
+# ifdef __GNUC__
+# define DIRENT
+# define HAVE_UNISTD_H
+# else /* SASC */
+# define NO_STDIN_FSTAT
+# define SYSDIR
+# define NO_SYMLINK
+# define NO_CHOWN
+# define NO_FCNTL_H
+# include <fcntl.h> /* for read() and write() */
+# define direct dirent
+ extern void _expand_args(int *argc, char ***argv);
+# define EXPAND(argc,argv) _expand_args(&argc,&argv);
+# undef O_BINARY /* disable useless --ascii option */
+# endif
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# ifndef STDC_HEADERS
+# define STDC_HEADERS
+# define HAVE_UNISTD_H
+# define DIRENT
+# endif
+# define ASMV
+# define OS_CODE 0x05
+# ifdef TOSFS
+# define PATH_SEP2 '\\'
+# define PATH_SEP3 ':'
+# define MAX_PATH_LEN 128
+# define NO_MULTIPLE_DOTS
+# define MAX_EXT_CHARS 3
+# define Z_SUFFIX "z"
+# define NO_CHOWN
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# define NO_SYMLINK
+# endif
+#endif
+
+#ifdef MACOS
+# define PATH_SEP ':'
+# define DYN_ALLOC
+# define PROTO
+# define NO_STDIN_FSTAT
+# define NO_CHOWN
+# define NO_UTIME
+# define chmod(file, mode) (0)
+# define OPEN(name, flags, mode) open(name, flags)
+# define OS_CODE 0x07
+# ifdef MPW
+# define isatty(fd) ((fd) <= 2)
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define PATH_SEP '>'
+# define STDC_HEADERS
+# define NO_MEMORY_H
+# define NO_UTIME_H
+# define NO_UTIME
+# define NO_CHOWN
+# define NO_STDIN_FSTAT
+# define NO_SIZE_CHECK
+# define NO_SYMLINK
+# define RECORD_IO 1
+# define casemap(c) tolow(c) /* Force file names to lower case */
+# define put_char(c) put_byte((c) & 0x7F)
+# define get_char(c) ascii2pascii(get_byte())
+# define OS_CODE 0x0F /* temporary, subject to change */
+# ifdef SIGTERM
+# undef SIGTERM /* We don't want a signal handler for SIGTERM */
+# endif
+#endif
+
+#if defined(pyr) && !defined(NOMEMCPY) /* Pyramid */
+# define NOMEMCPY /* problem with overlapping copies */
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifndef unix
+# define NO_ST_INO /* don't rely on inode numbers */
+#endif
+
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef PATH_SEP
+# define PATH_SEP '/'
+#endif
+
+#ifndef casemap
+# define casemap(c) (c)
+#endif
+
+#ifndef OPTIONS_VAR
+# define OPTIONS_VAR "GZIP"
+#endif
+
+#ifndef Z_SUFFIX
+# define Z_SUFFIX ".gz"
+#endif
+
+#ifdef MAX_EXT_CHARS
+# define MAX_SUFFIX MAX_EXT_CHARS
+#else
+# define MAX_SUFFIX 30
+#endif
+
+#ifndef MAKE_LEGAL_NAME
+# ifdef NO_MULTIPLE_DOTS
+# define MAKE_LEGAL_NAME(name) make_simple_name(name)
+# else
+# define MAKE_LEGAL_NAME(name)
+# endif
+#endif
+
+#ifndef MIN_PART
+# define MIN_PART 3
+ /* keep at least MIN_PART chars between dots in a file name. */
+#endif
+
+#ifndef EXPAND
+# define EXPAND(argc,argv)
+#endif
+
+#ifndef RECORD_IO
+# define RECORD_IO 0
+#endif
+
+#ifndef SET_BINARY_MODE
+# define SET_BINARY_MODE(fd)
+#endif
+
+#ifndef OPEN
+# define OPEN(name, flags, mode) open(name, flags, mode)
+#endif
+
+#ifndef get_char
+# define get_char() get_byte()
+#endif
+
+#ifndef put_char
+# define put_char(c) put_byte(c)
+#endif
diff --git a/gnu/usr.bin/gzip/trees.c b/gnu/usr.bin/gzip/trees.c
new file mode 100644
index 0000000..fe2405e
--- /dev/null
+++ b/gnu/usr.bin/gzip/trees.c
@@ -0,0 +1,1075 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+/*
+ * PURPOSE
+ *
+ * Encode various sets of source values using variable-length
+ * binary code trees.
+ *
+ * DISCUSSION
+ *
+ * The PKZIP "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in the ZIP file in a compressed form
+ * which is itself a Huffman encoding of the lengths of
+ * all the code strings (in ascending order by source values).
+ * The actual code strings are reconstructed from the lengths in
+ * the UNZIP process, as described in the "application note"
+ * (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
+ *
+ * REFERENCES
+ *
+ * Lynch, Thomas J.
+ * Data Compression: Techniques and Applications, pp. 53-55.
+ * Lifetime Learning Publications, 1985. ISBN 0-534-03418-7.
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ *
+ * INTERFACE
+ *
+ * void ct_init (ush *attr, int *methodp)
+ * Allocate the match buffer, initialize the various tables and save
+ * the location of the internal file attribute (ascii/binary) and
+ * method (DEFLATE/STORE)
+ *
+ * void ct_tally (int dist, int lc);
+ * Save the match info and tally the frequency counts.
+ *
+ * long flush_block (char *buf, ulg stored_len, int eof)
+ * Determine the best encoding for the current block: dynamic trees,
+ * static trees or store, and output the encoded block to the zip
+ * file. Returns the total compressed length for the file so far.
+ *
+ */
+
+#include <ctype.h>
+
+#include "tailor.h"
+#include "gzip.h"
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+
+local int near extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local int near extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local int near extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#ifndef LIT_BUFSIZE
+# ifdef SMALL_MEM
+# define LIT_BUFSIZE 0x2000
+# else
+# ifdef MEDIUM_MEM
+# define LIT_BUFSIZE 0x4000
+# else
+# define LIT_BUFSIZE 0x8000
+# endif
+# endif
+#endif
+#ifndef DIST_BUFSIZE
+# define DIST_BUFSIZE LIT_BUFSIZE
+#endif
+/* Sizes of match buffers for literals/lengths and distances. There are
+ * 4 reasons for limiting LIT_BUFSIZE to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input data is
+ * still in the window so we can still emit a stored block even when input
+ * comes from standard input. (This can also be done for all blocks if
+ * LIT_BUFSIZE is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting trees
+ * more frequently.
+ * - I can't count above 4
+ * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save
+ * memory at the expense of compression). Some optimizations would be possible
+ * if we rely on DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+#if LIT_BUFSIZE > INBUFSIZ
+ error cannot overlay l_buf and inbuf
+#endif
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+/* ===========================================================================
+ * Local data
+ */
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+local ct_data near dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+local ct_data near dyn_dtree[2*D_CODES+1]; /* distance tree */
+
+local ct_data near static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see ct_init
+ * below).
+ */
+
+local ct_data near static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+local ct_data near bl_tree[2*BL_CODES+1];
+/* Huffman tree for the bit lengths */
+
+typedef struct tree_desc {
+ ct_data near *dyn_tree; /* the dynamic tree */
+ ct_data near *static_tree; /* corresponding static tree or NULL */
+ int near *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+ int max_code; /* largest code with non zero frequency */
+} tree_desc;
+
+local tree_desc near l_desc =
+{dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0};
+
+local tree_desc near d_desc =
+{dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0};
+
+local tree_desc near bl_desc =
+{bl_tree, (ct_data near *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0};
+
+
+local ush near bl_count[MAX_BITS+1];
+/* number of codes at each bit length for an optimal tree */
+
+local uch near bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+local int near heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+local int heap_len; /* number of elements in the heap */
+local int heap_max; /* element of largest frequency */
+/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+local uch near depth[2*L_CODES+1];
+/* Depth of each subtree used as tie breaker for trees of equal frequency */
+
+local uch length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local uch dist_code[512];
+/* distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+local int near base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int near base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#define l_buf inbuf
+/* DECLARE(uch, l_buf, LIT_BUFSIZE); buffer for literals or lengths */
+
+/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */
+
+local uch near flag_buf[(LIT_BUFSIZE/8)];
+/* flag_buf is a bit array distinguishing literals from lengths in
+ * l_buf, thus indicating the presence or absence of a distance.
+ */
+
+local unsigned last_lit; /* running index in l_buf */
+local unsigned last_dist; /* running index in d_buf */
+local unsigned last_flags; /* running index in flag_buf */
+local uch flags; /* current flags not yet saved in flag_buf */
+local uch flag_bit; /* current bit used in flags */
+/* bits are filled in flags starting at bit 0 (least significant).
+ * Note: these flags are overkill in the current code since we don't
+ * take advantage of DIST_BUFSIZE == LIT_BUFSIZE.
+ */
+
+local ulg opt_len; /* bit length of current block with optimal trees */
+local ulg static_len; /* bit length of current block with static trees */
+
+local ulg compressed_len; /* total bit length of compressed file */
+
+local ulg input_len; /* total byte length of input file */
+/* input_len is for debugging only since we can get it by other means. */
+
+ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */
+int *file_method; /* pointer to DEFLATE or STORE */
+
+#ifdef DEBUG
+extern ulg bits_sent; /* bit length of the compressed data */
+extern long isize; /* byte length of input file */
+#endif
+
+extern long block_start; /* window offset of current block */
+extern unsigned near strstart; /* window offset of current string */
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void init_block OF((void));
+local void pqdownheap OF((ct_data near *tree, int k));
+local void gen_bitlen OF((tree_desc near *desc));
+local void gen_codes OF((ct_data near *tree, int max_code));
+local void build_tree OF((tree_desc near *desc));
+local void scan_tree OF((ct_data near *tree, int max_code));
+local void send_tree OF((ct_data near *tree, int max_code));
+local int build_bl_tree OF((void));
+local void send_all_trees OF((int lcodes, int dcodes, int blcodes));
+local void compress_block OF((ct_data near *ltree, ct_data near *dtree));
+local void set_file_type OF((void));
+
+
+#ifndef DEBUG
+# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(c, tree) \
+ { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(tree[c].Code, tree[c].Len); }
+#endif
+
+#define d_code(dist) \
+ ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. dist_code[256] and dist_code[257] are never
+ * used.
+ */
+
+#define MAX(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Allocate the match buffer, initialize the various tables and save the
+ * location of the internal file attribute (ascii/binary) and method
+ * (DEFLATE/STORE).
+ */
+void ct_init(attr, methodp)
+ ush *attr; /* pointer to internal file attribute */
+ int *methodp; /* pointer to compression method */
+{
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+
+ file_type = attr;
+ file_method = methodp;
+ compressed_len = input_len = 0L;
+
+ if (static_dtree[0].Len != 0) return; /* ct_init already called */
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "ct_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "ct_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "ct_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data near *)static_ltree, L_CODES+1);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse(n, 5);
+ }
+
+ /* Initialize the first block of the first file: */
+ init_block();
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block()
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0;
+
+ dyn_ltree[END_BLOCK].Freq = 1;
+ opt_len = static_len = 0L;
+ last_lit = last_dist = last_flags = 0;
+ flags = 0; flag_bit = 1;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(tree, top) \
+{\
+ top = heap[SMALLEST]; \
+ heap[SMALLEST] = heap[heap_len--]; \
+ pqdownheap(tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(tree, k)
+ ct_data near *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < heap_len && smaller(tree, heap[j+1], heap[j])) j++;
+
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, heap[j])) break;
+
+ /* Exchange v with the smallest son */
+ heap[k] = heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(desc)
+ tree_desc near *desc; /* the tree descriptor */
+{
+ ct_data near *tree = desc->dyn_tree;
+ int near *extra = desc->extra_bits;
+ int base = desc->extra_base;
+ int max_code = desc->max_code;
+ int max_length = desc->max_length;
+ ct_data near *stree = desc->static_tree;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[heap[heap_max]].Len = 0; /* root of the heap */
+
+ for (h = heap_max+1; h < HEAP_SIZE; h++) {
+ n = heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ opt_len += (ulg)f * (bits + xbits);
+ if (stree) static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (bl_count[bits] == 0) bits--;
+ bl_count[bits]--; /* move one leaf down the tree */
+ bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = bl_count[bits];
+ while (n != 0) {
+ m = heap[--h];
+ if (m > max_code) continue;
+ if (tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ opt_len += ((long)bits-(long)tree[m].Len)*(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code)
+ ct_data near *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracec(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(desc)
+ tree_desc near *desc; /* the tree descriptor */
+{
+ ct_data near *tree = desc->dyn_tree;
+ ct_data near *stree = desc->static_tree;
+ int elems = desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node = elems; /* next internal node of the tree */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ heap_len = 0, heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ heap[++heap_len] = max_code = n;
+ depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (heap_len < 2) {
+ int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[new].Freq = 1;
+ depth[new] = 0;
+ opt_len--; if (stree) static_len -= stree[new].Len;
+ /* new is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ do {
+ pqremove(tree, n); /* n = node of least frequency */
+ m = heap[SMALLEST]; /* m = node of next least frequency */
+
+ heap[--heap_max] = n; /* keep the nodes sorted by frequency */
+ heap[--heap_max] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ depth[node] = (uch) (MAX(depth[n], depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ heap[SMALLEST] = node++;
+ pqdownheap(tree, SMALLEST);
+
+ } while (heap_len >= 2);
+
+ heap[--heap_max] = heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen((tree_desc near *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data near *)tree, max_code);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree. Updates opt_len to take into account the repeat
+ * counts. (The contribution of the bit length codes will be added later
+ * during the construction of bl_tree.)
+ */
+local void scan_tree (tree, max_code)
+ ct_data near *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) bl_tree[curlen].Freq++;
+ bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ bl_tree[REPZ_3_10].Freq++;
+ } else {
+ bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (tree, max_code)
+ ct_data near *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(curlen, bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(REP_3_6, bl_tree); send_bits(count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3);
+
+ } else {
+ send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree()
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree((ct_data near *)dyn_ltree, l_desc.max_code);
+ scan_tree((ct_data near *)dyn_dtree, d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree((tree_desc near *)(&bl_desc));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(lcodes, dcodes, blcodes)
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(dcodes-1, 5);
+ send_bits(blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", bits_sent));
+
+ send_tree((ct_data near *)dyn_ltree, lcodes-1); /* send the literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", bits_sent));
+
+ send_tree((ct_data near *)dyn_dtree, dcodes-1); /* send the distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", bits_sent));
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length for the file so far.
+ */
+ulg flush_block(buf, stored_len, eof)
+ char *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */
+
+ /* Check if the file is ascii or binary */
+ if (*file_type == (ush)UNKNOWN) set_file_type();
+
+ /* Construct the literal and distance trees */
+ build_tree((tree_desc near *)(&l_desc));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len));
+
+ build_tree((tree_desc near *)(&d_desc));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", opt_len, static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree();
+
+ /* Determine the best encoding. Compute first the block length in bytes */
+ opt_lenb = (opt_len+3+7)>>3;
+ static_lenb = (static_len+3+7)>>3;
+ input_len += stored_len; /* for debugging only */
+
+ Trace((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ",
+ opt_lenb, opt_len, static_lenb, static_len, stored_len,
+ last_lit, last_dist));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ /* If compression failed and this is the first and last block,
+ * and if the zip file can be seeked (to rewrite the local header),
+ * the whole file is transformed into a stored file:
+ */
+#ifdef FORCE_METHOD
+ if (level == 1 && eof && compressed_len == 0L) { /* force stored file */
+#else
+ if (stored_len <= opt_lenb && eof && compressed_len == 0L && seekable()) {
+#endif
+ /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+ if (buf == (char*)0) error ("block vanished");
+
+ copy_block(buf, (unsigned)stored_len, 0); /* without header */
+ compressed_len = stored_len << 3;
+ *file_method = STORED;
+
+#ifdef FORCE_METHOD
+ } else if (level == 2 && buf != (char*)0) { /* force stored block */
+#else
+ } else if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ send_bits((STORED_BLOCK<<1)+eof, 3); /* send block type */
+ compressed_len = (compressed_len + 3 + 7) & ~7L;
+ compressed_len += (stored_len + 4) << 3;
+
+ copy_block(buf, (unsigned)stored_len, 1); /* with header */
+
+#ifdef FORCE_METHOD
+ } else if (level == 3) { /* force static trees */
+#else
+ } else if (static_lenb == opt_lenb) {
+#endif
+ send_bits((STATIC_TREES<<1)+eof, 3);
+ compress_block((ct_data near *)static_ltree, (ct_data near *)static_dtree);
+ compressed_len += 3 + static_len;
+ } else {
+ send_bits((DYN_TREES<<1)+eof, 3);
+ send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);
+ compress_block((ct_data near *)dyn_ltree, (ct_data near *)dyn_dtree);
+ compressed_len += 3 + opt_len;
+ }
+ Assert (compressed_len == bits_sent, "bad compressed size");
+ init_block();
+
+ if (eof) {
+ Assert (input_len == isize, "bad input size");
+ bi_windup();
+ compressed_len += 7; /* align on byte boundary */
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", compressed_len>>3,
+ compressed_len-7*eof));
+
+ return compressed_len >> 3;
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int ct_tally (dist, lc)
+ int dist; /* distance of matched string */
+ int lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ l_buf[last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ dyn_ltree[lc].Freq++;
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match");
+
+ dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
+ dyn_dtree[d_code(dist)].Freq++;
+
+ d_buf[last_dist++] = (ush)dist;
+ flags |= flag_bit;
+ }
+ flag_bit <<= 1;
+
+ /* Output the flags if they fill a byte: */
+ if ((last_lit & 7) == 0) {
+ flag_buf[last_flags++] = flags;
+ flags = 0, flag_bit = 1;
+ }
+ /* Try to guess if it is profitable to stop the current block here */
+ if (level > 2 && (last_lit & 0xfff) == 0) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)last_lit*8L;
+ ulg in_length = (ulg)strstart-block_start;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Trace((stderr,"\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ",
+ last_lit, last_dist, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (last_dist < last_lit/2 && out_length < in_length/2) return 1;
+ }
+ return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE);
+ /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(ltree, dtree)
+ ct_data near *ltree; /* literal tree */
+ ct_data near *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned dx = 0; /* running index in d_buf */
+ unsigned fx = 0; /* running index in flag_buf */
+ uch flag = 0; /* current flags */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (last_lit != 0) do {
+ if ((lx & 7) == 0) flag = flag_buf[fx++];
+ lc = l_buf[lx++];
+ if ((flag & 1) == 0) {
+ send_code(lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = length_code[lc];
+ send_code(code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(lc, extra); /* send the extra length bits */
+ }
+ dist = d_buf[dx++];
+ /* Here, dist is the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+ flag >>= 1;
+ } while (lx < last_lit);
+
+ send_code(END_BLOCK, ltree);
+}
+
+/* ===========================================================================
+ * Set the file type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+local void set_file_type()
+{
+ int n = 0;
+ unsigned ascii_freq = 0;
+ unsigned bin_freq = 0;
+ while (n < 7) bin_freq += dyn_ltree[n++].Freq;
+ while (n < 128) ascii_freq += dyn_ltree[n++].Freq;
+ while (n < LITERALS) bin_freq += dyn_ltree[n++].Freq;
+ *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
+ if (*file_type == BINARY && translate_eol) {
+ WARN((stderr, "-l used on binary file"));
+ }
+}
diff --git a/gnu/usr.bin/gzip/unlzh.c b/gnu/usr.bin/gzip/unlzh.c
new file mode 100644
index 0000000..971ecc0
--- /dev/null
+++ b/gnu/usr.bin/gzip/unlzh.c
@@ -0,0 +1,401 @@
+/* unlzh.c -- decompress files in SCO compress -H (LZH) format.
+ * The code in this file is directly derived from the public domain 'ar002'
+ * written by Haruhiko Okumura.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <stdio.h>
+
+#include "tailor.h"
+#include "gzip.h"
+#include "lzw.h" /* just for consistency checking */
+
+/* decode.c */
+
+local unsigned decode OF((unsigned count, uch buffer[]));
+local void decode_start OF((void));
+
+/* huf.c */
+local void huf_decode_start OF((void));
+local unsigned decode_c OF((void));
+local unsigned decode_p OF((void));
+local void read_pt_len OF((int nn, int nbit, int i_special));
+local void read_c_len OF((void));
+
+/* io.c */
+local void fillbuf OF((int n));
+local unsigned getbits OF((int n));
+local void init_getbits OF((void));
+
+/* maketbl.c */
+
+local void make_table OF((int nchar, uch bitlen[],
+ int tablebits, ush table[]));
+
+
+#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */
+#define DICSIZ ((unsigned) 1 << DICBIT)
+
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+#ifndef UCHAR_MAX
+# define UCHAR_MAX 255
+#endif
+
+#define BITBUFSIZ (CHAR_BIT * 2 * sizeof(char))
+/* Do not use CHAR_BIT * sizeof(bitbuf), does not work on machines
+ * for which short is not on 16 bits (Cray).
+ */
+
+/* encode.c and decode.c */
+
+#define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */
+#define THRESHOLD 3 /* choose optimal value */
+
+/* huf.c */
+
+#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD)
+ /* alphabet = {0, 1, 2, ..., NC - 1} */
+#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */
+#define CODE_BIT 16 /* codeword length */
+
+#define NP (DICBIT + 1)
+#define NT (CODE_BIT + 3)
+#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */
+#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */
+#if NT > NP
+# define NPT NT
+#else
+# define NPT NP
+#endif
+
+/* local ush left[2 * NC - 1]; */
+/* local ush right[2 * NC - 1]; */
+#define left prev
+#define right head
+#if NC > (1<<(BITS-2))
+ error cannot overlay left+right and prev
+#endif
+
+/* local uch c_len[NC]; */
+#define c_len outbuf
+#if NC > OUTBUFSIZ
+ error cannot overlay c_len and outbuf
+#endif
+
+local uch pt_len[NPT];
+local unsigned blocksize;
+local ush pt_table[256];
+
+/* local ush c_table[4096]; */
+#define c_table d_buf
+#if (DIST_BUFSIZE-1) < 4095
+ error cannot overlay c_table and d_buf
+#endif
+
+/***********************************************************
+ io.c -- input/output
+***********************************************************/
+
+local ush bitbuf;
+local unsigned subbitbuf;
+local int bitcount;
+
+local void fillbuf(n) /* Shift bitbuf n bits left, read n bits */
+ int n;
+{
+ bitbuf <<= n;
+ while (n > bitcount) {
+ bitbuf |= subbitbuf << (n -= bitcount);
+ subbitbuf = (unsigned)try_byte();
+ if ((int)subbitbuf == EOF) subbitbuf = 0;
+ bitcount = CHAR_BIT;
+ }
+ bitbuf |= subbitbuf >> (bitcount -= n);
+}
+
+local unsigned getbits(n)
+ int n;
+{
+ unsigned x;
+
+ x = bitbuf >> (BITBUFSIZ - n); fillbuf(n);
+ return x;
+}
+
+local void init_getbits()
+{
+ bitbuf = 0; subbitbuf = 0; bitcount = 0;
+ fillbuf(BITBUFSIZ);
+}
+
+/***********************************************************
+ maketbl.c -- make table for decoding
+***********************************************************/
+
+local void make_table(nchar, bitlen, tablebits, table)
+ int nchar;
+ uch bitlen[];
+ int tablebits;
+ ush table[];
+{
+ ush count[17], weight[17], start[18], *p;
+ unsigned i, k, len, ch, jutbits, avail, nextcode, mask;
+
+ for (i = 1; i <= 16; i++) count[i] = 0;
+ for (i = 0; i < (unsigned)nchar; i++) count[bitlen[i]]++;
+
+ start[1] = 0;
+ for (i = 1; i <= 16; i++)
+ start[i + 1] = start[i] + (count[i] << (16 - i));
+ if ((start[17] & 0xffff) != 0)
+ error("Bad table\n");
+
+ jutbits = 16 - tablebits;
+ for (i = 1; i <= (unsigned)tablebits; i++) {
+ start[i] >>= jutbits;
+ weight[i] = (unsigned) 1 << (tablebits - i);
+ }
+ while (i <= 16) {
+ weight[i] = (unsigned) 1 << (16 - i);
+ i++;
+ }
+
+ i = start[tablebits + 1] >> jutbits;
+ if (i != 0) {
+ k = 1 << tablebits;
+ while (i != k) table[i++] = 0;
+ }
+
+ avail = nchar;
+ mask = (unsigned) 1 << (15 - tablebits);
+ for (ch = 0; ch < (unsigned)nchar; ch++) {
+ if ((len = bitlen[ch]) == 0) continue;
+ nextcode = start[len] + weight[len];
+ if (len <= (unsigned)tablebits) {
+ for (i = start[len]; i < nextcode; i++) table[i] = ch;
+ } else {
+ k = start[len];
+ p = &table[k >> jutbits];
+ i = len - tablebits;
+ while (i != 0) {
+ if (*p == 0) {
+ right[avail] = left[avail] = 0;
+ *p = avail++;
+ }
+ if (k & mask) p = &right[*p];
+ else p = &left[*p];
+ k <<= 1; i--;
+ }
+ *p = ch;
+ }
+ start[len] = nextcode;
+ }
+}
+
+/***********************************************************
+ huf.c -- static Huffman
+***********************************************************/
+
+local void read_pt_len(nn, nbit, i_special)
+ int nn;
+ int nbit;
+ int i_special;
+{
+ int i, c, n;
+ unsigned mask;
+
+ n = getbits(nbit);
+ if (n == 0) {
+ c = getbits(nbit);
+ for (i = 0; i < nn; i++) pt_len[i] = 0;
+ for (i = 0; i < 256; i++) pt_table[i] = c;
+ } else {
+ i = 0;
+ while (i < n) {
+ c = bitbuf >> (BITBUFSIZ - 3);
+ if (c == 7) {
+ mask = (unsigned) 1 << (BITBUFSIZ - 1 - 3);
+ while (mask & bitbuf) { mask >>= 1; c++; }
+ }
+ fillbuf((c < 7) ? 3 : c - 3);
+ pt_len[i++] = c;
+ if (i == i_special) {
+ c = getbits(2);
+ while (--c >= 0) pt_len[i++] = 0;
+ }
+ }
+ while (i < nn) pt_len[i++] = 0;
+ make_table(nn, pt_len, 8, pt_table);
+ }
+}
+
+local void read_c_len()
+{
+ int i, c, n;
+ unsigned mask;
+
+ n = getbits(CBIT);
+ if (n == 0) {
+ c = getbits(CBIT);
+ for (i = 0; i < NC; i++) c_len[i] = 0;
+ for (i = 0; i < 4096; i++) c_table[i] = c;
+ } else {
+ i = 0;
+ while (i < n) {
+ c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+ if (c >= NT) {
+ mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
+ do {
+ if (bitbuf & mask) c = right[c];
+ else c = left [c];
+ mask >>= 1;
+ } while (c >= NT);
+ }
+ fillbuf((int) pt_len[c]);
+ if (c <= 2) {
+ if (c == 0) c = 1;
+ else if (c == 1) c = getbits(4) + 3;
+ else c = getbits(CBIT) + 20;
+ while (--c >= 0) c_len[i++] = 0;
+ } else c_len[i++] = c - 2;
+ }
+ while (i < NC) c_len[i++] = 0;
+ make_table(NC, c_len, 12, c_table);
+ }
+}
+
+local unsigned decode_c()
+{
+ unsigned j, mask;
+
+ if (blocksize == 0) {
+ blocksize = getbits(16);
+ if (blocksize == 0) {
+ return NC; /* end of file */
+ }
+ read_pt_len(NT, TBIT, 3);
+ read_c_len();
+ read_pt_len(NP, PBIT, -1);
+ }
+ blocksize--;
+ j = c_table[bitbuf >> (BITBUFSIZ - 12)];
+ if (j >= NC) {
+ mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12);
+ do {
+ if (bitbuf & mask) j = right[j];
+ else j = left [j];
+ mask >>= 1;
+ } while (j >= NC);
+ }
+ fillbuf((int) c_len[j]);
+ return j;
+}
+
+local unsigned decode_p()
+{
+ unsigned j, mask;
+
+ j = pt_table[bitbuf >> (BITBUFSIZ - 8)];
+ if (j >= NP) {
+ mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8);
+ do {
+ if (bitbuf & mask) j = right[j];
+ else j = left [j];
+ mask >>= 1;
+ } while (j >= NP);
+ }
+ fillbuf((int) pt_len[j]);
+ if (j != 0) j = ((unsigned) 1 << (j - 1)) + getbits((int) (j - 1));
+ return j;
+}
+
+local void huf_decode_start()
+{
+ init_getbits(); blocksize = 0;
+}
+
+/***********************************************************
+ decode.c
+***********************************************************/
+
+local int j; /* remaining bytes to copy */
+local int done; /* set at end of input */
+
+local void decode_start()
+{
+ huf_decode_start();
+ j = 0;
+ done = 0;
+}
+
+/* Decode the input and return the number of decoded bytes put in buffer
+ */
+local unsigned decode(count, buffer)
+ unsigned count;
+ uch buffer[];
+ /* The calling function must keep the number of
+ bytes to be processed. This function decodes
+ either 'count' bytes or 'DICSIZ' bytes, whichever
+ is smaller, into the array 'buffer[]' of size
+ 'DICSIZ' or more.
+ Call decode_start() once for each new file
+ before calling this function.
+ */
+{
+ local unsigned i;
+ unsigned r, c;
+
+ r = 0;
+ while (--j >= 0) {
+ buffer[r] = buffer[i];
+ i = (i + 1) & (DICSIZ - 1);
+ if (++r == count) return r;
+ }
+ for ( ; ; ) {
+ c = decode_c();
+ if (c == NC) {
+ done = 1;
+ return r;
+ }
+ if (c <= UCHAR_MAX) {
+ buffer[r] = c;
+ if (++r == count) return r;
+ } else {
+ j = c - (UCHAR_MAX + 1 - THRESHOLD);
+ i = (r - decode_p() - 1) & (DICSIZ - 1);
+ while (--j >= 0) {
+ buffer[r] = buffer[i];
+ i = (i + 1) & (DICSIZ - 1);
+ if (++r == count) return r;
+ }
+ }
+ }
+}
+
+
+/* ===========================================================================
+ * Unlzh in to out. Return OK or ERROR.
+ */
+int unlzh(in, out)
+ int in;
+ int out;
+{
+ unsigned n;
+ ifd = in;
+ ofd = out;
+
+ decode_start();
+ while (!done) {
+ n = decode((unsigned) DICSIZ, window);
+ if (!test && n > 0) {
+ write_buf(out, (char*)window, n);
+ }
+ }
+ return OK;
+}
diff --git a/gnu/usr.bin/gzip/unlzw.c b/gnu/usr.bin/gzip/unlzw.c
new file mode 100644
index 0000000..7e89ca4
--- /dev/null
+++ b/gnu/usr.bin/gzip/unlzw.c
@@ -0,0 +1,377 @@
+/* unlzw.c -- decompress files in LZW format.
+ * The code in this file is directly derived from the public domain 'compress'
+ * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
+ * Ken Turkowski, Dave Mack and Peter Jannesen.
+ *
+ * This is a temporary version which will be rewritten in some future version
+ * to accommodate in-memory decompression.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <sys/types.h>
+
+#include "tailor.h"
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef NO_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#include "gzip.h"
+#include "lzw.h"
+
+typedef unsigned char char_type;
+typedef long code_int;
+typedef unsigned long count_int;
+typedef unsigned short count_short;
+typedef unsigned long cmp_code_int;
+
+#define MAXCODE(n) (1L << (n))
+
+#ifndef REGISTERS
+# define REGISTERS 2
+#endif
+#define REG1
+#define REG2
+#define REG3
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+#define REG10
+#define REG11
+#define REG12
+#define REG13
+#define REG14
+#define REG15
+#define REG16
+#if REGISTERS >= 1
+# undef REG1
+# define REG1 register
+#endif
+#if REGISTERS >= 2
+# undef REG2
+# define REG2 register
+#endif
+#if REGISTERS >= 3
+# undef REG3
+# define REG3 register
+#endif
+#if REGISTERS >= 4
+# undef REG4
+# define REG4 register
+#endif
+#if REGISTERS >= 5
+# undef REG5
+# define REG5 register
+#endif
+#if REGISTERS >= 6
+# undef REG6
+# define REG6 register
+#endif
+#if REGISTERS >= 7
+# undef REG7
+# define REG7 register
+#endif
+#if REGISTERS >= 8
+# undef REG8
+# define REG8 register
+#endif
+#if REGISTERS >= 9
+# undef REG9
+# define REG9 register
+#endif
+#if REGISTERS >= 10
+# undef REG10
+# define REG10 register
+#endif
+#if REGISTERS >= 11
+# undef REG11
+# define REG11 register
+#endif
+#if REGISTERS >= 12
+# undef REG12
+# define REG12 register
+#endif
+#if REGISTERS >= 13
+# undef REG13
+# define REG13 register
+#endif
+#if REGISTERS >= 14
+# undef REG14
+# define REG14 register
+#endif
+#if REGISTERS >= 15
+# undef REG15
+# define REG15 register
+#endif
+#if REGISTERS >= 16
+# undef REG16
+# define REG16 register
+#endif
+
+#ifndef BYTEORDER
+# define BYTEORDER 0000
+#endif
+
+#ifndef NOALLIGN
+# define NOALLIGN 0
+#endif
+
+
+union bytes {
+ long word;
+ struct {
+#if BYTEORDER == 4321
+ char_type b1;
+ char_type b2;
+ char_type b3;
+ char_type b4;
+#else
+#if BYTEORDER == 1234
+ char_type b4;
+ char_type b3;
+ char_type b2;
+ char_type b1;
+#else
+# undef BYTEORDER
+ int dummy;
+#endif
+#endif
+ } bytes;
+};
+
+#if BYTEORDER == 4321 && NOALLIGN == 1
+# define input(b,o,c,n,m){ \
+ (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
+ (o) += (n); \
+ }
+#else
+# define input(b,o,c,n,m){ \
+ REG1 char_type *p = &(b)[(o)>>3]; \
+ (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
+ ((long)(p[2])<<16))>>((o)&0x7))&(m); \
+ (o) += (n); \
+ }
+#endif
+
+#ifndef MAXSEG_64K
+ /* DECLARE(ush, tab_prefix, (1<<BITS)); -- prefix code */
+# define tab_prefixof(i) tab_prefix[i]
+# define clear_tab_prefixof() memzero(tab_prefix, 256);
+#else
+ /* DECLARE(ush, tab_prefix0, (1<<(BITS-1)); -- prefix for even codes */
+ /* DECLARE(ush, tab_prefix1, (1<<(BITS-1)); -- prefix for odd codes */
+ ush *tab_prefix[2];
+# define tab_prefixof(i) tab_prefix[(i)&1][(i)>>1]
+# define clear_tab_prefixof() \
+ memzero(tab_prefix0, 128), \
+ memzero(tab_prefix1, 128);
+#endif
+#define de_stack ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
+#define tab_suffixof(i) tab_suffix[i]
+
+int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
+
+/* ============================================================================
+ * Decompress in to out. This routine adapts to the codes in the
+ * file building the "string" table on-the-fly; requiring no table to
+ * be stored in the compressed file.
+ * IN assertions: the buffer inbuf contains already the beginning of
+ * the compressed data, from offsets iptr to insize-1 included.
+ * The magic header has already been checked and skipped.
+ * bytes_in and bytes_out have been initialized.
+ */
+int unlzw(in, out)
+ int in, out; /* input and output file descriptors */
+{
+ REG2 char_type *stackp;
+ REG3 code_int code;
+ REG4 int finchar;
+ REG5 code_int oldcode;
+ REG6 code_int incode;
+ REG7 long inbits;
+ REG8 long posbits;
+ REG9 int outpos;
+/* REG10 int insize; (global) */
+ REG11 unsigned bitmask;
+ REG12 code_int free_ent;
+ REG13 code_int maxcode;
+ REG14 code_int maxmaxcode;
+ REG15 int n_bits;
+ REG16 int rsize;
+
+#ifdef MAXSEG_64K
+ tab_prefix[0] = tab_prefix0;
+ tab_prefix[1] = tab_prefix1;
+#endif
+ maxbits = get_byte();
+ block_mode = maxbits & BLOCK_MODE;
+ if ((maxbits & LZW_RESERVED) != 0) {
+ WARN((stderr, "\n%s: %s: warning, unknown flags 0x%x\n",
+ progname, ifname, maxbits & LZW_RESERVED));
+ }
+ maxbits &= BIT_MASK;
+ maxmaxcode = MAXCODE(maxbits);
+
+ if (maxbits > BITS) {
+ fprintf(stderr,
+ "\n%s: %s: compressed with %d bits, can only handle %d bits\n",
+ progname, ifname, maxbits, BITS);
+ exit_code = ERROR;
+ return ERROR;
+ }
+ rsize = insize;
+ maxcode = MAXCODE(n_bits = INIT_BITS)-1;
+ bitmask = (1<<n_bits)-1;
+ oldcode = -1;
+ finchar = 0;
+ outpos = 0;
+ posbits = inptr<<3;
+
+ free_ent = ((block_mode) ? FIRST : 256);
+
+ clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
+
+ for (code = 255 ; code >= 0 ; --code) {
+ tab_suffixof(code) = (char_type)code;
+ }
+ do {
+ REG1 int i;
+ int e;
+ int o;
+
+ resetbuf:
+ e = insize-(o = (posbits>>3));
+
+ for (i = 0 ; i < e ; ++i) {
+ inbuf[i] = inbuf[i+o];
+ }
+ insize = e;
+ posbits = 0;
+
+ if (insize < INBUF_EXTRA) {
+ if ((rsize = read(in, (char*)inbuf+insize, INBUFSIZ)) == EOF) {
+ read_error();
+ }
+ insize += rsize;
+ bytes_in += (ulg)rsize;
+ }
+ inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 :
+ ((long)insize<<3)-(n_bits-1));
+
+ while (inbits > posbits) {
+ if (free_ent > maxcode) {
+ posbits = ((posbits-1) +
+ ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
+ ++n_bits;
+ if (n_bits == maxbits) {
+ maxcode = maxmaxcode;
+ } else {
+ maxcode = MAXCODE(n_bits)-1;
+ }
+ bitmask = (1<<n_bits)-1;
+ goto resetbuf;
+ }
+ input(inbuf,posbits,code,n_bits,bitmask);
+ Tracev((stderr, "%d ", code));
+
+ if (oldcode == -1) {
+ if (code >= 256) error("corrupt input.");
+ outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
+ continue;
+ }
+ if (code == CLEAR && block_mode) {
+ clear_tab_prefixof();
+ free_ent = FIRST - 1;
+ posbits = ((posbits-1) +
+ ((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
+ maxcode = MAXCODE(n_bits = INIT_BITS)-1;
+ bitmask = (1<<n_bits)-1;
+ goto resetbuf;
+ }
+ incode = code;
+ stackp = de_stack;
+
+ if (code >= free_ent) { /* Special case for KwKwK string. */
+ if (code > free_ent) {
+#ifdef DEBUG
+ char_type *p;
+
+ posbits -= n_bits;
+ p = &inbuf[posbits>>3];
+ fprintf(stderr,
+ "code:%ld free_ent:%ld n_bits:%d insize:%u\n",
+ code, free_ent, n_bits, insize);
+ fprintf(stderr,
+ "posbits:%ld inbuf:%02X %02X %02X %02X %02X\n",
+ posbits, p[-1],p[0],p[1],p[2],p[3]);
+#endif
+ if (!test && outpos > 0) {
+ write_buf(out, (char*)outbuf, outpos);
+ bytes_out += (ulg)outpos;
+ }
+ error(to_stdout ? "corrupt input." :
+ "corrupt input. Use zcat to recover some data.");
+ }
+ *--stackp = (char_type)finchar;
+ code = oldcode;
+ }
+
+ while ((cmp_code_int)code >= (cmp_code_int)256) {
+ /* Generate output characters in reverse order */
+ *--stackp = tab_suffixof(code);
+ code = tab_prefixof(code);
+ }
+ *--stackp = (char_type)(finchar = tab_suffixof(code));
+
+ /* And put them out in forward order */
+ {
+ REG1 int i;
+
+ if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
+ do {
+ if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
+
+ if (i > 0) {
+ memcpy(outbuf+outpos, stackp, i);
+ outpos += i;
+ }
+ if (outpos >= OUTBUFSIZ) {
+ if (!test) {
+ write_buf(out, (char*)outbuf, outpos);
+ bytes_out += (ulg)outpos;
+ }
+ outpos = 0;
+ }
+ stackp+= i;
+ } while ((i = (de_stack-stackp)) > 0);
+ } else {
+ memcpy(outbuf+outpos, stackp, i);
+ outpos += i;
+ }
+ }
+
+ if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
+
+ tab_prefixof(code) = (unsigned short)oldcode;
+ tab_suffixof(code) = (char_type)finchar;
+ free_ent = code+1;
+ }
+ oldcode = incode; /* Remember previous code. */
+ }
+ } while (rsize != 0);
+
+ if (!test && outpos > 0) {
+ write_buf(out, (char*)outbuf, outpos);
+ bytes_out += (ulg)outpos;
+ }
+ return OK;
+}
diff --git a/gnu/usr.bin/gzip/unpack.c b/gnu/usr.bin/gzip/unpack.c
new file mode 100644
index 0000000..a0ef286
--- /dev/null
+++ b/gnu/usr.bin/gzip/unpack.c
@@ -0,0 +1,239 @@
+/* unpack.c -- decompress files in pack format.
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "tailor.h"
+#include "gzip.h"
+#include "crypt.h"
+
+#define MIN(a,b) ((a) <= (b) ? (a) : (b))
+/* The arguments must not have side effects. */
+
+#define MAX_BITLEN 25
+/* Maximum length of Huffman codes. (Minor modifications to the code
+ * would be needed to support 32 bits codes, but pack never generates
+ * more than 24 bits anyway.)
+ */
+
+#define LITERALS 256
+/* Number of literals, excluding the End of Block (EOB) code */
+
+#define MAX_PEEK 12
+/* Maximum number of 'peek' bits used to optimize traversal of the
+ * Huffman tree.
+ */
+
+local ulg orig_len; /* original uncompressed length */
+local int max_len; /* maximum bit length of Huffman codes */
+
+local uch literal[LITERALS];
+/* The literal bytes present in the Huffman tree. The EOB code is not
+ * represented.
+ */
+
+local int lit_base[MAX_BITLEN+1];
+/* All literals of a given bit length are contiguous in literal[] and
+ * have contiguous codes. literal[code+lit_base[len]] is the literal
+ * for a code of len bits.
+ */
+
+local int leaves [MAX_BITLEN+1]; /* Number of leaves for each bit length */
+local int parents[MAX_BITLEN+1]; /* Number of parents for each bit length */
+
+local int peek_bits; /* Number of peek bits currently used */
+
+/* local uch prefix_len[1 << MAX_PEEK]; */
+#define prefix_len outbuf
+/* For each bit pattern b of peek_bits bits, prefix_len[b] is the length
+ * of the Huffman code starting with a prefix of b (upper bits), or 0
+ * if all codes of prefix b have more than peek_bits bits. It is not
+ * necessary to have a huge table (large MAX_PEEK) because most of the
+ * codes encountered in the input stream are short codes (by construction).
+ * So for most codes a single lookup will be necessary.
+ */
+#if (1<<MAX_PEEK) > OUTBUFSIZ
+ error cannot overlay prefix_len and outbuf
+#endif
+
+local ulg bitbuf;
+/* Bits are added on the low part of bitbuf and read from the high part. */
+
+local int valid; /* number of valid bits in bitbuf */
+/* all bits above the last valid bit are always zero */
+
+/* Set code to the next 'bits' input bits without skipping them. code
+ * must be the name of a simple variable and bits must not have side effects.
+ * IN assertions: bits <= 25 (so that we still have room for an extra byte
+ * when valid is only 24), and mask = (1<<bits)-1.
+ */
+#define look_bits(code,bits,mask) \
+{ \
+ while (valid < (bits)) bitbuf = (bitbuf<<8) | (ulg)get_byte(), valid += 8; \
+ code = (bitbuf >> (valid-(bits))) & (mask); \
+}
+
+/* Skip the given number of bits (after having peeked at them): */
+#define skip_bits(bits) (valid -= (bits))
+
+#define clear_bitbuf() (valid = 0, bitbuf = 0)
+
+/* Local functions */
+
+local void read_tree OF((void));
+local void build_tree OF((void));
+
+/* ===========================================================================
+ * Read the Huffman tree.
+ */
+local void read_tree()
+{
+ int len; /* bit length */
+ int base; /* base offset for a sequence of leaves */
+ int n;
+
+ /* Read the original input size, MSB first */
+ orig_len = 0;
+ for (n = 1; n <= 4; n++) orig_len = (orig_len << 8) | (ulg)get_byte();
+
+ max_len = (int)get_byte(); /* maximum bit length of Huffman codes */
+ if (max_len > MAX_BITLEN) {
+ error("invalid compressed data -- Huffman code > 32 bits");
+ }
+
+ /* Get the number of leaves at each bit length */
+ n = 0;
+ for (len = 1; len <= max_len; len++) {
+ leaves[len] = (int)get_byte();
+ n += leaves[len];
+ }
+ if (n > LITERALS) {
+ error("too many leaves in Huffman tree");
+ }
+ Trace((stderr, "orig_len %ld, max_len %d, leaves %d\n",
+ orig_len, max_len, n));
+ /* There are at least 2 and at most 256 leaves of length max_len.
+ * (Pack arbitrarily rejects empty files and files consisting of
+ * a single byte even repeated.) To fit the last leaf count in a
+ * byte, it is offset by 2. However, the last literal is the EOB
+ * code, and is not transmitted explicitly in the tree, so we must
+ * adjust here by one only.
+ */
+ leaves[max_len]++;
+
+ /* Now read the leaves themselves */
+ base = 0;
+ for (len = 1; len <= max_len; len++) {
+ /* Remember where the literals of this length start in literal[] : */
+ lit_base[len] = base;
+ /* And read the literals: */
+ for (n = leaves[len]; n > 0; n--) {
+ literal[base++] = (uch)get_byte();
+ }
+ }
+ leaves[max_len]++; /* Now include the EOB code in the Huffman tree */
+}
+
+/* ===========================================================================
+ * Build the Huffman tree and the prefix table.
+ */
+local void build_tree()
+{
+ int nodes = 0; /* number of nodes (parents+leaves) at current bit length */
+ int len; /* current bit length */
+ uch *prefixp; /* pointer in prefix_len */
+
+ for (len = max_len; len >= 1; len--) {
+ /* The number of parent nodes at this level is half the total
+ * number of nodes at parent level:
+ */
+ nodes >>= 1;
+ parents[len] = nodes;
+ /* Update lit_base by the appropriate bias to skip the parent nodes
+ * (which are not represented in the literal array):
+ */
+ lit_base[len] -= nodes;
+ /* Restore nodes to be parents+leaves: */
+ nodes += leaves[len];
+ }
+ /* Construct the prefix table, from shortest leaves to longest ones.
+ * The shortest code is all ones, so we start at the end of the table.
+ */
+ peek_bits = MIN(max_len, MAX_PEEK);
+ prefixp = &prefix_len[1<<peek_bits];
+ for (len = 1; len <= peek_bits; len++) {
+ int prefixes = leaves[len] << (peek_bits-len); /* may be 0 */
+ while (prefixes--) *--prefixp = (uch)len;
+ }
+ /* The length of all other codes is unknown: */
+ while (prefixp > prefix_len) *--prefixp = 0;
+}
+
+/* ===========================================================================
+ * Unpack in to out. This routine does not support the old pack format
+ * with magic header \037\037.
+ *
+ * IN assertions: the buffer inbuf contains already the beginning of
+ * the compressed data, from offsets inptr to insize-1 included.
+ * The magic header has already been checked. The output buffer is cleared.
+ */
+int unpack(in, out)
+ int in, out; /* input and output file descriptors */
+{
+ int len; /* Bit length of current code */
+ unsigned eob; /* End Of Block code */
+ register unsigned peek; /* lookahead bits */
+ unsigned peek_mask; /* Mask for peek_bits bits */
+
+ ifd = in;
+ ofd = out;
+
+ read_tree(); /* Read the Huffman tree */
+ build_tree(); /* Build the prefix table */
+ clear_bitbuf(); /* Initialize bit input */
+ peek_mask = (1<<peek_bits)-1;
+
+ /* The eob code is the largest code among all leaves of maximal length: */
+ eob = leaves[max_len]-1;
+ Trace((stderr, "eob %d %x\n", max_len, eob));
+
+ /* Decode the input data: */
+ for (;;) {
+ /* Since eob is the longest code and not shorter than max_len,
+ * we can peek at max_len bits without having the risk of reading
+ * beyond the end of file.
+ */
+ look_bits(peek, peek_bits, peek_mask);
+ len = prefix_len[peek];
+ if (len > 0) {
+ peek >>= peek_bits - len; /* discard the extra bits */
+ } else {
+ /* Code of more than peek_bits bits, we must traverse the tree */
+ ulg mask = peek_mask;
+ len = peek_bits;
+ do {
+ len++, mask = (mask<<1)+1;
+ look_bits(peek, len, mask);
+ } while (peek < (unsigned)parents[len]);
+ /* loop as long as peek is a parent node */
+ }
+ /* At this point, peek is the next complete code, of len bits */
+ if (peek == eob && len == max_len) break; /* end of file? */
+ put_ubyte(literal[peek+lit_base[len]]);
+ Tracev((stderr,"%02d %04x %c\n", len, peek,
+ literal[peek+lit_base[len]]));
+ skip_bits(len);
+ } /* for (;;) */
+
+ flush_window();
+ Trace((stderr, "bytes_out %ld\n", bytes_out));
+ if (orig_len != (ulg)bytes_out) {
+ error("invalid compressed data--length error");
+ }
+ return OK;
+}
diff --git a/gnu/usr.bin/gzip/unzip.c b/gnu/usr.bin/gzip/unzip.c
new file mode 100644
index 0000000..e36555a
--- /dev/null
+++ b/gnu/usr.bin/gzip/unzip.c
@@ -0,0 +1,199 @@
+/* unzip.c -- decompress files in gzip or pkzip format.
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ *
+ * The code in this file is derived from the file funzip.c written
+ * and put in the public domain by Mark Adler.
+ */
+
+/*
+ This version can extract files in gzip or pkzip format.
+ For the latter, only the first entry is extracted, and it has to be
+ either deflated or stored.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include "tailor.h"
+#include "gzip.h"
+#include "crypt.h"
+
+/* PKZIP header definitions */
+#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */
+#define LOCFLG 6 /* offset of bit flag */
+#define CRPFLG 1 /* bit for encrypted entry */
+#define EXTFLG 8 /* bit for extended local header */
+#define LOCHOW 8 /* offset of compression method */
+#define LOCTIM 10 /* file mod time (for decryption) */
+#define LOCCRC 14 /* offset of crc */
+#define LOCSIZ 18 /* offset of compressed size */
+#define LOCLEN 22 /* offset of uncompressed length */
+#define LOCFIL 26 /* offset of file name field length */
+#define LOCEXT 28 /* offset of extra field length */
+#define LOCHDR 30 /* size of local header, including sig */
+#define EXTHDR 16 /* size of extended local header, inc sig */
+
+
+/* Globals */
+
+int decrypt; /* flag to turn on decryption */
+char *key; /* not used--needed to link crypt.c */
+int pkzip = 0; /* set for a pkzip file */
+int ext_header = 0; /* set if extended local header */
+
+/* ===========================================================================
+ * Check zip file and advance inptr to the start of the compressed data.
+ * Get ofname from the local header if necessary.
+ */
+int check_zipfile(in)
+ int in; /* input file descriptors */
+{
+ uch *h = inbuf + inptr; /* first local header */
+
+ ifd = in;
+
+ /* Check validity of local header, and skip name and extra fields */
+ inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
+
+ if (inptr > insize || LG(h) != LOCSIG) {
+ fprintf(stderr, "\n%s: %s: not a valid zip file\n",
+ progname, ifname);
+ exit_code = ERROR;
+ return ERROR;
+ }
+ method = h[LOCHOW];
+ if (method != STORED && method != DEFLATED) {
+ fprintf(stderr,
+ "\n%s: %s: first entry not deflated or stored -- use unzip\n",
+ progname, ifname);
+ exit_code = ERROR;
+ return ERROR;
+ }
+
+ /* If entry encrypted, decrypt and validate encryption header */
+ if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
+ fprintf(stderr, "\n%s: %s: encrypted file -- use unzip\n",
+ progname, ifname);
+ exit_code = ERROR;
+ return ERROR;
+ }
+
+ /* Save flags for unzip() */
+ ext_header = (h[LOCFLG] & EXTFLG) != 0;
+ pkzip = 1;
+
+ /* Get ofname and time stamp from local header (to be done) */
+ return OK;
+}
+
+/* ===========================================================================
+ * Unzip in to out. This routine works on both gzip and pkzip files.
+ *
+ * IN assertions: the buffer inbuf contains already the beginning of
+ * the compressed data, from offsets inptr to insize-1 included.
+ * The magic header has already been checked. The output buffer is cleared.
+ */
+int unzip(in, out)
+ int in, out; /* input and output file descriptors */
+{
+ ulg orig_crc = 0; /* original crc */
+ ulg orig_len = 0; /* original uncompressed length */
+ int n;
+ uch buf[EXTHDR]; /* extended local header */
+
+ ifd = in;
+ ofd = out;
+
+ updcrc(NULL, 0); /* initialize crc */
+
+ if (pkzip && !ext_header) { /* crc and length at the end otherwise */
+ orig_crc = LG(inbuf + LOCCRC);
+ orig_len = LG(inbuf + LOCLEN);
+ }
+
+ /* Decompress */
+ if (method == DEFLATED) {
+
+ int res = inflate();
+
+ if (res == 3) {
+ error("out of memory");
+ } else if (res != 0) {
+ error("invalid compressed data--format violated");
+ }
+
+ } else if (pkzip && method == STORED) {
+
+ register ulg n = LG(inbuf + LOCLEN);
+
+ if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
+
+ fprintf(stderr, "len %ld, siz %ld\n", n, LG(inbuf + LOCSIZ));
+ error("invalid compressed data--length mismatch");
+ }
+ while (n--) {
+ uch c = (uch)get_byte();
+#ifdef CRYPT
+ if (decrypt) zdecode(c);
+#endif
+ put_ubyte(c);
+ }
+ flush_window();
+ } else {
+ error("internal error, invalid method");
+ }
+
+ /* Get the crc and original length */
+ if (!pkzip) {
+ /* crc32 (see algorithm.doc)
+ * uncompressed input size modulo 2^32
+ */
+ for (n = 0; n < 8; n++) {
+ buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+ }
+ orig_crc = LG(buf);
+ orig_len = LG(buf+4);
+
+ } else if (ext_header) { /* If extended header, check it */
+ /* signature - 4bytes: 0x50 0x4b 0x07 0x08
+ * CRC-32 value
+ * compressed size 4-bytes
+ * uncompressed size 4-bytes
+ */
+ for (n = 0; n < EXTHDR; n++) {
+ buf[n] = (uch)get_byte(); /* may cause an error if EOF */
+ }
+ orig_crc = LG(buf+4);
+ orig_len = LG(buf+12);
+ }
+
+ /* Validate decompression */
+ if (orig_crc != updcrc(outbuf, 0)) {
+ error("invalid compressed data--crc error");
+ }
+ if (orig_len != (ulg)bytes_out) {
+ error("invalid compressed data--length error");
+ }
+
+ /* Check if there are more entries in a pkzip file */
+ if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
+ if (to_stdout) {
+ WARN((stderr,
+ "%s: %s has more than one entry--rest ignored\n",
+ progname, ifname));
+ } else {
+ /* Don't destroy the input zip file */
+ fprintf(stderr,
+ "%s: %s has more than one entry -- unchanged\n",
+ progname, ifname);
+ exit_code = ERROR;
+ ext_header = pkzip = 0;
+ return ERROR;
+ }
+ }
+ ext_header = pkzip = 0; /* for next file */
+ return OK;
+}
diff --git a/gnu/usr.bin/gzip/util.c b/gnu/usr.bin/gzip/util.c
new file mode 100644
index 0000000..684cc5d
--- /dev/null
+++ b/gnu/usr.bin/gzip/util.c
@@ -0,0 +1,456 @@
+/* util.c -- utility functions for gzip support
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "tailor.h"
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef NO_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
+# include <stdlib.h>
+#else
+ extern int errno;
+#endif
+
+#include "gzip.h"
+#include "crypt.h"
+
+extern ulg crc_32_tab[]; /* crc table, defined below */
+
+/* ===========================================================================
+ * Copy input to output unchanged: zcat == cat with --force.
+ * IN assertion: insize bytes have already been read in inbuf.
+ */
+int copy(in, out)
+ int in, out; /* input and output file descriptors */
+{
+ errno = 0;
+ while (insize != 0 && (int)insize != EOF) {
+ write_buf(out, (char*)inbuf, insize);
+ bytes_out += insize;
+ insize = read(in, (char*)inbuf, INBUFSIZ);
+ }
+ if ((int)insize == EOF && errno != 0) {
+ read_error();
+ }
+ bytes_in = bytes_out;
+ return OK;
+}
+
+/* ===========================================================================
+ * Run a set of bytes through the crc shift register. If s is a NULL
+ * pointer, then initialize the crc shift register contents instead.
+ * Return the current crc in either case.
+ */
+ulg updcrc(s, n)
+ uch *s; /* pointer to bytes to pump through */
+ unsigned n; /* number of bytes in s[] */
+{
+ register ulg c; /* temporary variable */
+
+ static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+
+ if (s == NULL) {
+ c = 0xffffffffL;
+ } else {
+ c = crc;
+ if (n) do {
+ c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
+ } while (--n);
+ }
+ crc = c;
+ return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
+}
+
+/* ===========================================================================
+ * Clear input and output buffers
+ */
+void clear_bufs()
+{
+ outcnt = 0;
+ insize = inptr = 0;
+ bytes_in = bytes_out = 0L;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty.
+ */
+int fill_inbuf(eof_ok)
+ int eof_ok; /* set if EOF acceptable as a result */
+{
+ int len;
+
+ /* Read as much as possible */
+ insize = 0;
+ errno = 0;
+ do {
+ len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
+ if (len == 0 || len == EOF) break;
+ insize += len;
+ } while (insize < INBUFSIZ);
+
+ if (insize == 0) {
+ if (eof_ok) return EOF;
+ read_error();
+ }
+ bytes_in += (ulg)insize;
+ inptr = 1;
+ return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
+ * (used for the compressed data only)
+ */
+void flush_outbuf()
+{
+ if (outcnt == 0) return;
+
+ write_buf(ofd, (char *)outbuf, outcnt);
+ bytes_out += (ulg)outcnt;
+ outcnt = 0;
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+void flush_window()
+{
+ if (outcnt == 0) return;
+ updcrc(window, outcnt);
+
+ if (!test) {
+ write_buf(ofd, (char *)window, outcnt);
+ }
+ bytes_out += (ulg)outcnt;
+ outcnt = 0;
+}
+
+/* ===========================================================================
+ * Does the same as write(), but also handles partial pipe writes and checks
+ * for error return.
+ */
+void write_buf(fd, buf, cnt)
+ int fd;
+ voidp buf;
+ unsigned cnt;
+{
+ unsigned n;
+
+ while ((n = write(fd, buf, cnt)) != cnt) {
+ if (n == (unsigned)(-1)) {
+ write_error();
+ }
+ cnt -= n;
+ buf = (voidp)((char*)buf+n);
+ }
+}
+
+/* ========================================================================
+ * Put string s in lower case, return s.
+ */
+char *strlwr(s)
+ char *s;
+{
+ char *t;
+ for (t = s; *t; t++) *t = tolow(*t);
+ return s;
+}
+
+/* ========================================================================
+ * Return the base name of a file (remove any directory prefix and
+ * any version suffix). For systems with file names that are not
+ * case sensitive, force the base name to lower case.
+ */
+char *basename(fname)
+ char *fname;
+{
+ char *p;
+
+ if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
+#ifdef PATH_SEP2
+ if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
+#endif
+#ifdef PATH_SEP3
+ if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
+#endif
+#ifdef SUFFIX_SEP
+ if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
+#endif
+ if (casemap('A') == 'a') strlwr(fname);
+ return fname;
+}
+
+/* ========================================================================
+ * Make a file name legal for file systems not allowing file names with
+ * multiple dots or starting with a dot (such as MSDOS), by changing
+ * all dots except the last one into underlines. A target dependent
+ * function can be used instead of this simple function by defining the macro
+ * MAKE_LEGAL_NAME in tailor.h and providing the function in a target
+ * dependent module.
+ */
+void make_simple_name(name)
+ char *name;
+{
+ char *p = strrchr(name, '.');
+ if (p == NULL) return;
+ if (p == name) p++;
+ do {
+ if (*--p == '.') *p = '_';
+ } while (p != name);
+}
+
+
+#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
+
+/* Provide missing strspn and strcspn functions. */
+
+# ifndef __STDC__
+# define const
+# endif
+
+int strspn OF((const char *s, const char *accept));
+int strcspn OF((const char *s, const char *reject));
+
+/* ========================================================================
+ * Return the length of the maximum initial segment
+ * of s which contains only characters in accept.
+ */
+int strspn(s, accept)
+ const char *s;
+ const char *accept;
+{
+ register const char *p;
+ register const char *a;
+ register int count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (a = accept; *a != '\0'; ++a) {
+ if (*p == *a) break;
+ }
+ if (*a == '\0') return count;
+ ++count;
+ }
+ return count;
+}
+
+/* ========================================================================
+ * Return the length of the maximum inital segment of s
+ * which contains no characters from reject.
+ */
+int strcspn(s, reject)
+ const char *s;
+ const char *reject;
+{
+ register int count = 0;
+
+ while (*s != '\0') {
+ if (strchr(reject, *s++) != NULL) return count;
+ ++count;
+ }
+ return count;
+}
+
+#endif /* NO_STRING_H */
+
+/* ========================================================================
+ * Add an environment variable (if any) before argv, and update argc.
+ * Return the expanded environment variable to be freed later, or NULL
+ * if no options were added to argv.
+ */
+#define SEPARATOR " \t" /* separators in env variable */
+
+char *add_envopt(argcp, argvp, env)
+ int *argcp; /* pointer to argc */
+ char ***argvp; /* pointer to argv */
+ char *env; /* name of environment variable */
+{
+ char *p; /* running pointer through env variable */
+ char **oargv; /* runs through old argv array */
+ char **nargv; /* runs through new argv array */
+ int oargc = *argcp; /* old argc */
+ int nargc = 0; /* number of arguments in env variable */
+
+ env = (char*)getenv(env);
+ if (env == NULL) return NULL;
+
+ p = (char*)xmalloc(strlen(env)+1);
+ env = strcpy(p, env); /* keep env variable intact */
+
+ for (p = env; *p; nargc++ ) { /* move through env */
+ p += strspn(p, SEPARATOR); /* skip leading separators */
+ if (*p == '\0') break;
+
+ p += strcspn(p, SEPARATOR); /* find end of word */
+ if (*p) *p++ = '\0'; /* mark it */
+ }
+ if (nargc == 0) {
+ free(env);
+ return NULL;
+ }
+ *argcp += nargc;
+ /* Allocate the new argv array, with an extra element just in case
+ * the original arg list did not end with a NULL.
+ */
+ nargv = (char**)calloc(*argcp+1, sizeof(char *));
+ if (nargv == NULL) error("out of memory");
+ oargv = *argvp;
+ *argvp = nargv;
+
+ /* Copy the program name first */
+ if (oargc-- < 0) error("argc<=0");
+ *(nargv++) = *(oargv++);
+
+ /* Then copy the environment args */
+ for (p = env; nargc > 0; nargc--) {
+ p += strspn(p, SEPARATOR); /* skip separators */
+ *(nargv++) = p; /* store start */
+ while (*p++) ; /* skip over word */
+ }
+
+ /* Finally copy the old args and add a NULL (usual convention) */
+ while (oargc--) *(nargv++) = *(oargv++);
+ *nargv = NULL;
+ return env;
+}
+
+/* ========================================================================
+ * Error handlers.
+ */
+void error(m)
+ char *m;
+{
+ fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m);
+ abort_gzip();
+}
+
+void read_error()
+{
+ fprintf(stderr, "\n%s: ", progname);
+ if (errno != 0) {
+ perror(ifname);
+ } else {
+ fprintf(stderr, "%s: unexpected end of file\n", ifname);
+ }
+ abort_gzip();
+}
+
+void write_error()
+{
+ fprintf(stderr, "\n%s: ", progname);
+ perror(ofname);
+ abort_gzip();
+}
+
+/* ========================================================================
+ * Display compression ratio on the given stream on 6 characters.
+ */
+void display_ratio(num, den, file)
+ long num;
+ long den;
+ FILE *file;
+{
+ long ratio; /* 1000 times the compression ratio */
+
+ if (den == 0) {
+ ratio = 0; /* no compression */
+ } else if (den < 2147483L) { /* (2**31 -1)/1000 */
+ ratio = 1000L*num/den;
+ } else {
+ ratio = num/(den/1000L);
+ }
+ if (ratio < 0) {
+ putc('-', file);
+ ratio = -ratio;
+ } else {
+ putc(' ', file);
+ }
+ fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L);
+}
+
+
+/* ========================================================================
+ * Semi-safe malloc -- never returns NULL.
+ */
+voidp xmalloc (size)
+ unsigned size;
+{
+ voidp cp = (voidp)malloc (size);
+
+ if (cp == NULL) error("out of memory");
+ return cp;
+}
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by makecrc.c)
+ */
+ulg crc_32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
diff --git a/gnu/usr.bin/gzip/zdiff b/gnu/usr.bin/gzip/zdiff
new file mode 100644
index 0000000..310a201
--- /dev/null
+++ b/gnu/usr.bin/gzip/zdiff
@@ -0,0 +1,71 @@
+#!/bin/sh
+# sh is buggy on RS/6000 AIX 3.2. Replace above line with #!/bin/ksh
+
+# Zcmp and zdiff are used to invoke the cmp or the diff pro-
+# gram on compressed files. All options specified are passed
+# directly to cmp or diff. If only 1 file is specified, then
+# the files compared are file1 and an uncompressed file1.gz.
+# If two files are specified, then they are uncompressed (if
+# necessary) and fed to cmp or diff. The exit status from cmp
+# or diff is preserved.
+#
+# $FreeBSD$
+
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+ *cmp) comp=${CMP-cmp} ;;
+ *) comp=${DIFF-diff} ;;
+esac
+
+OPTIONS=
+FILES=
+for ARG
+do
+ case "$ARG" in
+ -*) OPTIONS="$OPTIONS $ARG";;
+ *) if test -f "$ARG"; then
+ FILES="$FILES $ARG"
+ else
+ echo "${prog}: $ARG not found or not a regular file"
+ exit 1
+ fi ;;
+ esac
+done
+if test -z "$FILES"; then
+ echo "Usage: $prog [${comp}_options] file [file]"
+ exit 1
+fi
+set $FILES
+if test $# -eq 1; then
+ FILE=`echo "$1" | sed 's/[-.][zZtga]*$//'`
+ gzip -cd "$1" | $comp $OPTIONS - "$FILE"
+ STAT="$?"
+
+elif test $# -eq 2; then
+ case "$1" in
+ *[-.]gz* | *[-.][zZ] | *.t[ga]z)
+ case "$2" in
+ *[-.]gz* | *[-.][zZ] | *.t[ga]z)
+ F=`echo "$2" | sed 's|.*/||;s|[-.][zZtga]*||'`
+ tmp=`mktemp -t "$F"`
+ gzip -cdfq "$2" > "$tmp"
+ gzip -cdfq "$1" | $comp $OPTIONS - "$tmp"
+ STAT="$?"
+ /bin/rm -f "$tmp";;
+
+ *) gzip -cdfq "$1" | $comp $OPTIONS - "$2"
+ STAT="$?";;
+ esac;;
+ *) case "$2" in
+ *[-.]gz* | *[-.][zZ] | *.t[ga]z)
+ gzip -cdfq "$2" | $comp $OPTIONS "$1" -
+ STAT="$?";;
+ *) $comp $OPTIONS "$1" "$2"
+ STAT="$?";;
+ esac;;
+ esac
+ exit "$STAT"
+else
+ echo "Usage: $prog [${comp}_options] file [file]"
+ exit 1
+fi
diff --git a/gnu/usr.bin/gzip/zdiff.1 b/gnu/usr.bin/gzip/zdiff.1
new file mode 100644
index 0000000..ea3bf41
--- /dev/null
+++ b/gnu/usr.bin/gzip/zdiff.1
@@ -0,0 +1,44 @@
+.TH ZDIFF 1
+.SH NAME
+zcmp, zdiff \- compare compressed files
+.SH SYNOPSIS
+.B zcmp
+[ cmp_options ] file1
+[ file2 ]
+.br
+.B zdiff
+[ diff_options ] file1
+[ file2 ]
+.SH DESCRIPTION
+.I Zcmp
+and
+.I zdiff
+are used to invoke the
+.I cmp
+or the
+.I diff
+program on compressed files. All options specified are passed directly to
+.I cmp
+or
+.IR diff "."
+If only 1 file is specified, then the files compared are
+.I file1
+and an uncompressed
+.IR file1 ".gz."
+If two files are specified, then they are uncompressed if necessary and fed to
+.I cmp
+or
+.IR diff "."
+The exit status from
+.I cmp
+or
+.I diff
+is preserved.
+.SH "SEE ALSO"
+cmp(1), diff(1), zmore(1), zgrep(1), znew(1), zforce(1), gzip(1), gzexe(1)
+.SH BUGS
+Messages from the
+.I cmp
+or
+.I diff
+programs refer to temporary filenames instead of those specified.
diff --git a/gnu/usr.bin/gzip/zforce b/gnu/usr.bin/gzip/zforce
new file mode 100644
index 0000000..146db92
--- /dev/null
+++ b/gnu/usr.bin/gzip/zforce
@@ -0,0 +1,38 @@
+#!/bin/sh
+# zforce: force a gz extension on all gzip files so that gzip will not
+# compress them twice.
+#
+# This can be useful for files with names truncated after a file transfer.
+# foo is renamed to foo.gz
+#
+# $FreeBSD$
+
+x=`basename $0`
+if test $# = 0; then
+ echo "force a '.gz' extension on all gzip files"
+ echo usage: $x files...
+ exit 1
+fi
+
+res=0
+for i do
+ if test ! -f "$i" ; then
+ echo ${x}: $i not a file
+ res=1
+ continue
+ fi
+ test `expr "$i" : '.*[.-]z$'` -eq 0 || continue
+ test `expr "$i" : '.*[.-]gz$'` -eq 0 || continue
+ test `expr "$i" : '.*[.]t[ag]z$'` -eq 0 || continue
+
+ if gzip -lv < "$i" 2>/dev/null | grep '^defl' > /dev/null; then
+
+ new="$i.gz"
+ if mv "$i" "$new" 2>/dev/null; then
+ echo $i -- replaced with $new
+ continue
+ fi
+ res=1; echo ${x}: cannot rename $i to $new
+ fi
+done
+exit $res
diff --git a/gnu/usr.bin/gzip/zforce.1 b/gnu/usr.bin/gzip/zforce.1
new file mode 100644
index 0000000..2bfb20d
--- /dev/null
+++ b/gnu/usr.bin/gzip/zforce.1
@@ -0,0 +1,18 @@
+.TH ZFORCE 1
+.SH NAME
+zforce \- force a '.gz' extension on all gzip files
+.SH SYNOPSIS
+.B zforce
+name ...
+.SH DESCRIPTION
+.I zforce
+forces a .gz extension on all
+.I gzip
+files so that
+.I gzip
+will not compress them twice.
+This can be useful for files with names truncated after a file transfer.
+For example, 12345678901 is renamed to 12345678901.gz.
+A file name such as foo.tgz is left intact.
+.SH "SEE ALSO"
+gzip(1), znew(1), zmore(1), zgrep(1), zdiff(1), gzexe(1)
diff --git a/gnu/usr.bin/gzip/zgrep b/gnu/usr.bin/gzip/zgrep
new file mode 100644
index 0000000..fe5efb9
--- /dev/null
+++ b/gnu/usr.bin/gzip/zgrep
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+# zgrep -- a wrapper around a grep program that decompresses files as needed
+# Adapted from a version sent by Charles Levert <charles@comm.polymtl.ca>
+#
+# $FreeBSD$
+
+prog=`echo $0 | sed 's|.*/||'`
+case "$prog" in
+ *egrep) grep=${EGREP-egrep} ;;
+ *fgrep) grep=${FGREP-fgrep} ;;
+ *) grep=${GREP-grep} ;;
+esac
+A=
+fileno=0
+pat=""
+while test $# -ne 0; do
+ case "$1" in
+ -e | -f) opt="$opt $1"; shift; pat="$1"
+ if test "$grep" = grep; then # grep is buggy with -e on SVR4
+ grep=egrep
+ fi;;
+ -*) opt="$opt $1";;
+ *) if test -z "$pat"; then
+ pat="$1"
+ else
+ fileno=`expr $fileno + 1`
+ eval A$fileno=\$1
+ A="$A \"\$A$fileno\""
+ fi
+ ;;
+ esac
+ shift
+done
+
+if test -z "$pat"; then
+ echo "grep through gzip files"
+ echo "usage: $prog [grep_options] pattern [files]"
+ exit 1
+fi
+
+list=0
+silent=0
+op=`echo "$opt" | sed -e 's/ //g' -e 's/-//g'`
+case "$op" in
+ *l*) list=1
+esac
+case "$op" in
+ *h*) silent=1
+esac
+
+if test $fileno -eq 0; then
+ gzip -cdfq | $grep $opt "$pat"
+ exit $?
+fi
+eval set "$A" # files in $1, $2 ...
+
+res=0
+for i do
+ if test $list -eq 1; then
+ gzip -cdfq "$i" | $grep $opt "$pat" > /dev/null && echo $i
+ r=$?
+ elif test $# -eq 1 -o $silent -eq 1; then
+ gzip -cdfq "$i" | $grep $opt "$pat"
+ r=$?
+ else
+ gzip -cdfq "$i" | $grep $opt "$pat" | sed "s|^|${i}:|"
+ r=$?
+ fi
+ test "$r" -ne 0 && res="$r"
+done
+exit $res
diff --git a/gnu/usr.bin/gzip/zgrep.1 b/gnu/usr.bin/gzip/zgrep.1
new file mode 100644
index 0000000..a52a88a
--- /dev/null
+++ b/gnu/usr.bin/gzip/zgrep.1
@@ -0,0 +1,44 @@
+.TH ZGREP 1
+.SH NAME
+zgrep \- search possibly compressed files for a regular expression
+.SH SYNOPSIS
+.B zgrep
+[ grep_options ]
+.BI [\ -e\ ] " pattern"
+.IR filename ".\|.\|."
+.SH DESCRIPTION
+.IR Zgrep
+is used to invoke the
+.I grep
+on compress'ed or gzip'ed files. All options specified are passed directly to
+.I grep.
+If no file is specified, then the standard input is decompressed
+if necessary and fed to grep.
+Otherwise the given files are uncompressed if necessary and fed to
+.I grep.
+.PP
+If
+.I zgrep
+is invoked as
+.I zegrep
+or
+.I zfgrep
+then
+.I egrep
+or
+.I fgrep
+is used instead of
+.I grep.
+If the GREP environment variable is set,
+.I zgrep
+uses it as the
+.I grep
+program to be invoked. For example:
+
+ for sh: GREP=fgrep zgrep string files
+ for csh: (setenv GREP fgrep; zgrep string files)
+.SH AUTHOR
+Charles Levert (charles@comm.polymtl.ca)
+.SH "SEE ALSO"
+grep(1), egrep(1), fgrep(1), zdiff(1), zmore(1), znew(1), zforce(1),
+gzip(1), gzexe(1)
diff --git a/gnu/usr.bin/gzip/zgrep.getopt b/gnu/usr.bin/gzip/zgrep.getopt
new file mode 100644
index 0000000..e6811b7
--- /dev/null
+++ b/gnu/usr.bin/gzip/zgrep.getopt
@@ -0,0 +1,94 @@
+#!/bin/sh
+#
+# Copyright (c) April 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL [your name] OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# zgrep - search possibly compressed files for a regular expression
+#
+# $FreeBSD$
+
+
+PATH=/bin:/usr/bin:$PATH; export PATH
+
+# grep variant
+case "$0" in
+ *egrep) grep=${EGREP-egrep} ;;
+ *fgrep) grep=${FGREP-fgrep} ;;
+ *) grep=${GREP-grep} ;;
+esac
+
+gzip=gzip gzipopt="-cdfq" pattern= grepopt= files= line= header=
+
+# check options
+while getopts "0123456789A:B:CEFGVX:bce:f:hiLlnqsvwxy" option
+do
+ case "$option" in
+ e|f) pattern="-$option $OPTARG";; # -f file
+ l|L) line=-$option; grepopt="$grepopt -$option";;
+ h|q) header=-h; grepopt="$grepopt -$option";;
+ # rest
+ [0-9CEFGVbchiLlnqsvwxy]) grepopt="$grepopt -$option";;
+ [ABXef]) grepopt="$grepopt -$option $OPTARG";;
+ esac
+done
+shift $(($OPTIND - 1))
+
+# check pattern
+case X"$pattern" in
+ X) case $# in
+ 0) echo "usage: $0 [grep_options] pattern [files]"; exit 1;;
+ *) pattern=$1; shift;;
+ esac
+esac
+
+
+files="$@"
+# no shell loop neccessary for option -q or -h
+# and a single file or reading from stdin
+case "$header"X"$#" in
+ -h*|-q*|X0|X1) $gzip $gzipopt -- $files | $grep $grepopt -- "$pattern"
+ exit $?;;
+esac
+
+for f in $files
+do
+ case "$line" in
+ -l) if $gzip $gzipopt -- $f |
+ $grep $grepopt -- "$pattern" >/dev/null
+ then
+ echo $f
+ fi
+ ;;
+ -L) if $gzip $gzipopt -- $f |
+ $grep $grepopt -- "$pattern" >/dev/null; then :
+ else
+ echo $f
+ fi
+ ;;
+
+ *) $gzip $gzipopt -- $f | $grep $grepopt -- "$pattern" |
+ sed "s%^%${f}:%"
+ ;;
+ esac
+done
diff --git a/gnu/usr.bin/gzip/zgrep.libz b/gnu/usr.bin/gzip/zgrep.libz
new file mode 100644
index 0000000..3001efa
--- /dev/null
+++ b/gnu/usr.bin/gzip/zgrep.libz
@@ -0,0 +1,18 @@
+#!/bin/sh
+# Copyright (c) Dec 1997 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+# Public Domain.
+#
+# zgrep - Search possibly compressed files for a regular expression. This
+# version of zgrep(1) depend on a grep(1) linked with libz.
+#
+# $FreeBSD$
+
+PATH=/bin:/usr/bin; export PATH
+
+case "$0" in # grep variant
+ *egrep) grep=${EGREP-egrep};;
+ *fgrep) grep=${FGREP-fgrep};;
+ *) grep=${GREP-grep};;
+esac
+
+exec ${grep} -Z "$@"
diff --git a/gnu/usr.bin/gzip/zip.c b/gnu/usr.bin/gzip/zip.c
new file mode 100644
index 0000000..c5b985e
--- /dev/null
+++ b/gnu/usr.bin/gzip/zip.c
@@ -0,0 +1,117 @@
+/* zip.c -- compress files to the gzip or pkzip format
+ * Copyright (C) 1992-1993 Jean-loup Gailly
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License, see the file COPYING.
+ */
+
+#ifdef RCSID
+static char rcsid[] = "$FreeBSD$";
+#endif
+
+#include <ctype.h>
+#include <sys/types.h>
+
+#include "tailor.h"
+#include "gzip.h"
+#include "crypt.h"
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef NO_FCNTL_H
+# include <fcntl.h>
+#endif
+
+local ulg crc; /* crc on uncompressed file data */
+long header_bytes; /* number of bytes in gzip header */
+
+/* ===========================================================================
+ * Deflate in to out.
+ * IN assertions: the input and output buffers are cleared.
+ * The variables time_stamp and save_orig_name are initialized.
+ */
+int zip(in, out)
+ int in, out; /* input and output file descriptors */
+{
+ uch flags = 0; /* general purpose bit flags */
+ ush attr = 0; /* ascii/binary flag */
+ ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
+
+ ifd = in;
+ ofd = out;
+ outcnt = 0;
+
+ /* Write the header to the gzip file. See algorithm.doc for the format */
+
+ method = DEFLATED;
+ put_byte(GZIP_MAGIC[0]); /* magic header */
+ put_byte(GZIP_MAGIC[1]);
+ put_byte(DEFLATED); /* compression method */
+
+ if (save_orig_name) {
+ flags |= ORIG_NAME;
+ }
+ put_byte(flags); /* general flags */
+ put_long(time_stamp);
+
+ /* Write deflated file to zip file */
+ crc = updcrc(0, 0);
+
+ bi_init(out);
+ ct_init(&attr, &method);
+ lm_init(level, &deflate_flags);
+
+ put_byte((uch)deflate_flags); /* extra flags */
+ put_byte(OS_CODE); /* OS identifier */
+
+ if (save_orig_name) {
+ char *p = basename(ifname); /* Don't save the directory part. */
+ do {
+ put_char(*p);
+ } while (*p++);
+ }
+ header_bytes = (long)outcnt;
+
+ (void)deflate();
+
+#if !defined(NO_SIZE_CHECK) && !defined(RECORD_IO)
+ /* Check input size (but not in VMS -- variable record lengths mess it up)
+ * and not on MSDOS -- diet in TSR mode reports an incorrect file size)
+ */
+ if (ifile_size != -1L && isize != (ulg)ifile_size) {
+ Trace((stderr, " actual=%ld, read=%ld ", ifile_size, isize));
+ fprintf(stderr, "%s: %s: file size changed while zipping\n",
+ progname, ifname);
+ }
+#endif
+
+ /* Write the crc and uncompressed size */
+ put_long(crc);
+ put_long(isize);
+ header_bytes += 2*sizeof(long);
+
+ flush_outbuf();
+ return OK;
+}
+
+
+/* ===========================================================================
+ * Read a new buffer from the current input file, perform end-of-line
+ * translation, and update the crc and input file size.
+ * IN assertion: size >= 2 (for end-of-line translation)
+ */
+int file_read(buf, size)
+ char *buf;
+ unsigned size;
+{
+ unsigned len;
+
+ Assert(insize == 0, "inbuf not empty");
+
+ len = read(ifd, buf, size);
+ if (len == (unsigned)(-1) || len == 0) return (int)len;
+
+ crc = updcrc((uch*)buf, len);
+ isize += (ulg)len;
+ return (int)len;
+}
diff --git a/gnu/usr.bin/gzip/zmore b/gnu/usr.bin/gzip/zmore
new file mode 100644
index 0000000..f5c2d5f
--- /dev/null
+++ b/gnu/usr.bin/gzip/zmore
@@ -0,0 +1,52 @@
+#!/bin/sh
+#
+# $FreeBSD$
+
+if test "`echo -n a`" = "-n a"; then
+ # looks like a SysV system:
+ n1=''; n2='\c'
+else
+ n1='-n'; n2=''
+fi
+oldtty=`stty -g 2>/dev/null`
+if stty -cbreak 2>/dev/null; then
+ cb='cbreak'; ncb='-cbreak'
+else
+ # 'stty min 1' resets eof to ^a on both SunOS and SysV!
+ cb='min 1 -icanon'; ncb='icanon eof ^d'
+fi
+if test $? -eq 0 -a -n "$oldtty"; then
+ trap 'stty $oldtty 2>/dev/null; exit' 0 2 3 5 10 13 15
+else
+ trap 'stty $ncb echo 2>/dev/null; exit' 0 2 3 5 10 13 15
+fi
+
+if test $# = 0; then
+ if test -t 0; then
+ echo usage: zmore files...
+ else
+ gzip -cdfq | eval ${PAGER-more}
+ fi
+else
+ FIRST=1
+ for FILE
+ do
+ if test $FIRST -eq 0; then
+ echo $n1 "--More--(Next file: $FILE)$n2"
+ stty $cb -echo 2>/dev/null
+ ANS=`dd bs=1 count=1 2>/dev/null`
+ stty $ncb echo 2>/dev/null
+ echo " "
+ if test "$ANS" = 'e' -o "$ANS" = 'q'; then
+ exit
+ fi
+ fi
+ if test "$ANS" != 's'; then
+ echo "------> $FILE <------"
+ gzip -cdfq "$FILE" | eval ${PAGER-more}
+ fi
+ if test -t; then
+ FIRST=0
+ fi
+ done
+fi
diff --git a/gnu/usr.bin/gzip/zmore.1 b/gnu/usr.bin/gzip/zmore.1
new file mode 100644
index 0000000..b8157e5
--- /dev/null
+++ b/gnu/usr.bin/gzip/zmore.1
@@ -0,0 +1,147 @@
+.\" $FreeBSD$
+.\"
+.TH ZMORE 1
+.SH NAME
+zmore \- file perusal filter for crt viewing of compressed text
+.SH SYNOPSIS
+.B zmore
+[ name ... ]
+.SH DESCRIPTION
+.I Zmore
+is a filter which allows examination of compressed or plain text files
+one screenful at a time on a soft-copy terminal.
+.I zmore
+works on files compressed with
+.I compress, pack
+or
+.I gzip,
+and also on uncompressed files.
+If a file does not exist,
+.I zmore
+looks for a file of the same name with the addition of a .gz, .z or .Z suffix.
+.PP
+.I Zmore
+normally pauses after each screenful, printing --More--
+at the bottom of the screen.
+If the user then types a carriage return, one more line is displayed.
+If the user hits a space,
+another screenful is displayed. Other possibilities are enumerated later.
+.PP
+.I Zmore
+looks in the file
+.I /usr/share/misc/termcap
+to determine terminal characteristics,
+and to determine the default window size.
+On a terminal capable of displaying 24 lines,
+the default window size is 22 lines.
+To use a pager other than the default
+.I more,
+set environment variable PAGER to the name of the desired program, such as
+.I less.
+.PP
+Other sequences which may be typed when
+.I zmore
+pauses, and their effects, are as follows (\fIi\fP is an optional integer
+argument, defaulting to 1) :
+.PP
+.IP \fIi\|\fP<space>
+display
+.I i
+more lines, (or another screenful if no argument is given)
+.PP
+.IP ^D
+display 11 more lines (a ``scroll'').
+If
+.I i
+is given, then the scroll size is set to \fIi\|\fP.
+.PP
+.IP d
+same as ^D (control-D)
+.PP
+.IP \fIi\|\fPz
+same as typing a space except that \fIi\|\fP, if present, becomes the new
+window size. Note that the window size reverts back to the default at the
+end of the current file.
+.PP
+.IP \fIi\|\fPs
+skip \fIi\|\fP lines and print a screenful of lines
+.PP
+.IP \fIi\|\fPf
+skip \fIi\fP screenfuls and print a screenful of lines
+.PP
+.IP "q or Q"
+quit reading the current file; go on to the next (if any)
+.PP
+.IP "e or q"
+When the prompt --More--(Next file:
+.IR file )
+is printed, this command causes zmore to exit.
+.PP
+.IP s
+When the prompt --More--(Next file:
+.IR file )
+is printed, this command causes zmore to skip the next file and continue.
+.PP
+.IP =
+Display the current line number.
+.PP
+.IP \fIi\|\fP/expr
+search for the \fIi\|\fP-th occurrence of the regular expression \fIexpr.\fP
+If the pattern is not found,
+.I zmore
+goes on to the next file (if any).
+Otherwise, a screenful is displayed, starting two lines before the place
+where the expression was found.
+The user's erase and kill characters may be used to edit the regular
+expression.
+Erasing back past the first column cancels the search command.
+.PP
+.IP \fIi\|\fPn
+search for the \fIi\|\fP-th occurrence of the last regular expression entered.
+.PP
+.IP !command
+invoke a shell with \fIcommand\|\fP.
+The character `!' in "command" are replaced with the
+previous shell command. The sequence "\\!" is replaced by "!".
+.PP
+.IP ":q or :Q"
+quit reading the current file; go on to the next (if any)
+(same as q or Q).
+.PP
+.IP .
+(dot) repeat the previous command.
+.PP
+The commands take effect immediately, i.e., it is not necessary to
+type a carriage return.
+Up to the time when the command character itself is given,
+the user may hit the line kill character to cancel the numerical
+argument being formed.
+In addition, the user may hit the erase character to redisplay the
+--More-- message.
+.PP
+At any time when output is being sent to the terminal, the user can
+hit the quit key (normally control\-\\).
+.I Zmore
+will stop sending output, and will display the usual --More--
+prompt.
+The user may then enter one of the above commands in the normal manner.
+Unfortunately, some output is lost when this is done, due to the
+fact that any characters waiting in the terminal's output queue
+are flushed when the quit signal occurs.
+.PP
+The terminal is set to
+.I noecho
+mode by this program so that the output can be continuous.
+What you type will thus not show on your terminal, except for the / and !
+commands.
+.PP
+If the standard output is not a teletype, then
+.I zmore
+acts just like
+.I zcat,
+except that a header is printed before each file.
+.SH FILES
+.DT
+/etc/termcap Terminal data base
+.SH "SEE ALSO"
+more(1), gzip(1), zdiff(1), zgrep(1), znew(1), zforce(1), gzexe(1)
diff --git a/gnu/usr.bin/gzip/znew b/gnu/usr.bin/gzip/znew
new file mode 100644
index 0000000..52b0ae9
--- /dev/null
+++ b/gnu/usr.bin/gzip/znew
@@ -0,0 +1,150 @@
+#!/bin/sh
+#
+# $FreeBSD$
+
+check=0
+pipe=0
+opt=
+files=
+keep=0
+res=0
+old=0
+new=0
+block=1024
+# block is the disk block size (best guess, need not be exact)
+
+warn="(does not preserve modes and timestamp)"
+tmp=`mktemp -d -t znew`
+if test -z "$tmp"; then
+ echo znew: could not create temporary directory
+ exit 1
+fi
+echo hi > $tmp/1
+echo hi > $tmp/2
+if test -z "`(${CPMOD-cpmod} $tmp/1 $tmp/2) 2>&1`"; then
+ cpmod=${CPMOD-cpmod}
+ warn=""
+fi
+
+if test -z "$cpmod" && ${TOUCH-touch} -r $tmp/1 $tmp/2 2>/dev/null; then
+ cpmod="${TOUCH-touch}"
+ cpmodarg="-r"
+ warn="(does not preserve file modes)"
+fi
+
+# check if GZIP env. variable uses -S or --suffix
+gzip -q $tmp/1
+ext=`echo $tmp/1* | sed "s|$tmp/1||"`
+rm -rf $tmp
+if test -z "$ext"; then
+ echo znew: error determining gzip extension
+ exit 1
+fi
+if test "$ext" = ".Z"; then
+ echo znew: cannot use .Z as gzip extension.
+ exit 1
+fi
+
+for arg
+do
+ case "$arg" in
+ -*) opt="$opt $arg"; shift;;
+ *) break;;
+ esac
+done
+
+if test $# -eq 0; then
+ echo "recompress .Z files into $ext (gzip) files"
+ echo usage: `echo $0 | sed 's,^.*/,,'` "[-tv9KP]" file.Z...
+ echo " -t tests the new files before deleting originals"
+ echo " -v be verbose"
+ echo " -9 use the slowest compression method (optimal compression)"
+ echo " -K keep a .Z file when it is smaller than the $ext file"
+ echo " -P use pipes for the conversion $warn"
+ exit 1
+fi
+
+opt=`echo "$opt" | sed -e 's/ //g' -e 's/-//g'`
+case "$opt" in
+ *t*) check=1; opt=`echo "$opt" | sed 's/t//g'`
+esac
+case "$opt" in
+ *K*) keep=1; opt=`echo "$opt" | sed 's/K//g'`
+esac
+case "$opt" in
+ *P*) pipe=1; opt=`echo "$opt" | sed 's/P//g'`
+esac
+if test -n "$opt"; then
+ opt="-$opt"
+fi
+
+for i do
+ n=`echo $i | sed 's/.Z$//'`
+ if test ! -f "$n.Z" ; then
+ echo $n.Z not found
+ res=1; continue
+ fi
+ test $keep -eq 1 && old=`wc -c < "$n.Z"`
+ if test $pipe -eq 1; then
+ if gzip -d < "$n.Z" | gzip $opt > "$n$ext"; then
+ # Copy file attributes from old file to new one, if possible.
+ test -n "$cpmod" && $cpmod $cpmodarg "$n.Z" "$n$ext" 2> /dev/null
+ else
+ echo error while recompressing $n.Z
+ res=1; continue
+ fi
+ else
+ if test $check -eq 1; then
+ if cp -p "$n.Z" "$n.$$" 2> /dev/null || cp "$n.Z" "$n.$$"; then
+ :
+ else
+ echo cannot backup "$n.Z"
+ res=1; continue
+ fi
+ fi
+ if gzip -d "$n.Z"; then
+ :
+ else
+ test $check -eq 1 && mv "$n.$$" "$n.Z"
+ echo error while uncompressing $n.Z
+ res=1; continue
+ fi
+ if gzip $opt "$n"; then
+ :
+ else
+ if test $check -eq 1; then
+ mv "$n.$$" "$n.Z" && rm -f "$n"
+ echo error while recompressing $n
+ else
+ # compress $n (might be dangerous if disk full)
+ echo error while recompressing $n, left uncompressed
+ fi
+ res=1; continue
+ fi
+ fi
+ test $keep -eq 1 && new=`wc -c < "$n$ext"`
+ if test $keep -eq 1 -a `expr \( $old + $block - 1 \) / $block` -lt \
+ `expr \( $new + $block - 1 \) / $block`; then
+ if test $pipe -eq 1; then
+ rm -f "$n$ext"
+ elif test $check -eq 1; then
+ mv "$n.$$" "$n.Z" && rm -f "$n$ext"
+ else
+ gzip -d "$n$ext" && compress "$n" && rm -f "$n$ext"
+ fi
+ echo "$n.Z smaller than $n$ext -- unchanged"
+
+ elif test $check -eq 1; then
+ if gzip -t "$n$ext" ; then
+ rm -f "$n.$$" "$n.Z"
+ else
+ test $pipe -eq 0 && mv "$n.$$" "$n.Z"
+ rm -f "$n$ext"
+ echo error while testing $n$ext, $n.Z unchanged
+ res=1; continue
+ fi
+ elif test $pipe -eq 1; then
+ rm -f "$n.Z"
+ fi
+done
+exit $res
diff --git a/gnu/usr.bin/gzip/znew.1 b/gnu/usr.bin/gzip/znew.1
new file mode 100644
index 0000000..5cfb472
--- /dev/null
+++ b/gnu/usr.bin/gzip/znew.1
@@ -0,0 +1,39 @@
+.TH ZNEW 1
+.SH NAME
+znew \- recompress .Z files to .gz files
+.SH SYNOPSIS
+.B znew
+[ -ftv9PK] [ name.Z ... ]
+.SH DESCRIPTION
+.I Znew
+recompresses files from .Z (compress) format to .gz (gzip) format.
+If you want to recompress a file already in gzip format, rename the file
+to force a .Z extension then apply znew.
+.SH OPTIONS
+.TP
+.B \-f
+Force recompression from .Z to .gz format even if a .gz file already exists.
+.TP
+.B \-t
+Tests the new files before deleting originals.
+.TP
+.B \-v
+Verbose. Display the name and percentage reduction for each file compressed.
+.TP
+.B \-9
+Use the slowest compression method (optimal compression).
+.TP
+.B \-P
+Use pipes for the conversion to reduce disk space usage.
+.TP
+.B \-K
+Keep a .Z file when it is smaller than the .gz file
+.SH "SEE ALSO"
+gzip(1), zmore(1), zdiff(1), zgrep(1), zforce(1), gzexe(1), compress(1)
+.SH BUGS
+.I Znew
+does not maintain the time stamp with the -P option if
+.I cpmod(1)
+is not available and
+.I touch(1)
+does not support the -r option.
diff --git a/gnu/usr.bin/ld/Makefile b/gnu/usr.bin/ld/Makefile
new file mode 100644
index 0000000..a52f510
--- /dev/null
+++ b/gnu/usr.bin/ld/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+#
+
+RTLD= ${.CURDIR}/../../../libexec/rtld-aout
+
+PROG= ld
+BINDIR= /usr/libexec/aout
+MAN= ld.1aout
+SRCS= ld.c symbol.c lib.c shlib.c warnings.c support.c rrs.c xbits.c md.c \
+ cplus-dem.c
+CFLAGS+= -I${.CURDIR} -I${RTLD} -I${RTLD}/${MACHINE_ARCH} \
+ -DIN_GCC -DDEMANGLE_CPLUSPLUS -DFREEBSD_AOUT
+NOSHARED?= yes
+
+.PATH: ${RTLD} ${RTLD}/${MACHINE_ARCH}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/ld/PORTING b/gnu/usr.bin/ld/PORTING
new file mode 100644
index 0000000..4a91ff8
--- /dev/null
+++ b/gnu/usr.bin/ld/PORTING
@@ -0,0 +1,194 @@
+$FreeBSD$
+
+This document describes some of the machine dependent parts in ld(1) and rtld(?)
+Most of the machine dependencies are a result of different ways in which
+relocation information is conveyed in an architecture's object files.
+Especially RISC architectures are likely candidates to have deviated from the
+traditional relocation record structure due a tendency to use odd sized
+"bitfields" to denote immediate operands within their fixed size instructions.
+
+Also, there may be slight differences in the model used for Position
+Independent Code generation by the compiler.
+
+Lastly, both ld and rtld must fiddle with actual machine instructions to setup
+a transfer vector to accommodate PIC code and dynamic linking.
+
+
+Machine dependent macros and data structures.
+
+typedef struct jmpslot { ... } jmpslot_t;
+
+ The Procedure Linkage Table (PLT) is an array of these structures.
+ The structure contains room for a control transfer instruction
+ and a relocation index. md_make_jmpslot() and md_fix_jmpslot()
+ are responsible for filling these in.
+
+JMPSLOT_NEEDS_RELOC()
+
+ Macro indicating whether or not a jmpslot entry needs a run-time
+ relocation when ld has already resolved the symbolic reference
+ (eg. when `-Bsymbolic' was given). Usually the case if the control
+ transfer instruction is PC relative or something.
+
+RELOC_STATICS_THROUGH_GOT_P(r)
+
+ Predicate taking a `struct relocation_info *' as an argument. It
+ decides whether variables with file scope are addressed relative to
+ the start Global Offset Table (1) or an entry in GOT must be
+ allocated (0). The compiler has a say in this.
+
+
+Some other random macros:
+
+BAD_MID(ex)
+
+ Tells whether the machine ID in an input file header is acceptable.
+
+N_SET_FLAG(ex,f)
+
+ Set flags F in a.out header. Must account for possible non-NetBSD
+ headers; QMAGIC is still a documented ld output format.
+
+N_IS_DYNAMIC(ex)
+
+ Return true if this appears to be a dynamically linked object.
+
+#define relocation_info reloc_info_<machine>
+
+ Define (possibly machine dependent) relocation record format.
+ Should convert to a typedef someday for greater opacity.
+
+md_got_reloc(r)
+
+ Adjustment to be applied to the relocation value of references
+ to "_GLOBAL_OFFSET_TABLE". It's here because of Sun's sparc as(1),
+ (it's is a *bug*), and could have been `#ifdef SUN_COMPAT' if I
+ had not let it slip into NetBSD's gas for compatibility.
+
+md_get_rt_segment_addend(r,a)
+
+ Another SunOS bug workaround.
+
+
+The macros below have defaults defined in ld.h for the traditional relocation
+structure format; each takes a `struct relocation_info *' argument (see
+ld.h for more detailed comments):
+
+RELOC_ADDRESS(r) - the address at which to relocate
+RELOC_EXTERN_P(r) - relocation for external symbol
+RELOC_TYPE(r) - segment (text/data/bss), non-external relocs
+RELOC_SYMBOL(r) - symbol index, external relocs
+RELOC_MEMORY_SUB_P(r) - relocation involves something to subtract
+RELOC_MEMORY_ADD_P(r) - relocation involves something to add
+RELOC_ADD_EXTRA(r) - <disused> (moved into MD files)
+RELOC_PCREL_P(r) - relocation is PC relative
+RELOC_VALUE_RIGHTSHIFT(r) - <disused>
+RELOC_TARGET_SIZE(r) - size (in bytes) of relocated value
+RELOC_TARGET_BITPOS(r) - <disused> (moved into MD files)
+RELOC_TARGET_BITSIZE(r) - <disused> (moved into MD files)
+RELOC_JMPTAB_P(r) - relocation is for a PLT entry
+RELOC_BASEREL_P(r) - relocation is for a GOT entry
+RELOC_RELATIVE_P(r) - relocation is load address relative
+RELOC_COPY_P(r) - relocation involves an initialization
+RELOC_INIT_SEGMENT_RELOC(r) - initialize a relocation record pertaining to
+ a segment; traditional archs can use bzero().
+RELOC_LAZY_P(r) - (run-time) resolution can be lazy.
+CHECK_GOT_RELOC(r) - consistency check on relocations involving
+ the "_GLOBAL_OFFSET_TABLE" symbol
+
+
+
+Things which are currently defined as routines in <machine>/md.c:
+
+
+md_init_header(struct exec *hp, int magic, int flags)
+
+ Initializes the output file header. Straightforward, unless
+ multiple OS'es are supported.
+
+
+md_swap*_exec_hdr(struct exec *)
+
+ Input/output a.out header in target byte-order.
+
+
+md_swap*_reloc(struct relocation_info *, n)
+
+ Input/output N relocation records in target byte-order.
+
+
+md_get_addend(struct relocation_info *rp, char *addr)
+
+ Return a relocation addend. Traditionally found in the object file
+ at address ADDR. The relocation record determines the data width
+ in bytes (using RELOC_TARGET_SIZE()).
+
+md_relocate(struct relocation_info *rp, long reloc, char *addr,
+ int relocatable_output)
+
+ Perform a relocation at the given address, usually by entering
+ the specified value RELOC into the object file. Some architectures
+ may store the relocation in RP when RELOCATABLE_OUTPUT is set.
+ Again, the byte size of the relocation value is determined from
+ RP through RELOC_TARGET_SIZE().
+
+md_make_reloc(struct relocation_info *rp, int type)
+
+ Construct the machine dependent part of a relocation record used
+ for run-time relocation. Sets RP's type field or one or more
+ bitfields according to TYPE which is ld's internal relocation
+ representation of the type of (run-time) relocation. TYPE is a
+ combination of the following bits:
+
+ RELTYPE_EXTERN - relocation is for unresolved symbol
+ RELTYPE_JMPSLOT - relocation is for a PLT entry
+ RELTYPE_BASEREL - <not used>
+ RELTYPE_RELATIVE - relocation is load address relative
+ RELTYPE_COPY - relocation is an initalization
+
+md_make_jmpreloc(struct relocation_info *rp, *r, int type)
+
+ Set up a run-time relocation record pertaining to a jmpslot.
+ This usually sets a bit or a relocation type dedicated to jmpslot
+ relocations. R is the relocation record to be updated (ie. the
+ run-time relocation record), while RP points at the relocation
+ record from the object file on behalf of which we allocated a
+ PLT entry. RP may not be needed.
+
+md_make_gotreloc(struct relocation_info *rp, *r, int type)
+
+ Set up a run-time relocation record pertaining to a GOT entry.
+ This usually sets a bit or a relocation type dedicated to GOT
+ relocations. R is the relocation record to be updated (ie. the
+ run-time relocation record), while RP points at the relocation
+ record from the object file on behalf of which we allocated a
+ GOT entry.
+
+md_make_cpyreloc(struct relocation_info *rp, *r)
+
+ Mark the relocation record as pertaining to a location that needs
+ run-time initializing from some shared object source.
+ R and RP same as above.
+
+md_make_jmpslot(jmpslot_t *sp, long offset, long index)
+
+ Construct a jmpslot, ie. fill in the machine opcodes that comprise
+ a transfer to slot 0 of the PLT. OFFSET is the location of SP
+ relative to the start of the PLT (ie. (int)sp - (int)&PLT[0] ).
+ INDEX is the entry in the run-time relocation record table which
+ determines what symbol this jmpslot is supposed to resolve.
+
+md_fix_jmpslot(jmpslot_t *sp, long offset, long addr)
+
+ Fix up a jmpslot so that it will transfer directly to ADDR
+ in stead of to PLT[0]. OFFSET has the same meaning as in
+ md_make_jmpslot(). This function is called by binder() after
+ it has resolved a symbol into a (run-time) address.
+
+md_set_breakpoint(long where, long *savep)
+
+ Set a breakpoint. Used when run under a debugger. The breakpoint
+ instruction is to be set at location WHERE. The original contents
+ of *WHERE is to be saved in *SAVEP.
+
+
diff --git a/gnu/usr.bin/ld/cplus-dem.c b/gnu/usr.bin/ld/cplus-dem.c
new file mode 100644
index 0000000..de88deb
--- /dev/null
+++ b/gnu/usr.bin/ld/cplus-dem.c
@@ -0,0 +1,3003 @@
+/* Demangler for GNU C++
+ Copyright 1989, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.uucp)
+ Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
+
+ This file imports xmalloc and xrealloc, which are like malloc and
+ realloc except that they generate a fatal error if there is no
+ available memory. */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <demangle.h>
+#undef CURRENT_DEMANGLING_STYLE
+#define CURRENT_DEMANGLING_STYLE work->options
+
+extern char *xmalloc PARAMS((unsigned));
+extern char *xrealloc PARAMS((char *, unsigned));
+
+char *
+mystrstr (s1, s2)
+ char *s1, *s2;
+{
+ register char *p = s1;
+ register int len = strlen (s2);
+
+ for (; (p = strchr (p, *s2)) != 0; p++)
+ {
+ if (strncmp (p, s2, len) == 0)
+ {
+ return (p);
+ }
+ }
+ return (0);
+}
+
+/* In order to allow a single demangler executable to demangle strings
+ using various common values of CPLUS_MARKER, as well as any specific
+ one set at compile time, we maintain a string containing all the
+ commonly used ones, and check to see if the marker we are looking for
+ is in that string. CPLUS_MARKER is usually '$' on systems where the
+ assembler can deal with that. Where the assembler can't, it's usually
+ '.' (but on many systems '.' is used for other things). We put the
+ current defined CPLUS_MARKER first (which defaults to '$'), followed
+ by the next most common value, followed by an explicit '$' in case
+ the value of CPLUS_MARKER is not '$'.
+
+ We could avoid this if we could just get g++ to tell us what the actual
+ cplus marker character is as part of the debug information, perhaps by
+ ensuring that it is the character that terminates the gcc<n>_compiled
+ marker symbol (FIXME). */
+
+#if !defined (CPLUS_MARKER)
+#define CPLUS_MARKER '$'
+#endif
+
+enum demangling_styles current_demangling_style = gnu_demangling;
+
+static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
+
+void
+set_cplus_marker_for_demangling (ch)
+ int ch;
+{
+ cplus_markers[0] = ch;
+}
+
+/* Stuff that is shared between sub-routines.
+ * Using a shared structure allows cplus_demangle to be reentrant. */
+
+struct work_stuff
+{
+ int options;
+ char **typevec;
+ int ntypes;
+ int typevec_size;
+ int constructor;
+ int destructor;
+ int static_type; /* A static member function */
+ int const_type; /* A const member function */
+};
+
+#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
+#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
+
+static const struct optable
+{
+ const char *in;
+ const char *out;
+ int flags;
+} optable[] = {
+ {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
+ {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
+ {"new", " new", 0}, /* old (1.91, and 1.x) */
+ {"delete", " delete", 0}, /* old (1.91, and 1.x) */
+ {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */
+ {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */
+ {"as", "=", DMGL_ANSI}, /* ansi */
+ {"ne", "!=", DMGL_ANSI}, /* old, ansi */
+ {"eq", "==", DMGL_ANSI}, /* old, ansi */
+ {"ge", ">=", DMGL_ANSI}, /* old, ansi */
+ {"gt", ">", DMGL_ANSI}, /* old, ansi */
+ {"le", "<=", DMGL_ANSI}, /* old, ansi */
+ {"lt", "<", DMGL_ANSI}, /* old, ansi */
+ {"plus", "+", 0}, /* old */
+ {"pl", "+", DMGL_ANSI}, /* ansi */
+ {"apl", "+=", DMGL_ANSI}, /* ansi */
+ {"minus", "-", 0}, /* old */
+ {"mi", "-", DMGL_ANSI}, /* ansi */
+ {"ami", "-=", DMGL_ANSI}, /* ansi */
+ {"mult", "*", 0}, /* old */
+ {"ml", "*", DMGL_ANSI}, /* ansi */
+ {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
+ {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
+ {"convert", "+", 0}, /* old (unary +) */
+ {"negate", "-", 0}, /* old (unary -) */
+ {"trunc_mod", "%", 0}, /* old */
+ {"md", "%", DMGL_ANSI}, /* ansi */
+ {"amd", "%=", DMGL_ANSI}, /* ansi */
+ {"trunc_div", "/", 0}, /* old */
+ {"dv", "/", DMGL_ANSI}, /* ansi */
+ {"adv", "/=", DMGL_ANSI}, /* ansi */
+ {"truth_andif", "&&", 0}, /* old */
+ {"aa", "&&", DMGL_ANSI}, /* ansi */
+ {"truth_orif", "||", 0}, /* old */
+ {"oo", "||", DMGL_ANSI}, /* ansi */
+ {"truth_not", "!", 0}, /* old */
+ {"nt", "!", DMGL_ANSI}, /* ansi */
+ {"postincrement","++", 0}, /* old */
+ {"pp", "++", DMGL_ANSI}, /* ansi */
+ {"postdecrement","--", 0}, /* old */
+ {"mm", "--", DMGL_ANSI}, /* ansi */
+ {"bit_ior", "|", 0}, /* old */
+ {"or", "|", DMGL_ANSI}, /* ansi */
+ {"aor", "|=", DMGL_ANSI}, /* ansi */
+ {"bit_xor", "^", 0}, /* old */
+ {"er", "^", DMGL_ANSI}, /* ansi */
+ {"aer", "^=", DMGL_ANSI}, /* ansi */
+ {"bit_and", "&", 0}, /* old */
+ {"ad", "&", DMGL_ANSI}, /* ansi */
+ {"aad", "&=", DMGL_ANSI}, /* ansi */
+ {"bit_not", "~", 0}, /* old */
+ {"co", "~", DMGL_ANSI}, /* ansi */
+ {"call", "()", 0}, /* old */
+ {"cl", "()", DMGL_ANSI}, /* ansi */
+ {"alshift", "<<", 0}, /* old */
+ {"ls", "<<", DMGL_ANSI}, /* ansi */
+ {"als", "<<=", DMGL_ANSI}, /* ansi */
+ {"arshift", ">>", 0}, /* old */
+ {"rs", ">>", DMGL_ANSI}, /* ansi */
+ {"ars", ">>=", DMGL_ANSI}, /* ansi */
+ {"component", "->", 0}, /* old */
+ {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
+ {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
+ {"indirect", "*", 0}, /* old */
+ {"method_call", "->()", 0}, /* old */
+ {"addr", "&", 0}, /* old (unary &) */
+ {"array", "[]", 0}, /* old */
+ {"vc", "[]", DMGL_ANSI}, /* ansi */
+ {"compound", ", ", 0}, /* old */
+ {"cm", ", ", DMGL_ANSI}, /* ansi */
+ {"cond", "?:", 0}, /* old */
+ {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
+ {"max", ">?", 0}, /* old */
+ {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
+ {"min", "<?", 0}, /* old */
+ {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
+ {"nop", "", 0}, /* old (for operator=) */
+ {"rm", "->*", DMGL_ANSI} /* ansi */
+};
+
+
+typedef struct string /* Beware: these aren't required to be */
+{ /* '\0' terminated. */
+ char *b; /* pointer to start of string */
+ char *p; /* pointer after last character */
+ char *e; /* pointer after end of allocated space */
+} string;
+
+#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
+#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
+ string_prepend(str, " ");}
+#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
+ string_append(str, " ");}
+
+#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
+#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
+
+/* Prototypes for local functions */
+
+static char *
+mop_up PARAMS ((struct work_stuff *, string *, int));
+
+#if 0
+static int
+demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *));
+#endif
+
+static int
+demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
+ string *));
+
+static int
+demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
+ int, int));
+
+static int
+demangle_class PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+gnu_special PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+arm_special PARAMS ((struct work_stuff *, const char **, string *));
+
+static void
+string_need PARAMS ((string *, int));
+
+static void
+string_delete PARAMS ((string *));
+
+static void
+string_init PARAMS ((string *));
+
+static void
+string_clear PARAMS ((string *));
+
+#if 0
+static int
+string_empty PARAMS ((string *));
+#endif
+
+static void
+string_append PARAMS ((string *, const char *));
+
+static void
+string_appends PARAMS ((string *, string *));
+
+static void
+string_appendn PARAMS ((string *, const char *, int));
+
+static void
+string_prepend PARAMS ((string *, const char *));
+
+static void
+string_prependn PARAMS ((string *, const char *, int));
+
+static int
+get_count PARAMS ((const char **, int *));
+
+static int
+consume_count PARAMS ((const char **));
+
+static int
+demangle_args PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+do_type PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+do_arg PARAMS ((struct work_stuff *, const char **, string *));
+
+static void
+demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
+ const char *));
+
+static void
+remember_type PARAMS ((struct work_stuff *, const char *, int));
+
+static void
+forget_types PARAMS ((struct work_stuff *));
+
+static void
+string_prepends PARAMS ((string *, string *));
+
+/* Translate count to integer, consuming tokens in the process.
+ Conversion terminates on the first non-digit character.
+ Trying to consume something that isn't a count results in
+ no consumption of input and a return of 0. */
+
+static int
+consume_count (type)
+ const char **type;
+{
+ int count = 0;
+
+ while (isdigit (**type))
+ {
+ count *= 10;
+ count += **type - '0';
+ (*type)++;
+ }
+ return (count);
+}
+
+int
+cplus_demangle_opname (opname, result, options)
+ char *opname;
+ char *result;
+ int options;
+{
+ int len, i, len1, ret;
+ string type;
+ struct work_stuff work[1];
+ const char *tem;
+
+ len = strlen(opname);
+ result[0] = '\0';
+ ret = 0;
+ work->options = options;
+
+ if (opname[0] == '_' && opname[1] == '_'
+ && opname[2] == 'o' && opname[3] == 'p')
+ {
+ /* ANSI. */
+ /* type conversion operator. */
+ tem = opname + 4;
+ if (do_type (work, &tem, &type))
+ {
+ strcat (result, "operator ");
+ strncat (result, type.b, type.p - type.b);
+ string_delete (&type);
+ ret = 1;
+ }
+ }
+ else if (opname[0] == '_' && opname[1] == '_'
+ && opname[2] >= 'a' && opname[2] <= 'z'
+ && opname[3] >= 'a' && opname[3] <= 'z')
+ {
+ if (opname[4] == '\0')
+ {
+ /* Operator. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 2
+ && memcmp (optable[i].in, opname + 2, 2) == 0)
+ {
+ strcat (result, "operator");
+ strcat (result, optable[i].out);
+ ret = 1;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (opname[2] == 'a' && opname[5] == '\0')
+ {
+ /* Assignment. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 3
+ && memcmp (optable[i].in, opname + 2, 3) == 0)
+ {
+ strcat (result, "operator");
+ strcat (result, optable[i].out);
+ ret = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (len >= 3
+ && opname[0] == 'o'
+ && opname[1] == 'p'
+ && strchr (cplus_markers, opname[2]) != NULL)
+ {
+ /* see if it's an assignment expression */
+ if (len >= 10 /* op$assign_ */
+ && memcmp (opname + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ len1 = len - 10;
+ if (strlen (optable[i].in) == len1
+ && memcmp (optable[i].in, opname + 10, len1) == 0)
+ {
+ strcat (result, "operator");
+ strcat (result, optable[i].out);
+ strcat (result, "=");
+ ret = 1;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ len1 = len - 3;
+ if (strlen (optable[i].in) == len1
+ && memcmp (optable[i].in, opname + 3, len1) == 0)
+ {
+ strcat (result, "operator");
+ strcat (result, optable[i].out);
+ ret = 1;
+ break;
+ }
+ }
+ }
+ }
+ else if (len >= 5 && memcmp (opname, "type", 4) == 0
+ && strchr (cplus_markers, opname[4]) != NULL)
+ {
+ /* type conversion operator */
+ tem = opname + 5;
+ if (do_type (work, &tem, &type))
+ {
+ strcat (result, "operator ");
+ strncat (result, type.b, type.p - type.b);
+ string_delete (&type);
+ ret = 1;
+ }
+ }
+ return ret;
+
+}
+/* Takes operator name as e.g. "++" and returns mangled
+ operator name (e.g. "postincrement_expr"), or NULL if not found.
+
+ If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
+ if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
+
+char *
+cplus_mangle_opname (opname, options)
+ char *opname;
+ int options;
+{
+ int i;
+ int len;
+
+ len = strlen (opname);
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].out) == len
+ && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
+ && memcmp (optable[i].out, opname, len) == 0)
+ return ((char *)optable[i].in);
+ }
+ return (0);
+}
+
+/* check to see whether MANGLED can match TEXT in the first TEXT_LEN
+ characters. */
+
+int cplus_match (mangled, text, text_len)
+ const char *mangled;
+ char *text;
+ int text_len;
+{
+ if (strncmp (mangled, text, text_len) != 0) {
+ return(0); /* cannot match either */
+ } else {
+ return(1); /* matches mangled, may match demangled */
+ }
+}
+
+/* char *cplus_demangle (const char *mangled, int options)
+
+ If MANGLED is a mangled function name produced by GNU C++, then
+ a pointer to a malloced string giving a C++ representation
+ of the name will be returned; otherwise NULL will be returned.
+ It is the caller's responsibility to free the string which
+ is returned.
+
+ The OPTIONS arg may contain one or more of the following bits:
+
+ DMGL_ANSI ANSI qualifiers such as `const' and `void' are
+ included.
+ DMGL_PARAMS Function parameters are included.
+
+ For example,
+
+ cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", 0) => "A::foo"
+
+ cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", 0) => "A::foo"
+
+ Note that any leading underscores, or other such characters prepended by
+ the compilation system, are presumed to have already been stripped from
+ MANGLED. */
+
+char *
+cplus_demangle (mangled, options)
+ const char *mangled;
+ int options;
+{
+ string decl;
+ int success = 0;
+ struct work_stuff work[1];
+ char *demangled = NULL;
+
+ if ((mangled != NULL) && (*mangled != '\0'))
+ {
+ memset ((char *) work, 0, sizeof (work));
+ work -> options = options;
+ if ((work->options & DMGL_STYLE_MASK) == 0)
+ work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
+
+ string_init (&decl);
+
+ /* First check to see if gnu style demangling is active and if the
+ string to be demangled contains a CPLUS_MARKER. If so, attempt to
+ recognize one of the gnu special forms rather than looking for a
+ standard prefix. In particular, don't worry about whether there
+ is a "__" string in the mangled string. Consider "_$_5__foo" for
+ example. */
+
+ if ((AUTO_DEMANGLING || GNU_DEMANGLING))
+ {
+ success = gnu_special (work, &mangled, &decl);
+ }
+ if (!success)
+ {
+ success = demangle_prefix (work, &mangled, &decl);
+ }
+ if (success && (*mangled != '\0'))
+ {
+ success = demangle_signature (work, &mangled, &decl);
+ }
+ if (work->constructor == 2)
+ {
+ string_prepend(&decl, "global constructors keyed to ");
+ work->constructor = 0;
+ }
+ else if (work->destructor == 2)
+ {
+ string_prepend(&decl, "global destructors keyed to ");
+ work->destructor = 0;
+ }
+ demangled = mop_up (work, &decl, success);
+ }
+ return (demangled);
+}
+
+static char *
+mop_up (work, declp, success)
+ struct work_stuff *work;
+ string *declp;
+ int success;
+{
+ char *demangled = NULL;
+
+ /* Discard the remembered types, if any. */
+
+ forget_types (work);
+ if (work -> typevec != NULL)
+ {
+ free ((char *) work -> typevec);
+ }
+
+ /* If demangling was successful, ensure that the demangled string is null
+ terminated and return it. Otherwise, free the demangling decl. */
+
+ if (!success)
+ {
+ string_delete (declp);
+ }
+ else
+ {
+ string_appendn (declp, "", 1);
+ demangled = declp -> b;
+ }
+ return (demangled);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_signature -- demangle the signature part of a mangled name
+
+SYNOPSIS
+
+ static int
+ demangle_signature (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+DESCRIPTION
+
+ Consume and demangle the signature portion of the mangled name.
+
+ DECLP is the string where demangled output is being built. At
+ entry it contains the demangled root name from the mangled name
+ prefix. I.E. either a demangled operator name or the root function
+ name. In some special cases, it may contain nothing.
+
+ *MANGLED points to the current unconsumed location in the mangled
+ name. As tokens are consumed and demangling is performed, the
+ pointer is updated to continuously point at the next token to
+ be consumed.
+
+ Demangling GNU style mangled names is nasty because there is no
+ explicit token that marks the start of the outermost function
+ argument list.
+*/
+
+static int
+demangle_signature (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 1;
+ int func_done = 0;
+ int expect_func = 0;
+ const char *oldmangled = NULL;
+ string trawname;
+ string tname;
+
+ while (success && (**mangled != '\0'))
+ {
+ switch (**mangled)
+ {
+ case 'Q':
+ oldmangled = *mangled;
+ success = demangle_qualified (work, mangled, declp, 1, 0);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
+
+ case 'S':
+ /* Static member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> static_type = 1;
+ break;
+
+ case 'C':
+ /* a const member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> const_type = 1;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ success = demangle_class (work, mangled, declp);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
+
+ case 'F':
+ /* Function */
+ /* ARM style demangling includes a specific 'F' character after
+ the class name. For GNU style, it is just implied. So we can
+ safely just consume any 'F' at this point and be compatible
+ with either style. */
+
+ oldmangled = NULL;
+ func_done = 1;
+ (*mangled)++;
+
+ /* For lucid/ARM style we have to forget any types we might
+ have remembered up to this point, since they were not argument
+ types. GNU style considers all types seen as available for
+ back references. See comment in demangle_args() */
+
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+ forget_types (work);
+ }
+ success = demangle_args (work, mangled, declp);
+ break;
+
+ case 't':
+ /* G++ Template */
+ string_init(&trawname);
+ string_init(&tname);
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ success = demangle_template (work, mangled, &tname, &trawname);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ string_append(&tname, "::");
+ string_prepends(declp, &tname);
+ if (work -> destructor & 1)
+ {
+ string_prepend (&trawname, "~");
+ string_appends (declp, &trawname);
+ work->destructor -= 1;
+ }
+ if ((work->constructor & 1) || (work->destructor & 1))
+ {
+ string_appends (declp, &trawname);
+ work->constructor -= 1;
+ }
+ string_delete(&trawname);
+ string_delete(&tname);
+ oldmangled = NULL;
+ expect_func = 1;
+ break;
+
+ case '_':
+ /* At the outermost level, we cannot have a return type specified,
+ so if we run into another '_' at this point we are dealing with
+ a mangled name that is either bogus, or has been mangled by
+ some algorithm we don't know how to deal with. So just
+ reject the entire demangling. */
+ success = 0;
+ break;
+
+ default:
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ /* Assume we have stumbled onto the first outermost function
+ argument token, and start processing args. */
+ func_done = 1;
+ success = demangle_args (work, mangled, declp);
+ }
+ else
+ {
+ /* Non-GNU demanglers use a specific token to mark the start
+ of the outermost function argument tokens. Typically 'F',
+ for ARM-demangling, for example. So if we find something
+ we are not prepared for, it must be an error. */
+ success = 0;
+ }
+ break;
+ }
+/*
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+*/
+ {
+ if (success && expect_func)
+ {
+ func_done = 1;
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+ }
+ if (success && !func_done)
+ {
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+ bar__3fooi is 'foo::bar(int)'. We get here when we find the
+ first case, and need to ensure that the '(void)' gets added to
+ the current declp. Note that with ARM, the first case
+ represents the name of a static data member 'foo::bar',
+ which is in the current declp, so we leave it alone. */
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+ if (success && work -> static_type && PRINT_ARG_TYPES)
+ {
+ string_append (declp, " static");
+ }
+ if (success && work -> const_type && PRINT_ARG_TYPES)
+ {
+ string_append (declp, " const");
+ }
+ return (success);
+}
+
+#if 0
+
+static int
+demangle_method_args (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 0;
+
+ if (work -> static_type)
+ {
+ string_append (declp, *mangled + 1);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ success = demangle_args (work, mangled, declp);
+ }
+ return (success);
+}
+
+#endif
+
+static int
+demangle_template (work, mangled, tname, trawname)
+ struct work_stuff *work;
+ const char **mangled;
+ string *tname;
+ string *trawname;
+{
+ int i;
+ int is_pointer;
+ int is_real;
+ int is_integral;
+ int is_char;
+ int is_bool;
+ int r;
+ int need_comma = 0;
+ int success = 0;
+ int done;
+ const char *old_p;
+ const char *start;
+ int symbol_len;
+ string temp;
+
+ (*mangled)++;
+ start = *mangled;
+ /* get template name */
+ if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
+ {
+ return (0);
+ }
+ if (trawname)
+ string_appendn (trawname, *mangled, r);
+ string_appendn (tname, *mangled, r);
+ *mangled += r;
+ string_append (tname, "<");
+ /* get size of template parameter list */
+ if (!get_count (mangled, &r))
+ {
+ return (0);
+ }
+ for (i = 0; i < r; i++)
+ {
+ if (need_comma)
+ {
+ string_append (tname, ", ");
+ }
+ /* Z for type parameters */
+ if (**mangled == 'Z')
+ {
+ (*mangled)++;
+ /* temp is initialized in do_type */
+ success = do_type (work, mangled, &temp);
+ if (success)
+ {
+ string_appends (tname, &temp);
+ }
+ string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+ }
+ else
+ {
+ /* otherwise, value parameter */
+ old_p = *mangled;
+ is_pointer = 0;
+ is_real = 0;
+ is_integral = 0;
+ is_char = 0;
+ done = 0;
+ /* temp is initialized in do_type */
+ success = do_type (work, mangled, &temp);
+/*
+ if (success)
+ {
+ string_appends (tname, &temp);
+ }
+*/
+ string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+/*
+ string_append (tname, "=");
+*/
+ while (*old_p && !done)
+ {
+ switch (*old_p)
+ {
+ case 'P':
+ case 'p':
+ case 'R':
+ done = is_pointer = 1;
+ break;
+ case 'C': /* const */
+ case 'S': /* explicitly signed [char] */
+ case 'U': /* unsigned */
+ case 'V': /* volatile */
+ case 'F': /* function */
+ case 'M': /* member function */
+ case 'O': /* ??? */
+ old_p++;
+ continue;
+ case 'Q': /* qualified name */
+ done = is_integral = 1;
+ break;
+ case 'T': /* remembered type */
+ abort ();
+ break;
+ case 'v': /* void */
+ abort ();
+ break;
+ case 'x': /* long long */
+ case 'l': /* long */
+ case 'i': /* int */
+ case 's': /* short */
+ case 'w': /* wchar_t */
+ done = is_integral = 1;
+ break;
+ case 'b': /* bool */
+ done = is_bool = 1;
+ break;
+ case 'c': /* char */
+ done = is_char = 1;
+ break;
+ case 'r': /* long double */
+ case 'd': /* double */
+ case 'f': /* float */
+ done = is_real = 1;
+ break;
+ default:
+ /* it's probably user defined type, let's assume
+ it's integral, it seems hard to figure out
+ what it really is */
+ done = is_integral = 1;
+ }
+ }
+ if (is_integral)
+ {
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ else if (is_char)
+ {
+ char tmp[2];
+ int val;
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ string_appendn (tname, "'", 1);
+ val = consume_count(mangled);
+ if (val == 0)
+ {
+ success = 0;
+ break;
+ }
+ tmp[0] = (char)val;
+ tmp[1] = '\0';
+ string_appendn (tname, &tmp[0], 1);
+ string_appendn (tname, "'", 1);
+ }
+ else if (is_bool)
+ {
+ int val = consume_count (mangled);
+ if (val == 0)
+ string_appendn (tname, "false", 5);
+ else if (val == 1)
+ string_appendn (tname, "true", 4);
+ else
+ success = 0;
+ }
+ else if (is_real)
+ {
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ if (**mangled == '.') /* fraction */
+ {
+ string_appendn (tname, ".", 1);
+ (*mangled)++;
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ if (**mangled == 'e') /* exponent */
+ {
+ string_appendn (tname, "e", 1);
+ (*mangled)++;
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ }
+ else if (is_pointer)
+ {
+ if (!get_count (mangled, &symbol_len))
+ {
+ success = 0;
+ break;
+ }
+ string_appendn (tname, *mangled, symbol_len);
+ *mangled += symbol_len;
+ }
+ }
+ need_comma = 1;
+ }
+ if (tname->p[-1] == '>')
+ string_append (tname, " ");
+ string_append (tname, ">");
+
+/*
+ if (work -> static_type)
+ {
+ string_append (declp, *mangled + 1);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+*/
+ return (success);
+}
+
+static int
+arm_pt (work, mangled, n, anchor, args)
+ struct work_stuff *work;
+ const char *mangled;
+ int n;
+ const char **anchor, **args;
+{
+ /* ARM template? */
+ if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
+ {
+ int len;
+ *args = *anchor + 6;
+ len = consume_count (args);
+ if (*args + len == mangled + n && **args == '_')
+ {
+ ++*args;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+demangle_arm_pt (work, mangled, n, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ int n;
+ string *declp;
+{
+ const char *p;
+ const char *args;
+ const char *e = *mangled + n;
+
+ /* ARM template? */
+ if (arm_pt (work, *mangled, n, &p, &args))
+ {
+ string arg;
+ string_init (&arg);
+ string_appendn (declp, *mangled, p - *mangled);
+ string_append (declp, "<");
+ /* should do error checking here */
+ while (args < e) {
+ string_clear (&arg);
+ do_type (work, &args, &arg);
+ string_appends (declp, &arg);
+ string_append (declp, ",");
+ }
+ string_delete (&arg);
+ --declp->p;
+ string_append (declp, ">");
+ }
+ else
+ {
+ string_appendn (declp, *mangled, n);
+ }
+ *mangled += n;
+}
+
+static int
+demangle_class_name (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 0;
+
+ n = consume_count (mangled);
+ if (strlen (*mangled) >= n)
+ {
+ demangle_arm_pt (work, mangled, n, declp);
+ success = 1;
+ }
+
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_class -- demangle a mangled class sequence
+
+SYNOPSIS
+
+ static int
+ demangle_class (struct work_stuff *work, const char **mangled,
+ strint *declp)
+
+DESCRIPTION
+
+ DECLP points to the buffer into which demangling is being done.
+
+ *MANGLED points to the current token to be demangled. On input,
+ it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
+ On exit, it points to the next token after the mangled class on
+ success, or the first unconsumed token on failure.
+
+ If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
+ we are demangling a constructor or destructor. In this case
+ we prepend "class::class" or "class::~class" to DECLP.
+
+ Otherwise, we prepend "class::" to the current DECLP.
+
+ Reset the constructor/destructor flags once they have been
+ "consumed". This allows demangle_class to be called later during
+ the same demangling, to do normal class demangling.
+
+ Returns 1 if demangling is successful, 0 otherwise.
+
+*/
+
+static int
+demangle_class (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 0;
+ string class_name;
+
+ string_init (&class_name);
+ if (demangle_class_name (work, mangled, &class_name))
+ {
+ if ((work->constructor & 1) || (work->destructor & 1))
+ {
+ string_prepends (declp, &class_name);
+ if (work -> destructor & 1)
+ {
+ string_prepend (declp, "~");
+ work -> destructor -= 1;
+ }
+ else
+ {
+ work -> constructor -= 1;
+ }
+ }
+ string_prepend (declp, "::");
+ string_prepends (declp, &class_name);
+ success = 1;
+ }
+ string_delete (&class_name);
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_prefix -- consume the mangled name prefix and find signature
+
+SYNOPSIS
+
+ static int
+ demangle_prefix (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+DESCRIPTION
+
+ Consume and demangle the prefix of the mangled name.
+
+ DECLP points to the string buffer into which demangled output is
+ placed. On entry, the buffer is empty. On exit it contains
+ the root function name, the demangled operator name, or in some
+ special cases either nothing or the completely demangled result.
+
+ MANGLED points to the current pointer into the mangled name. As each
+ token of the mangled name is consumed, it is updated. Upon entry
+ the current mangled name pointer points to the first character of
+ the mangled name. Upon exit, it should point to the first character
+ of the signature if demangling was successful, or to the first
+ unconsumed character if demangling of the prefix was unsuccessful.
+
+ Returns 1 on success, 0 otherwise.
+ */
+
+static int
+demangle_prefix (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 1;
+ const char *scan;
+ int i;
+
+ if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
+ {
+ char *marker = strchr (cplus_markers, (*mangled)[8]);
+ if (marker != NULL && *marker == (*mangled)[10])
+ {
+ if ((*mangled)[9] == 'D')
+ {
+ /* it's a GNU global destructor to be executed at program exit */
+ (*mangled) += 11;
+ work->destructor = 2;
+ if (gnu_special (work, mangled, declp))
+ return success;
+ }
+ else if ((*mangled)[9] == 'I')
+ {
+ /* it's a GNU global constructor to be executed at program init */
+ (*mangled) += 11;
+ work->constructor = 2;
+ if (gnu_special (work, mangled, declp))
+ return success;
+ }
+ }
+ }
+ else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
+ {
+ /* it's a ARM global destructor to be executed at program exit */
+ (*mangled) += 7;
+ work->destructor = 2;
+ }
+ else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
+ {
+ /* it's a ARM global constructor to be executed at program initial */
+ (*mangled) += 7;
+ work->constructor = 2;
+ }
+
+/* This block of code is a reduction in strength time optimization
+ of:
+ scan = mystrstr (*mangled, "__"); */
+
+ {
+ scan = *mangled;
+
+ do {
+ scan = strchr (scan, '_');
+ } while (scan != NULL && *++scan != '_');
+
+ if (scan != NULL) --scan;
+ }
+
+ if (scan != NULL)
+ {
+ /* We found a sequence of two or more '_', ensure that we start at
+ the last pair in the sequence. */
+ i = strspn (scan, "_");
+ if (i > 2)
+ {
+ scan += (i - 2);
+ }
+ }
+
+ if (scan == NULL)
+ {
+ success = 0;
+ }
+ else if (work -> static_type)
+ {
+ if (!isdigit (scan[0]) && (scan[0] != 't'))
+ {
+ success = 0;
+ }
+ }
+ else if ((scan == *mangled) &&
+ (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
+ {
+ /* The ARM says nothing about the mangling of local variables.
+ But cfront mangles local variables by prepending __<nesting_level>
+ to them. As an extension to ARM demangling we handle this case. */
+ if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
+ {
+ *mangled = scan + 2;
+ consume_count (mangled);
+ string_append (declp, *mangled);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ /* A GNU style constructor starts with __[0-9Qt]. But cfront uses
+ names like __Q2_3foo3bar for nested type names. So don't accept
+ this style of constructor for cfront demangling. */
+ if (!(LUCID_DEMANGLING || ARM_DEMANGLING))
+ work -> constructor += 1;
+ *mangled = scan + 2;
+ }
+ }
+ else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
+ {
+ /* Mangled name starts with "__". Skip over any leading '_' characters,
+ then find the next "__" that separates the prefix from the signature.
+ */
+ if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
+ || (arm_special (work, mangled, declp) == 0))
+ {
+ while (*scan == '_')
+ {
+ scan++;
+ }
+ if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
+ {
+ /* No separator (I.E. "__not_mangled"), or empty signature
+ (I.E. "__not_mangled_either__") */
+ success = 0;
+ }
+ else
+ {
+ demangle_function_name (work, mangled, declp, scan);
+ }
+ }
+ }
+ else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
+ {
+ /* Cfront-style parameterized type. Handled later as a signature. */
+ success = 1;
+
+ /* ARM template? */
+ demangle_arm_pt (work, mangled, strlen (*mangled), declp);
+ }
+ else if (*(scan + 2) != '\0')
+ {
+ /* Mangled name does not start with "__" but does have one somewhere
+ in there with non empty stuff after it. Looks like a global
+ function name. */
+ demangle_function_name (work, mangled, declp, scan);
+ }
+ else
+ {
+ /* Doesn't look like a mangled name */
+ success = 0;
+ }
+
+ if (!success && (work->constructor == 2 || work->destructor == 2))
+ {
+ string_append (declp, *mangled);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ gnu_special -- special handling of gnu mangled strings
+
+SYNOPSIS
+
+ static int
+ gnu_special (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+
+DESCRIPTION
+
+ Process some special GNU style mangling forms that don't fit
+ the normal pattern. For example:
+
+ _$_3foo (destructor for class foo)
+ _vt$foo (foo virtual table)
+ _vt$foo$bar (foo::bar virtual table)
+ __vt_foo (foo virtual table, new style with thunks)
+ _3foo$varname (static data member)
+ _Q22rs2tu$vw (static data member)
+ __t6vector1Zii (constructor with template)
+ __thunk_4__$_7ostream (virtual function thunk)
+ */
+
+static int
+gnu_special (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 1;
+ const char *p;
+
+ if ((*mangled)[0] == '_'
+ && strchr (cplus_markers, (*mangled)[1]) != NULL
+ && (*mangled)[2] == '_')
+ {
+ /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
+ (*mangled) += 3;
+ work -> destructor += 1;
+ }
+ else if ((*mangled)[0] == '_'
+ && (((*mangled)[1] == '_'
+ && (*mangled)[2] == 'v'
+ && (*mangled)[3] == 't'
+ && (*mangled)[4] == '_')
+ || ((*mangled)[1] == 'v'
+ && (*mangled)[2] == 't'
+ && strchr (cplus_markers, (*mangled)[3]) != NULL)))
+ {
+ /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
+ and create the decl. Note that we consume the entire mangled
+ input string, which means that demangle_signature has no work
+ to do. */
+ if ((*mangled)[2] == 'v')
+ (*mangled) += 5; /* New style, with thunks: "__vt_" */
+ else
+ (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
+ while (**mangled != '\0')
+ {
+ p = strpbrk (*mangled, cplus_markers);
+ switch (**mangled)
+ {
+ case 'Q':
+ success = demangle_qualified (work, mangled, declp, 0, 1);
+ break;
+ case 't':
+ success = demangle_template (work, mangled, declp, 0);
+ break;
+ default:
+ if (isdigit(*mangled[0]))
+ {
+ n = consume_count(mangled);
+ }
+ else
+ {
+ n = strcspn (*mangled, cplus_markers);
+ }
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+ }
+
+ if (success && ((p == NULL) || (p == *mangled)))
+ {
+ if (p != NULL)
+ {
+ string_append (declp, "::");
+ (*mangled)++;
+ }
+ }
+ else
+ {
+ success = 0;
+ break;
+ }
+ }
+ if (success)
+ string_append (declp, " virtual table");
+ }
+ else if ((*mangled)[0] == '_'
+ && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
+ && (p = strpbrk (*mangled, cplus_markers)) != NULL)
+ {
+ /* static data member, "_3foo$varname" for example */
+ (*mangled)++;
+ switch (**mangled)
+ {
+ case 'Q':
+ success = demangle_qualified (work, mangled, declp, 0, 1);
+ break;
+ case 't':
+ success = demangle_template (work, mangled, declp, 0);
+ break;
+ default:
+ n = consume_count (mangled);
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+ }
+ if (success && (p == *mangled))
+ {
+ /* Consumed everything up to the cplus_marker, append the
+ variable name. */
+ (*mangled)++;
+ string_append (declp, "::");
+ n = strlen (*mangled);
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+ }
+ else
+ {
+ success = 0;
+ }
+ }
+ else if (strncmp (*mangled, "__thunk_", 8) == 0)
+ {
+ int delta = ((*mangled) += 8, consume_count (mangled));
+ char *method = cplus_demangle (++*mangled, work->options);
+ if (method)
+ {
+ char buf[50];
+ sprintf (buf, "virtual function thunk (delta:%d) for ", -delta);
+ string_append (declp, buf);
+ string_append (declp, method);
+ free (method);
+ n = strlen (*mangled);
+ (*mangled) += n;
+ }
+ else
+ {
+ success = 0;
+ }
+ }
+ else
+ {
+ success = 0;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ arm_special -- special handling of ARM/lucid mangled strings
+
+SYNOPSIS
+
+ static int
+ arm_special (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+
+DESCRIPTION
+
+ Process some special ARM style mangling forms that don't fit
+ the normal pattern. For example:
+
+ __vtbl__3foo (foo virtual table)
+ __vtbl__3foo__3bar (bar::foo virtual table)
+
+ */
+
+static int
+arm_special (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 1;
+ const char *scan;
+
+ if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
+ {
+ /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
+ and create the decl. Note that we consume the entire mangled
+ input string, which means that demangle_signature has no work
+ to do. */
+ scan = *mangled + ARM_VTABLE_STRLEN;
+ while (*scan != '\0') /* first check it can be demangled */
+ {
+ n = consume_count (&scan);
+ if (n==0)
+ {
+ return (0); /* no good */
+ }
+ scan += n;
+ if (scan[0] == '_' && scan[1] == '_')
+ {
+ scan += 2;
+ }
+ }
+ (*mangled) += ARM_VTABLE_STRLEN;
+ while (**mangled != '\0')
+ {
+ n = consume_count (mangled);
+ string_prependn (declp, *mangled, n);
+ (*mangled) += n;
+ if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
+ {
+ string_prepend (declp, "::");
+ (*mangled) += 2;
+ }
+ }
+ string_append (declp, " virtual table");
+ }
+ else
+ {
+ success = 0;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_qualified -- demangle 'Q' qualified name strings
+
+SYNOPSIS
+
+ static int
+ demangle_qualified (struct work_stuff *, const char *mangled,
+ string *result, int isfuncname, int append);
+
+DESCRIPTION
+
+ Demangle a qualified name, such as "Q25Outer5Inner" which is
+ the mangled form of "Outer::Inner". The demangled output is
+ prepended or appended to the result string according to the
+ state of the append flag.
+
+ If isfuncname is nonzero, then the qualified name we are building
+ is going to be used as a member function name, so if it is a
+ constructor or destructor function, append an appropriate
+ constructor or destructor name. I.E. for the above example,
+ the result for use as a constructor is "Outer::Inner::Inner"
+ and the result for use as a destructor is "Outer::Inner::~Inner".
+
+BUGS
+
+ Numeric conversion is ASCII dependent (FIXME).
+
+ */
+
+static int
+demangle_qualified (work, mangled, result, isfuncname, append)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+ int isfuncname;
+ int append;
+{
+ int qualifiers;
+ int namelength;
+ int success = 1;
+ const char *p;
+ char num[2];
+ string temp;
+
+ string_init (&temp);
+ switch ((*mangled)[1])
+ {
+ case '_':
+ /* GNU mangled name with more than 9 classes. The count is preceded
+ by an underscore (to distinguish it from the <= 9 case) and followed
+ by an underscore. */
+ p = *mangled + 2;
+ qualifiers = atoi (p);
+ if (!isdigit (*p) || *p == '0')
+ success = 0;
+
+ /* Skip the digits. */
+ while (isdigit (*p))
+ ++p;
+
+ if (*p != '_')
+ success = 0;
+
+ *mangled = p + 1;
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* The count is in a single digit. */
+ num[0] = (*mangled)[1];
+ num[1] = '\0';
+ qualifiers = atoi (num);
+
+ /* If there is an underscore after the digit, skip it. This is
+ said to be for ARM-qualified names, but the ARM makes no
+ mention of such an underscore. Perhaps cfront uses one. */
+ if ((*mangled)[2] == '_')
+ {
+ (*mangled)++;
+ }
+ (*mangled) += 2;
+ break;
+
+ case '0':
+ default:
+ success = 0;
+ }
+
+ if (!success)
+ return success;
+
+ /* Pick off the names and collect them in the temp buffer in the order
+ in which they are found, separated by '::'. */
+
+ while (qualifiers-- > 0)
+ {
+ if (*mangled[0] == '_')
+ *mangled = *mangled + 1;
+ if (*mangled[0] == 't')
+ {
+ success = demangle_template(work, mangled, &temp, 0);
+ if (!success) break;
+ }
+ else
+ {
+ namelength = consume_count (mangled);
+ if (strlen (*mangled) < namelength)
+ {
+ /* Simple sanity check failed */
+ success = 0;
+ break;
+ }
+ string_appendn (&temp, *mangled, namelength);
+ *mangled += namelength;
+ }
+ if (qualifiers > 0)
+ {
+ string_appendn (&temp, "::", 2);
+ }
+ }
+
+ /* If we are using the result as a function name, we need to append
+ the appropriate '::' separated constructor or destructor name.
+ We do this here because this is the most convenient place, where
+ we already have a pointer to the name and the length of the name. */
+
+ if (isfuncname && (work->constructor & 1 || work->destructor & 1))
+ {
+ string_appendn (&temp, "::", 2);
+ if (work -> destructor & 1)
+ {
+ string_append (&temp, "~");
+ }
+ string_appendn (&temp, (*mangled) - namelength, namelength);
+ }
+
+ /* Now either prepend the temp buffer to the result, or append it,
+ depending upon the state of the append flag. */
+
+ if (append)
+ {
+ string_appends (result, &temp);
+ }
+ else
+ {
+ if (!STRING_EMPTY (result))
+ {
+ string_appendn (&temp, "::", 2);
+ }
+ string_prepends (result, &temp);
+ }
+
+ string_delete (&temp);
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ get_count -- convert an ascii count to integer, consuming tokens
+
+SYNOPSIS
+
+ static int
+ get_count (const char **type, int *count)
+
+DESCRIPTION
+
+ Return 0 if no conversion is performed, 1 if a string is converted.
+*/
+
+static int
+get_count (type, count)
+ const char **type;
+ int *count;
+{
+ const char *p;
+ int n;
+
+ if (!isdigit (**type))
+ {
+ return (0);
+ }
+ else
+ {
+ *count = **type - '0';
+ (*type)++;
+ if (isdigit (**type))
+ {
+ p = *type;
+ n = *count;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p++;
+ }
+ while (isdigit (*p));
+ if (*p == '_')
+ {
+ *type = p + 1;
+ *count = n;
+ }
+ }
+ }
+ return (1);
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (work, mangled, result)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+{
+ int n;
+ int done;
+ int success;
+ string decl;
+ const char *remembered_type;
+ int constp;
+ int volatilep;
+
+ string_init (&decl);
+ string_init (result);
+
+ done = 0;
+ success = 1;
+ while (success && !done)
+ {
+ int member;
+ switch (**mangled)
+ {
+
+ /* A pointer type */
+ case 'P':
+ case 'p':
+ (*mangled)++;
+ string_prepend (&decl, "*");
+ break;
+
+ /* A reference type */
+ case 'R':
+ (*mangled)++;
+ string_prepend (&decl, "&");
+ break;
+
+ /* An array */
+ case 'A':
+ {
+ const char *p = ++(*mangled);
+
+ string_prepend (&decl, "(");
+ string_append (&decl, ")[");
+ /* Copy anything up until the next underscore (the size of the
+ array). */
+ while (**mangled && **mangled != '_')
+ ++(*mangled);
+ if (**mangled == '_')
+ {
+ string_appendn (&decl, p, *mangled - p);
+ string_append (&decl, "]");
+ *mangled += 1;
+ }
+ else
+ success = 0;
+ break;
+ }
+
+ /* A back reference to a previously seen type */
+ case 'T':
+ (*mangled)++;
+ if (!get_count (mangled, &n) || n >= work -> ntypes)
+ {
+ success = 0;
+ }
+ else
+ {
+ remembered_type = work -> typevec[n];
+ mangled = &remembered_type;
+ }
+ break;
+
+ /* A function */
+ case 'F':
+ (*mangled)++;
+ if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
+ {
+ string_prepend (&decl, "(");
+ string_append (&decl, ")");
+ }
+ /* After picking off the function args, we expect to either find the
+ function return type (preceded by an '_') or the end of the
+ string. */
+ if (!demangle_args (work, mangled, &decl)
+ || (**mangled != '_' && **mangled != '\0'))
+ {
+ success = 0;
+ }
+ if (success && (**mangled == '_'))
+ {
+ (*mangled)++;
+ }
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ constp = 0;
+ volatilep = 0;
+
+ member = **mangled == 'M';
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ {
+ success = 0;
+ break;
+ }
+ n = consume_count (mangled);
+ if (strlen (*mangled) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_append (&decl, ")");
+ string_prepend (&decl, "::");
+ string_prependn (&decl, *mangled, n);
+ string_prepend (&decl, "(");
+ *mangled += n;
+ if (member)
+ {
+ if (**mangled == 'C')
+ {
+ (*mangled)++;
+ constp = 1;
+ }
+ if (**mangled == 'V')
+ {
+ (*mangled)++;
+ volatilep = 1;
+ }
+ if (*(*mangled)++ != 'F')
+ {
+ success = 0;
+ break;
+ }
+ }
+ if ((member && !demangle_args (work, mangled, &decl))
+ || **mangled != '_')
+ {
+ success = 0;
+ break;
+ }
+ (*mangled)++;
+ if (! PRINT_ANSI_QUALIFIERS)
+ {
+ break;
+ }
+ if (constp)
+ {
+ APPEND_BLANK (&decl);
+ string_append (&decl, "const");
+ }
+ if (volatilep)
+ {
+ APPEND_BLANK (&decl);
+ string_append (&decl, "volatile");
+ }
+ break;
+ }
+ case 'G':
+ (*mangled)++;
+ break;
+
+ case 'C':
+ (*mangled)++;
+/*
+ if ((*mangled)[1] == 'P')
+ {
+*/
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ if (!STRING_EMPTY (&decl))
+ {
+ string_prepend (&decl, " ");
+ }
+ string_prepend (&decl, "const");
+ }
+ break;
+/*
+ }
+*/
+
+ /* fall through */
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ switch (**mangled)
+ {
+ /* A qualified name, such as "Outer::Inner". */
+ case 'Q':
+ success = demangle_qualified (work, mangled, result, 0, 1);
+ break;
+
+ default:
+ success = demangle_fund_type (work, mangled, result);
+ break;
+ }
+
+ if (success)
+ {
+ if (!STRING_EMPTY (&decl))
+ {
+ string_append (result, " ");
+ string_appends (result, &decl);
+ }
+ }
+ else
+ {
+ string_delete (result);
+ }
+ string_delete (&decl);
+ return (success);
+}
+
+/* Given a pointer to a type string that represents a fundamental type
+ argument (int, long, unsigned int, etc) in TYPE, a pointer to the
+ string in which the demangled output is being built in RESULT, and
+ the WORK structure, decode the types and add them to the result.
+
+ For example:
+
+ "Ci" => "const int"
+ "Sl" => "signed long"
+ "CUs" => "const unsigned short"
+
+ */
+
+static int
+demangle_fund_type (work, mangled, result)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+{
+ int done = 0;
+ int success = 1;
+
+ /* First pick off any type qualifiers. There can be more than one. */
+
+ while (!done)
+ {
+ switch (**mangled)
+ {
+ case 'C':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "const");
+ }
+ break;
+ case 'U':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "unsigned");
+ break;
+ case 'S': /* signed char only */
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "signed");
+ break;
+ case 'V':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "volatile");
+ }
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ /* Now pick off the fundamental type. There can be only one. */
+
+ switch (**mangled)
+ {
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "void");
+ break;
+ case 'x':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long long");
+ break;
+ case 'l':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long");
+ break;
+ case 'i':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "int");
+ break;
+ case 's':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "short");
+ break;
+ case 'b':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "bool");
+ break;
+ case 'c':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "char");
+ break;
+ case 'w':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "wchar_t");
+ break;
+ case 'r':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long double");
+ break;
+ case 'd':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "double");
+ break;
+ case 'f':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "float");
+ break;
+ case 'G':
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ {
+ success = 0;
+ break;
+ }
+ /* fall through */
+ /* An explicit type, such as "6mytype" or "7integer" */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ APPEND_BLANK (result);
+ if (!demangle_class_name (work, mangled, result)) {
+ --result->p;
+ success = 0;
+ }
+ break;
+ case 't':
+ success = demangle_template(work,mangled, result, 0);
+ break;
+ default:
+ success = 0;
+ break;
+ }
+
+ return (success);
+}
+
+/* `result' will be initialized in do_type; it will be freed on failure */
+
+static int
+do_arg (work, mangled, result)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+{
+ const char *start = *mangled;
+
+ if (!do_type (work, mangled, result))
+ {
+ return (0);
+ }
+ else
+ {
+ remember_type (work, start, *mangled - start);
+ return (1);
+ }
+}
+
+static void
+remember_type (work, start, len)
+ struct work_stuff *work;
+ const char *start;
+ int len;
+{
+ char *tem;
+
+ if (work -> ntypes >= work -> typevec_size)
+ {
+ if (work -> typevec_size == 0)
+ {
+ work -> typevec_size = 3;
+ work -> typevec =
+ (char **) xmalloc (sizeof (char *) * work -> typevec_size);
+ }
+ else
+ {
+ work -> typevec_size *= 2;
+ work -> typevec =
+ (char **) xrealloc ((char *)work -> typevec,
+ sizeof (char *) * work -> typevec_size);
+ }
+ }
+ tem = xmalloc (len + 1);
+ memcpy (tem, start, len);
+ tem[len] = '\0';
+ work -> typevec[work -> ntypes++] = tem;
+}
+
+/* Forget the remembered types, but not the type vector itself. */
+
+static void
+forget_types (work)
+ struct work_stuff *work;
+{
+ int i;
+
+ while (work -> ntypes > 0)
+ {
+ i = --(work -> ntypes);
+ if (work -> typevec[i] != NULL)
+ {
+ free (work -> typevec[i]);
+ work -> typevec[i] = NULL;
+ }
+ }
+}
+
+/* Process the argument list part of the signature, after any class spec
+ has been consumed, as well as the first 'F' character (if any). For
+ example:
+
+ "__als__3fooRT0" => process "RT0"
+ "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
+
+ DECLP must be already initialised, usually non-empty. It won't be freed
+ on failure.
+
+ Note that g++ differs significantly from ARM and lucid style mangling
+ with regards to references to previously seen types. For example, given
+ the source fragment:
+
+ class foo {
+ public:
+ foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
+ };
+
+ foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+ void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+
+ g++ produces the names:
+
+ __3fooiRT0iT2iT2
+ foo__FiR3fooiT1iT1
+
+ while lcc (and presumably other ARM style compilers as well) produces:
+
+ foo__FiR3fooT1T2T1T2
+ __ct__3fooFiR3fooT1T2T1T2
+
+ Note that g++ bases it's type numbers starting at zero and counts all
+ previously seen types, while lucid/ARM bases it's type numbers starting
+ at one and only considers types after it has seen the 'F' character
+ indicating the start of the function args. For lucid/ARM style, we
+ account for this difference by discarding any previously seen types when
+ we see the 'F' character, and subtracting one from the type number
+ reference.
+
+ */
+
+static int
+demangle_args (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ string arg;
+ int need_comma = 0;
+ int r;
+ int t;
+ const char *tem;
+ char temptype;
+
+ if (PRINT_ARG_TYPES)
+ {
+ string_append (declp, "(");
+ if (**mangled == '\0')
+ {
+ string_append (declp, "void");
+ }
+ }
+
+ while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
+ {
+ if ((**mangled == 'N') || (**mangled == 'T'))
+ {
+ temptype = *(*mangled)++;
+
+ if (temptype == 'N')
+ {
+ if (!get_count (mangled, &r))
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ r = 1;
+ }
+ if (ARM_DEMANGLING && work -> ntypes >= 10)
+ {
+ /* If we have 10 or more types we might have more than a 1 digit
+ index so we'll have to consume the whole count here. This
+ will lose if the next thing is a type name preceded by a
+ count but it's impossible to demangle that case properly
+ anyway. Eg if we already have 12 types is T12Pc "(..., type1,
+ Pc, ...)" or "(..., type12, char *, ...)" */
+ if ((t = consume_count(mangled)) == 0)
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ if (!get_count (mangled, &t))
+ {
+ return (0);
+ }
+ }
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+ t--;
+ }
+ /* Validate the type index. Protect against illegal indices from
+ malformed type strings. */
+ if ((t < 0) || (t >= work -> ntypes))
+ {
+ return (0);
+ }
+ while (--r >= 0)
+ {
+ tem = work -> typevec[t];
+ if (need_comma && PRINT_ARG_TYPES)
+ {
+ string_append (declp, ", ");
+ }
+ if (!do_arg (work, &tem, &arg))
+ {
+ return (0);
+ }
+ if (PRINT_ARG_TYPES)
+ {
+ string_appends (declp, &arg);
+ }
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+ else
+ {
+ if (need_comma & PRINT_ARG_TYPES)
+ {
+ string_append (declp, ", ");
+ }
+ if (!do_arg (work, mangled, &arg))
+ {
+ return (0);
+ }
+ if (PRINT_ARG_TYPES)
+ {
+ string_appends (declp, &arg);
+ }
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+
+ if (**mangled == 'e')
+ {
+ (*mangled)++;
+ if (PRINT_ARG_TYPES)
+ {
+ if (need_comma)
+ {
+ string_append (declp, ",");
+ }
+ string_append (declp, "...");
+ }
+ }
+
+ if (PRINT_ARG_TYPES)
+ {
+ string_append (declp, ")");
+ }
+ return (1);
+}
+
+static void
+demangle_function_name (work, mangled, declp, scan)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+ const char *scan;
+{
+ int i;
+ int len;
+ string type;
+ const char *tem;
+
+ string_appendn (declp, (*mangled), scan - (*mangled));
+ string_need (declp, 1);
+ *(declp -> p) = '\0';
+
+ /* Consume the function name, including the "__" separating the name
+ from the signature. We are guaranteed that SCAN points to the
+ separator. */
+
+ (*mangled) = scan + 2;
+
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+
+ /* See if we have an ARM style constructor or destructor operator.
+ If so, then just record it, clear the decl, and return.
+ We can't build the actual constructor/destructor decl until later,
+ when we recover the class name from the signature. */
+
+ if (strcmp (declp -> b, "__ct") == 0)
+ {
+ work -> constructor += 1;
+ string_clear (declp);
+ return;
+ }
+ else if (strcmp (declp -> b, "__dt") == 0)
+ {
+ work -> destructor += 1;
+ string_clear (declp);
+ return;
+ }
+ }
+
+ if (declp->p - declp->b >= 3
+ && declp->b[0] == 'o'
+ && declp->b[1] == 'p'
+ && strchr (cplus_markers, declp->b[2]) != NULL)
+ {
+ /* see if it's an assignment expression */
+ if (declp->p - declp->b >= 10 /* op$assign_ */
+ && memcmp (declp->b + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ len = declp->p - declp->b - 10;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, declp->b + 10, len) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ string_append (declp, "=");
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ int len = declp->p - declp->b - 3;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, declp->b + 3, len) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ }
+ else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0
+ && strchr (cplus_markers, declp->b[4]) != NULL)
+ {
+ /* type conversion operator */
+ tem = declp->b + 5;
+ if (do_type (work, &tem, &type))
+ {
+ string_clear (declp);
+ string_append (declp, "operator ");
+ string_appends (declp, &type);
+ string_delete (&type);
+ }
+ }
+ else if (declp->b[0] == '_' && declp->b[1] == '_'
+ && declp->b[2] == 'o' && declp->b[3] == 'p')
+ {
+ /* ANSI. */
+ /* type conversion operator. */
+ tem = declp->b + 4;
+ if (do_type (work, &tem, &type))
+ {
+ string_clear (declp);
+ string_append (declp, "operator ");
+ string_appends (declp, &type);
+ string_delete (&type);
+ }
+ }
+ else if (declp->b[0] == '_' && declp->b[1] == '_'
+ && declp->b[2] >= 'a' && declp->b[2] <= 'z'
+ && declp->b[3] >= 'a' && declp->b[3] <= 'z')
+ {
+ if (declp->b[4] == '\0')
+ {
+ /* Operator. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 2
+ && memcmp (optable[i].in, declp->b + 2, 2) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (declp->b[2] == 'a' && declp->b[5] == '\0')
+ {
+ /* Assignment. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 3
+ && memcmp (optable[i].in, declp->b + 2, 3) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+ string *s;
+ int n;
+{
+ int tem;
+
+ if (s->b == NULL)
+ {
+ if (n < 32)
+ {
+ n = 32;
+ }
+ s->p = s->b = xmalloc (n);
+ s->e = s->b + n;
+ }
+ else if (s->e - s->p < n)
+ {
+ tem = s->p - s->b;
+ n += tem;
+ n *= 2;
+ s->b = xrealloc (s->b, n);
+ s->p = s->b + tem;
+ s->e = s->b + n;
+ }
+}
+
+static void
+string_delete (s)
+ string *s;
+{
+ if (s->b != NULL)
+ {
+ free (s->b);
+ s->b = s->e = s->p = NULL;
+ }
+}
+
+static void
+string_init (s)
+ string *s;
+{
+ s->b = s->p = s->e = NULL;
+}
+
+static void
+string_clear (s)
+ string *s;
+{
+ s->p = s->b;
+}
+
+#if 0
+
+static int
+string_empty (s)
+ string *s;
+{
+ return (s->b == s->p);
+}
+
+#endif
+
+static void
+string_append (p, s)
+ string *p;
+ const char *s;
+{
+ int n;
+ if (s == NULL || *s == '\0')
+ return;
+ n = strlen (s);
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_appends (p, s)
+ string *p, *s;
+{
+ int n;
+
+ if (s->b != s->p)
+ {
+ n = s->p - s->b;
+ string_need (p, n);
+ memcpy (p->p, s->b, n);
+ p->p += n;
+ }
+}
+
+static void
+string_appendn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ if (n != 0)
+ {
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+ }
+}
+
+static void
+string_prepend (p, s)
+ string *p;
+ const char *s;
+{
+ if (s != NULL && *s != '\0')
+ {
+ string_prependn (p, s, strlen (s));
+ }
+}
+
+static void
+string_prepends (p, s)
+ string *p, *s;
+{
+ if (s->b != s->p)
+ {
+ string_prependn (p, s->b, s->p - s->b);
+ }
+}
+
+static void
+string_prependn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ char *q;
+
+ if (n != 0)
+ {
+ string_need (p, n);
+ for (q = p->p - 1; q >= p->b; q--)
+ {
+ q[n] = q[0];
+ }
+ memcpy (p->b, s, n);
+ p->p += n;
+ }
+}
+
+/* To generate a standalone demangler program for testing purposes,
+ just compile and link this file with -DMAIN and libiberty.a. When
+ run, it demangles each command line arg, or each stdin string, and
+ prints the result on stdout. */
+
+#ifdef MAIN
+
+static void
+demangle_it (mangled_name)
+ char *mangled_name;
+{
+ char *result;
+
+ result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
+ if (result == NULL)
+ {
+ printf ("%s\n", mangled_name);
+ }
+ else
+ {
+ printf ("%s\n", result);
+ free (result);
+ }
+}
+
+#include "getopt.h"
+
+static char *program_name;
+static char *program_version = VERSION;
+
+static void
+usage (stream, status)
+ FILE *stream;
+ int status;
+{
+ fprintf (stream, "\
+Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
+ [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
+ [--help] [--version] [arg...]\n",
+ program_name);
+ exit (status);
+}
+
+#define MBUF_SIZE 512
+char mbuffer[MBUF_SIZE];
+
+/* Defined in the automatically-generated underscore.c. */
+extern int prepends_underscore;
+
+int strip_underscore = 0;
+
+static struct option long_options[] = {
+ {"strip-underscores", no_argument, 0, '_'},
+ {"format", required_argument, 0, 's'},
+ {"help", no_argument, 0, 'h'},
+ {"no-strip-underscores", no_argument, 0, 'n'},
+ {"version", no_argument, 0, 'v'},
+ {0, no_argument, 0, 0}
+};
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *result;
+ int c;
+
+ program_name = argv[0];
+
+ strip_underscore = prepends_underscore;
+
+ while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
+ {
+ switch (c)
+ {
+ case '?':
+ usage (stderr, 1);
+ break;
+ case 'h':
+ usage (stdout, 0);
+ case 'n':
+ strip_underscore = 0;
+ break;
+ case 'v':
+ printf ("GNU %s version %s\n", program_name, program_version);
+ exit (0);
+ case '_':
+ strip_underscore = 1;
+ break;
+ case 's':
+ if (strcmp (optarg, "gnu") == 0)
+ {
+ current_demangling_style = gnu_demangling;
+ }
+ else if (strcmp (optarg, "lucid") == 0)
+ {
+ current_demangling_style = lucid_demangling;
+ }
+ else if (strcmp (optarg, "arm") == 0)
+ {
+ current_demangling_style = arm_demangling;
+ }
+ else
+ {
+ fprintf (stderr, "%s: unknown demangling style `%s'\n",
+ program_name, optarg);
+ exit (1);
+ }
+ break;
+ }
+ }
+
+ if (optind < argc)
+ {
+ for ( ; optind < argc; optind++)
+ {
+ demangle_it (argv[optind]);
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ int i = 0;
+ c = getchar ();
+ /* Try to read a label. */
+ while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
+ {
+ if (i >= MBUF_SIZE-1)
+ break;
+ mbuffer[i++] = c;
+ c = getchar ();
+ }
+ if (i > 0)
+ {
+ int skip_first = 0;
+
+ if (mbuffer[0] == '.')
+ ++skip_first;
+ if (strip_underscore && mbuffer[skip_first] == '_')
+ ++skip_first;
+
+ if (skip_first > i)
+ skip_first = i;
+
+ mbuffer[i] = 0;
+
+ result = cplus_demangle (mbuffer + skip_first,
+ DMGL_PARAMS | DMGL_ANSI);
+ if (result)
+ {
+ if (mbuffer[0] == '.')
+ putc ('.', stdout);
+ fputs (result, stdout);
+ free (result);
+ }
+ else
+ fputs (mbuffer, stdout);
+
+ fflush (stdout);
+ }
+ if (c == EOF)
+ break;
+ putchar (c);
+ }
+ }
+
+ exit (0);
+}
+
+static void
+fatal (str)
+ char *str;
+{
+ fprintf (stderr, "%s: %s\n", program_name, str);
+ exit (1);
+}
+
+char * malloc ();
+char * realloc ();
+
+char *
+xmalloc (size)
+ unsigned size;
+{
+ register char *value = (char *) malloc (size);
+ if (value == 0)
+ fatal ("virtual memory exhausted");
+ return value;
+}
+
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ unsigned size;
+{
+ register char *value = (char *) realloc (ptr, size);
+ if (value == 0)
+ fatal ("virtual memory exhausted");
+ return value;
+}
+#endif /* main */
diff --git a/gnu/usr.bin/ld/demangle.h b/gnu/usr.bin/ld/demangle.h
new file mode 100644
index 0000000..223c4e0
--- /dev/null
+++ b/gnu/usr.bin/ld/demangle.h
@@ -0,0 +1,110 @@
+/* Defs for interface to demanglers.
+ Copyright 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, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* $FreeBSD$ */
+
+
+#if !defined (DEMANGLE_H)
+#define DEMANGLE_H
+
+#ifdef IN_GCC
+
+/* Add prototype support. */
+#ifndef PROTO
+#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
+#define PROTO(ARGS) ARGS
+#else
+#define PROTO(ARGS) ()
+#endif
+#endif
+
+#define PARAMS(ARGS) PROTO(ARGS)
+
+#ifdef __STDC__
+#define PTR void *
+#else
+#ifndef const
+#define const
+#endif
+#define PTR char *
+#endif
+
+#else /* ! IN_GCC */
+#include <ansidecl.h>
+#endif /* IN_GCC */
+
+/* Options passed to cplus_demangle (in 2nd parameter). */
+
+#define DMGL_NO_OPTS 0 /* For readability... */
+#define DMGL_PARAMS (1 << 0) /* Include function args */
+#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
+
+#define DMGL_AUTO (1 << 8)
+#define DMGL_GNU (1 << 9)
+#define DMGL_LUCID (1 << 10)
+#define DMGL_ARM (1 << 11)
+/* If none of these are set, use 'current_demangling_style' as the default. */
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM)
+
+/* Enumeration of possible demangling styles.
+
+ Lucid and ARM styles are still kept logically distinct, even though
+ they now both behave identically. The resulting style is actual the
+ union of both. I.E. either style recognizes both "__pt__" and "__rf__"
+ for operator "->", even though the first is lucid style and the second
+ is ARM style. (FIXME?) */
+
+extern enum demangling_styles
+{
+ unknown_demangling = 0,
+ auto_demangling = DMGL_AUTO,
+ gnu_demangling = DMGL_GNU,
+ lucid_demangling = DMGL_LUCID,
+ arm_demangling = DMGL_ARM
+} current_demangling_style;
+
+/* Define string names for the various demangling styles. */
+
+#define AUTO_DEMANGLING_STYLE_STRING "auto"
+#define GNU_DEMANGLING_STYLE_STRING "gnu"
+#define LUCID_DEMANGLING_STYLE_STRING "lucid"
+#define ARM_DEMANGLING_STYLE_STRING "arm"
+
+/* Some macros to test what demangling style is active. */
+
+#define CURRENT_DEMANGLING_STYLE current_demangling_style
+#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
+#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
+#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
+#define ARM_DEMANGLING (CURRENT_DEMANGLING_STYLE & DMGL_ARM)
+
+extern char *
+cplus_demangle PARAMS ((const char *mangled, int options));
+
+extern int
+cplus_demangle_opname PARAMS ((char *opname, char *result, int options));
+
+extern char *
+cplus_mangle_opname PARAMS ((char *opname, int options));
+
+/* Note: This sets global state. FIXME if you care about multi-threading. */
+
+extern void
+set_cplus_marker_for_demangling PARAMS ((int ch));
+
+#endif /* DEMANGLE_H */
diff --git a/gnu/usr.bin/ld/ld.1 b/gnu/usr.bin/ld/ld.1
new file mode 100644
index 0000000..f60de7f
--- /dev/null
+++ b/gnu/usr.bin/ld/ld.1
@@ -0,0 +1,295 @@
+.\"
+.\" Copyright (c) 1993 Paul Kranenburg
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Paul Kranenburg.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 14, 1993
+.Dt LD 1
+.Os
+.Sh NAME
+.Nm ld
+.Nd link editor
+.Sh SYNOPSIS
+.Nm
+.Op Fl fMNnrSstXxz
+.Bk -words
+.Op Fl A Ar symbol-file
+.Op Fl assert Ar keyword
+.Op Fl B Ns Ar linkmode
+.Op Fl D Ar datasize
+.Op Fl d Ar c
+.Op Fl d Ar p
+.Op Fl e Ar entry
+.Op Fl l Ns Ar library-specifier
+.Op Fl L Ns Ar library-search-path
+.Op Fl nostdlib
+.Op Fl O Ar filename
+.Op Fl o Ar filename
+.Op Fl R Ns Ar record-library-search-path
+.Op Fl T Ar address
+.Op Fl u Ar symbol
+.Op Fl V Ar shlib-version
+.Op Fl y Ar symbol
+.Ek
+.Sh DESCRIPTION
+.Nm
+combines the object and archive files given on the command line into a new
+object file. The output object file is either an executable program, a
+shared object suitable for loading at run-time, or an object file that can
+once again be processed by
+.Nm .
+Object files and archives are processed in the order given on the command line.
+.Pp
+The options are as follows:
+.Pp
+.Bl -tag -width indent
+.It Fl A Ar symbol-file
+The the symbol-file is taken as a base for link-editing the object files
+on the command line.
+.It Fl assert Ar keyword
+This option is here mainly for compatibility with SunOS
+.Nm .
+Most conditions which would cause a Sun assertion to fail will
+currently always cause error or warning messages from
+.Nm .
+The only keyword implemented by
+.Nm
+is
+.Ar pure-text ,
+which generates a warning if a position independent object is being
+created and some of the files being linked are not position
+independent.
+.It Fl B Ns Ar dynamic
+Specifies that linking against dynamic libraries can take place. If a library
+specifier of the form -lx appears on the command line,
+.Nm
+searches for a library of the from libx.so.n.m
+(see the
+.Fl l
+option)
+according to the search rules in effect. If such a file can not be
+found a traditional archive is looked for.
+This options can appear anywhere on the command line and is complementary
+to
+.Fl B Ns Ar static .
+.It Fl B Ns Ar forcedynamic
+This is similar to
+.Fl B Ns Ar dynamic
+except that if no dynamic libraries are linked against,
+.Nm
+will still produce a dynamic executable. This is useful for programs
+which are static but still need to load dynamic objects at runtime.
+.It Fl B Ns Ar static
+The counterpart of
+.Fl B Ns Ar dynamic .
+This option turns off dynamic linking for
+all library specifiers until a
+.Fl B Ns Ar dynamic
+is once again given. Any explicitly
+mentioned shared object encountered on the command line while this option is
+in effect is flagged as an error.
+.It Fl B Ns Ar shareable
+Instructs the linker to build a shared object from the object files rather
+than a normal executable image.
+.It Fl B Ns Ar symbolic
+This option causes all symbolic references in the output to be resolved in
+this link-edit session. The only remaining run-time relocation requirements are
+.Em base-relative
+relocations, ie. translation with respect to the load address. Failure to
+resolve any symbolic reference causes an error to be reported.
+.It Fl B Ns Ar forcearchive
+Force all members of archives to be loaded, whether or not such members
+contribute a definition to any plain object files. Useful for making a
+shared library from an archive of PIC objects without having to unpack
+the archive.
+.It Fl B Ns Ar silly
+Search for
+.Em \.sa
+silly archive companions of shared objects. Useful for compatibility with
+version 3 shared objects.
+.It Fl D Ar data-size
+Set the size of the data segment. For sanity's sake, this should be larger
+than the cumulative data sizes of the input files.
+.It Fl d Ar c
+Force allocation of commons even producing relocatable output.
+.It Fl d Ar p
+Force alias definitions of procedure calls in non-PIC code. Useful to
+obtain shareable code in the presence of run-time relocations as such
+calls will be re-directed through the Procedure Linkage Table (see
+.Xr link 5 )
+.It Fl e Ar entry-symbol
+Specifies the entry symbol for an executable.
+.It Fl f
+List the resolved paths of all the object files and libraries on the
+standard output, and exit.
+.It Fl L Ns Ar path
+Add
+.Ar path
+to the list of directories to search for libraries specified with the
+.Fl l
+option.
+.It Fl l Ns Ar lib-spec
+This option specifies a library to be considered for inclusion in the
+output. If the
+.Fl B Ns Ar dynamic
+option is in effect, a shared library of the
+form lib<spec>.so.m.n
+(where
+.Em m
+is the major, and
+.Em n
+is the minor version number, respectively)
+is searched for first. The
+library with the highest version found in the search path is selected.
+If no shared library is found or the
+.Fl B Ns Ar static
+options is in effect, an archive of the form lib<spec>.a is looked for in
+the library search path.
+.It Fl M
+Produce output about the mapping of segments of the input files and the
+values assigned to
+(global)
+symbols in the output file.
+.It Fl N
+Produce a
+.Dv OMAGIC
+output file.
+.It Fl n
+Produce a
+.Dv NMAGIC
+output file.
+.It Fl nostdlib
+Do not search the built-in path
+(usually
+.Dq /usr/lib )
+for
+.Fl l
+specified libraries.
+.It Fl O Ar filename
+Specifies the name of the output file.
+The file is created as
+.Ar filename Ns Pa .tmp
+and when output is complete renamed to
+.Ar filename .
+.It Fl o Ar filename
+Specifies the name of the output file. Defaults to
+.Dq Pa a.out .
+.It Fl Q
+Produce a
+.Dv QMAGIC
+.Pq Fx Ns / Ns Tn BSDi Ns -i386
+output file. This is the default.
+.It Fl r
+Produce relocatable object file, suitable for another pass through
+.Nm .
+.It Fl R
+Record the given path within the executable for run-time library search.
+This only applies to dynamically linked executables.
+.It Fl S
+Strip all debugger symbols from the output.
+.It Fl s
+Strip all symbols from the output.
+.It Fl T
+Specifies the start address of the text segment, with respect to which
+all input files will be relocated.
+.It Fl t
+Leave a trace of the input files as they are processed.
+.It Fl u Ar symbol
+Force
+.Ar symbol
+to be marked as undefined. Useful to force loading of an archive member
+in the absence of any other references to that member.
+.It Fl V Ar version
+Put the given version number into the output shared library
+(if one is created).
+Useful to make shared libraries compatible with other operating
+systems. E.g., SunOS 4.x libraries use version number 3. Defaults to 8.
+.It Fl X
+Discard local symbols in the input files that start with the letter
+.Dq L
+.It Fl x
+Discard all local symbols in the input files.
+.It Fl y Ar symbol
+Trace the manipulations inflicted on
+.Ar symbol
+.It Fl Z
+Make a
+.Bx 386
+.Dv ZMAGIC
+output file.
+.It Fl z
+Make a
+.Nx
+.Dv ZMAGIC
+output file.
+.El
+.Sh ENVIRONMENT
+.Nm
+utilizes the following environment variables:
+.Bl -tag -width "LD_LIBRARY_PATH"
+.It Ev LD_LIBRARY_PATH
+This colon-separated list of directories is inserted into the search
+path for libraries following any directories specified via
+.Fl L
+options and preceding the built-in path.
+.\" .It Ev LD_NOSTD_PATH
+.\" When set, do not search the built-in path for libraries.
+.\" This is an alternative to the
+.\" .Fl nostdlib
+.\" command-line flag.
+.El
+.Sh FILES
+.Sh SEE ALSO
+.Xr ldd 1 ,
+.Xr rtld 1 ,
+.Xr link 5 ,
+.Xr ldconfig 8
+.Sh CAVEATS
+An entry point must now explicitly be given if the output is intended to be
+a normal executable program. This was not the case for the previous version of
+.Nm .
+.Sh BUGS
+Shared objects are not properly checked for undefined symbols.
+.Pp
+Cascading of shared object defeats the
+.Dq -Bstatic
+option.
+.Pp
+All shared objects presented to
+.Nm
+are marked for run-time loading in the output file, even if no symbols
+are needed from them.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+The shared library model employed by
+.Nm
+appeared first in SunOS 4.0
diff --git a/gnu/usr.bin/ld/ld.1aout b/gnu/usr.bin/ld/ld.1aout
new file mode 100644
index 0000000..0592d98
--- /dev/null
+++ b/gnu/usr.bin/ld/ld.1aout
@@ -0,0 +1,295 @@
+.\"
+.\" Copyright (c) 1993 Paul Kranenburg
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Paul Kranenburg.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 14, 1993
+.Dt LD 1
+.Os
+.Sh NAME
+.Nm ld
+.Nd link editor
+.Sh SYNOPSIS
+.Nm ld
+.Op Fl fMNnrSstXxz
+.Bk -words
+.Op Fl A Ar symbol-file
+.Op Fl assert Ar keyword
+.Op Fl B Ns Ar linkmode
+.Op Fl D Ar datasize
+.Op Fl d Ar c
+.Op Fl d Ar p
+.Op Fl e Ar entry
+.Op Fl l Ns Ar library-specifier
+.Op Fl L Ns Ar library-search-path
+.Op Fl nostdlib
+.Op Fl O Ar filename
+.Op Fl o Ar filename
+.Op Fl R Ns Ar record-library-search-path
+.Op Fl T Ar address
+.Op Fl u Ar symbol
+.Op Fl V Ar shlib-version
+.Op Fl y Ar symbol
+.Ek
+.Sh DESCRIPTION
+.Nm
+combines the object and archive files given on the command line into a new
+object file. The output object file is either an executable program, a
+shared object suitable for loading at run-time, or an object file that can
+once again be processed by
+.Nm .
+Object files and archives are processed in the order given on the command line.
+.Pp
+The options are as follows:
+.Pp
+.Bl -tag -width indent
+.It Fl A Ar symbol-file
+The the symbol-file is taken as a base for link-editing the object files
+on the command line.
+.It Fl assert Ar keyword
+This option is here mainly for compatibility with SunOS
+.Nm .
+Most conditions which would cause a Sun assertion to fail will
+currently always cause error or warning messages from
+.Nm .
+The only keyword implemented by
+.Nm
+is
+.Nm pure-text ,
+which generates a warning if a position independent object is being
+created and some of the files being linked are not position
+independent.
+.It Fl B Ns Ar dynamic
+Specifies that linking against dynamic libraries can take place. If a library
+specifier of the form -lx appears on the command line,
+.Nm
+searches for a library of the from libx.so.n.m
+(see the
+.Fl l
+option)
+according to the search rules in effect. If such a file can not be
+found a traditional archive is looked for.
+This options can appear anywhere on the command line and is complementary
+to
+.Fl B Ns Ar static .
+.It Fl B Ns Ar forcedynamic
+This is similar to
+.Fl B Ns Ar dynamic
+except that if no dynamic libraries are linked against,
+.Nm
+will still produce a dynamic executable. This is useful for programs
+which are static but still need to load dynamic objects at runtime.
+.It Fl B Ns Ar static
+The counterpart of
+.Fl B Ns Ar dynamic .
+This option turns off dynamic linking for
+all library specifiers until a
+.Fl B Ns Ar dynamic
+is once again given. Any explicitly
+mentioned shared object encountered on the command line while this option is
+in effect is flagged as an error.
+.It Fl B Ns Ar shareable
+Instructs the linker to build a shared object from the object files rather
+than a normal executable image.
+.It Fl B Ns Ar symbolic
+This option causes all symbolic references in the output to be resolved in
+this link-edit session. The only remaining run-time relocation requirements are
+.Em base-relative
+relocations, ie. translation with respect to the load address. Failure to
+resolve any symbolic reference causes an error to be reported.
+.It Fl B Ns Ar forcearchive
+Force all members of archives to be loaded, whether or not such members
+contribute a definition to any plain object files. Useful for making a
+shared library from an archive of PIC objects without having to unpack
+the archive.
+.It Fl B Ns Ar silly
+Search for
+.Em \.sa
+silly archive companions of shared objects. Useful for compatibility with
+version 3 shared objects.
+.It Fl D Ar data-size
+Set the size of the data segment. For sanity's sake, this should be larger
+than the cumulative data sizes of the input files.
+.It Fl d Ar c
+Force allocation of commons even producing relocatable output.
+.It Fl d Ar p
+Force alias definitions of procedure calls in non-PIC code. Useful to
+obtain shareable code in the presence of run-time relocations as such
+calls will be re-directed through the Procedure Linkage Table (see
+.Xr link 5 )
+.It Fl e Ar entry-symbol
+Specifies the entry symbol for an executable.
+.It Fl f
+List the resolved paths of all the object files and libraries on the
+standard output, and exit.
+.It Fl L Ns Ar path
+Add
+.Ar path
+to the list of directories to search for libraries specified with the
+.Fl l
+option.
+.It Fl l Ns Ar lib-spec
+This option specifies a library to be considered for inclusion in the
+output. If the
+.Fl B Ns Ar dynamic
+option is in effect, a shared library of the
+form lib<spec>.so.m.n
+(where
+.Em m
+is the major, and
+.Em n
+is the minor version number, respectively)
+is searched for first. The
+library with the highest version found in the search path is selected.
+If no shared library is found or the
+.Fl B Ns Ar static
+options is in effect, an archive of the form lib<spec>.a is looked for in
+the library search path.
+.It Fl M
+Produce output about the mapping of segments of the input files and the
+values assigned to
+(global)
+symbols in the output file.
+.It Fl N
+Produce a
+.Dv OMAGIC
+output file.
+.It Fl n
+Produce a
+.Dv NMAGIC
+output file.
+.It Fl nostdlib
+Do not search the built-in path
+(usually
+.Dq /usr/lib )
+for
+.Fl l
+specified libraries.
+.It Fl O Ar filename
+Specifies the name of the output file.
+The file is created as
+.Ar filename Ns Pa .tmp
+and when output is complete renamed to
+.Ar filename .
+.It Fl o Ar filename
+Specifies the name of the output file. Defaults to
+.Dq Pa a.out .
+.It Fl Q
+Produce a
+.Dv QMAGIC
+.Pq Fx , Bsx Ns -i386
+output file. This is the default.
+.It Fl r
+Produce relocatable object file, suitable for another pass through
+.Nm .
+.It Fl R
+Record the given path within the executable for run-time library search.
+This only applies to dynamically linked executables.
+.It Fl S
+Strip all debugger symbols from the output.
+.It Fl s
+Strip all symbols from the output.
+.It Fl T
+Specifies the start address of the text segment, with respect to which
+all input files will be relocated.
+.It Fl t
+Leave a trace of the input files as they are processed.
+.It Fl u Ar symbol
+Force
+.Ar symbol
+to be marked as undefined. Useful to force loading of an archive member
+in the absence of any other references to that member.
+.It Fl V Ar version
+Put the given version number into the output shared library
+(if one is created).
+Useful to make shared libraries compatible with other operating
+systems. E.g., SunOS 4.x libraries use version number 3. Defaults to 8.
+.It Fl X
+Discard local symbols in the input files that start with the letter
+.Dq L
+.It Fl x
+Discard all local symbols in the input files.
+.It Fl y Ar symbol
+Trace the manipulations inflicted on
+.Ar symbol
+.It Fl Z
+Make a
+.Bx 386
+.Dv ZMAGIC
+output file.
+.It Fl z
+Make a
+.Nx
+.Dv ZMAGIC
+output file.
+.El
+.Sh ENVIRONMENT
+.Nm
+utilizes the following environment variables:
+.Bl -tag -width "LD_LIBRARY_PATH"
+.It Ev LD_LIBRARY_PATH
+This colon-separated list of directories is inserted into the search
+path for libraries following any directories specified via
+.Fl L
+options and preceding the built-in path.
+.\" .It Ev LD_NOSTD_PATH
+.\" When set, do not search the built-in path for libraries.
+.\" This is an alternative to the
+.\" .Fl nostdlib
+.\" command-line flag.
+.El
+.Sh FILES
+.Sh SEE ALSO
+.Xr ldd 1 ,
+.Xr rtld 1 ,
+.Xr link 5 ,
+.Xr ldconfig 8
+.Sh CAVEATS
+An entry point must now explicitly be given if the output is intended to be
+a normal executable program. This was not the case for the previous version of
+.Nm .
+.Sh BUGS
+Shared objects are not properly checked for undefined symbols.
+.Pp
+Cascading of shared object defeats the
+.Dq -Bstatic
+option.
+.Pp
+All shared objects presented to
+.Nm
+are marked for run-time loading in the output file, even if no symbols
+are needed from them.
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v1 .
+The shared library model employed by
+.Nm
+appeared first in SunOS 4.0
diff --git a/gnu/usr.bin/ld/ld.c b/gnu/usr.bin/ld/ld.c
new file mode 100644
index 0000000..316df28
--- /dev/null
+++ b/gnu/usr.bin/ld/ld.c
@@ -0,0 +1,3825 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Modified 1993 by Paul Kranenburg, Erasmus University
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)ld.c 6.10 (Berkeley) 5/22/91";
+#endif /* not lint */
+
+/* Linker `ld' for GNU
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Richard Stallman with some help from Eric Albert.
+ Set, indirect, and warning symbol features added by Randy Smith. */
+
+/*
+ * $FreeBSD$
+ */
+
+/* Define how to initialize system-dependent header fields. */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <fcntl.h>
+#include <ar.h>
+#include <ranlib.h>
+#include <a.out.h>
+#include <stab.h>
+#include <string.h>
+
+#include "ld.h"
+#include "dynamic.h"
+
+/* Vector of entries for input files specified by arguments.
+ These are all the input files except for members of specified libraries. */
+struct file_entry *file_table;
+int number_of_files;
+
+/* 1 => write relocation into output file so can re-input it later. */
+int relocatable_output;
+
+/* 1 => building a shared object, set by `-Bshareable'. */
+int building_shared_object;
+
+/* 1 => create the output executable. */
+int make_executable;
+
+/* Force the executable to be output, even if there are non-fatal errors */
+int force_executable;
+
+/* 1 => assign space to common symbols even if `relocatable_output'. */
+int force_common_definition;
+
+/* 1 => assign jmp slots to text symbols in shared objects even if non-PIC */
+int force_alias_definition;
+
+/* 1 => some files contain PIC code, affects relocation bits
+ if `relocatable_output'. */
+int pic_code_seen;
+
+/* 1 => segments must be page aligned (ZMAGIC, QMAGIC) */
+int page_align_segments;
+
+/* 1 => data segment must be page aligned, even if `-n' or `-N' */
+int page_align_data;
+
+/* 1 => do not use standard library search path */
+int nostdlib;
+
+/* Version number to put in __DYNAMIC (set by -V) */
+int soversion;
+
+int text_size; /* total size of text. */
+int text_start; /* start of text */
+int text_pad; /* clear space between text and data */
+int data_size; /* total size of data. */
+int data_start; /* start of data */
+int data_pad; /* part of bss segment as part of data */
+
+int bss_size; /* total size of bss. */
+int bss_start; /* start of bss */
+
+int text_reloc_size; /* total size of text relocation. */
+int data_reloc_size; /* total size of data relocation. */
+
+int rrs_section_type; /* What's in the RRS section */
+int rrs_text_size; /* Size of RRS text additions */
+int rrs_text_start; /* Location of above */
+int rrs_data_size; /* Size of RRS data additions */
+int rrs_data_start; /* Location of above */
+
+/* Specifications of start and length of the area reserved at the end
+ of the data segment for the set vectors. Computed in 'digest_symbols' */
+int set_sect_start; /* start of set element vectors */
+int set_sect_size; /* size of above */
+
+int link_mode; /* Current link mode */
+int pic_type; /* PIC type */
+
+/*
+ * When loading the text and data, we can avoid doing a close
+ * and another open between members of the same library.
+ *
+ * These two variables remember the file that is currently open.
+ * Both are zero if no file is open.
+ *
+ * See `each_file' and `file_close'.
+ */
+struct file_entry *input_file;
+int input_desc;
+
+/* The name of the file to write; "a.out" by default. */
+char *output_filename; /* Output file name. */
+char *real_output_filename; /* Output file name. */
+FILE *outstream; /* Output file descriptor. */
+struct exec outheader; /* Output file header. */
+int magic; /* Output file magic. */
+int oldmagic;
+int relocatable_output; /* `-r'-ed output */
+
+symbol *entry_symbol; /* specified by `-e' */
+int entry_offset; /* program entry if no `-e' given */
+
+int page_size; /* Size of a page (machine dependent) */
+
+/*
+ * Keep a list of any symbols referenced from the command line (so
+ * that error messages for these guys can be generated). This list is
+ * zero terminated.
+ */
+symbol **cmdline_references;
+int cl_refs_allocated;
+
+/*
+ * Which symbols should be stripped (omitted from the output): none, all, or
+ * debugger symbols.
+ */
+enum {
+ STRIP_NONE, STRIP_ALL, STRIP_DEBUGGER
+} strip_symbols;
+
+/*
+ * Which local symbols should be omitted: none, all, or those starting with L.
+ * This is irrelevant if STRIP_NONE.
+ */
+enum {
+ DISCARD_NONE, DISCARD_ALL, DISCARD_L
+} discard_locals;
+
+int global_sym_count; /* # of nlist entries for global symbols */
+int size_sym_count; /* # of N_SIZE nlist entries for output
+ (relocatable_output only) */
+int local_sym_count; /* # of nlist entries for local symbols. */
+int non_L_local_sym_count; /* # of nlist entries for non-L symbols */
+int debugger_sym_count; /* # of nlist entries for debugger info. */
+int undefined_global_sym_count; /* # of global symbols referenced and
+ not defined. */
+int undefined_shobj_sym_count; /* # of undefined symbols referenced
+ by shared objects */
+int multiple_def_count; /* # of multiply defined symbols. */
+int defined_global_sym_count; /* # of defined global symbols. */
+int common_defined_global_count; /* # of common symbols. */
+int undefined_weak_sym_count; /* # of weak symbols referenced and
+ not defined. */
+
+#if notused
+int special_sym_count; /* # of linker defined symbols. */
+ /* XXX - Currently, only __DYNAMIC and _G_O_T_ go here if required,
+ * perhaps _etext, _edata and _end should go here too.
+ */
+#endif
+int global_alias_count; /* # of aliased symbols */
+int set_symbol_count; /* # of N_SET* symbols. */
+int set_vector_count; /* # of set vectors in output. */
+int warn_sym_count; /* # of warning symbols encountered. */
+int flag_list_files; /* 1 => print pathnames of files, don't link */
+int list_warning_symbols; /* 1 => warning symbols referenced */
+
+struct string_list_element *set_element_prefixes;
+
+int trace_files; /* print names of input files as processed (`-t'). */
+int write_map; /* write a load map (`-M') */
+
+/*
+ * `text-start' address is normally this much plus a page boundary.
+ * This is not a user option; it is fixed for each system.
+ */
+int text_start_alignment;
+
+/*
+ * Nonzero if -T was specified in the command line.
+ * This prevents text_start from being set later to default values.
+ */
+int T_flag_specified;
+
+/*
+ * Nonzero if -Tdata was specified in the command line.
+ * This prevents data_start from being set later to default values.
+ */
+int Tdata_flag_specified;
+
+/*
+ * Size to pad data section up to.
+ * We simply increase the size of the data section, padding with zeros,
+ * and reduce the size of the bss section to match.
+ */
+int specified_data_size;
+
+long *set_vectors;
+int setv_fill_count;
+
+static void decode_option __P((char *, char *));
+static void decode_command __P((int, char **));
+static int classify_arg __P((char *));
+static void load_symbols __P((void));
+static void enter_global_ref __P((struct localsymbol *,
+ char *, struct file_entry *));
+static void digest_symbols __P((void));
+static void digest_pass1 __P((void)), digest_pass2 __P((void));
+static void consider_file_section_lengths __P((struct file_entry *));
+static void relocate_file_addresses __P((struct file_entry *));
+static void consider_relocation __P((struct file_entry *, int));
+static void consider_local_symbols __P((struct file_entry *));
+static void perform_relocation __P((char *, int,
+ struct relocation_info *, int,
+ struct file_entry *, int));
+static void copy_text __P((struct file_entry *));
+static void copy_data __P((struct file_entry *));
+static void coptxtrel __P((struct file_entry *));
+static void copdatrel __P((struct file_entry *));
+static void write_output __P((void));
+static void write_header __P((void));
+static void write_text __P((void));
+static void write_data __P((void));
+static void write_rel __P((void));
+static void write_syms __P((void));
+static void assign_symbolnums __P((struct file_entry *, int *));
+static void cleanup __P((void));
+static int parse __P((char *, char *, char *));
+static void list_files __P((void));
+
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+
+ /* Added this to stop ld core-dumping on very large .o files. */
+#ifdef RLIMIT_STACK
+ /* Get rid of any avoidable limit on stack size. */
+ {
+ struct rlimit rlim;
+
+ /* Set the stack limit huge so that alloca does not fail. */
+ if (getrlimit(RLIMIT_STACK, &rlim) != 0)
+ warn("getrlimit");
+ else {
+ rlim.rlim_cur = rlim.rlim_max;
+ if (setrlimit(RLIMIT_STACK, &rlim) != 0)
+ warn("setrlimit");
+ }
+ }
+#endif /* RLIMIT_STACK */
+
+ page_size = PAGSIZ;
+
+ /* Clear the cumulative info on the output file. */
+
+ text_size = 0;
+ data_size = 0;
+ bss_size = 0;
+ text_reloc_size = 0;
+ data_reloc_size = 0;
+
+ data_pad = 0;
+ text_pad = 0;
+ page_align_segments = 0;
+ page_align_data = 0;
+
+ /* Initialize the data about options. */
+
+ specified_data_size = 0;
+ strip_symbols = STRIP_NONE;
+ trace_files = 0;
+ discard_locals = DISCARD_NONE;
+ entry_symbol = 0;
+ write_map = 0;
+ relocatable_output = 0;
+ force_common_definition = 0;
+ T_flag_specified = 0;
+ Tdata_flag_specified = 0;
+ magic = DEFAULT_MAGIC;
+ make_executable = 1;
+ force_executable = 0;
+ link_mode = DYNAMIC;
+#ifdef SUNOS4
+ link_mode |= SILLYARCHIVE;
+#endif
+ soversion = DEFAULT_SOVERSION;
+
+ /* Initialize the cumulative counts of symbols. */
+
+ local_sym_count = 0;
+ non_L_local_sym_count = 0;
+ debugger_sym_count = 0;
+ undefined_global_sym_count = 0;
+ warn_sym_count = 0;
+ list_warning_symbols = 0;
+ multiple_def_count = 0;
+ common_defined_global_count = 0;
+
+ /* Keep a list of symbols referenced from the command line */
+ cl_refs_allocated = 10;
+ cmdline_references = (symbol **)
+ xmalloc(cl_refs_allocated * sizeof(symbol *));
+ *cmdline_references = 0;
+
+ /* Completely decode ARGV. */
+ decode_command(argc, argv);
+
+ if (flag_list_files)
+ list_files();
+
+ building_shared_object =
+ (!relocatable_output && (link_mode & SHAREABLE));
+
+ if (building_shared_object && entry_symbol) {
+ errx(1,"`-Bshareable' and `-e' options are mutually exclusive");
+ }
+
+ /* Create the symbols `etext', `edata' and `end'. */
+ symtab_init(relocatable_output);
+
+ /*
+ * Determine whether to count the header as part of the text size,
+ * and initialize the text size accordingly. This depends on the kind
+ * of system and on the output format selected.
+ */
+
+ if (magic == ZMAGIC || magic == QMAGIC)
+ page_align_segments = 1;
+
+ md_init_header(&outheader, magic, 0);
+
+ text_size = sizeof(struct exec);
+ text_size -= N_TXTOFF(outheader);
+
+ if (text_size < 0)
+ text_size = 0;
+ entry_offset = text_size;
+
+ if (!T_flag_specified && !relocatable_output)
+ text_start = TEXT_START(outheader);
+
+ /* The text-start address is normally this far past a page boundary. */
+ text_start_alignment = text_start % page_size;
+
+ /*
+ * Load symbols of all input files. Also search all libraries and
+ * decide which library members to load.
+ */
+ load_symbols();
+
+ /* Compute where each file's sections go, and relocate symbols. */
+ digest_symbols();
+
+ /*
+ * Print error messages for any missing symbols, for any warning
+ * symbols, and possibly multiple definitions
+ */
+ make_executable &= do_warnings(stderr);
+
+ /* Print a map, if requested. */
+ if (write_map)
+ print_symbols(stdout);
+
+ /* Write the output file. */
+ if (make_executable || force_executable)
+ write_output();
+
+ exit(!make_executable);
+}
+
+/*
+ * Analyze a command line argument. Return 0 if the argument is a filename.
+ * Return 1 if the argument is a option complete in itself. Return 2 if the
+ * argument is a option which uses an argument.
+ *
+ * Thus, the value is the number of consecutive arguments that are part of
+ * options.
+ */
+
+static int
+classify_arg(arg)
+ register char *arg;
+{
+ if (*arg != '-')
+ return 0;
+ switch (arg[1]) {
+ case 'a':
+ if (!strcmp(&arg[2], "ssert"))
+ return 2;
+ case 'A':
+ case 'D':
+ case 'e':
+ case 'L':
+ case 'l':
+ case 'O':
+ case 'o':
+ case 'R':
+ case 'u':
+ case 'V':
+ case 'y':
+ if (arg[2])
+ return 1;
+ return 2;
+
+ case 'B':
+ if (!strcmp(&arg[2], "static"))
+ return 1;
+ if (!strcmp(&arg[2], "dynamic"))
+ return 1;
+ if (!strcmp(&arg[2], "forcedynamic"))
+ return 1;
+
+ case 'T':
+ if (arg[2] == 0)
+ return 2;
+ if (!strcmp(&arg[2], "text"))
+ return 2;
+ if (!strcmp(&arg[2], "data"))
+ return 2;
+ return 1;
+ }
+
+ return 1;
+}
+
+/*
+ * Process the command arguments, setting up file_table with an entry for
+ * each input file, and setting variables according to the options.
+ */
+
+static void
+decode_command(argc, argv)
+ int argc;
+ char **argv;
+{
+ register int i;
+ register struct file_entry *p;
+
+ number_of_files = 0;
+ output_filename = "a.out";
+
+ /*
+ * First compute number_of_files so we know how long to make
+ * file_table.
+ * Also process most options completely.
+ */
+
+ for (i = 1; i < argc; i++) {
+ register int code = classify_arg(argv[i]);
+ if (code) {
+ if (i + code > argc)
+ errx(1, "no argument following %s", argv[i]);
+
+ decode_option(argv[i], argv[i + 1]);
+
+ if (argv[i][1] == 'l' || argv[i][1] == 'A')
+ number_of_files++;
+
+ i += code - 1;
+ } else
+ number_of_files++;
+ }
+
+ if (!number_of_files) {
+ if (flag_list_files)
+ exit(0);
+ errx(1, "No input files specified");
+ }
+
+ p = file_table = (struct file_entry *)
+ xmalloc(number_of_files * sizeof(struct file_entry));
+ bzero(p, number_of_files * sizeof(struct file_entry));
+
+ /* Now scan again and fill in file_table. */
+ /* All options except -A and -l are ignored here. */
+
+ for (i = 1; i < argc; i++) {
+ char *string;
+ register int code = classify_arg(argv[i]);
+
+ if (code == 0) {
+ p->filename = argv[i];
+ p->local_sym_name = argv[i];
+ p++;
+ continue;
+ }
+ if (code == 2)
+ string = argv[i + 1];
+ else
+ string = &argv[i][2];
+
+ if (argv[i][1] == 'B') {
+ if (strcmp(string, "static") == 0)
+ link_mode &= ~DYNAMIC;
+ else if (strcmp(string, "dynamic") == 0)
+ link_mode |= DYNAMIC;
+ else if (strcmp(string, "forcedynamic") == 0)
+ link_mode |= DYNAMIC|FORCEDYNAMIC;
+ else if (strcmp(string, "symbolic") == 0)
+ link_mode |= SYMBOLIC;
+ else if (strcmp(string, "forcearchive") == 0)
+ link_mode |= FORCEARCHIVE;
+ else if (strcmp(string, "shareable") == 0)
+ link_mode |= SHAREABLE;
+#ifdef SUN_COMPAT
+ else if (strcmp(string, "silly") == 0)
+ link_mode |= SILLYARCHIVE;
+ else if (strcmp(string, "~silly") == 0)
+ link_mode &= ~SILLYARCHIVE;
+#endif
+ }
+ if (!strcmp(argv[i] + 1, "assert")) {
+ if (!strcmp(string, "pure-text"))
+ link_mode |= WARNRRSTEXT;
+ }
+ if (argv[i][1] == 'A') {
+ if (p != file_table)
+ errx(1, "-A specified before an input file other than the first");
+ p->filename = string;
+ p->local_sym_name = string;
+ p->flags |= E_JUST_SYMS;
+ link_mode &= ~DYNAMIC;
+ p++;
+ }
+ if (argv[i][1] == 'l') {
+ p->filename = string;
+ p->local_sym_name = concat("-l", string, "");
+ p->flags |= E_SEARCH_DIRS;
+ if (link_mode & DYNAMIC && !relocatable_output)
+ p->flags |= E_SEARCH_DYNAMIC;
+ p++;
+ }
+ i += code - 1;
+ }
+
+ /* Now check some option settings for consistency. */
+
+ if (page_align_segments &&
+ (text_start - text_start_alignment) & (page_size - 1))
+ errx(1, "incorrect alignment of text start address");
+
+ /* Append the standard search directories to the user-specified ones. */
+ add_search_path(getenv("LD_LIBRARY_PATH"));
+ if (!nostdlib)
+ std_search_path();
+}
+
+void
+add_cmdline_ref(sp)
+ symbol *sp;
+{
+ symbol **ptr;
+
+ for (ptr = cmdline_references;
+ ptr < cmdline_references + cl_refs_allocated && *ptr;
+ ptr++);
+
+ if (ptr >= cmdline_references + cl_refs_allocated - 1) {
+ int diff = ptr - cmdline_references;
+
+ cl_refs_allocated *= 2;
+ cmdline_references = (symbol **)
+ xrealloc(cmdline_references,
+ cl_refs_allocated * sizeof(symbol *));
+ ptr = cmdline_references + diff;
+ }
+ *ptr++ = sp;
+ *ptr = (symbol *)0;
+}
+
+int
+set_element_prefixed_p(name)
+ char *name;
+{
+ struct string_list_element *p;
+ int i;
+
+ for (p = set_element_prefixes; p; p = p->next) {
+
+ for (i = 0; p->str[i] != '\0' && (p->str[i] == name[i]); i++);
+ if (p->str[i] == '\0')
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Record an option and arrange to act on it later. ARG should be the
+ * following command argument, which may or may not be used by this option.
+ *
+ * The `l' and `A' options are ignored here since they actually specify input
+ * files.
+ */
+
+static void
+decode_option(swt, arg)
+ register char *swt, *arg;
+{
+ if (!strcmp(swt + 1, "Bstatic"))
+ return;
+ if (!strcmp(swt + 1, "Bdynamic"))
+ return;
+ if (!strcmp(swt + 1, "Bforcedynamic"))
+ return;
+ if (!strcmp(swt + 1, "Bsymbolic"))
+ return;
+ if (!strcmp(swt + 1, "Bforcearchive"))
+ return;
+ if (!strcmp(swt + 1, "Bshareable"))
+ return;
+ if (!strcmp(swt + 1, "assert"))
+ return;
+#ifdef SUN_COMPAT
+ if (!strcmp(swt + 1, "Bsilly"))
+ return;
+#endif
+ if (!strcmp(swt + 1, "Ttext")) {
+ text_start = parse(arg, "%x", "invalid argument to -Ttext");
+ T_flag_specified = 1;
+ return;
+ }
+ if (!strcmp(swt + 1, "Tdata")) {
+ rrs_data_start = parse(arg, "%x", "invalid argument to -Tdata");
+ Tdata_flag_specified = 1;
+ return;
+ }
+ if (!strcmp(swt + 1, "noinhibit-exec")) {
+ force_executable = 1;
+ return;
+ }
+ if (!strcmp(swt + 1, "nostdlib")) {
+ nostdlib = 1;
+ return;
+ }
+ if (swt[2] != 0)
+ arg = &swt[2];
+
+ switch (swt[1]) {
+ case 'A':
+ return;
+
+ case 'D':
+ specified_data_size = parse(arg, "%x", "invalid argument to -D");
+ return;
+
+ case 'd':
+ if (swt[2] == 0 || *arg == 'c')
+ force_common_definition = 1;
+ else if (*arg == 'p')
+ force_alias_definition = 1;
+ else
+ errx(1, "-d option takes 'c' or 'p' argument");
+ return;
+
+ case 'e':
+ entry_symbol = getsym(arg);
+ if (!entry_symbol->defined &&
+ !(entry_symbol->flags & GS_REFERENCED))
+ undefined_global_sym_count++;
+ entry_symbol->flags |= GS_REFERENCED;
+ add_cmdline_ref(entry_symbol);
+ return;
+
+ case 'f':
+ flag_list_files = 1;
+ return;
+
+ case 'l':
+ return;
+
+ case 'L':
+ add_search_dir(arg);
+ return;
+
+ case 'M':
+ write_map = 1;
+ return;
+
+ case 'N':
+ magic = OMAGIC;
+ return;
+
+ case 'n':
+ magic = NMAGIC;
+ return;
+
+ case 'O':
+ output_filename = xmalloc(strlen(arg)+5);
+ strcpy(output_filename, arg);
+ strcat(output_filename, ".tmp");
+ real_output_filename = arg;
+ return;
+
+ case 'o':
+ output_filename = arg;
+ return;
+
+ case 'p':
+ page_align_data = 1;
+ return;
+
+#ifdef QMAGIC
+ case 'Q':
+ magic = QMAGIC;
+ return;
+#endif
+
+ case 'r':
+ relocatable_output = 1;
+ magic = OMAGIC;
+ text_start = 0;
+ return;
+
+ case 'R':
+ rrs_search_paths = (rrs_search_paths == NULL)
+ ? strdup(arg)
+ : concat(rrs_search_paths, ":", arg);
+ return;
+
+ case 'S':
+ strip_symbols = STRIP_DEBUGGER;
+ return;
+
+ case 's':
+ strip_symbols = STRIP_ALL;
+ return;
+
+ case 'T':
+ text_start = parse(arg, "%x", "invalid argument to -T");
+ T_flag_specified = 1;
+ return;
+
+ case 't':
+ trace_files = 1;
+ return;
+
+ case 'u':
+ {
+ register symbol *sp = getsym(arg);
+
+ if (!sp->defined && !(sp->flags & GS_REFERENCED))
+ undefined_global_sym_count++;
+ sp->flags |= GS_REFERENCED;
+ add_cmdline_ref(sp);
+ }
+ return;
+
+#if 1
+ case 'V':
+ soversion = parse(arg, "%d", "invalid argument to -V");
+ return;
+#endif
+
+ case 'X':
+ discard_locals = DISCARD_L;
+ return;
+
+ case 'x':
+ discard_locals = DISCARD_ALL;
+ return;
+
+ case 'y':
+ {
+ register symbol *sp = getsym(&swt[2]);
+ sp->flags |= GS_TRACE;
+ }
+ return;
+
+ case 'z':
+ magic = ZMAGIC;
+ oldmagic = 0;
+#ifdef __FreeBSD__
+ netzmagic = 1;
+#endif
+ return;
+
+ case 'Z':
+ magic = oldmagic = ZMAGIC;
+#ifdef __FreeBSD__
+ netzmagic = 0;
+#endif
+ return;
+
+ default:
+ errx(1, "invalid command option `%s'", swt);
+ }
+}
+
+/* Convenient functions for operating on one or all files being loaded. */
+
+/*
+ * Call FUNCTION on each input file entry. Do not call for entries for
+ * libraries; instead, call once for each library member that is being
+ * loaded.
+ *
+ * FUNCTION receives two arguments: the entry, and ARG.
+ */
+
+void
+each_file(function, arg)
+ register void (*function)();
+ register void *arg;
+{
+ register int i;
+
+ for (i = 0; i < number_of_files; i++) {
+ register struct file_entry *entry = &file_table[i];
+ register struct file_entry *subentry;
+
+ if (entry->flags & E_SCRAPPED)
+ continue;
+
+ if (!(entry->flags & E_IS_LIBRARY))
+ (*function)(entry, arg);
+
+ subentry = entry->subfiles;
+ for (; subentry; subentry = subentry->chain) {
+ if (subentry->flags & E_SCRAPPED)
+ continue;
+ (*function)(subentry, arg);
+ }
+
+#ifdef SUN_COMPAT
+ if (entry->silly_archive) {
+
+ if (!(entry->flags & E_DYNAMIC))
+ warnx("Silly");
+
+ if (!(entry->silly_archive->flags & E_IS_LIBRARY))
+ warnx("Sillier");
+
+ subentry = entry->silly_archive->subfiles;
+ for (; subentry; subentry = subentry->chain) {
+ if (subentry->flags & E_SCRAPPED)
+ continue;
+ (*function)(subentry, arg);
+ }
+ }
+#endif
+ }
+}
+
+/*
+ * Call FUNCTION on each input file entry until it returns a non-zero value.
+ * Return this value. Do not call for entries for libraries; instead, call
+ * once for each library member that is being loaded.
+ *
+ * FUNCTION receives two arguments: the entry, and ARG. It must be a function
+ * returning unsigned long (though this can probably be fudged).
+ */
+
+unsigned long
+check_each_file(function, arg)
+ register unsigned long (*function)();
+ register void *arg;
+{
+ register int i;
+ register unsigned long return_val;
+
+ for (i = 0; i < number_of_files; i++) {
+ register struct file_entry *entry = &file_table[i];
+ if (entry->flags & E_SCRAPPED)
+ continue;
+ if (entry->flags & E_IS_LIBRARY) {
+ register struct file_entry *subentry = entry->subfiles;
+ for (; subentry; subentry = subentry->chain) {
+ if (subentry->flags & E_SCRAPPED)
+ continue;
+ if ( (return_val = (*function)(subentry, arg)) )
+ return return_val;
+ }
+ } else if ( (return_val = (*function)(entry, arg)) )
+ return return_val;
+ }
+ return 0;
+}
+
+/* Like `each_file' but ignore files that were just for symbol definitions. */
+
+void
+each_full_file(function, arg)
+ register void (*function)();
+ register void *arg;
+{
+ register int i;
+
+ for (i = 0; i < number_of_files; i++) {
+ register struct file_entry *entry = &file_table[i];
+ register struct file_entry *subentry;
+
+ if (entry->flags & (E_SCRAPPED | E_JUST_SYMS))
+ continue;
+
+#ifdef SUN_COMPAT
+ if (entry->silly_archive) {
+
+ if (!(entry->flags & E_DYNAMIC))
+ warnx("Silly");
+
+ if (!(entry->silly_archive->flags & E_IS_LIBRARY))
+ warnx("Sillier");
+
+ subentry = entry->silly_archive->subfiles;
+ for (; subentry; subentry = subentry->chain) {
+ if (subentry->flags & E_SCRAPPED)
+ continue;
+ (*function)(subentry, arg);
+ }
+ }
+#endif
+ if (entry->flags & E_DYNAMIC)
+ continue;
+
+ if (!(entry->flags & E_IS_LIBRARY))
+ (*function)(entry, arg);
+
+ subentry = entry->subfiles;
+ for (; subentry; subentry = subentry->chain) {
+ if (subentry->flags & E_SCRAPPED)
+ continue;
+ (*function)(subentry, arg);
+ }
+
+ }
+}
+
+/* Close the input file that is now open. */
+
+void
+file_close()
+{
+ close(input_desc);
+ input_desc = 0;
+ input_file = 0;
+}
+
+/*
+ * Open the input file specified by 'entry', and return a descriptor. The
+ * open file is remembered; if the same file is opened twice in a row, a new
+ * open is not actually done.
+ */
+int
+file_open(entry)
+ register struct file_entry *entry;
+{
+ register int fd;
+
+ if (entry->superfile && (entry->superfile->flags & E_IS_LIBRARY))
+ return file_open(entry->superfile);
+
+ if (entry == input_file)
+ return input_desc;
+
+ if (input_file)
+ file_close();
+
+ if (entry->flags & E_SEARCH_DIRS) {
+ fd = findlib(entry);
+ } else
+ fd = open(entry->filename, O_RDONLY, 0);
+
+ if (fd >= 0) {
+ input_file = entry;
+ input_desc = fd;
+ return fd;
+ }
+
+ if (entry->flags & E_SEARCH_DIRS)
+ errx(1, "%s: no match", entry->local_sym_name);
+ else
+ err(1, "%s", entry->filename);
+ return fd;
+}
+
+int
+text_offset(entry)
+ struct file_entry *entry;
+{
+ return entry->starting_offset + N_TXTOFF (entry->header);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Read a file's header into the proper place in the file_entry. FD is the
+ * descriptor on which the file is open. ENTRY is the file's entry.
+ */
+void
+read_header(fd, entry)
+ int fd;
+ struct file_entry *entry;
+{
+ register int len;
+
+ if (lseek(fd, entry->starting_offset, L_SET) !=
+ entry->starting_offset)
+ err(1, "%s: read_header: lseek", get_file_name(entry));
+
+ len = read(fd, &entry->header, sizeof(struct exec));
+ if (len != sizeof (struct exec))
+ err(1, "%s: read_header: read", get_file_name(entry));
+
+ md_swapin_exec_hdr(&entry->header);
+
+ if (N_BADMAG (entry->header))
+ errx(1, "%s: bad magic", get_file_name(entry));
+
+ if (N_BADMID(entry->header))
+ errx(1, "%s: non-native input file", get_file_name(entry));
+
+ entry->flags |= E_HEADER_VALID;
+}
+
+/*
+ * Read the symbols of file ENTRY into core. Assume it is already open, on
+ * descriptor FD. Also read the length of the string table, which follows
+ * the symbol table, but don't read the contents of the string table.
+ */
+
+void
+read_entry_symbols(fd, entry)
+ struct file_entry *entry;
+ int fd;
+{
+ int str_size;
+ struct nlist *np;
+ int i;
+
+ if (!(entry->flags & E_HEADER_VALID))
+ read_header(fd, entry);
+
+ np = (struct nlist *)alloca(entry->header.a_syms);
+ entry->nsymbols = entry->header.a_syms / sizeof(struct nlist);
+ if (entry->nsymbols == 0)
+ return;
+
+ entry->symbols = (struct localsymbol *)
+ xmalloc(entry->nsymbols * sizeof(struct localsymbol));
+
+ if (lseek(fd, N_SYMOFF(entry->header) + entry->starting_offset, L_SET)
+ != N_SYMOFF(entry->header) + entry->starting_offset)
+ err(1, "%s: read_symbols: lseek(syms)", get_file_name(entry));
+
+ if (entry->header.a_syms != read(fd, np, entry->header.a_syms))
+ errx(1, "%s: read_symbols: premature end of file in symbols",
+ get_file_name(entry));
+
+ md_swapin_symbols(np, entry->header.a_syms / sizeof(struct nlist));
+
+ for (i = 0; i < entry->nsymbols; i++) {
+ entry->symbols[i].nzlist.nlist = *np++;
+ entry->symbols[i].nzlist.nz_size = 0;
+ entry->symbols[i].symbol = NULL;
+ entry->symbols[i].next = NULL;
+ entry->symbols[i].entry = entry;
+ entry->symbols[i].gotslot_offset = -1;
+ entry->symbols[i].flags = 0;
+ }
+
+ entry->strings_offset = N_STROFF(entry->header) +
+ entry->starting_offset;
+ if (lseek(fd, entry->strings_offset, 0) == (off_t)-1)
+ err(1, "%s: read_symbols: lseek(strings)",
+ get_file_name(entry));
+ if (sizeof str_size != read(fd, &str_size, sizeof str_size))
+ errx(1, "%s: read_symbols: cannot read string table size",
+ get_file_name(entry));
+
+ entry->string_size = md_swap_long(str_size);
+}
+
+/*
+ * Read the string table of file ENTRY open on descriptor FD, into core.
+ */
+void
+read_entry_strings(fd, entry)
+ struct file_entry *entry;
+ int fd;
+{
+
+ if (entry->string_size == 0)
+ return;
+
+ if (!(entry->flags & E_HEADER_VALID) || !entry->strings_offset)
+ errx(1, "%s: read_strings: string table unavailable",
+ get_file_name(entry));
+
+ if (lseek(fd, entry->strings_offset, L_SET) !=
+ entry->strings_offset)
+ err(1, "%s: read_strings: lseek",
+ get_file_name(entry));
+
+ if (read(fd, entry->strings, entry->string_size) !=
+ entry->string_size)
+ errx(1, "%s: read_strings: premature end of file in strings",
+ get_file_name(entry));
+
+ return;
+}
+
+/* Read in the relocation sections of ENTRY if necessary */
+
+void
+read_entry_relocation(fd, entry)
+ int fd;
+ struct file_entry *entry;
+{
+ register struct relocation_info *reloc;
+ off_t pos;
+
+ if (!entry->textrel) {
+
+ reloc = (struct relocation_info *)
+ xmalloc(entry->header.a_trsize);
+
+ pos = text_offset(entry) +
+ entry->header.a_text + entry->header.a_data;
+
+ if (lseek(fd, pos, L_SET) != pos)
+ err(1, "%s: read_reloc(text): lseek",
+ get_file_name(entry));
+
+ if (read(fd, reloc, entry->header.a_trsize) !=
+ entry->header.a_trsize)
+ errx(1, "%s: read_reloc(text): premature EOF",
+ get_file_name(entry));
+
+ md_swapin_reloc(reloc, entry->header.a_trsize / sizeof(*reloc));
+ entry->textrel = reloc;
+ entry->ntextrel = entry->header.a_trsize / sizeof(*reloc);
+
+ }
+
+ if (!entry->datarel) {
+
+ reloc = (struct relocation_info *)
+ xmalloc(entry->header.a_drsize);
+
+ pos = text_offset(entry) + entry->header.a_text +
+ entry->header.a_data + entry->header.a_trsize;
+
+ if (lseek(fd, pos, L_SET) != pos)
+ err(1, "%s: read_reloc(data): lseek",
+ get_file_name(entry));
+
+ if (read(fd, reloc, entry->header.a_drsize) !=
+ entry->header.a_drsize)
+ errx(1, "%s: read_reloc(data): premature EOF",
+ get_file_name(entry));
+
+ md_swapin_reloc(reloc, entry->header.a_drsize / sizeof(*reloc));
+ entry->datarel = reloc;
+ entry->ndatarel = entry->header.a_drsize / sizeof(*reloc);
+
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Read in the symbols of all input files.
+ */
+static void
+load_symbols()
+{
+ register int i;
+
+ if (trace_files)
+ fprintf(stderr, "Loading symbols:\n\n");
+
+ for (i = 0; i < number_of_files; i++)
+ read_file_symbols(&file_table[i]);
+
+ if (trace_files)
+ fprintf(stderr, "\n");
+}
+
+/*
+ * If ENTRY is a rel file, read its symbol and string sections into core. If
+ * it is a library, search it and load the appropriate members (which means
+ * calling this function recursively on those members).
+ */
+
+void
+read_file_symbols(entry)
+ register struct file_entry *entry;
+{
+ register int fd;
+ register int len;
+ struct exec hdr;
+
+ fd = file_open(entry);
+
+ len = read(fd, &hdr, sizeof hdr);
+ if (len != sizeof hdr)
+ errx(1, "%s: read_file_symbols(header): premature EOF",
+ get_file_name(entry));
+
+ md_swapin_exec_hdr(&hdr);
+
+ if (!N_BADMAG (hdr)) {
+ if (N_IS_DYNAMIC(hdr) && !(entry->flags & E_JUST_SYMS)) {
+ if (relocatable_output) {
+ errx(1,
+ "%s: -r and shared objects currently not supported",
+ get_file_name(entry));
+ return;
+ }
+#if notyet /* Compatibility */
+ if (!(N_GETFLAG(hdr) & EX_PIC))
+ warnx("%s: EX_PIC not set",
+ get_file_name(entry));
+#endif
+ entry->flags |= E_DYNAMIC;
+ if (entry->superfile || rrs_add_shobj(entry))
+ read_shared_object(fd, entry);
+ else
+ entry->flags |= E_SCRAPPED;
+ } else {
+ if (N_GETFLAG(hdr) & EX_PIC)
+ pic_code_seen = 1;
+ read_entry_symbols(fd, entry);
+ entry->strings = (char *)alloca(entry->string_size);
+ read_entry_strings(fd, entry);
+ read_entry_relocation(fd, entry);
+ enter_file_symbols(entry);
+ entry->strings = 0;
+ }
+ } else {
+ char armag[SARMAG];
+
+ lseek (fd, 0, 0);
+ if (SARMAG != read(fd, armag, SARMAG) ||
+ strncmp (armag, ARMAG, SARMAG))
+ errx(1,
+ "%s: malformed input file (not rel or archive)",
+ get_file_name(entry));
+ entry->flags |= E_IS_LIBRARY;
+ search_library(fd, entry);
+ }
+
+ file_close();
+}
+
+
+/*
+ * Enter the external symbol defs and refs of ENTRY in the hash table.
+ */
+
+void
+enter_file_symbols(entry)
+ struct file_entry *entry;
+{
+ struct localsymbol *lsp, *lspend;
+
+ if (trace_files)
+ prline_file_name(entry, stderr);
+
+ lspend = entry->symbols + entry->nsymbols;
+
+ for (lsp = entry->symbols; lsp < lspend; lsp++) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+
+ if (p->n_type == (N_SETV | N_EXT))
+ continue;
+
+ /*
+ * Turn magically prefixed symbols into set symbols of
+ * a corresponding type.
+ */
+ if (set_element_prefixes &&
+ set_element_prefixed_p(entry->strings+lsp->nzlist.nz_strx))
+ lsp->nzlist.nz_type += (N_SETA - N_ABS);
+
+ if (SET_ELEMENT_P(p->n_type)) {
+ set_symbol_count++;
+ if (!relocatable_output)
+ enter_global_ref(lsp,
+ p->n_un.n_strx + entry->strings, entry);
+ } else if (p->n_type == N_WARNING) {
+ char *msg = p->n_un.n_strx + entry->strings;
+
+ /* Grab the next entry. */
+ lsp++;
+ p = &lsp->nzlist.nlist;
+ if (p->n_type != (N_UNDF | N_EXT)) {
+ warnx(
+ "%s: Warning symbol without external reference following.",
+ get_file_name(entry));
+ make_executable = 0;
+ lsp--; /* Process normally. */
+ } else {
+ symbol *sp;
+ char *name = p->n_un.n_strx + entry->strings;
+ /* Deal with the warning symbol. */
+ lsp->flags |= LS_WARNING;
+ enter_global_ref(lsp, name, entry);
+ sp = getsym(name);
+ if (sp->warning == NULL) {
+ sp->warning = (char *)
+ xmalloc(strlen(msg)+1);
+ strcpy(sp->warning, msg);
+ warn_sym_count++;
+ } else if (strcmp(sp->warning, msg))
+ warnx(
+ "%s: multiple definitions for warning symbol `%s'",
+ get_file_name(entry), demangle(sp->name));
+ }
+ } else if (p->n_type & N_EXT) {
+ enter_global_ref(lsp,
+ p->n_un.n_strx + entry->strings, entry);
+ } else if (p->n_un.n_strx &&
+ (p->n_un.n_strx + entry->strings)[0] == LPREFIX)
+ lsp->flags |= LS_L_SYMBOL;
+ }
+
+}
+
+/*
+ * Enter one global symbol in the hash table. LSP points to the `struct
+ * localsymbol' from the file that describes the global symbol. NAME is the
+ * symbol's name. ENTRY is the file entry for the file the symbol comes from.
+ *
+ * LSP is put on the chain of all such structs that refer to the same symbol.
+ * This chain starts in the `refs' for symbols from relocatable objects. A
+ * backpointer to the global symbol is kept in LSP.
+ *
+ * Symbols from shared objects are linked through `soref'. For such symbols
+ * that's all we do at this stage, with the exception of the case where the
+ * symbol is a common. The `referenced' bit is only set for references from
+ * relocatable objects.
+ *
+ */
+
+static void
+enter_global_ref(lsp, name, entry)
+ struct localsymbol *lsp;
+ char *name;
+ struct file_entry *entry;
+{
+ register struct nzlist *nzp = &lsp->nzlist;
+ register symbol *sp = getsym(name);
+ register int type = nzp->nz_type;
+ int oldref = (sp->flags & GS_REFERENCED);
+ int olddef = sp->defined;
+ int com = sp->defined && sp->common_size;
+
+ if (type == (N_INDR | N_EXT) && !olddef) {
+ sp->alias = getsym(entry->strings + (lsp + 1)->nzlist.nz_strx);
+ if (sp == sp->alias) {
+ warnx("%s: %s is alias for itself",
+ get_file_name(entry), name);
+ /* Rewrite symbol as global text symbol with value 0 */
+ lsp->nzlist.nz_type = N_TEXT|N_EXT;
+ lsp->nzlist.nz_value = 0;
+ make_executable = 0;
+ }
+#if 0
+ if (sp->flags & GS_REFERENCED)
+ sp->alias->flags |= GS_REFERENCED;
+#endif
+ }
+
+ if (entry->flags & E_DYNAMIC) {
+ lsp->next = sp->sorefs;
+ sp->sorefs = lsp;
+ lsp->symbol = sp;
+
+ /*
+ * Handle commons from shared objects:
+ * 1) If symbol hitherto undefined, turn it into a common.
+ * 2) If symbol already common, update size if necessary.
+ */
+/*XXX - look at case where commons are only in shared objects */
+ if (type == (N_UNDF | N_EXT) && nzp->nz_value) {
+ if (!olddef) {
+ if (oldref)
+ undefined_global_sym_count--;
+ common_defined_global_count++;
+ sp->common_size = nzp->nz_value;
+ sp->defined = N_UNDF | N_EXT;
+ } else if (com && sp->common_size < nzp->nz_value) {
+ sp->common_size = nzp->nz_value;
+ }
+ } else if (type != (N_UNDF | N_EXT) && !oldref) {
+ /*
+ * This is an ex common...
+ */
+ if (com)
+ common_defined_global_count--;
+ sp->common_size = 0;
+ sp->defined = 0;
+ }
+
+ /*
+ * Handle size information in shared objects.
+ */
+ if (nzp->nz_size > sp->size)
+ sp->size = nzp->nz_size;
+
+ if ((lsp->flags & LS_WARNING) && (sp->flags & GS_REFERENCED))
+ /*
+ * Prevent warning symbols from getting
+ * gratuitously referenced.
+ */
+ list_warning_symbols = 1;
+ return;
+ }
+
+ lsp->next = sp->refs;
+ sp->refs = lsp;
+ lsp->symbol = sp;
+
+ if (lsp->flags & LS_WARNING) {
+ /*
+ * Prevent warning symbols from getting
+ * gratuitously referenced.
+ */
+ if (sp->flags & GS_REFERENCED)
+ list_warning_symbols = 1;
+ return;
+ }
+
+ if (sp->warning)
+ list_warning_symbols = 1;
+
+ sp->flags |= GS_REFERENCED;
+
+ if (sp == dynamic_symbol || sp == got_symbol) {
+ if (type != (N_UNDF | N_EXT) && !(entry->flags & E_JUST_SYMS))
+ errx(1,"Linker reserved symbol %s defined as type %x ",
+ name, type);
+ return;
+ }
+
+ if (olddef && N_ISWEAK(&nzp->nlist) && !(sp->flags & GS_WEAK)) {
+#ifdef DEBUG
+ printf("%s: not overridden by weak symbol from %s\n",
+ demangle(sp->name), get_file_name(entry));
+#endif
+ return;
+ }
+
+ if (type == (N_SIZE | N_EXT)) {
+
+ if (relocatable_output && nzp->nz_value != 0 && sp->size == 0)
+ size_sym_count++;
+ if (sp->size < nzp->nz_value)
+ sp->size = nzp->nz_value;
+
+ } else if (type != (N_UNDF | N_EXT) || nzp->nz_value) {
+
+ /*
+ * Set `->defined' here, so commons and undefined globals
+ * can be counted correctly.
+ */
+ if (!sp->defined || sp->defined == (N_UNDF | N_EXT)) {
+ sp->defined = type;
+ }
+
+ if ((sp->flags & GS_WEAK) && !N_ISWEAK(&nzp->nlist)) {
+ /*
+ * Upgrade an existing weak definition.
+ * We fake it by pretending the symbol is undefined;
+ * must undo any common fiddling, however.
+ */
+ if (!oldref)
+ errx(1, "internal error: enter_glob_ref: "
+ "weak symbol not referenced");
+ if (!olddef && !com)
+ undefined_weak_sym_count--;
+ undefined_global_sym_count++;
+ sp->defined = type;
+ sp->flags &= ~GS_WEAK;
+ olddef = 0;
+ if (com)
+ common_defined_global_count--;
+ com = 0;
+ sp->common_size = 0;
+ }
+ if (oldref && !olddef) {
+ /*
+ * It used to be undefined and we're defining it.
+ */
+ undefined_global_sym_count--;
+ if (sp->flags & GS_WEAK)
+ /* Used to be a weak reference */
+ undefined_weak_sym_count--;
+ if (undefined_global_sym_count < 0 ||
+ undefined_weak_sym_count < 0)
+ errx(1, "internal error: enter_glob_ref: "
+ "undefined_global_sym_count = %d, "
+ "undefined_weak_sym_count = %d",
+ undefined_global_sym_count,
+ undefined_weak_sym_count);
+
+ }
+
+ if (N_ISWEAK(&nzp->nlist))
+ /* The definition is weak */
+ sp->flags |= GS_WEAK;
+
+ if (!olddef && type == (N_UNDF | N_EXT) && nzp->nz_value) {
+ /*
+ * First definition and it's common.
+ */
+ common_defined_global_count++;
+ sp->common_size = nzp->nz_value;
+ } else if (com && type != (N_UNDF | N_EXT)) {
+ /*
+ * It used to be common and we're defining
+ * it as something else.
+ */
+ common_defined_global_count--;
+ sp->common_size = 0;
+ } else if (com && type == (N_UNDF | N_EXT) &&
+ sp->common_size < nzp->nz_value)
+ /*
+ * It used to be common and this is a new common entry
+ * to which we need to pay attention.
+ */
+ sp->common_size = nzp->nz_value;
+
+ if (SET_ELEMENT_P(type) && (!olddef || com))
+ set_vector_count++;
+
+ } else if (!oldref && !com) {
+ /*
+ * An unreferenced symbol can already be defined
+ * as common by shared objects.
+ */
+ undefined_global_sym_count++;
+ if (N_ISWEAK(&nzp->nlist)) {
+ /* The reference is weak */
+ sp->flags |= GS_WEAK;
+ undefined_weak_sym_count++;
+ }
+ }
+
+ if (sp == end_symbol && (entry->flags & E_JUST_SYMS) &&
+ !T_flag_specified)
+ text_start = nzp->nz_value;
+
+ if (sp->flags & GS_TRACE) {
+ register char *reftype;
+ switch (type & N_TYPE) {
+ case N_UNDF:
+ reftype = nzp->nz_value
+ ? "defined as common" : "referenced";
+ break;
+
+ case N_ABS:
+ reftype = "defined as absolute";
+ break;
+
+ case N_TEXT:
+ reftype = "defined in text section";
+ break;
+
+ case N_DATA:
+ reftype = "defined in data section";
+ break;
+
+ case N_BSS:
+ reftype = "defined in BSS section";
+ break;
+
+ case N_INDR:
+ reftype = "alias";
+ break;
+
+ case N_SIZE:
+ reftype = "size spec";
+ break;
+
+ default:
+ reftype = "I don't know this type";
+ break;
+ }
+
+ fprintf(stderr, "symbol %s %s%s in ", demangle(sp->name),
+ (N_ISWEAK(&nzp->nlist))?"weakly ":"", reftype);
+ print_file_name (entry, stderr);
+ fprintf(stderr, "\n");
+ }
+}
+
+/*
+ * This returns 0 if the given file entry's symbol table does *not* contain
+ * the nlist point entry, and it returns the files entry pointer (cast to
+ * unsigned long) if it does.
+ */
+
+unsigned long
+contains_symbol(entry, np)
+ struct file_entry *entry;
+ register struct nlist *np;
+{
+ if (np >= &entry->symbols->nzlist.nlist &&
+ np < &(entry->symbols + entry->nsymbols)->nzlist.nlist)
+ return (unsigned long) entry;
+ return 0;
+}
+
+
+/*
+ * Having entered all the global symbols and found the sizes of sections of
+ * all files to be linked, make all appropriate deductions from this data.
+ *
+ * We propagate global symbol values from definitions to references. We compute
+ * the layout of the output file and where each input file's contents fit
+ * into it.
+ *
+ * This is now done in several stages.
+ *
+ * 1) All global symbols are examined for definitions in relocatable (.o)
+ * files. The symbols' type is set according to the definition found,
+ * but its value can not yet be determined. In stead, we keep a pointer
+ * to the file entry's localsymbol that bequeathed the global symbol with
+ * its definition. Also, multiple (incompatible) definitions are checked
+ * for in this pass. If no definition comes forward, the set of local
+ * symbols originating from shared objects is searched for a definition.
+ *
+ * 2) Then the relocation information of each relocatable file is examined
+ * for possible contributions to the RRS section.
+ *
+ * 3) When this is done, the sizes and start addresses are set of all segments
+ * that will appear in the output file (including the RRS segment).
+ *
+ * 4) Finally, all symbols are relocated according according to the start
+ * of the entry they are part of. Then global symbols are assigned their
+ * final values. Also, space for commons and imported data are allocated
+ * during this pass, if the link mode in effect so demands.
+ *
+ */
+
+static void
+digest_symbols()
+{
+
+ if (trace_files)
+ fprintf(stderr, "Digesting symbol information:\n\n");
+
+ if (!relocatable_output) {
+ /*
+ * The set sector size is the number of set elements + a word
+ * for each symbol for the length word at the beginning of
+ * the vector, plus a word for each symbol for a zero at the
+ * end of the vector (for incremental linking).
+ */
+ set_sect_size = (set_symbol_count + 2 * set_vector_count) *
+ sizeof (unsigned long);
+ set_vectors = (long *)xmalloc (set_sect_size);
+ setv_fill_count = 0;
+ }
+
+ /* Pass 1: check and define symbols */
+ defined_global_sym_count = 0;
+ digest_pass1();
+
+ each_full_file(consider_relocation, (void *)0); /* Text */
+ each_full_file(consider_relocation, (void *)1); /* Data */
+
+ each_file(consider_local_symbols, (void *)0);
+
+ /*
+ * Compute total size of sections.
+ * RRS data is the first output data section, RRS text is the last
+ * text section. Thus, DATA_START is calculated from RRS_DATA_START
+ * and RRS_DATA_SIZE, while RRS_TEXT_START is derived from TEXT_START
+ * and TEXT_SIZE.
+ */
+ consider_rrs_section_lengths();
+ each_full_file(consider_file_section_lengths, 0);
+ rrs_text_start = text_start + text_size;
+ text_size += rrs_text_size;
+ data_size += rrs_data_size;
+
+ /*
+ * If necessary, pad text section to full page in the file. Include
+ * the padding in the text segment size.
+ */
+
+ if (page_align_segments || page_align_data) {
+ int text_end = text_size + N_TXTOFF(outheader);
+ text_pad = PALIGN(text_end, page_size) - text_end;
+ text_size += text_pad;
+ }
+ outheader.a_text = text_size;
+
+ /*
+ * Make the data segment address start in memory on a suitable
+ * boundary.
+ */
+
+ if (!Tdata_flag_specified)
+ rrs_data_start = text_start +
+ DATA_START(outheader) - TEXT_START(outheader);
+
+ data_start = rrs_data_start + rrs_data_size;
+ if (!relocatable_output) {
+ set_sect_start = rrs_data_start + data_size;
+ data_size += MALIGN(set_sect_size);
+ }
+ bss_start = rrs_data_start + data_size;
+
+#ifdef DEBUG
+printf("textstart = %#x, textsize = %#x, rrs_text_start = %#x, rrs_text_size %#x\n",
+ text_start, text_size, rrs_text_start, rrs_text_size);
+printf("datastart = %#x, datasize = %#x, rrs_data_start %#x, rrs_data_size %#x\n",
+ data_start, data_size, rrs_data_start, rrs_data_size);
+printf("bssstart = %#x, bsssize = %#x\n",
+ bss_start, bss_size);
+printf("set_sect_start = %#x, set_sect_size = %#x\n",
+ set_sect_start, set_sect_size);
+#endif
+
+ /* Compute start addresses of each file's sections and symbols. */
+
+ each_full_file(relocate_file_addresses, 0);
+ relocate_rrs_addresses();
+
+ /* Pass 2: assign values to symbols */
+ digest_pass2();
+
+ if (end_symbol) { /* These are null if -r. */
+ etext_symbol->value = text_start + text_size - text_pad;
+ edata_symbol->value = rrs_data_start + data_size;
+ end_symbol->value = rrs_data_start + data_size + bss_size;
+ }
+ /*
+ * Figure the data_pad now, so that it overlaps with the bss
+ * addresses.
+ */
+
+ if (specified_data_size && specified_data_size > data_size)
+ data_pad = specified_data_size - data_size;
+
+ if (page_align_segments)
+ data_pad = PALIGN(data_pad + data_size, page_size) - data_size;
+
+ bss_size -= data_pad;
+ if (bss_size < 0)
+ bss_size = 0;
+
+ data_size += data_pad;
+
+ /*
+ * Calculate total number of symbols that will go into
+ * the output symbol table (barring DISCARD_* settings).
+ */
+ global_sym_count = defined_global_sym_count +
+ undefined_global_sym_count;
+
+ if (dynamic_symbol->flags & GS_REFERENCED)
+ global_sym_count++;
+
+ if (got_symbol->flags & GS_REFERENCED)
+ global_sym_count++;
+
+ if (relocatable_output || building_shared_object) {
+ /* For each alias we write out two struct nlists */
+ global_sym_count += global_alias_count;
+ /* Propagate warning symbols; costs two extra struct nlists */
+ global_sym_count += 2 * warn_sym_count;
+ }
+
+ if (relocatable_output)
+ /* We write out the original N_SIZE symbols */
+ global_sym_count += size_sym_count;
+
+#ifdef DEBUG
+printf(
+"global symbols %d "
+"(defined %d, undefined %d, weak %d, aliases %d, warnings 2 * %d, "
+"size symbols %d)\ncommons %d, locals: %d, debug symbols: %d, set_symbols %d\n",
+ global_sym_count,
+ defined_global_sym_count, undefined_global_sym_count,
+ undefined_weak_sym_count,
+ global_alias_count, warn_sym_count, size_sym_count,
+ common_defined_global_count, local_sym_count,
+ debugger_sym_count, set_symbol_count);
+#endif
+}
+
+/*
+ * Determine the definition of each global symbol.
+ */
+static void
+digest_pass1()
+{
+
+ /*
+ * For each symbol, verify that it is defined globally at most
+ * once within relocatable files (except when building a shared lib).
+ * and set the `defined' field if there is a definition.
+ *
+ * Then check the shared object symbol chain for any remaining
+ * undefined symbols. Set the `so_defined' field for any
+ * definition find this way.
+ */
+ FOR_EACH_SYMBOL(i, sp) {
+ symbol *spsave;
+ struct localsymbol *lsp;
+ int defs = 0;
+
+ if (!(sp->flags & GS_REFERENCED)) {
+#if 0
+ /* Check for undefined symbols in shared objects */
+ int type;
+ for (lsp = sp->sorefs; lsp; lsp = lsp->next) {
+ type = lsp->nzlist.nlist.n_type;
+ if ((type & N_EXT) && type != (N_UNDF | N_EXT))
+ break;
+ }
+ if ((type & N_EXT) && type == (N_UNDF | N_EXT))
+ undefined_shobj_sym_count++;
+#endif
+
+ /* Superfluous symbol from shared object */
+ continue;
+ }
+ if (sp->so_defined)
+ /* Already examined; must have been an alias */
+ continue;
+
+ if (sp == got_symbol || sp == dynamic_symbol)
+ continue;
+
+ for (lsp = sp->refs; lsp; lsp = lsp->next) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+ register int type = p->n_type;
+
+ if (SET_ELEMENT_P(type)) {
+ if (relocatable_output)
+ errx(1,
+ "internal error: global ref to set el %s with -r",
+ demangle(sp->name));
+ if (!defs++) {
+ sp->defined = N_SETV | N_EXT;
+ sp->value =
+ setv_fill_count++ * sizeof(long);
+ } else if ((sp->defined & N_TYPE) != N_SETV) {
+ sp->mult_defs = 1;
+ multiple_def_count++;
+ }
+ /* Keep count and remember symbol */
+ sp->setv_count++;
+ set_vectors[setv_fill_count++] = (long)p;
+ if (building_shared_object) {
+ struct relocation_info reloc;
+
+ /*
+ * Make sure to relocate the contents
+ * of this set vector.
+ */
+ bzero(&reloc, sizeof(reloc));
+ RELOC_INIT_SEGMENT_RELOC(&reloc);
+ RELOC_ADDRESS(&reloc) =
+ setv_fill_count * sizeof(long);
+ alloc_rrs_segment_reloc(NULL, &reloc);
+ }
+
+ } else if ((type & N_EXT) && type != (N_UNDF | N_EXT)
+ && (type & N_TYPE) != N_FN
+ && (type & N_TYPE) != N_SIZE) {
+ /* non-common definition */
+ if (!N_ISWEAK(p))
+ ++defs;
+ if (defs > 1) {
+ sp->mult_defs = 1;
+ multiple_def_count++;
+ } else if (!N_ISWEAK(p) ||
+ (!sp->def_lsp && !sp->common_size)) {
+ sp->def_lsp = lsp;
+ lsp->entry->flags |= E_SYMBOLS_USED;
+ sp->defined = type;
+ sp->aux = N_AUX(p);
+ }
+ }
+ }
+
+ /*
+ * If this symbol has acquired final definition, we're done.
+ * Commons must be allowed to bind to shared object data
+ * definitions.
+ */
+ if (sp->defined &&
+ (sp->common_size == 0 ||
+ relocatable_output || building_shared_object)) {
+ if ((sp->defined & N_TYPE) == N_SETV)
+ /* Allocate zero entry in set vector */
+ setv_fill_count++;
+ /*
+ * At this stage, we do not know whether an alias
+ * is going to be defined for real here, or whether
+ * it refers to a shared object symbol. The decision
+ * is deferred until digest_pass2().
+ */
+ if (!sp->alias)
+ defined_global_sym_count++;
+ continue;
+ }
+
+ if (relocatable_output)
+ /* We're done */
+ continue;
+
+ /*
+ * Still undefined, search the shared object symbols for a
+ * definition. This symbol must go into the RRS.
+ */
+ if (building_shared_object) {
+ /* Just punt for now */
+ undefined_global_sym_count--;
+ if (undefined_global_sym_count < 0)
+ errx(1,
+ "internal error: digest_pass1,1: %s: undefined_global_sym_count = %d",
+ demangle(sp->name), undefined_global_sym_count);
+ continue;
+ }
+
+ spsave=sp; /*XXX*/
+ again:
+ for (lsp = sp->sorefs; lsp; lsp = lsp->next) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+ register int type = p->n_type;
+
+ if ((type & N_EXT) && type != (N_UNDF | N_EXT) &&
+ (type & N_TYPE) != N_FN) {
+ /* non-common definition */
+ if (sp->common_size) {
+ /*
+ * This common has an so defn; switch
+ * to it iff defn is: data, first-class
+ * and not weak.
+ */
+ if (N_AUX(p) != AUX_OBJECT ||
+ N_ISWEAK(p) ||
+ (lsp->entry->flags & E_SECONDCLASS))
+ continue;
+
+ /*
+ * Change common to so ref. First,
+ * downgrade common to undefined.
+ */
+ sp->common_size = 0;
+ sp->defined = 0;
+ common_defined_global_count--;
+ undefined_global_sym_count++;
+ }
+ sp->def_lsp = lsp;
+ sp->so_defined = type;
+ sp->aux = N_AUX(p);
+ if (lsp->entry->flags & E_SECONDCLASS)
+ /* Keep looking for something better */
+ continue;
+ if (N_ISWEAK(p))
+ /* Keep looking for something better */
+ continue;
+ break;
+ }
+ }
+ if (sp->def_lsp) {
+#ifdef DEBUG
+printf("pass1: SO definition for %s, type %x in %s at %#x\n",
+ demangle(sp->name), sp->so_defined, get_file_name(sp->def_lsp->entry),
+ sp->def_lsp->nzlist.nz_value);
+#endif
+ sp->def_lsp->entry->flags |= E_SYMBOLS_USED;
+ if (sp->flags & GS_REFERENCED) {
+ undefined_global_sym_count--;
+ } else
+ sp->flags |= GS_REFERENCED;
+ if (undefined_global_sym_count < 0)
+ errx(1, "internal error: digest_pass1,2: "
+ "%s: undefined_global_sym_count = %d",
+ demangle(sp->name), undefined_global_sym_count);
+ if (sp->alias &&
+ !(sp->alias->flags & GS_REFERENCED)) {
+ sp = sp->alias;
+ goto again;
+ }
+ } else if (sp->defined) {
+ if (sp->common_size == 0)
+ errx(1, "internal error: digest_pass1,3: "
+ "%s: not a common: %x",
+ demangle(sp->name), sp->defined);
+ /*
+ * Common not bound to shared object data; treat
+ * it now like other defined symbols were above.
+ */
+ if (!sp->alias)
+ defined_global_sym_count++;
+ }
+ sp=spsave; /*XXX*/
+ } END_EACH_SYMBOL;
+
+ if (setv_fill_count != set_sect_size/sizeof(long))
+ errx(1, "internal error: allocated set symbol space (%d) "
+ "doesn't match actual (%d)",
+ set_sect_size/sizeof(long), setv_fill_count);
+}
+
+
+/*
+ * Scan relocation info in ENTRY for contributions to the RRS section
+ * of the output file.
+ */
+static void
+consider_relocation(entry, dataseg)
+ struct file_entry *entry;
+ int dataseg;
+{
+ struct relocation_info *reloc, *end;
+ struct localsymbol *lsp;
+ symbol *sp;
+
+ if (dataseg == 0) {
+ /* Text relocations */
+ reloc = entry->textrel;
+ end = entry->textrel + entry->ntextrel;
+ } else {
+ /* Data relocations */
+ reloc = entry->datarel;
+ end = entry->datarel + entry->ndatarel;
+ }
+
+ for (; reloc < end; reloc++) {
+
+ if (relocatable_output) {
+ lsp = &entry->symbols[reloc->r_symbolnum];
+ if (RELOC_BASEREL_P(reloc)) {
+ pic_code_seen = 1; /* Compatibility */
+ if (!RELOC_EXTERN_P(reloc))
+ lsp->flags |= LS_RENAME;
+ }
+ continue;
+ }
+
+ /*
+ * First, do the PIC specific relocs.
+ * r_relative and r_copy should not occur at this point
+ * (we do output them). The others break down to these
+ * combinations:
+ *
+ * jmptab: extern: needs jmp slot
+ * !extern: "intersegment" jump/call,
+ * should get resolved in output
+ *
+ * baserel: extern: need GOT entry
+ * !extern: may need GOT entry,
+ * machine dependent
+ *
+ * baserel's always refer to symbol through `r_symbolnum'
+ * whether extern or not. Internal baserels refer to statics
+ * that must be accessed either *through* the GOT table like
+ * global data, or by means of an offset from the GOT table.
+ * The macro RELOC_STATICS_THROUGH_GOT_P() determines which
+ * applies, since this is a machine (compiler?) dependent
+ * addressing mode.
+ */
+
+ if (RELOC_JMPTAB_P(reloc)) {
+
+ if (!RELOC_EXTERN_P(reloc))
+ continue;
+
+ lsp = &entry->symbols[reloc->r_symbolnum];
+ sp = lsp->symbol;
+ if (sp->alias)
+ sp = sp->alias;
+ if (sp->flags & GS_TRACE) {
+ fprintf(stderr, "symbol %s has jmpslot in %s\n",
+ demangle(sp->name), get_file_name(entry));
+ }
+ alloc_rrs_jmpslot(entry, sp);
+
+ } else if (RELOC_BASEREL_P(reloc)) {
+
+ lsp = &entry->symbols[reloc->r_symbolnum];
+ alloc_rrs_gotslot(entry, reloc, lsp);
+ if (pic_type != PIC_TYPE_NONE &&
+ RELOC_PIC_TYPE(reloc) != pic_type)
+ errx(1, "%s: illegal reloc type mix",
+ get_file_name(entry));
+ pic_type = RELOC_PIC_TYPE(reloc);
+
+ } else if (RELOC_EXTERN_P(reloc)) {
+
+ /*
+ * Non-PIC relocations.
+ * If the definition comes from a shared object
+ * we need a relocation entry in RRS.
+ *
+ * If the .so definition is N_TEXT a jmpslot is
+ * allocated.
+ *
+ * If it is N_DATA we allocate an address in BSS (?)
+ * and arrange for the data to be copied at run-time.
+ * The symbol is temporarily marked with N_SIZE in
+ * the `defined' field, so we know what to do in
+ * pass2() and during actual relocation. We convert
+ * the type back to something real again when writing
+ * out the symbols.
+ *
+ */
+ lsp = &entry->symbols[reloc->r_symbolnum];
+ sp = lsp->symbol;
+ if (sp == NULL)
+ errx(1, "%s: bogus relocation record",
+ get_file_name(entry));
+
+ if (sp->alias)
+ sp = sp->alias;
+
+ /*
+ * Skip refs to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC
+ */
+ if (sp == got_symbol) {
+ if (!CHECK_GOT_RELOC(reloc))
+ errx(1,
+ "%s: Unexpected relocation type for GOT symbol",
+ get_file_name(entry));
+ continue;
+ }
+
+ /*
+ * This symbol gives rise to a RRS entry
+ */
+
+ if (building_shared_object) {
+ if (sp->flags & GS_TRACE) {
+ fprintf(stderr,
+ "symbol %s RRS entry in %s\n",
+ demangle(sp->name), get_file_name(entry));
+ }
+ alloc_rrs_reloc(entry, sp);
+ continue;
+ }
+
+ if (force_alias_definition && sp->so_defined &&
+ sp->aux == AUX_FUNC) {
+
+ /* Call to shared library procedure */
+ alloc_rrs_jmpslot(entry, sp);
+
+ } else if (sp->size && sp->so_defined &&
+ sp->aux == AUX_OBJECT) {
+
+ /* Reference to shared library data */
+ alloc_rrs_cpy_reloc(entry, sp);
+ sp->defined = N_SIZE;
+
+ } else if (!sp->defined && sp->common_size == 0 &&
+ sp->so_defined)
+ alloc_rrs_reloc(entry, sp);
+
+ } else {
+ /*
+ * Segment relocation.
+ * Prepare an RRS relocation as these are load
+ * address dependent.
+ */
+ if (building_shared_object && !RELOC_PCREL_P(reloc)) {
+ alloc_rrs_segment_reloc(entry, reloc);
+ }
+ }
+ }
+}
+
+/*
+ * Determine the disposition of each local symbol.
+ */
+static void
+consider_local_symbols(entry)
+ register struct file_entry *entry;
+{
+ register struct localsymbol *lsp, *lspend;
+
+ if (entry->flags & E_DYNAMIC)
+ return;
+
+ lspend = entry->symbols + entry->nsymbols;
+
+ /*
+ * For each symbol determine whether it should go
+ * in the output symbol table.
+ */
+
+ for (lsp = entry->symbols; lsp < lspend; lsp++) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+ register int type = p->n_type;
+
+ if (type == N_WARNING)
+ continue;
+
+ if (SET_ELEMENT_P (type)) {
+ /*
+ * This occurs even if global. These types of
+ * symbols are never written globally, though
+ * they are stored globally.
+ */
+ if (relocatable_output)
+ lsp->flags |= LS_WRITE;
+
+ } else if (!(type & (N_STAB | N_EXT))) {
+
+ /*
+ * Ordinary local symbol
+ */
+ if ((lsp->flags & LS_RENAME) || (
+ discard_locals != DISCARD_ALL &&
+ !(discard_locals == DISCARD_L &&
+ (lsp->flags & LS_L_SYMBOL))) ) {
+
+ lsp->flags |= LS_WRITE;
+ local_sym_count++;
+ }
+
+ } else if (!(type & N_EXT)) {
+
+ /*
+ * Debugger symbol
+ */
+ if (strip_symbols == STRIP_NONE) {
+ lsp->flags |= LS_WRITE;
+ debugger_sym_count++;
+ }
+ }
+ }
+
+ /*
+ * Count one for the local symbol that we generate,
+ * whose name is the file's name (usually) and whose address
+ * is the start of the file's text.
+ */
+ if (discard_locals != DISCARD_ALL)
+ local_sym_count++;
+}
+
+/*
+ * Accumulate the section sizes of input file ENTRY into the section sizes of
+ * the output file.
+ */
+static void
+consider_file_section_lengths(entry)
+ register struct file_entry *entry;
+{
+
+ entry->text_start_address = text_size;
+ /* If there were any vectors, we need to chop them off */
+ text_size += entry->header.a_text;
+ entry->data_start_address = data_size;
+ data_size += entry->header.a_data;
+ entry->bss_start_address = bss_size;
+ bss_size += MALIGN(entry->header.a_bss);
+
+ text_reloc_size += entry->header.a_trsize;
+ data_reloc_size += entry->header.a_drsize;
+}
+
+/*
+ * Determine where the sections of ENTRY go into the output file,
+ * whose total section sizes are already known.
+ * Also relocate the addresses of the file's local and debugger symbols.
+ */
+static void
+relocate_file_addresses(entry)
+ register struct file_entry *entry;
+{
+ register struct localsymbol *lsp, *lspend;
+
+ entry->text_start_address += text_start;
+ /*
+ * Note that `data_start' and `data_size' have not yet been
+ * adjusted for `data_pad'. If they had been, we would get the wrong
+ * results here.
+ */
+ entry->data_start_address += data_start;
+ entry->bss_start_address += bss_start;
+#ifdef DEBUG
+printf("%s: datastart: %#x, bss %#x\n", get_file_name(entry),
+ entry->data_start_address, entry->bss_start_address);
+#endif
+
+ lspend = entry->symbols + entry->nsymbols;
+
+ for (lsp = entry->symbols; lsp < lspend; lsp++) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+ register int type = p->n_type;
+
+ /*
+ * If this belongs to a section, update it
+ * by the section's start address
+ */
+
+ switch (type & N_TYPE) {
+ case N_TEXT:
+ case N_SETT:
+ p->n_value += entry->text_start_address;
+ break;
+ case N_DATA:
+ case N_SETD:
+ case N_SETV:
+ /*
+ * A symbol whose value is in the data section is
+ * present in the input file as if the data section
+ * started at an address equal to the length of the
+ * file's text.
+ */
+ p->n_value += entry->data_start_address -
+ entry->header.a_text;
+ break;
+ case N_BSS:
+ case N_SETB:
+ /* likewise for symbols with value in BSS. */
+ p->n_value += entry->bss_start_address -
+ (entry->header.a_text +
+ entry->header.a_data);
+ break;
+ }
+
+ }
+
+}
+
+/*
+ * Assign a value to each global symbol.
+ */
+static void
+digest_pass2()
+{
+ FOR_EACH_SYMBOL(i, sp) {
+ int size;
+ int align = sizeof(int);
+
+ if (!(sp->flags & GS_REFERENCED))
+ continue;
+
+ if (sp->alias &&
+ (relocatable_output || building_shared_object ||
+ (sp->alias->defined && !sp->alias->so_defined))) {
+ /*
+ * The alias points at a defined symbol, so it
+ * must itself be counted as one too, in order to
+ * compute the correct number of symbol table entries.
+ */
+ if (!sp->defined) {
+ /*
+ * Change aliased symbol's definition too.
+ * These things happen if shared object commons
+ * or data is going into our symbol table.
+ */
+ if (sp->so_defined != (N_INDR+N_EXT))
+ warnx( "pass2: %s: alias isn't",
+ demangle(sp->name));
+ sp->defined = sp->so_defined;
+ sp->so_defined = 0;
+ }
+ defined_global_sym_count++;
+ }
+
+ /*
+ * Count the aliases that will appear in the output.
+ */
+ if (sp->alias && !sp->so_defined && !sp->alias->so_defined &&
+ (sp->defined || relocatable_output ||
+ !building_shared_object))
+ global_alias_count++;
+
+ if ((sp->defined & N_TYPE) == N_SETV) {
+ /*
+ * Set length word at front of vector and zero byte
+ * at end. Reverse the vector itself to put it in
+ * file order.
+ */
+ unsigned long i, *p, *q;
+ unsigned long length_word_index =
+ sp->value / sizeof(long);
+
+ /* Relocate symbol value */
+ sp->value += set_sect_start;
+
+ set_vectors[length_word_index] = sp->setv_count;
+
+ /*
+ * Relocate vector to final address.
+ */
+ for (i = 0; i < sp->setv_count; i++) {
+ struct nlist *p = (struct nlist *)
+ set_vectors[1+i+length_word_index];
+
+ set_vectors[1+i+length_word_index] = p->n_value;
+ if (building_shared_object) {
+ struct relocation_info reloc;
+
+ bzero(&reloc, sizeof(reloc));
+ RELOC_INIT_SEGMENT_RELOC(&reloc);
+ RELOC_ADDRESS(&reloc) =
+ (1 + i + length_word_index) *
+ sizeof(long)
+ + set_sect_start;
+ RELOC_TYPE(&reloc) =
+ (p->n_type - (N_SETA - N_ABS)) & N_TYPE;
+ claim_rrs_segment_reloc(NULL, &reloc);
+ }
+ }
+
+ /*
+ * Reverse the vector.
+ */
+ p = &set_vectors[length_word_index + 1];
+ q = &set_vectors[length_word_index + sp->setv_count];
+ while (p < q) {
+ unsigned long tmp = *p;
+ *p++ = *q;
+ *q-- = tmp;
+ }
+
+ /* Clear terminating entry */
+ set_vectors[length_word_index + sp->setv_count + 1] = 0;
+ continue;
+ }
+
+ if (sp->def_lsp) {
+ if (sp->defined && (sp->defined & ~N_EXT) != N_SETV)
+ sp->value = sp->def_lsp->nzlist.nz_value;
+ if (sp->so_defined &&
+ (sp->def_lsp->entry->flags & E_SECONDCLASS))
+ /* Flag second-hand definitions */
+ undefined_global_sym_count++;
+ if (sp->flags & GS_TRACE)
+ printf("symbol %s assigned to location %#lx\n",
+ demangle(sp->name), sp->value);
+ }
+
+ /*
+ * If not -r'ing, allocate common symbols in the BSS section.
+ */
+ if (building_shared_object && !(link_mode & SYMBOLIC))
+ /* No common allocation in shared objects */
+ continue;
+
+ if ((size = sp->common_size) != 0) {
+ /*
+ * It's a common.
+ */
+ if (sp->defined != (N_UNDF + N_EXT))
+ errx(1, "%s: common isn't", demangle(sp->name));
+
+ } else if ((size = sp->size) != 0 && sp->defined == N_SIZE) {
+ /*
+ * It's data from shared object with size info.
+ */
+ if (!sp->so_defined)
+ errx(1, "%s: Bogus N_SIZE item", demangle(sp->name));
+
+ } else
+ /*
+ * It's neither
+ */
+ continue;
+
+
+ if (relocatable_output && !force_common_definition) {
+ sp->defined = 0;
+ undefined_global_sym_count++;
+ defined_global_sym_count--;
+ continue;
+ }
+
+ /*
+ * Round up to nearest sizeof (int). I don't know whether
+ * this is necessary or not (given that alignment is taken
+ * care of later), but it's traditional, so I'll leave it in.
+ * Note that if this size alignment is ever removed, ALIGN
+ * above will have to be initialized to 1 instead of sizeof
+ * (int).
+ */
+
+ size = PALIGN(size, sizeof(int));
+
+ while (align < MAX_ALIGNMENT && !(size & align))
+ align <<= 1;
+
+ bss_size = PALIGN(bss_size + data_size + rrs_data_start, align)
+ - (data_size + rrs_data_start);
+
+ sp->value = rrs_data_start + data_size + bss_size;
+ if (sp->defined == (N_UNDF | N_EXT))
+ sp->defined = N_BSS | N_EXT;
+ else {
+ sp->so_defined = 0;
+ defined_global_sym_count++;
+ }
+ bss_size += size;
+ if (write_map)
+ printf("Allocating %s %s: %x at %lx\n",
+ sp->defined==(N_BSS|N_EXT)?"common":"data",
+ demangle(sp->name), size, sp->value);
+
+ } END_EACH_SYMBOL;
+}
+
+
+/* -------------------------------------------------------------------*/
+
+/* Write the output file */
+void
+write_output()
+{
+ struct stat statbuf;
+ int filemode;
+ mode_t u_mask;
+
+ if (lstat(output_filename, &statbuf) == 0) {
+ if (S_ISREG(statbuf.st_mode))
+ (void)unlink(output_filename);
+ }
+
+ u_mask = umask(0);
+ (void)umask(u_mask);
+
+ outstream = fopen(output_filename, "w");
+ if (outstream == NULL)
+ err(1, "fopen: %s", output_filename);
+
+ if (atexit(cleanup))
+ err(1, "atexit");
+
+ if (fstat(fileno(outstream), &statbuf) < 0)
+ err(1, "fstat: %s", output_filename);
+
+ filemode = statbuf.st_mode;
+
+ if (S_ISREG(statbuf.st_mode) &&
+ chmod(output_filename, filemode & ~0111) == -1)
+ err(1, "chmod: %s", output_filename);
+
+ /* Output the a.out header. */
+ write_header();
+
+ /* Output the text and data segments, relocating as we go. */
+ write_text();
+ write_data();
+
+ /* Output the merged relocation info, if requested with `-r'. */
+ if (relocatable_output)
+ write_rel();
+
+ /* Output the symbol table (both globals and locals). */
+ write_syms();
+
+ /* Output the RSS section */
+ write_rrs();
+
+ if (chmod (output_filename, filemode | (0111 & ~u_mask)) == -1)
+ err(1, "chmod: %s", output_filename);
+
+ fflush(outstream);
+ /* Report I/O error such as disk full. */
+ if (ferror(outstream) || fclose(outstream) != 0)
+ err(1, "write_output: %s", output_filename);
+ outstream = 0;
+ if (real_output_filename)
+ if (rename(output_filename, real_output_filename))
+ err(1, "rename output: %s to %s",
+ output_filename, real_output_filename);
+}
+
+/* Total number of symbols to be written in the output file. */
+static int nsyms;
+
+void
+write_header()
+{
+ int flags;
+
+ if (link_mode & SHAREABLE)
+ /* Output is shared object */
+ flags = EX_DYNAMIC | EX_PIC;
+ else if (relocatable_output && pic_code_seen)
+ /* Output is relocatable and contains PIC code */
+ flags = EX_PIC;
+ else if (rrs_section_type == RRS_FULL)
+ /* Output is a dynamic executable */
+ flags = EX_DYNAMIC;
+ else
+ /*
+ * Output is a static executable
+ * or a non-PIC relocatable object
+ */
+ flags = 0;
+
+ if (oldmagic && (flags & EX_DPMASK) && !(link_mode & FORCEDYNAMIC))
+ warnx("Cannot set flag in old magic headers\n");
+
+ N_SET_FLAG (outheader, flags);
+
+ outheader.a_text = text_size;
+ outheader.a_data = data_size;
+ outheader.a_bss = bss_size;
+ outheader.a_entry = (entry_symbol ? entry_symbol->value
+ : text_start + entry_offset);
+
+ if (strip_symbols == STRIP_ALL)
+ nsyms = 0;
+ else
+ nsyms = global_sym_count + local_sym_count + debugger_sym_count;
+
+ if (relocatable_output)
+ nsyms += set_symbol_count;
+
+ outheader.a_syms = nsyms * sizeof (struct nlist);
+
+ if (relocatable_output) {
+ outheader.a_trsize = text_reloc_size;
+ outheader.a_drsize = data_reloc_size;
+ } else {
+ outheader.a_trsize = 0;
+ outheader.a_drsize = 0;
+ }
+
+ md_swapout_exec_hdr(&outheader);
+ mywrite(&outheader, 1, sizeof (struct exec), outstream);
+ md_swapin_exec_hdr(&outheader);
+
+ /*
+ * Output whatever padding is required in the executable file
+ * between the header and the start of the text.
+ */
+
+#ifndef COFF_ENCAPSULATE
+ padfile(N_TXTOFF(outheader) - sizeof outheader, outstream);
+#endif
+}
+
+/*
+ * Relocate the text segment of each input file
+ * and write to the output file.
+ */
+void
+write_text()
+{
+
+ if (trace_files)
+ fprintf(stderr, "Copying and relocating text:\n\n");
+
+ each_full_file(copy_text, 0);
+ file_close();
+
+ if (trace_files)
+ fprintf(stderr, "\n");
+
+ padfile(text_pad, outstream);
+}
+
+/*
+ * Read the text segment contents of ENTRY, relocate them, and write the
+ * result to the output file. If `-r', save the text relocation for later
+ * reuse.
+ */
+void
+copy_text(entry)
+ struct file_entry *entry;
+{
+ register char *bytes;
+ register int fd;
+
+ if (trace_files)
+ prline_file_name(entry, stderr);
+
+ fd = file_open(entry);
+
+ /* Allocate space for the file's text section */
+ bytes = (char *)alloca(entry->header.a_text);
+
+ /* Deal with relocation information however is appropriate */
+ if (entry->textrel == NULL)
+ errx(1, "%s: no text relocation", get_file_name(entry));
+
+ /* Read the text section into core. */
+ if (lseek(fd, text_offset(entry), L_SET) == (off_t)-1)
+ err(1, "%s: copy_text: lseek", get_file_name(entry));
+ if (entry->header.a_text != read(fd, bytes, entry->header.a_text))
+ errx(1, "%s: copy_text: premature EOF", get_file_name(entry));
+
+ /* Relocate the text according to the text relocation. */
+ perform_relocation (bytes, entry->header.a_text,
+ entry->textrel, entry->ntextrel, entry, 0);
+
+ /* Write the relocated text to the output file. */
+ mywrite(bytes, entry->header.a_text, 1, outstream);
+}
+
+/*
+ * Relocate the data segment of each input file
+ * and write to the output file.
+ */
+
+void
+write_data()
+{
+ off_t pos;
+
+ if (trace_files)
+ fprintf(stderr, "Copying and relocating data:\n\n");
+
+ pos = N_DATOFF(outheader) + data_start - rrs_data_start;
+ if (fseek(outstream, pos, SEEK_SET) != 0)
+ errx(1, "write_data: fseek");
+
+ each_full_file(copy_data, 0);
+ file_close();
+
+ /*
+ * Write out the set element vectors. See digest symbols for
+ * description of length of the set vector section.
+ */
+
+ if (set_vector_count) {
+ swap_longs(set_vectors, set_symbol_count + 2*set_vector_count);
+ mywrite(set_vectors, set_symbol_count + 2*set_vector_count,
+ sizeof (unsigned long), outstream);
+ }
+
+ if (trace_files)
+ fprintf(stderr, "\n");
+
+ padfile(data_pad, outstream);
+}
+
+/*
+ * Read the data segment contents of ENTRY, relocate them, and write the
+ * result to the output file. If `-r', save the data relocation for later
+ * reuse. See comments in `copy_text'.
+ */
+void
+copy_data(entry)
+ struct file_entry *entry;
+{
+ register char *bytes;
+ register int fd;
+
+ if (trace_files)
+ prline_file_name (entry, stderr);
+
+ fd = file_open(entry);
+
+ bytes = (char *)alloca(entry->header.a_data);
+
+ if (entry->datarel == NULL)
+ errx(1, "%s: no data relocation", get_file_name(entry));
+
+ if (lseek(fd, text_offset(entry) + entry->header.a_text, L_SET) ==
+ (off_t)-1)
+ err(1, "%s: copy_data: lseek", get_file_name(entry));
+ if (entry->header.a_data != read(fd, bytes, entry->header.a_data))
+ errx(1, "%s: copy_data: premature EOF", get_file_name(entry));
+
+ perform_relocation(bytes, entry->header.a_data,
+ entry->datarel, entry->ndatarel, entry, 1);
+
+ mywrite(bytes, entry->header.a_data, 1, outstream);
+}
+
+/*
+ * Relocate ENTRY's text or data section contents. DATA is the address of the
+ * contents, in core. DATA_SIZE is the length of the contents. PC_RELOCATION
+ * is the difference between the address of the contents in the output file
+ * and its address in the input file. RELOC is the address of the
+ * relocation info, in core. NRELOC says how many there are.
+ */
+
+int pc_relocation;
+
+void
+perform_relocation(data, data_size, reloc, nreloc, entry, dataseg)
+ char *data;
+ int data_size;
+ struct relocation_info *reloc;
+ int nreloc;
+ struct file_entry *entry;
+ int dataseg;
+{
+
+ register struct relocation_info *r = reloc;
+ struct relocation_info *end = reloc + nreloc;
+
+ int text_relocation = entry->text_start_address;
+ int data_relocation = entry->data_start_address - entry->header.a_text;
+ int bss_relocation = entry->bss_start_address -
+ entry->header.a_text - entry->header.a_data;
+ pc_relocation = dataseg
+ ? entry->data_start_address - entry->header.a_text
+ : entry->text_start_address;
+
+ for (; r < end; r++) {
+ int addr = RELOC_ADDRESS(r);
+ long addend = md_get_addend(r, data+addr);
+ long relocation;
+
+ /*
+ * Loop over the relocations again as we did in
+ * consider_relocation(), claiming the reserved RRS
+ * relocations.
+ */
+
+ if (addr >= data_size)
+ errx(1, "%s: relocation address out of range",
+ get_file_name(entry));
+
+ if (RELOC_JMPTAB_P(r)) {
+
+ int symindex = RELOC_SYMBOL(r);
+ struct localsymbol *lsp = &entry->symbols[symindex];
+ symbol *sp;
+
+ if (symindex >= entry->nsymbols)
+ errx(1, "%s: relocation symbolnum out of range",
+ get_file_name(entry));
+
+ sp = lsp->symbol;
+ if (sp == NULL)
+ errx(1, "%s: bogus relocation record",
+ get_file_name(entry));
+ if (sp->alias)
+ sp = sp->alias;
+
+ if (relocatable_output)
+ relocation = addend;
+ else if (!RELOC_EXTERN_P(r)) {
+ relocation = addend +
+ data_relocation - text_relocation;
+ } else
+ relocation = addend +
+ claim_rrs_jmpslot(entry, r, sp, addend);
+
+ } else if (RELOC_BASEREL_P(r)) {
+
+ int symindex = RELOC_SYMBOL(r);
+ struct localsymbol *lsp = &entry->symbols[symindex];
+
+ if (symindex >= entry->nsymbols)
+ errx(1, "%s: relocation symbolnum out of range",
+ get_file_name(entry));
+
+ if (relocatable_output)
+ relocation = addend;
+ else if (!RELOC_EXTERN_P(r))
+ relocation = claim_rrs_internal_gotslot(
+ entry, r, lsp, addend);
+ else
+ relocation = claim_rrs_gotslot(
+ entry, r, lsp, addend);
+
+ } else if (RELOC_EXTERN_P(r)) {
+
+ int symindex = RELOC_SYMBOL(r);
+ symbol *sp;
+
+ if (symindex >= entry->nsymbols)
+ errx(1, "%s: relocation symbolnum out of range",
+ get_file_name(entry));
+
+ sp = entry->symbols[symindex].symbol;
+ if (sp == NULL)
+ errx(1, "%s: bogus relocation record",
+ get_file_name(entry));
+ if (sp->alias)
+ sp = sp->alias;
+
+ if (relocatable_output) {
+ relocation = addend;
+ /*
+ * In PIC code, we keep the reference to the
+ * external symbol, even if defined now.
+ */
+ if (!pic_code_seen)
+ relocation += sp->value;
+ } else if (sp->defined) {
+ if (sp->flags & GS_TRACE) {
+ fprintf(stderr,
+ "symbol %s defined as %x in %s\n",
+ demangle(sp->name), sp->defined,
+ get_file_name(entry) );
+ }
+ if (sp == got_symbol) {
+ /* Handle _GOT_ refs */
+ relocation = addend + sp->value
+ + md_got_reloc(r);
+ } else if (building_shared_object) {
+ /*
+ * Normal (non-PIC) relocation needs
+ * to be converted into an RRS reloc
+ * when building a shared object.
+ */
+ r->r_address += dataseg?
+ entry->data_start_address:
+ entry->text_start_address;
+ relocation = addend;
+ if (claim_rrs_reloc(
+ entry, r, sp, &relocation))
+ continue;
+ } else if (sp->defined == N_SIZE) {
+ /*
+ * If size is known, arrange a
+ * run-time copy.
+ */
+ if (!sp->size)
+ errx(1, "Copy item isn't: %s",
+ demangle(sp->name));
+
+ relocation = addend + sp->value;
+ r->r_address = sp->value;
+ claim_rrs_cpy_reloc(entry, r, sp);
+ } else
+ /* Plain old relocation */
+ relocation = addend + sp->value;
+ } else {
+ /*
+ * If the symbol is undefined, we relocate it
+ * in a way similar to -r case. We use an
+ * RRS relocation to resolve the symbol at
+ * run-time. The r_address field is updated
+ * to reflect the changed position in the
+ * output file.
+ */
+ if (sp->flags & GS_TRACE) {
+ fprintf(stderr,
+ "symbol %s claims RRS in %s%s\n",
+ demangle(sp->name), get_file_name(entry),
+ (sp->so_defined == (N_TEXT+N_EXT) &&
+ sp->flags & GS_HASJMPSLOT)?
+ " (JMPSLOT)":"");
+ }
+ if (sp->so_defined == (N_TEXT+N_EXT) &&
+ sp->flags & GS_HASJMPSLOT) {
+ /*
+ * Claim a jmpslot if one was allocated.
+ *
+ * At this point, a jmpslot can only
+ * result from a shared object reference
+ * while `force_alias' is in effect.
+ */
+ relocation = addend +
+ claim_rrs_jmpslot(
+ entry, r, sp, addend);
+ } else {
+ r->r_address += dataseg?
+ entry->data_start_address:
+ entry->text_start_address;
+ relocation = addend;
+ if ((building_shared_object ||
+ sp->so_defined) &&
+ claim_rrs_reloc(entry, r, sp,
+ &relocation))
+ continue;
+ }
+ }
+
+ } else {
+
+ switch (RELOC_TYPE(r)) {
+ case N_TEXT:
+ case N_TEXT | N_EXT:
+ relocation = addend + text_relocation;
+ break;
+
+ case N_DATA:
+ case N_DATA | N_EXT:
+ /*
+ * A word that points to beginning of the the
+ * data section initially contains not 0 but
+ * rather the "address" of that section in
+ * the input file, which is the length of the
+ * file's text.
+ */
+ relocation = addend + data_relocation;
+ break;
+
+ case N_BSS:
+ case N_BSS | N_EXT:
+ /*
+ * Similarly, an input word pointing to the
+ * beginning of the bss initially contains
+ * the length of text plus data of the file.
+ */
+ relocation = addend + bss_relocation;
+ break;
+
+ case N_ABS:
+ case N_ABS | N_EXT:
+ /*
+ * Don't know why this code would occur, but
+ * apparently it does.
+ */
+ break;
+
+ default:
+ errx(1, "%s: nonexternal relocation invalid",
+ get_file_name(entry));
+ }
+
+ /*
+ * When building a shared object, these segment
+ * relocations need a "load address relative"
+ * RRS fixup.
+ */
+ if (building_shared_object && !RELOC_PCREL_P(r)) {
+ r->r_address += dataseg?
+ entry->data_start_address:
+ entry->text_start_address;
+ claim_rrs_segment_reloc(entry, r);
+ }
+ }
+
+ if (RELOC_PCREL_P(r))
+ relocation -= pc_relocation;
+
+ md_relocate(r, relocation, data+addr, relocatable_output);
+
+ }
+}
+
+
+/*
+ * For relocatable_output only: write out the relocation,
+ * relocating the addresses-to-be-relocated.
+ */
+void
+write_rel()
+{
+ int count = 0;
+
+ if (trace_files)
+ fprintf(stderr, "Writing text relocation:\n\n");
+
+ /*
+ * Assign each global symbol a sequence number, giving the order
+ * in which `write_syms' will write it.
+ * This is so we can store the proper symbolnum fields
+ * in relocation entries we write.
+ */
+
+ /* BLECH - Assign number 0 to __DYNAMIC (!! Sun compatibility) */
+
+ if (dynamic_symbol->flags & GS_REFERENCED)
+ dynamic_symbol->symbolnum = count++;
+ FOR_EACH_SYMBOL(i, sp) {
+ if (sp == dynamic_symbol)
+ continue;
+ if (sp->warning)
+ count += 2;
+ if (!(sp->flags & GS_REFERENCED))
+ continue;
+ sp->symbolnum = count++;
+ if (sp->size)
+ count++;
+ if (sp->alias)
+ count++;
+ } END_EACH_SYMBOL;
+
+ if (count != global_sym_count)
+ errx(1, "internal error: write_rel: count = %d", count);
+
+ each_full_file(assign_symbolnums, &count);
+
+ /* Write out the relocations of all files, remembered from copy_text. */
+ each_full_file(coptxtrel, 0);
+
+ if (trace_files)
+ fprintf(stderr, "\nWriting data relocation:\n\n");
+
+ each_full_file(copdatrel, 0);
+
+ if (trace_files)
+ fprintf(stderr, "\n");
+}
+
+
+/*
+ * Assign symbol ordinal numbers to local symbols in each entry.
+ */
+static void
+assign_symbolnums(entry, countp)
+ struct file_entry *entry;
+ int *countp;
+{
+ struct localsymbol *lsp, *lspend;
+ int n = *countp;
+
+ lspend = entry->symbols + entry->nsymbols;
+
+ if (discard_locals != DISCARD_ALL)
+ /* Count the N_FN symbol for this entry */
+ n++;
+
+ for (lsp = entry->symbols; lsp < lspend; lsp++) {
+ if (lsp->flags & LS_WRITE)
+ lsp->symbolnum = n++;
+ }
+ *countp = n;
+}
+
+static void
+coptxtrel(entry)
+ struct file_entry *entry;
+{
+ register struct relocation_info *r, *end;
+ register int reloc = entry->text_start_address;
+
+ r = entry->textrel;
+ end = r + entry->ntextrel;
+
+ for (; r < end; r++) {
+ register int symindex;
+ struct localsymbol *lsp;
+ symbol *sp;
+
+ RELOC_ADDRESS(r) += reloc;
+
+ symindex = RELOC_SYMBOL(r);
+ lsp = &entry->symbols[symindex];
+
+ if (!RELOC_EXTERN_P(r)) {
+ if (!pic_code_seen)
+ continue;
+ if (RELOC_BASEREL_P(r))
+ RELOC_SYMBOL(r) = lsp->symbolnum;
+ continue;
+ }
+
+ if (symindex >= entry->nsymbols)
+ errx(1, "%s: relocation symbolnum out of range",
+ get_file_name(entry));
+
+ sp = lsp->symbol;
+
+#ifdef N_INDR
+ /* Resolve indirection. */
+ if ((sp->defined & ~N_EXT) == N_INDR) {
+ if (sp->alias == NULL)
+ errx(1, "internal error: alias in hyperspace");
+ sp = sp->alias;
+ }
+#endif
+
+ /*
+ * If the symbol is now defined, change the external
+ * relocation to an internal one.
+ */
+
+ if (sp->defined) {
+ if (!pic_code_seen) {
+ RELOC_EXTERN_P(r) = 0;
+ RELOC_SYMBOL(r) = (sp->defined & N_TYPE);
+ } else
+ RELOC_SYMBOL(r) = sp->symbolnum;
+ } else
+ /*
+ * Global symbols come first.
+ */
+ RELOC_SYMBOL(r) = sp->symbolnum;
+ }
+ md_swapout_reloc(entry->textrel, entry->ntextrel);
+ mywrite(entry->textrel, entry->ntextrel,
+ sizeof(struct relocation_info), outstream);
+}
+
+static void
+copdatrel(entry)
+ struct file_entry *entry;
+{
+ register struct relocation_info *r, *end;
+ /*
+ * Relocate the address of the relocation. Old address is relative to
+ * start of the input file's data section. New address is relative to
+ * start of the output file's data section.
+ */
+ register int reloc = entry->data_start_address - text_size;
+
+ r = entry->datarel;
+ end = r + entry->ndatarel;
+
+ for (; r < end; r++) {
+ register int symindex;
+ symbol *sp;
+ int symtype;
+
+ RELOC_ADDRESS(r) += reloc;
+
+ if (!RELOC_EXTERN_P(r)) {
+ if (RELOC_BASEREL_P(r))
+ errx(1, "%s: Unsupported relocation type",
+ get_file_name(entry));
+ continue;
+ }
+
+ symindex = RELOC_SYMBOL(r);
+ sp = entry->symbols[symindex].symbol;
+
+ if (symindex >= entry->header.a_syms)
+ errx(1, "%s: relocation symbolnum out of range",
+ get_file_name(entry));
+
+#ifdef N_INDR
+ /* Resolve indirection. */
+ if ((sp->defined & ~N_EXT) == N_INDR) {
+ if (sp->alias == NULL)
+ errx(1, "internal error: alias in hyperspace");
+ sp = sp->alias;
+ }
+#endif
+
+ symtype = sp->defined & N_TYPE;
+
+ if (!pic_code_seen && ( symtype == N_BSS ||
+ symtype == N_DATA ||
+ symtype == N_TEXT ||
+ symtype == N_ABS)) {
+ RELOC_EXTERN_P(r) = 0;
+ RELOC_SYMBOL(r) = symtype;
+ } else
+ /*
+ * Global symbols come first.
+ */
+ RELOC_SYMBOL(r) =
+ entry->symbols[symindex].symbol->symbolnum;
+ }
+ md_swapout_reloc(entry->datarel, entry->ndatarel);
+ mywrite(entry->datarel, entry->ndatarel,
+ sizeof(struct relocation_info), outstream);
+}
+
+void write_file_syms __P((struct file_entry *, int *));
+void write_string_table __P((void));
+
+/* Offsets and current lengths of symbol and string tables in output file. */
+
+static int symtab_offset;
+static int symtab_len;
+
+/* Address in output file where string table starts. */
+static int strtab_offset;
+
+/* Offset within string table
+ where the strings in `strtab_vector' should be written. */
+static int strtab_len;
+
+/* Total size of string table strings allocated so far,
+ including strings in `strtab_vector'. */
+static int strtab_size;
+
+/* Vector whose elements are strings to be added to the string table. */
+static char **strtab_vector;
+
+/* Vector whose elements are the lengths of those strings. */
+static int *strtab_lens;
+
+/* Index in `strtab_vector' at which the next string will be stored. */
+static int strtab_index;
+
+/*
+ * Add the string NAME to the output file string table. Record it in
+ * `strtab_vector' to be output later. Return the index within the string
+ * table that this string will have.
+ */
+
+static int
+assign_string_table_index(name)
+ char *name;
+{
+ register int index = strtab_size;
+ register int len = strlen(name) + 1;
+
+ strtab_size += len;
+ strtab_vector[strtab_index] = name;
+ strtab_lens[strtab_index++] = len;
+
+ return index;
+}
+
+/*
+ * Write the contents of `strtab_vector' into the string table. This is done
+ * once for each file's local&debugger symbols and once for the global
+ * symbols.
+ */
+void
+write_string_table()
+{
+ register int i;
+
+ if (fseek(outstream, strtab_offset + strtab_len, SEEK_SET) != 0)
+ err(1, "write_string_table: %s: fseek", output_filename);
+
+ for (i = 0; i < strtab_index; i++) {
+ mywrite(strtab_vector[i], strtab_lens[i], 1, outstream);
+ strtab_len += strtab_lens[i];
+ }
+}
+
+/* Write the symbol table and string table of the output file. */
+
+void
+write_syms()
+{
+ /* Number of symbols written so far. */
+ int syms_written = 0;
+ struct nlist nl;
+
+ /*
+ * Buffer big enough for all the global symbols. One extra struct
+ * for each indirect symbol to hold the extra reference following.
+ */
+ struct nlist *buf = (struct nlist *)
+ alloca(global_sym_count * sizeof(struct nlist));
+ /* Pointer for storing into BUF. */
+ register struct nlist *bufp = buf;
+
+ /* Size of string table includes the bytes that store the size. */
+ strtab_size = sizeof strtab_size;
+
+ symtab_offset = N_SYMOFF(outheader);
+ symtab_len = 0;
+ strtab_offset = N_STROFF(outheader);
+ strtab_len = strtab_size;
+
+ if (strip_symbols == STRIP_ALL)
+ return;
+
+ /* First, write out the global symbols. */
+
+ /*
+ * Allocate two vectors that record the data to generate the string
+ * table from the global symbols written so far. This must include
+ * extra space for the references following indirect outputs.
+ */
+
+ strtab_vector = (char **)alloca((global_sym_count) * sizeof(char *));
+ strtab_lens = (int *)alloca((global_sym_count) * sizeof(int));
+ strtab_index = 0;
+
+ /*
+ * __DYNAMIC symbol *must* be first for Sun compatibility, as Sun's
+ * ld.so reads the shared object's first symbol. This means that
+ * (Sun's) shared libraries cannot be stripped! (We only assume
+ * that __DYNAMIC is the first item in the data segment)
+ *
+ * If defined (ie. not relocatable_output), make it look
+ * like an internal symbol.
+ */
+ if (dynamic_symbol->flags & GS_REFERENCED) {
+ nl.n_other = 0;
+ nl.n_desc = 0;
+ nl.n_type = dynamic_symbol->defined;
+ if (nl.n_type == N_UNDF)
+ nl.n_type |= N_EXT;
+ else
+ nl.n_type &= ~N_EXT;
+ nl.n_value = dynamic_symbol->value;
+ nl.n_un.n_strx = assign_string_table_index(dynamic_symbol->name);
+ *bufp++ = nl;
+ syms_written++;
+ }
+
+ /* Scan the symbol hash table, bucket by bucket. */
+
+ FOR_EACH_SYMBOL(i, sp) {
+
+ if (sp == dynamic_symbol)
+ /* Already dealt with above */
+ continue;
+
+ /*
+ * Propagate N_WARNING symbols.
+ */
+ if ((relocatable_output || building_shared_object)
+ && sp->warning) {
+ nl.n_type = N_WARNING;
+ nl.n_un.n_strx = assign_string_table_index(sp->warning);
+ nl.n_value = 0;
+ nl.n_other = 0;
+ nl.n_desc = 0;
+ *bufp++ = nl;
+ syms_written++;
+
+ nl.n_type = N_UNDF + N_EXT;
+ nl.n_un.n_strx = assign_string_table_index(sp->name);
+ nl.n_value = 0;
+ nl.n_other = 0;
+ nl.n_desc = 0;
+ *bufp++ = nl;
+ syms_written++;
+ }
+
+ if (!(sp->flags & GS_REFERENCED))
+ /* Came from shared object but was not used */
+ continue;
+
+ if (sp->so_defined || (sp->alias && sp->alias->so_defined))
+ /*
+ * Definition came from shared object,
+ * don't mention it here
+ */
+ continue;
+
+ if (!sp->defined && !relocatable_output) {
+ /*
+ * We're building a shared object and there
+ * are still undefined symbols. Don't output
+ * these, symbol was discounted in digest_pass1()
+ * (they are in the RRS symbol table).
+ */
+ if (building_shared_object)
+ continue;
+ if (!(sp->flags & GS_WEAK))
+ warnx("symbol %s remains undefined", demangle(sp->name));
+ }
+
+ if (syms_written >= global_sym_count)
+ errx(1,
+ "internal error: number of symbols exceeds alloc'd %d",
+ global_sym_count);
+
+ /*
+ * Construct a `struct nlist' for the symbol.
+ */
+ nl.n_other = 0;
+ nl.n_desc = 0;
+
+ if (sp->defined > 1) {
+ /*
+ * defined with known type
+ */
+ if (!relocatable_output && !building_shared_object &&
+ sp->alias && sp->alias->defined > 1) {
+ /*
+ * If the target of an indirect symbol has
+ * been defined and we are outputting an
+ * executable, resolve the indirection; it's
+ * no longer needed.
+ */
+ nl.n_type = sp->alias->defined;
+ nl.n_value = sp->alias->value;
+ nl.n_other = N_OTHER(0, sp->alias->aux);
+ } else {
+ int bind = 0;
+
+ if (sp->defined == N_SIZE)
+ nl.n_type = N_DATA | N_EXT;
+ else
+ nl.n_type = sp->defined;
+ if (nl.n_type == (N_INDR|N_EXT) &&
+ sp->value != 0)
+ errx(1, "%s: N_INDR has value %#lx",
+ demangle(sp->name), sp->value);
+ nl.n_value = sp->value;
+ if (sp->def_lsp)
+ bind = N_BIND(&sp->def_lsp->nzlist.nlist);
+ nl.n_other = N_OTHER(bind, sp->aux);
+ }
+
+ } else if (sp->common_size) {
+ /*
+ * defined as common but not allocated,
+ * happens only with -r and not -d, write out
+ * a common definition.
+ *
+ * common condition needs to be before undefined
+ * condition because unallocated commons are set
+ * undefined in digest_symbols.
+ */
+ nl.n_type = N_UNDF | N_EXT;
+ nl.n_value = sp->common_size;
+ } else if (!sp->defined) {
+ /* undefined -- legit only if -r */
+ nl.n_type = N_UNDF | N_EXT;
+ nl.n_value = 0;
+ } else
+ errx(1,
+ "internal error: %s defined in mysterious way",
+ demangle(sp->name));
+
+ /*
+ * Allocate string table space for the symbol name.
+ */
+
+ nl.n_un.n_strx = assign_string_table_index(sp->name);
+
+ /* Output to the buffer and count it. */
+
+ *bufp++ = nl;
+ syms_written++;
+
+ /*
+ * Write second symbol of an alias pair.
+ */
+ if (nl.n_type == N_INDR + N_EXT) {
+ if (sp->alias == NULL)
+ errx(1, "internal error: alias in hyperspace");
+ nl.n_type = N_UNDF + N_EXT;
+ nl.n_un.n_strx =
+ assign_string_table_index(sp->alias->name);
+ nl.n_value = 0;
+ nl.n_other = 0;
+ nl.n_desc = 0;
+ *bufp++ = nl;
+ syms_written++;
+ }
+
+ /*
+ * Write N_SIZE symbol for a symbol with a known size.
+ */
+ if (relocatable_output && sp->size) {
+ nl.n_type = N_SIZE + N_EXT;
+ nl.n_un.n_strx = assign_string_table_index(sp->name);
+ nl.n_value = sp->size;
+ nl.n_other = 0;
+ nl.n_desc = 0;
+ *bufp++ = nl;
+ syms_written++;
+ }
+
+#ifdef DEBUG
+printf("writesym(#%d): %s, type %x\n", syms_written, demangle(sp->name), sp->defined);
+#endif
+ } END_EACH_SYMBOL;
+
+ if (syms_written != strtab_index || strtab_index != global_sym_count)
+ errx(1, "internal error: wrong number (%d) of global symbols "
+ "written into output file, should be %d",
+ syms_written, global_sym_count);
+
+ /* Output the buffer full of `struct nlist's. */
+
+ if (fseek(outstream, symtab_offset + symtab_len, SEEK_SET) != 0)
+ err(1, "write_syms: fseek");
+ md_swapout_symbols(buf, bufp - buf);
+ mywrite(buf, bufp - buf, sizeof(struct nlist), outstream);
+ symtab_len += sizeof(struct nlist) * (bufp - buf);
+
+ /* Write the strings for the global symbols. */
+ write_string_table();
+
+ /* Write the local symbols defined by the various files. */
+ each_file(write_file_syms, (void *)&syms_written);
+ file_close();
+
+ if (syms_written != nsyms)
+ errx(1, "internal error: wrong number of symbols (%d) "
+ "written into output file, should be %d",
+ syms_written, nsyms);
+
+ if (symtab_offset + symtab_len != strtab_offset)
+ errx(1,
+ "internal error: inconsistent symbol table length: %d vs %d",
+ symtab_offset + symtab_len, strtab_offset);
+
+ if (fseek(outstream, strtab_offset, SEEK_SET) != 0)
+ err(1, "write_syms: fseek");
+ strtab_size = md_swap_long(strtab_size);
+ mywrite(&strtab_size, sizeof(int), 1, outstream);
+}
+
+
+/*
+ * Write the local and debugger symbols of file ENTRY. Increment
+ * *SYMS_WRITTEN_ADDR for each symbol that is written.
+ */
+
+/*
+ * Note that we do not combine identical names of local symbols. dbx or gdb
+ * would be confused if we did that.
+ */
+void
+write_file_syms(entry, syms_written_addr)
+ struct file_entry *entry;
+ int *syms_written_addr;
+{
+ struct localsymbol *lsp, *lspend;
+
+ /* Upper bound on number of syms to be written here. */
+ int max_syms = entry->nsymbols + 1;
+
+ /*
+ * Buffer to accumulate all the syms before writing them. It has one
+ * extra slot for the local symbol we generate here.
+ */
+ struct nlist *buf = (struct nlist *)
+ alloca(max_syms * sizeof(struct nlist));
+
+ register struct nlist *bufp = buf;
+
+ if (entry->flags & E_DYNAMIC)
+ return;
+
+ /*
+ * Make tables that record, for each symbol, its name and its name's
+ * length. The elements are filled in by `assign_string_table_index'.
+ */
+
+ strtab_vector = (char **)alloca(max_syms * sizeof(char *));
+ strtab_lens = (int *)alloca(max_syms * sizeof(int));
+ strtab_index = 0;
+
+ /* Generate a local symbol for the start of this file's text. */
+
+ if (discard_locals != DISCARD_ALL) {
+ struct nlist nl;
+
+ nl.n_type = N_FN | N_EXT;
+ nl.n_un.n_strx =
+ assign_string_table_index(entry->local_sym_name);
+ nl.n_value = entry->text_start_address;
+ nl.n_desc = 0;
+ nl.n_other = 0;
+ *bufp++ = nl;
+ (*syms_written_addr)++;
+ }
+ /* Read the file's string table. */
+
+ entry->strings = (char *)alloca(entry->string_size);
+ read_entry_strings(file_open(entry), entry);
+
+ lspend = entry->symbols + entry->nsymbols;
+
+ for (lsp = entry->symbols; lsp < lspend; lsp++) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+ char *name;
+
+ if (!(lsp->flags & LS_WRITE))
+ continue;
+
+ if (discard_locals == DISCARD_ALL ||
+ (discard_locals == DISCARD_L &&
+ (lsp->flags & LS_L_SYMBOL))) {
+ /*
+ * The user wants to discard this symbol, but it
+ * is referenced by a relocation. We can still
+ * save some file space by suppressing the unique
+ * renaming of the symbol.
+ */
+ lsp->flags &= ~LS_RENAME;
+ }
+
+ if (p->n_un.n_strx == 0)
+ name = NULL;
+ else if (!(lsp->flags & LS_RENAME))
+ name = p->n_un.n_strx + entry->strings;
+ else {
+ char *cp = p->n_un.n_strx + entry->strings;
+ name = (char *)alloca(
+ strlen(entry->local_sym_name) +
+ strlen(cp) + 2 );
+ (void)sprintf(name, "%s.%s", entry->local_sym_name, cp);
+ }
+
+ /*
+ * If this symbol has a name, allocate space for it
+ * in the output string table.
+ */
+
+ if (name)
+ p->n_un.n_strx = assign_string_table_index(name);
+
+ /* Output this symbol to the buffer and count it. */
+
+ *bufp++ = *p;
+ (*syms_written_addr)++;
+ }
+
+ /* All the symbols are now in BUF; write them. */
+
+ if (fseek(outstream, symtab_offset + symtab_len, SEEK_SET) != 0)
+ err(1, "write local symbols: fseek");
+ md_swapout_symbols(buf, bufp - buf);
+ mywrite(buf, bufp - buf, sizeof(struct nlist), outstream);
+ symtab_len += sizeof(struct nlist) * (bufp - buf);
+
+ /*
+ * Write the string-table data for the symbols just written, using
+ * the data in vectors `strtab_vector' and `strtab_lens'.
+ */
+
+ write_string_table();
+ entry->strings = 0; /* Since it will disappear anyway. */
+}
+
+/*
+ * Parse the string ARG using scanf format FORMAT, and return the result.
+ * If it does not parse, report fatal error
+ * generating the error message using format string ERROR and ARG as arg.
+ */
+
+static int
+parse(arg, format, error)
+ char *arg, *format, *error;
+{
+ int x;
+
+ if (1 != sscanf(arg, format, &x))
+ errx(1, error, arg);
+ return x;
+}
+
+/*
+ * Output COUNT*ELTSIZE bytes of data at BUF to the descriptor FD.
+ */
+void
+mywrite(buf, count, eltsize, fd)
+ void *buf;
+ int count;
+ int eltsize;
+ FILE *fd;
+{
+
+ if (fwrite(buf, eltsize, count, fd) != count)
+ err(1, "write");
+}
+
+static void
+cleanup()
+{
+ struct stat statbuf;
+
+ if (outstream == 0)
+ return;
+
+ if (fstat(fileno(outstream), &statbuf) == 0) {
+ if (S_ISREG(statbuf.st_mode))
+ (void)unlink(output_filename);
+ }
+}
+
+/*
+ * Output PADDING zero-bytes to descriptor FD.
+ * PADDING may be negative; in that case, do nothing.
+ */
+void
+padfile(padding, fd)
+ int padding;
+ FILE *fd;
+{
+ register char *buf;
+ if (padding <= 0)
+ return;
+
+ buf = (char *)alloca(padding);
+ bzero(buf, padding);
+ mywrite(buf, padding, 1, fd);
+}
+
+static void
+list_files()
+{
+ int error, i;
+
+ error = 0;
+ for (i = 0; i < number_of_files; i++) {
+ register struct file_entry *entry = &file_table[i];
+ int fd;
+
+ if (entry->flags & E_SEARCH_DIRS)
+ fd = findlib(entry);
+ else
+ fd = open(entry->filename, O_RDONLY, 0);
+ if (fd < 0)
+ error = 1;
+ else
+ close(fd);
+
+ /*
+ * Print the name even if the file doesn't exist except in
+ * the -lfoo case. This allows `ld -f' to work as well as
+ * possible when it is used to generate dependencies before
+ * the libraries exist.
+ */
+ if (fd >= 0 || !(entry->flags & E_SEARCH_DIRS))
+ printf("%s\n", entry->filename);
+ }
+ exit(error);
+}
diff --git a/gnu/usr.bin/ld/ld.h b/gnu/usr.bin/ld/ld.h
new file mode 100644
index 0000000..4aaa775
--- /dev/null
+++ b/gnu/usr.bin/ld/ld.h
@@ -0,0 +1,387 @@
+/*
+ * $FreeBSD$
+ */
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ */
+
+#define SUN_COMPAT
+
+#ifndef N_SIZE
+#define N_SIZE 0xc
+#endif
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef __P
+#ifndef __STDC__
+#define __P(a) ()
+#else
+#define __P(a) a
+#endif
+#endif
+
+/* If compiled with GNU C, use the built-in alloca */
+#if defined(__GNUC__) || defined(sparc)
+#define alloca __builtin_alloca
+#endif
+
+#include "md.h"
+#include "link.h"
+
+/* Macro to control the number of undefined references printed */
+#define MAX_UREFS_PRINTED 10
+
+/* Align to power-of-two boundary */
+#define PALIGN(x,p) (((x) + (u_long)(p) - 1) & (-(u_long)(p)))
+
+/* Align to machine dependent boundary */
+#define MALIGN(x) PALIGN(x,MAX_ALIGNMENT)
+
+/* Define this to specify the default executable format. */
+#ifndef DEFAULT_MAGIC
+#ifdef __FreeBSD__
+#define DEFAULT_MAGIC QMAGIC
+extern int netzmagic;
+#else
+#define DEFAULT_MAGIC ZMAGIC
+#endif
+#endif
+
+#ifdef DEMANGLE_CPLUSPLUS
+extern char *demangle __P((char*));
+#else
+#define demangle(name) name
+#endif
+
+/*
+ * Ok. Following are the relocation information macros. If your
+ * system should not be able to use the default set (below), you must
+ * define the following:
+
+ * relocation_info: This must be typedef'd (or #define'd) to the type
+ * of structure that is stored in the relocation info section of your
+ * a.out files. Often this is defined in the a.out.h for your system.
+ *
+ * RELOC_ADDRESS (rval): Offset into the current section of the
+ * <whatever> to be relocated. *Must be an lvalue*.
+ *
+ * RELOC_EXTERN_P (rval): Is this relocation entry based on an
+ * external symbol (1), or was it fully resolved upon entering the
+ * loader (0) in which case some combination of the value in memory
+ * (if RELOC_MEMORY_ADD_P) and the extra (if RELOC_ADD_EXTRA) contains
+ * what the value of the relocation actually was. *Must be an lvalue*.
+ *
+ * RELOC_TYPE (rval): If this entry was fully resolved upon
+ * entering the loader, what type should it be relocated as?
+ *
+ * RELOC_SYMBOL (rval): If this entry was not fully resolved upon
+ * entering the loader, what is the index of it's symbol in the symbol
+ * table? *Must be a lvalue*.
+ *
+ * RELOC_MEMORY_ADD_P (rval): This should return true if the final
+ * relocation value output here should be added to memory, or if the
+ * section of memory described should simply be set to the relocation
+ * value.
+ *
+ * RELOC_ADD_EXTRA (rval): (Optional) This macro, if defined, gives
+ * an extra value to be added to the relocation value based on the
+ * individual relocation entry. *Must be an lvalue if defined*.
+ *
+ * RELOC_PCREL_P (rval): True if the relocation value described is
+ * pc relative.
+ *
+ * RELOC_VALUE_RIGHTSHIFT (rval): Number of bits right to shift the
+ * final relocation value before putting it where it belongs.
+ *
+ * RELOC_TARGET_SIZE (rval): log to the base 2 of the number of
+ * bytes of size this relocation entry describes; 1 byte == 0; 2 bytes
+ * == 1; 4 bytes == 2, and etc. This is somewhat redundant (we could
+ * do everything in terms of the bit operators below), but having this
+ * macro could end up producing better code on machines without fancy
+ * bit twiddling. Also, it's easier to understand/code big/little
+ * endian distinctions with this macro.
+ *
+ * RELOC_TARGET_BITPOS (rval): The starting bit position within the
+ * object described in RELOC_TARGET_SIZE in which the relocation value
+ * will go.
+ *
+ * RELOC_TARGET_BITSIZE (rval): How many bits are to be replaced
+ * with the bits of the relocation value. It may be assumed by the
+ * code that the relocation value will fit into this many bits. This
+ * may be larger than RELOC_TARGET_SIZE if such be useful.
+ *
+ *
+ * Things I haven't implemented
+ * ----------------------------
+ *
+ * Values for RELOC_TARGET_SIZE other than 0, 1, or 2.
+ *
+ * Pc relative relocation for External references.
+ *
+ *
+ */
+
+
+/* Default macros */
+#ifndef RELOC_ADDRESS
+
+#define RELOC_ADDRESS(r) ((r)->r_address)
+#define RELOC_EXTERN_P(r) ((r)->r_extern)
+#define RELOC_TYPE(r) ((r)->r_symbolnum)
+#define RELOC_SYMBOL(r) ((r)->r_symbolnum)
+#define RELOC_MEMORY_SUB_P(r) 0
+#define RELOC_MEMORY_ADD_P(r) 1
+#undef RELOC_ADD_EXTRA
+#define RELOC_PCREL_P(r) ((r)->r_pcrel)
+#define RELOC_VALUE_RIGHTSHIFT(r) 0
+#if defined(RTLD) && defined(SUN_COMPAT)
+#define RELOC_TARGET_SIZE(r) (2) /* !!!!! Sun BUG compatible */
+#else
+#define RELOC_TARGET_SIZE(r) ((r)->r_length)
+#endif
+#define RELOC_TARGET_BITPOS(r) 0
+#define RELOC_TARGET_BITSIZE(r) 32
+
+#endif
+
+#ifdef nounderscore
+#define LPREFIX '.'
+#else
+#define LPREFIX 'L'
+#endif
+
+#ifndef TEXT_START
+#define TEXT_START(x) N_TXTADDR(x)
+#endif
+
+#ifndef DATA_START
+#define DATA_START(x) N_DATADDR(x)
+#endif
+
+/* If a this type of symbol is encountered, its name is a warning
+ message to print each time the symbol referenced by the next symbol
+ table entry is referenced.
+
+ This feature may be used to allow backwards compatibility with
+ certain functions (eg. gets) but to discourage programmers from
+ their use.
+
+ So if, for example, you wanted to have ld print a warning whenever
+ the function "gets" was used in their C program, you would add the
+ following to the assembler file in which gets is defined:
+
+ .stabs "Obsolete function \"gets\" referenced",30,0,0,0
+ .stabs "_gets",1,0,0,0
+
+ These .stabs do not necessarily have to be in the same file as the
+ gets function, they simply must exist somewhere in the compilation. */
+
+#ifndef N_WARNING
+#define N_WARNING 0x1E /* Warning message to print if symbol
+ included */
+#endif /* This is input to ld */
+
+/* Special global symbol types understood by GNU LD. */
+
+/* The following type indicates the definition of a symbol as being
+ an indirect reference to another symbol. The other symbol
+ appears as an undefined reference, immediately following this symbol.
+
+ Indirection is asymmetrical. The other symbol's value will be used
+ to satisfy requests for the indirect symbol, but not vice versa.
+ If the other symbol does not have a definition, libraries will
+ be searched to find a definition.
+
+ So, for example, the following two lines placed in an assembler
+ input file would result in an object file which would direct gnu ld
+ to resolve all references to symbol "foo" as references to symbol
+ "bar".
+
+ .stabs "_foo",11,0,0,0
+ .stabs "_bar",1,0,0,0
+
+ Note that (11 == (N_INDR | N_EXT)) and (1 == (N_UNDF | N_EXT)). */
+
+#ifndef N_INDR
+#define N_INDR 0xa
+#endif
+
+/* The following symbols refer to set elements. These are expected
+ only in input to the loader; they should not appear in loader
+ output (unless relocatable output is requested). To be recognized
+ by the loader, the input symbols must have their N_EXT bit set.
+ All the N_SET[ATDB] symbols with the same name form one set. The
+ loader collects all of these elements at load time and outputs a
+ vector for each name.
+ Space (an array of 32 bit words) is allocated for the set in the
+ data section, and the n_value field of each set element value is
+ stored into one word of the array.
+ The first word of the array is the length of the set (number of
+ elements). The last word of the vector is set to zero for possible
+ use by incremental loaders. The array is ordered by the linkage
+ order; the first symbols which the linker encounters will be first
+ in the array.
+
+ In C syntax this looks like:
+
+ struct set_vector {
+ unsigned int length;
+ unsigned int vector[length];
+ unsigned int always_zero;
+ };
+
+ Before being placed into the array, each element is relocated
+ according to its type. This allows the loader to create an array
+ of pointers to objects automatically. N_SETA type symbols will not
+ be relocated.
+
+ 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.
+
+ For the purposes of determining whether or not to load in a library
+ file, set element definitions are not considered "real
+ definitions"; they will not cause the loading of a library
+ member.
+
+ If relocatable output is requested, none of this processing is
+ done. The symbols are simply relocated and passed through to the
+ output file.
+
+ So, for example, the following three lines of assembler code
+ (whether in one file or scattered between several different ones)
+ will produce a three element vector (total length is five words;
+ see above), referenced by the symbol "_xyzzy", which will have the
+ addresses of the routines _init1, _init2, and _init3.
+
+ *NOTE*: If symbolic addresses are used in the n_value field of the
+ defining .stabs, those symbols must be defined in the same file as
+ that containing the .stabs.
+
+ .stabs "_xyzzy",23,0,0,_init1
+ .stabs "_xyzzy",23,0,0,_init2
+ .stabs "_xyzzy",23,0,0,_init3
+
+ Note that (23 == (N_SETT | N_EXT)). */
+
+#ifndef N_SETA
+#define N_SETA 0x14 /* Absolute set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+#ifndef N_SETT
+#define N_SETT 0x16 /* Text set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+#ifndef N_SETD
+#define N_SETD 0x18 /* Data set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+#ifndef N_SETB
+#define N_SETB 0x1A /* Bss set element symbol */
+#endif /* This is input to LD, in a .o file. */
+
+/* Macros dealing with the set element symbols defined in a.out.h */
+#define SET_ELEMENT_P(x) ((x) >= N_SETA && (x) <= (N_SETB|N_EXT))
+#define TYPE_OF_SET_ELEMENT(x) ((x) - N_SETA + N_ABS)
+
+#ifndef N_SETV
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+#endif /* This is output from LD. */
+
+
+#ifndef __GNU_STAB__
+/* Line number for the data section. This is to be used to describe
+ the source location of a variable declaration. */
+#ifndef N_DSLINE
+#define N_DSLINE (N_SLINE+N_DATA-N_TEXT)
+#endif
+
+/* Line number for the bss section. This is to be used to describe
+ the source location of a variable declaration. */
+#ifndef N_BSLINE
+#define N_BSLINE (N_SLINE+N_BSS-N_TEXT)
+#endif
+#endif /* not __GNU_STAB__ */
+
+
+/* Number of buckets in symbol hash table */
+#define SYMTABSIZE 1009
+
+/* # of global symbols referenced and not defined. */
+extern int undefined_global_sym_count;
+
+/* # of weak symbols referenced and not defined. */
+extern int undefined_weak_sym_count;
+
+/* # of undefined symbols referenced by shared objects */
+extern int undefined_shobj_sym_count;
+
+/* # of multiply defined symbols. */
+extern int multiple_def_count;
+
+/* # of common symbols. */
+extern int common_defined_global_count;
+
+/* # of warning symbols encountered. */
+extern int warn_sym_count;
+extern int list_warning_symbols;
+
+/*
+ * Define a linked list of strings which define symbols which should be
+ * treated as set elements even though they aren't. Any symbol with a prefix
+ * matching one of these should be treated as a set element.
+ *
+ * This is to make up for deficiencies in many assemblers which aren't willing
+ * to pass any stabs through to the loader which they don't understand.
+ */
+struct string_list_element {
+ char *str;
+ struct string_list_element *next;
+};
+
+struct glosym;
+#ifndef __symbol_defined__
+#define __symbol_defined__
+typedef struct glosym symbol;
+#endif
+
+extern symbol *entry_symbol; /* the entry symbol, if any */
+extern symbol *edata_symbol; /* the symbol _edata */
+extern symbol *etext_symbol; /* the symbol _etext */
+extern symbol *end_symbol; /* the symbol _end */
+
+/*
+ * Section start addresses.
+ */
+extern int text_size; /* total size of text. */
+extern int text_start; /* start of text */
+extern int text_pad; /* clear space between text and data */
+extern int data_size; /* total size of data. */
+extern int data_start; /* start of data */
+extern int data_pad; /* part of bss segment within data */
+
+extern int bss_size; /* total size of bss. */
+extern int bss_start; /* start of bss */
+
+extern int text_reloc_size; /* total size of text relocation. */
+extern int data_reloc_size; /* total size of data relocation. */
+
+extern int magic; /* Output file magic. */
+extern int relocatable_output;
+
+/* Size of a page. */
+extern int page_size;
+
+extern char **search_dirs; /* Directories to search for libraries. */
+extern int n_search_dirs; /* Length of above. */
+
+extern int write_map; /* write a load map (`-M') */
+
+#include "dynamic.h"
diff --git a/gnu/usr.bin/ld/lib.c b/gnu/usr.bin/ld/lib.c
new file mode 100644
index 0000000..7881584
--- /dev/null
+++ b/gnu/usr.bin/ld/lib.c
@@ -0,0 +1,876 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Modified 1993 by Paul Kranenburg, Erasmus University
+ */
+
+/* Derived from ld.c: "@(#)ld.c 6.10 (Berkeley) 5/22/91"; */
+
+/* Linker `ld' for GNU
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Richard Stallman with some help from Eric Albert.
+ Set, indirect, and warning symbol features added by Randy Smith. */
+
+/*
+ * $FreeBSD$ - library routines
+ */
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <err.h>
+#include <fcntl.h>
+#include <ar.h>
+#include <ranlib.h>
+#include <a.out.h>
+#include <stab.h>
+#include <string.h>
+#include <dirent.h>
+#include <ctype.h>
+
+#include "ld.h"
+#include "dynamic.h"
+
+static void linear_library __P((int, struct file_entry *));
+static void symdef_library __P((int, struct file_entry *, int));
+static struct file_entry *decode_library_subfile __P((int,
+ struct file_entry *,
+ int, int *));
+
+/*
+ * Search the library ENTRY, already open on descriptor FD. This means
+ * deciding which library members to load, making a chain of `struct
+ * file_entry' for those members, and entering their global symbols in the
+ * hash table.
+ */
+
+void
+search_library(fd, entry)
+ int fd;
+ struct file_entry *entry;
+{
+ int member_length;
+ register char *name;
+ register struct file_entry *subentry;
+
+ if (!(link_mode & FORCEARCHIVE) && !undefined_global_sym_count)
+ return;
+
+ /* Examine its first member, which starts SARMAG bytes in. */
+ subentry = decode_library_subfile(fd, entry, SARMAG, &member_length);
+ if (!subentry)
+ return;
+
+ name = subentry->filename;
+ free(subentry);
+
+ /* Search via __.SYMDEF if that exists, else linearly. */
+
+ if (!strcmp(name, "__.SYMDEF"))
+ symdef_library(fd, entry, member_length);
+ else
+ linear_library(fd, entry);
+}
+
+/*
+ * Construct and return a file_entry for a library member. The library's
+ * file_entry is library_entry, and the library is open on FD.
+ * SUBFILE_OFFSET is the byte index in the library of this member's header.
+ * We store the length of the member into *LENGTH_LOC.
+ */
+
+static struct file_entry *
+decode_library_subfile(fd, library_entry, subfile_offset, length_loc)
+ int fd;
+ struct file_entry *library_entry;
+ int subfile_offset;
+ int *length_loc;
+{
+ int bytes_read;
+ register int namelen;
+ int member_length, content_length;
+ int starting_offset;
+ register char *name;
+ struct ar_hdr hdr1;
+ register struct file_entry *subentry;
+
+ lseek(fd, subfile_offset, 0);
+
+ bytes_read = read(fd, &hdr1, sizeof hdr1);
+ if (!bytes_read)
+ return 0; /* end of archive */
+
+ if (sizeof hdr1 != bytes_read)
+ errx(1, "%s: malformed library archive",
+ get_file_name(library_entry));
+
+ if (sscanf(hdr1.ar_size, "%d", &member_length) != 1)
+ errx(1, "%s: malformatted header of archive member: %.*s",
+ get_file_name(library_entry),
+ (int)sizeof(hdr1.ar_name), hdr1.ar_name);
+
+ subentry = (struct file_entry *) xmalloc(sizeof(struct file_entry));
+ bzero(subentry, sizeof(struct file_entry));
+
+ for (namelen = 0;
+ namelen < sizeof hdr1.ar_name
+ && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' '
+ && hdr1.ar_name[namelen] != '/';
+ namelen++);
+
+ starting_offset = subfile_offset + sizeof hdr1;
+ content_length = member_length;
+
+#ifdef AR_EFMT1
+ /*
+ * BSD 4.4 extended AR format: #1/<namelen>, with name as the
+ * first <namelen> bytes of the file
+ */
+ if (strncmp(hdr1.ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 &&
+ isdigit(hdr1.ar_name[sizeof(AR_EFMT1) - 1])) {
+
+ namelen = atoi(&hdr1.ar_name[sizeof(AR_EFMT1) - 1]);
+ name = (char *)xmalloc(namelen + 1);
+ if (read(fd, name, namelen) != namelen)
+ errx(1, "%s: malformatted archive member: %.*s",
+ get_file_name(library_entry),
+ (int)sizeof(hdr1.ar_name), hdr1.ar_name);
+ name[namelen] = 0;
+ content_length -= namelen;
+ starting_offset += namelen;
+ } else
+
+#endif
+ {
+ name = (char *)xmalloc(namelen + 1);
+ strncpy(name, hdr1.ar_name, namelen);
+ name[namelen] = 0;
+ }
+
+ subentry->filename = name;
+ subentry->local_sym_name = name;
+ subentry->starting_offset = starting_offset;
+ subentry->superfile = library_entry;
+ subentry->total_size = content_length;
+#if 0
+ subentry->symbols = 0;
+ subentry->strings = 0;
+ subentry->subfiles = 0;
+ subentry->chain = 0;
+ subentry->flags = 0;
+#endif
+
+ (*length_loc) = member_length;
+
+ return subentry;
+}
+
+static int subfile_wanted_p __P((struct file_entry *));
+
+/*
+ * Search a library that has a __.SYMDEF member. FD is a descriptor on
+ * which the library is open. The file pointer is assumed to point at the
+ * __.SYMDEF data. ENTRY is the library's file_entry. MEMBER_LENGTH is the
+ * length of the __.SYMDEF data.
+ */
+
+static void
+symdef_library(fd, entry, member_length)
+ int fd;
+ struct file_entry *entry;
+ int member_length;
+{
+ int *symdef_data = (int *) xmalloc(member_length);
+ register struct ranlib *symdef_base;
+ char *sym_name_base;
+ int nsymdefs;
+ int length_of_strings;
+ int not_finished;
+ int bytes_read;
+ register int i;
+ struct file_entry *prev = 0;
+ int prev_offset = 0;
+
+ bytes_read = read(fd, symdef_data, member_length);
+ if (bytes_read != member_length)
+ errx(1, "%s: malformatted __.SYMDEF",
+ get_file_name(entry));
+
+ nsymdefs = md_swap_long(*symdef_data) / sizeof(struct ranlib);
+ if (nsymdefs < 0 ||
+ nsymdefs * sizeof(struct ranlib) + 2 * sizeof(int) > member_length)
+ errx(1, "%s: malformatted __.SYMDEF",
+ get_file_name(entry));
+
+ symdef_base = (struct ranlib *) (symdef_data + 1);
+ length_of_strings = md_swap_long(*(int *) (symdef_base + nsymdefs));
+
+ if (length_of_strings < 0
+ || nsymdefs * sizeof(struct ranlib) + length_of_strings
+ + 2 * sizeof(int) > member_length)
+ errx(1, "%s: malformatted __.SYMDEF",
+ get_file_name(entry));
+
+ sym_name_base = sizeof(int) + (char *) (symdef_base + nsymdefs);
+
+ /* Check all the string indexes for validity. */
+ md_swapin_ranlib_hdr(symdef_base, nsymdefs);
+ for (i = 0; i < nsymdefs; i++) {
+ register int index = symdef_base[i].ran_un.ran_strx;
+ if (index < 0 || index >= length_of_strings
+ || (index && *(sym_name_base + index - 1)))
+ errx(1, "%s: malformatted __.SYMDEF",
+ get_file_name(entry));
+ }
+
+ /*
+ * Search the symdef data for members to load. Do this until one
+ * whole pass finds nothing to load.
+ */
+
+ not_finished = 1;
+ while (not_finished) {
+
+ not_finished = 0;
+
+ /*
+ * Scan all the symbols mentioned in the symdef for ones that
+ * we need. Load the library members that contain such
+ * symbols.
+ */
+
+ for (i = 0; (i < nsymdefs &&
+ ((link_mode & FORCEARCHIVE) ||
+ undefined_global_sym_count ||
+ common_defined_global_count)); i++) {
+
+ register symbol *sp;
+ int junk;
+ register int j;
+ register int offset = symdef_base[i].ran_off;
+ struct file_entry *subentry;
+
+
+ if (symdef_base[i].ran_un.ran_strx < 0)
+ continue;
+
+ sp = getsym_soft(sym_name_base
+ + symdef_base[i].ran_un.ran_strx);
+
+ /*
+ * If we find a symbol that appears to be needed,
+ * think carefully about the archive member that the
+ * symbol is in.
+ */
+
+ /*
+ * Per Mike Karels' recommendation, we no longer load
+ * library files if the only reference(s) that would
+ * be satisfied are 'common' references. This
+ * prevents some problems with name pollution (e.g. a
+ * global common 'utime' linked to a function).
+ *
+ * If we're not forcing the archive in then we don't
+ * need to bother if: we've never heard of the symbol,
+ * or if it is already defined. The last clause causes
+ * archive members to be searched for definitions
+ * satisfying undefined shared object symbols.
+ */
+ if (!(link_mode & FORCEARCHIVE) &&
+ (!sp || sp->defined ||
+ (!(sp->flags & GS_REFERENCED) &&
+ !sp->sorefs)))
+ continue;
+
+ /*
+ * Don't think carefully about any archive member
+ * more than once in a given pass.
+ */
+
+ if (prev_offset == offset)
+ continue;
+ prev_offset = offset;
+
+ /*
+ * Read the symbol table of the archive member.
+ */
+
+ subentry = decode_library_subfile(fd,
+ entry, offset, &junk);
+ if (subentry == 0)
+ errx(1,
+ "invalid offset for %s in symbol table of %s",
+ sym_name_base
+ + symdef_base[i].ran_un.ran_strx,
+ entry->filename);
+
+ read_entry_symbols(fd, subentry);
+ subentry->strings = (char *)
+ alloca(subentry->string_size);
+ read_entry_strings(fd, subentry);
+
+ /*
+ * Now scan the symbol table and decide whether to
+ * load.
+ */
+
+ if (!(link_mode & FORCEARCHIVE) &&
+ !subfile_wanted_p(subentry)) {
+ if (subentry->symbols)
+ free(subentry->symbols);
+ free(subentry);
+ } else {
+ /*
+ * This member is needed; load it. Since we
+ * are loading something on this pass, we
+ * must make another pass through the symdef
+ * data.
+ */
+
+ not_finished = 1;
+
+ read_entry_relocation(fd, subentry);
+ enter_file_symbols(subentry);
+
+ if (prev)
+ prev->chain = subentry;
+ else
+ entry->subfiles = subentry;
+ prev = subentry;
+
+ /*
+ * Clear out this member's symbols from the
+ * symdef data so that following passes won't
+ * waste time on them.
+ */
+
+ for (j = 0; j < nsymdefs; j++) {
+ if (symdef_base[j].ran_off == offset)
+ symdef_base[j].ran_un.ran_strx = -1;
+ }
+
+ /*
+ * We'll read the strings again
+ * if we need them.
+ */
+ subentry->strings = 0;
+ }
+ }
+ }
+
+ free(symdef_data);
+}
+
+/*
+ * Search a library that has no __.SYMDEF. ENTRY is the library's file_entry.
+ * FD is the descriptor it is open on.
+ */
+
+static void
+linear_library(fd, entry)
+ int fd;
+ struct file_entry *entry;
+{
+ register struct file_entry *prev = 0;
+ register int this_subfile_offset = SARMAG;
+
+ while ((link_mode & FORCEARCHIVE) ||
+ undefined_global_sym_count || common_defined_global_count) {
+
+ int member_length;
+ register struct file_entry *subentry;
+
+ subentry = decode_library_subfile(fd, entry,
+ this_subfile_offset, &member_length);
+
+ if (!subentry)
+ return;
+
+ read_entry_symbols(fd, subentry);
+ subentry->strings = (char *)alloca(subentry->string_size);
+ read_entry_strings(fd, subentry);
+
+ if (!(link_mode & FORCEARCHIVE) &&
+ !subfile_wanted_p(subentry)) {
+ if (subentry->symbols)
+ free(subentry->symbols);
+ free(subentry);
+ } else {
+ read_entry_relocation(fd, subentry);
+ enter_file_symbols(subentry);
+
+ if (prev)
+ prev->chain = subentry;
+ else
+ entry->subfiles = subentry;
+ prev = subentry;
+ subentry->strings = 0; /* Since space will dissapear
+ * on return */
+ }
+
+ this_subfile_offset += member_length + sizeof(struct ar_hdr);
+ if (this_subfile_offset & 1)
+ this_subfile_offset++;
+ }
+}
+
+/*
+ * ENTRY is an entry for a library member. Its symbols have been read into
+ * core, but not entered. Return nonzero if we ought to load this member.
+ */
+
+static int
+subfile_wanted_p(entry)
+ struct file_entry *entry;
+{
+ struct localsymbol *lsp, *lspend;
+#ifdef DOLLAR_KLUDGE
+ register int dollar_cond = 0;
+#endif
+
+ lspend = entry->symbols + entry->nsymbols;
+
+ for (lsp = entry->symbols; lsp < lspend; lsp++) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+ register int type = p->n_type;
+ register char *name = p->n_un.n_strx + entry->strings;
+ register symbol *sp = getsym_soft(name);
+
+ /*
+ * If the symbol has an interesting definition, we could
+ * potentially want it.
+ */
+ if (! (type & N_EXT)
+ || (type == (N_UNDF | N_EXT) && p->n_value == 0
+
+#ifdef DOLLAR_KLUDGE
+ && name[1] != '$'
+#endif
+ )
+#ifdef SET_ELEMENT_P
+ || SET_ELEMENT_P(type)
+ || set_element_prefixed_p(name)
+#endif
+ )
+ continue;
+
+
+#ifdef DOLLAR_KLUDGE
+ if (name[1] == '$') {
+ sp = getsym_soft(&name[2]);
+ dollar_cond = 1;
+ if (!sp)
+ continue;
+ if (sp->flags & SP_REFERENCED) {
+ if (write_map) {
+ print_file_name(entry, stdout);
+ fprintf(stdout, " needed due to $-conditional %s\n", name);
+ }
+ return 1;
+ }
+ continue;
+ }
+#endif
+
+ /*
+ * If this symbol has not been hashed, we can't be
+ * looking for it.
+ */
+
+ if (!sp)
+ continue;
+
+ /*
+ * We don't load a file if it merely satisfies a
+ * common reference (see explanation above in
+ * symdef_library()).
+ */
+ if ((sp->flags & GS_REFERENCED) && !sp->defined) {
+ /*
+ * This is a symbol we are looking for. It
+ * is either not yet defined or defined as a
+ * common.
+ */
+#ifdef DOLLAR_KLUDGE
+ if (dollar_cond)
+ continue;
+#endif
+ if (type == (N_UNDF | N_EXT)) {
+ /*
+ * Symbol being defined as common.
+ * Remember this, but don't load
+ * subfile just for this.
+ */
+
+ /*
+ * If it didn't used to be common, up
+ * the count of common symbols.
+ */
+ if (!sp->common_size)
+ common_defined_global_count++;
+
+ if (sp->common_size < p->n_value)
+ sp->common_size = p->n_value;
+ if (!sp->defined)
+ undefined_global_sym_count--;
+ sp->defined = type;
+ continue;
+ }
+ if (sp->flags & GS_WEAK)
+ /* Weak symbols don't pull archive members */
+ continue;
+ if (write_map) {
+ print_file_name(entry, stdout);
+ fprintf(stdout, " needed due to %s\n", demangle(sp->name));
+ }
+ return 1;
+ } else if (!sp->defined && sp->sorefs) {
+ /*
+ * Check for undefined symbols or commons
+ * in shared objects.
+ */
+ struct localsymbol *lsp;
+
+ for (lsp = sp->sorefs; lsp; lsp = lsp->next) {
+ int type = lsp->nzlist.nlist.n_type;
+ if ( (type & N_EXT) &&
+ (type & N_STAB) == 0 &&
+ type != (N_UNDF | N_EXT))
+ break; /* We don't need it */
+ }
+ if (lsp != NULL)
+ /*
+ * We have a worthy definition in a shared
+ * object that was specified ahead of the
+ * archive we're examining now. So, punt.
+ */
+ continue;
+
+ /*
+ * At this point, we have an undefined shared
+ * object reference. Again, if the archive member
+ * defines a common we just note the its size.
+ * Otherwise, the member gets included.
+ */
+
+ if (type == (N_UNDF|N_EXT) && p->n_value) {
+ /*
+ * New symbol is common, just takes its
+ * size, but don't load.
+ */
+ sp->common_size = p->n_value;
+ sp->defined = type;
+ continue;
+ }
+
+ /*
+ * THIS STILL MISSES the case where one shared
+ * object defines a common and the next defines
+ * more strongly; fix this someday by making
+ * `struct glosym' and enter_global_ref() more
+ * symmetric.
+ */
+
+ if (write_map) {
+ print_file_name(entry, stdout);
+ fprintf(stdout,
+ " needed due to shared lib ref %s (%d)\n",
+ demangle(sp->name),
+ lsp ? lsp->nzlist.nlist.n_type : -1);
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Read the symbols of dynamic entity ENTRY into core. Assume it is already
+ * open, on descriptor FD.
+ */
+void
+read_shared_object(fd, entry)
+ struct file_entry *entry;
+ int fd;
+{
+ struct _dynamic dyn;
+ struct section_dispatch_table sdt;
+ struct nlist *np;
+ struct nzlist *nzp;
+ int n, i, has_nz = 0;
+
+ if (!(entry->flags & E_HEADER_VALID))
+ read_header(fd, entry);
+
+ /* Read DYNAMIC structure (first in data segment) */
+ if (lseek(fd, text_offset(entry) + entry->header.a_text, L_SET) ==
+ (off_t)-1)
+ err(1, "%s: lseek", get_file_name(entry));
+ if (read(fd, &dyn, sizeof dyn) != sizeof dyn) {
+ errx(1, "%s: premature EOF reading _dynamic",
+ get_file_name(entry));
+ }
+ md_swapin__dynamic(&dyn);
+
+ /* Check version */
+ switch (dyn.d_version) {
+ default:
+ errx(1, "%s: unsupported _DYNAMIC version: %d",
+ get_file_name(entry), dyn.d_version);
+ break;
+ case LD_VERSION_SUN:
+ break;
+ case LD_VERSION_BSD:
+ has_nz = 1;
+ break;
+ }
+
+ /* Read Section Dispatch Table (from data segment) */
+ if (lseek(fd,
+ text_offset(entry) + (long)dyn.d_un.d_sdt -
+ (DATA_START(entry->header) - N_DATOFF(entry->header)),
+ L_SET) == (off_t)-1)
+ err(1, "%s: lseek", get_file_name(entry));
+ if (read(fd, &sdt, sizeof sdt) != sizeof sdt)
+ errx(1, "%s: premature EOF reading sdt",
+ get_file_name(entry));
+ md_swapin_section_dispatch_table(&sdt);
+
+ /* Read symbols (text segment) */
+ n = sdt.sdt_strings - sdt.sdt_nzlist;
+ entry->nsymbols = n /
+ (has_nz ? sizeof(struct nzlist) : sizeof(struct nlist));
+ nzp = (struct nzlist *)(np = (struct nlist *)alloca (n));
+ entry->symbols = (struct localsymbol *)
+ xmalloc(entry->nsymbols * sizeof(struct localsymbol));
+
+ if (lseek(fd,
+ text_offset(entry) + (long)sdt.sdt_nzlist -
+ (TEXT_START(entry->header) - N_TXTOFF(entry->header)),
+ L_SET) == (off_t)-1)
+ err(1, "%s: lseek", get_file_name(entry));
+ if (read(fd, (char *)nzp, n) != n)
+ errx(1, "%s: premature EOF reading symbols ",
+ get_file_name(entry));
+
+ if (has_nz)
+ md_swapin_zsymbols(nzp, entry->nsymbols);
+ else
+ md_swapin_symbols(np, entry->nsymbols);
+
+ /* Convert to structs localsymbol */
+ for (i = 0; i < entry->nsymbols; i++) {
+ if (has_nz) {
+ entry->symbols[i].nzlist = *nzp++;
+ } else {
+ entry->symbols[i].nzlist.nlist = *np++;
+ entry->symbols[i].nzlist.nz_size = 0;
+ }
+ entry->symbols[i].symbol = NULL;
+ entry->symbols[i].next = NULL;
+ entry->symbols[i].entry = entry;
+ entry->symbols[i].gotslot_offset = -1;
+ entry->symbols[i].flags = 0;
+ }
+
+ /* Read strings (text segment) */
+ n = entry->string_size = sdt.sdt_str_sz;
+ entry->strings = (char *)alloca(n);
+ entry->strings_offset = text_offset(entry) + sdt.sdt_strings;
+ if (lseek(fd,
+ entry->strings_offset -
+ (TEXT_START(entry->header) - N_TXTOFF(entry->header)),
+ L_SET) == (off_t)-1)
+ err(1, "%s: lseek", get_file_name(entry));
+ if (read(fd, entry->strings, n) != n)
+ errx(1, "%s: premature EOF reading strings",
+ get_file_name(entry));
+ enter_file_symbols (entry);
+ entry->strings = 0;
+
+ /*
+ * Load any subsidiary shared objects.
+ */
+ if (sdt.sdt_sods) {
+ struct sod sod;
+ off_t offset;
+ struct file_entry *prev = NULL;
+
+ offset = (off_t)sdt.sdt_sods;
+ while (1) {
+ struct file_entry *subentry;
+ char *libname, name[MAXPATHLEN]; /*XXX*/
+
+ subentry = (struct file_entry *)
+ xmalloc(sizeof(struct file_entry));
+ bzero(subentry, sizeof(struct file_entry));
+ subentry->superfile = entry;
+ subentry->flags = E_SECONDCLASS;
+
+ if (lseek(fd,
+ offset - (TEXT_START(entry->header) -
+ N_TXTOFF(entry->header)),
+ L_SET) == (off_t)-1)
+ err(1, "%s: lseek", get_file_name(entry));
+ if (read(fd, &sod, sizeof(sod)) != sizeof(sod))
+ errx(1, "%s: premature EOF reding sod",
+ get_file_name(entry));
+ md_swapin_sod(&sod, 1);
+ if (lseek(fd,
+ (off_t)sod.sod_name - (TEXT_START(entry->header) -
+ N_TXTOFF(entry->header)),
+ L_SET) == (off_t)-1)
+ err(1, "%s: lseek", get_file_name(entry));
+ (void)read(fd, name, sizeof(name)); /*XXX*/
+ if (sod.sod_library) {
+ int sod_major = sod.sod_major;
+ int sod_minor = sod.sod_minor;
+
+ libname = findshlib(name,
+ &sod_major, &sod_minor, 0);
+ if (libname == NULL)
+ errx(1,"no shared -l%s.%d.%d available",
+ name, sod.sod_major, sod.sod_minor);
+ subentry->filename = libname;
+ subentry->local_sym_name = concat("-l", name, "");
+ } else {
+ subentry->filename = strdup(name);
+ subentry->local_sym_name = strdup(name);
+ }
+ read_file_symbols(subentry);
+
+ if (prev)
+ prev->chain = subentry;
+ else
+ entry->subfiles = subentry;
+ prev = subentry;
+ fd = file_open(entry);
+ if ((offset = (off_t)sod.sod_next) == 0)
+ break;
+ }
+ }
+#ifdef SUN_COMPAT
+ if (link_mode & SILLYARCHIVE) {
+ char *cp, *sa_name;
+ char armag[SARMAG];
+ int fd;
+ struct file_entry *subentry;
+
+ sa_name = strdup(entry->filename);
+ if (sa_name == NULL)
+ goto out;
+ cp = sa_name + strlen(sa_name) - 1;
+ while (cp > sa_name) {
+ if (!isdigit(*cp) && *cp != '.')
+ break;
+ --cp;
+ }
+ if (cp <= sa_name || *cp != 'o') {
+ /* Not in `libxxx.so.n.m' form */
+ free(sa_name);
+ goto out;
+ }
+
+ *cp = 'a';
+ if ((fd = open(sa_name, O_RDONLY, 0)) < 0)
+ goto out;
+
+ /* Read archive magic */
+ bzero(armag, SARMAG);
+ (void)read(fd, armag, SARMAG);
+ (void)close(fd);
+ if (strncmp(armag, ARMAG, SARMAG) != 0) {
+ warnx("%s: malformed silly archive",
+ get_file_name(entry));
+ goto out;
+ }
+
+ subentry = (struct file_entry *)
+ xmalloc(sizeof(struct file_entry));
+ bzero(subentry, sizeof(struct file_entry));
+
+ entry->silly_archive = subentry;
+ subentry->superfile = entry;
+ subentry->filename = sa_name;
+ subentry->local_sym_name = sa_name;
+ subentry->flags |= E_IS_LIBRARY;
+ search_library(file_open(subentry), subentry);
+out:
+ ;
+ }
+#endif
+}
+
+#undef major
+#undef minor
+
+int
+findlib(p)
+struct file_entry *p;
+{
+ int i;
+ int fd = -1;
+ int major = -1, minor = -1;
+ char *cp, *fname = NULL;
+
+ if (!(p->flags & E_SEARCH_DYNAMIC))
+ goto dot_a;
+
+ fname = findshlib(p->filename, &major, &minor, 1);
+
+ if (fname && (fd = open(fname, O_RDONLY, 0)) >= 0) {
+ p->filename = fname;
+ p->lib_major = major;
+ p->lib_minor = minor;
+ p->flags &= ~E_SEARCH_DIRS;
+ return fd;
+ }
+ (void)free(fname);
+
+dot_a:
+ p->flags &= ~E_SEARCH_DYNAMIC;
+ if ( (cp = strrchr(p->filename, '/')) ) {
+ *cp++ = '\0';
+ fname = concat(concat(p->filename, "/lib", cp), ".a", "");
+ *(--cp) = '/';
+ } else
+ fname = concat("lib", p->filename, ".a");
+
+ for (i = 0; i < n_search_dirs; i++) {
+ register char *path
+ = concat(search_dirs[i], "/", fname);
+ fd = open(path, O_RDONLY, 0);
+ if (fd >= 0) {
+ p->filename = path;
+ p->flags &= ~E_SEARCH_DIRS;
+ break;
+ }
+ (void)free(path);
+ }
+ (void)free(fname);
+ return fd;
+}
diff --git a/gnu/usr.bin/ld/rrs.c b/gnu/usr.bin/ld/rrs.c
new file mode 100644
index 0000000..fbd356c
--- /dev/null
+++ b/gnu/usr.bin/ld/rrs.c
@@ -0,0 +1,1272 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <fcntl.h>
+#include <ar.h>
+#include <ranlib.h>
+#include <a.out.h>
+#include <stab.h>
+#include <string.h>
+
+#include "ld.h"
+#include "dynamic.h"
+
+static struct _dynamic rrs_dyn; /* defined in link.h */
+static struct so_debug rrs_so_debug; /* defined in link.h */
+static struct section_dispatch_table rrs_sdt; /* defined in link.h */
+static got_t *rrs_got;
+static jmpslot_t *rrs_plt; /* defined in md.h */
+static struct relocation_info *rrs_reloc;
+static struct nzlist *rrs_symbols; /* RRS symbol table */
+static char *rrs_strtab; /* RRS strings */
+static struct rrs_hash *rrs_hashtab; /* RT hash table */
+static struct shobj *rrs_shobjs;
+char *rrs_search_paths; /* `-L' RT search */
+static int rrs_search_paths_size;
+
+static int reserved_rrs_relocs;
+static int claimed_rrs_relocs;
+static int discarded_rrs_relocs;
+
+static int number_of_gotslots = 1;
+static int number_of_jmpslots = 1;
+static int number_of_rrs_hash_entries;
+static int number_of_rrs_symbols;
+static int rrs_strtab_size;
+static int rrs_symbol_size;
+
+static int current_jmpslot_offset;
+static int current_got_offset;
+static int max_got_offset;
+static int min_got_offset;
+static int got_origin;
+static int current_reloc_offset;
+static int current_hash_index;
+int number_of_shobjs;
+
+/* Convert a GOT offset into a table entry */
+#define GOTP(off) ((got_t *)((long)rrs_got + got_origin + (off)))
+
+struct shobj {
+ struct shobj *next;
+ struct file_entry *entry;
+};
+
+/*
+RRS text segment:
+ +-------------------+ <-- sdt_rel (rrs_text_start)
+ | |
+ | relocation |
+ | |
+ +-------------------+ <-- <sdt>.sdt_hash
+ | |
+ | hash buckets |
+ | |
+ +-------------------+ <-- <sdt>.sdt_nzlist
+ | |
+ | symbols |
+ | |
+ +-------------------+ <-- <sdt>.sdt_strings
+ | |
+ | strings |
+ | |
+ +-------------------+ <-- <sdt>.sdt_sods
+ | |
+ | shobjs |
+ | |
+ +-------------------+
+ | |
+ | shobjs strings | <-- <shobj>.sod_name
+ | |
+ +-------------------+
+
+
+RRS data segment:
+
+ +-------------------+ <-- __DYNAMIC (rrs_data_start)
+ | |
+ | _dymamic |
+ | |
+ +-------------------+ <-- __DYNAMIC.d_debug
+ | |
+ | so_debug |
+ | |
+ +-------------------+ <-- __DYNAMIC.d_un.d_sdt
+ | |
+ | sdt |
+ | |
+ +-------------------+ <-- sdt_got
+ | |
+ | _GOT_ | <-- _GLOBAL_OFFSET_TABLE_
+ | | ( == sdt_got + got_origin)
+ | |
+ +-------------------+ <-- sdt_plt
+ | |
+ | PLT |
+ | |
+ +-------------------+
+*/
+
+/*
+ * Add NAME to the list of needed run-time objects.
+ * Return 1 if ENTRY was added to the list.
+ */
+int
+rrs_add_shobj(entry)
+ struct file_entry *entry;
+{
+ struct shobj **p;
+
+ for (p = &rrs_shobjs; *p != NULL; p = &(*p)->next)
+ if (strcmp((*p)->entry->filename, entry->filename) == 0)
+ return 0;
+ *p = (struct shobj *)xmalloc(sizeof(struct shobj));
+ (*p)->next = NULL;
+ (*p)->entry = entry;
+
+ number_of_shobjs++;
+ return 1;
+}
+
+void
+alloc_rrs_reloc(entry, sp)
+ struct file_entry *entry;
+ symbol *sp;
+{
+#ifdef DEBUG
+printf("alloc_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
+#endif
+ reserved_rrs_relocs++;
+}
+
+void
+alloc_rrs_segment_reloc(entry, r)
+ struct file_entry *entry;
+ struct relocation_info *r;
+{
+#ifdef DEBUG
+printf("alloc_rrs_segment_reloc at %#x in %s\n",
+ r->r_address, get_file_name(entry));
+#endif
+ reserved_rrs_relocs++;
+}
+
+void
+alloc_rrs_jmpslot(entry, sp)
+ struct file_entry *entry;
+ symbol *sp;
+{
+ if (sp->flags & GS_HASJMPSLOT)
+ return;
+
+ sp->flags |= GS_HASJMPSLOT;
+ number_of_jmpslots++;
+ reserved_rrs_relocs++;
+}
+
+void
+alloc_rrs_gotslot(entry, r, lsp)
+ struct file_entry *entry;
+ struct relocation_info *r;
+ struct localsymbol *lsp;
+{
+ symbol *sp = lsp->symbol;
+
+ if (!RELOC_EXTERN_P(r)) {
+
+ if (sp != NULL) {
+ warnx("%s: relocation for internal symbol "
+ "expected at %#x",
+ get_file_name(entry), RELOC_ADDRESS(r));
+ return;
+ }
+
+ if (!RELOC_STATICS_THROUGH_GOT_P(r))
+ /* No need for a GOT slot */
+ return;
+
+ if (lsp->flags & LS_HASGOTSLOT)
+ return;
+
+ lsp->flags |= LS_HASGOTSLOT;
+
+ } else {
+
+ if (sp == NULL) {
+ warnx("%s: relocation must refer "
+ "to global symbol at %#x",
+ get_file_name(entry), RELOC_ADDRESS(r));
+ return;
+ }
+
+ if (sp->alias)
+ sp = sp->alias;
+
+ if (sp->flags & GS_HASGOTSLOT)
+ return;
+
+ sp->flags |= GS_HASGOTSLOT;
+ }
+
+ number_of_gotslots++;
+ reserved_rrs_relocs++;
+}
+
+void
+alloc_rrs_cpy_reloc(entry, sp)
+ struct file_entry *entry;
+ symbol *sp;
+{
+ if (sp->flags & GS_CPYRELOCRESERVED)
+ return;
+#ifdef DEBUG
+printf("alloc_rrs_copy: %s in %s\n", demangle(sp->name), get_file_name(entry));
+#endif
+ sp->flags |= GS_CPYRELOCRESERVED;
+ reserved_rrs_relocs++;
+}
+
+static struct relocation_info *
+rrs_next_reloc()
+{
+ struct relocation_info *r;
+
+ r = rrs_reloc + claimed_rrs_relocs++;
+ if (claimed_rrs_relocs > reserved_rrs_relocs)
+ errx(1, "internal error: RRS relocs exceed allocation %d",
+ reserved_rrs_relocs);
+ return r;
+}
+
+/*
+ * Claim a RRS relocation as a result of a regular (ie. non-PIC)
+ * relocation record in a rel file.
+ *
+ * Return 1 if the output file needs no further updating.
+ * Return 0 if the relocation value pointed to by RELOCATION must
+ * written to a.out.
+ */
+int
+claim_rrs_reloc(entry, rp, sp, relocation)
+ struct file_entry *entry;
+ struct relocation_info *rp;
+ symbol *sp;
+ long *relocation;
+{
+ struct relocation_info *r = rrs_next_reloc();
+
+ if (rp->r_address < text_start + text_size
+ && (link_mode & WARNRRSTEXT))
+ warnx("%s: RRS text relocation at %#x for \"%s\"",
+ get_file_name(entry), rp->r_address, demangle(sp->name));
+
+#ifdef DEBUG
+printf("claim_rrs_reloc: %s in %s\n", demangle(sp->name), get_file_name(entry));
+#endif
+ r->r_address = rp->r_address;
+ r->r_symbolnum = sp->rrs_symbolnum;
+
+ if (link_mode & SYMBOLIC) {
+ if (!sp->defined)
+ warnx("Cannot reduce symbol \"%s\" in %s",
+ demangle(sp->name), get_file_name(entry));
+ RELOC_EXTERN_P(r) = 0;
+ *relocation += sp->value;
+ (void) md_make_reloc(rp, r, RELTYPE_RELATIVE);
+ return 0;
+ } else {
+ RELOC_EXTERN_P(r) = 1;
+ return md_make_reloc(rp, r, RELTYPE_EXTERN);
+ }
+}
+
+/*
+ * Claim a jmpslot. Setup RRS relocation if claimed for the first time.
+ */
+long
+claim_rrs_jmpslot(entry, rp, sp, addend)
+ struct file_entry *entry;
+ struct relocation_info *rp;
+ symbol *sp;
+ long addend;
+{
+ struct relocation_info *r;
+
+ if (!(sp->flags & GS_HASJMPSLOT))
+ errx(1, "internal error: "
+ "%s: claim_rrs_jmpslot: %s: no reservation",
+ get_file_name(entry),
+ demangle(sp->name));
+
+ if (sp->jmpslot_offset != -1)
+ return rrs_sdt.sdt_plt + sp->jmpslot_offset;
+
+ sp->jmpslot_offset = current_jmpslot_offset;
+ current_jmpslot_offset += sizeof(jmpslot_t);
+
+#ifdef DEBUG
+printf("claim_rrs_jmpslot: %s: %s(%d) -> offset %x\n",
+ get_file_name(entry),
+ demangle(sp->name), sp->rrs_symbolnum, sp->jmpslot_offset);
+#endif
+
+ if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
+ if (!sp->defined)
+ warnx("Cannot reduce symbol \"%s\" in %s",
+ demangle(sp->name), get_file_name(entry));
+
+ md_fix_jmpslot( rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
+ rrs_sdt.sdt_plt + sp->jmpslot_offset,
+ sp->value);
+ if (rrs_section_type == RRS_PARTIAL || !JMPSLOT_NEEDS_RELOC) {
+ /* PLT is self-contained */
+ discarded_rrs_relocs++;
+ return rrs_sdt.sdt_plt + sp->jmpslot_offset;
+ }
+ } else {
+ md_make_jmpslot(rrs_plt + sp->jmpslot_offset/sizeof(jmpslot_t),
+ sp->jmpslot_offset,
+ claimed_rrs_relocs);
+ }
+
+ /*
+ * Install a run-time relocation for this PLT entry.
+ */
+ r = rrs_next_reloc();
+
+ RELOC_SYMBOL(r) = sp->rrs_symbolnum;
+
+ r->r_address = (long)rrs_sdt.sdt_plt + sp->jmpslot_offset;
+
+ if (link_mode & SYMBOLIC) {
+ RELOC_EXTERN_P(r) = 0;
+ md_make_jmpreloc(rp, r, RELTYPE_RELATIVE);
+ } else {
+ RELOC_EXTERN_P(r) = 1;
+ md_make_jmpreloc(rp, r, 0);
+ }
+
+ return rrs_sdt.sdt_plt + sp->jmpslot_offset;
+}
+
+/*
+ * Claim GOT entry for a global symbol. If this is the first relocation
+ * claiming the entry, setup a RRS relocation for it.
+ * Return offset into the GOT allocated to this symbol.
+ */
+long
+claim_rrs_gotslot(entry, rp, lsp, addend)
+ struct file_entry *entry;
+ struct relocation_info *rp;
+ struct localsymbol *lsp;
+ long addend;
+{
+ struct relocation_info *r;
+ symbol *sp = lsp->symbol;
+ int reloc_type = 0;
+
+ if (sp == NULL) {
+ return 0;
+ }
+
+ if (sp->alias)
+ sp = sp->alias;
+
+ if (!(sp->flags & GS_HASGOTSLOT))
+ errx(1, "internal error: "
+ "%s: claim_rrs_gotslot: %s: no reservation",
+ get_file_name(entry), demangle(sp->name));
+
+ if (sp->gotslot_offset != -1) {
+#ifdef DIAGNOSTIC
+ if (*GOTP(sp->gotslot_offset) != addend +
+ ((!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))
+ ? sp->value : 0))
+ errx(1, "%s: %s: gotslot at %#x is multiple valued, "
+ "*got = %#x, addend = %#x, sp->value = %#x",
+ get_file_name(entry), demangle(sp->name),
+ sp->gotslot_offset,
+ *GOTP(sp->gotslot_offset), addend, sp->value);
+#endif
+ /* This symbol already passed here before. */
+ return sp->gotslot_offset;
+ }
+
+ if (current_got_offset == 0)
+ /* GOT offset 0 is reserved */
+ current_got_offset += sizeof(got_t);
+
+ if (current_got_offset > max_got_offset)
+ errx(1, "%s: GOT overflow on symbol `%s' at %#x",
+ get_file_name(entry), demangle(sp->name), RELOC_ADDRESS(rp));
+
+ sp->gotslot_offset = current_got_offset;
+ current_got_offset += sizeof(got_t);
+
+#ifdef DEBUG
+printf("claim_rrs_gotslot: %s(%d,%#x) slot offset %#x, addend %#x\n",
+ demangle(sp->name), sp->rrs_symbolnum, sp->value, sp->gotslot_offset, addend);
+#endif
+
+ if (sp->defined &&
+ (!(link_mode & SHAREABLE) || (link_mode & SYMBOLIC))) {
+
+ /*
+ * Reduce to just a base-relative translation.
+ */
+
+ *GOTP(sp->gotslot_offset) = sp->value + addend;
+ reloc_type = RELTYPE_RELATIVE;
+
+ } else if ((link_mode & SYMBOLIC) || rrs_section_type == RRS_PARTIAL) {
+ /*
+ * SYMBOLIC: all symbols must be known.
+ * RRS_PARTIAL: we don't link against shared objects,
+ * so again all symbols must be known.
+ */
+ warnx("Cannot reduce symbol \"%s\" in %s",
+ demangle(sp->name), get_file_name(entry));
+
+ } else {
+
+ /*
+ * This gotslot will be updated with symbol value at run-time.
+ */
+
+ *GOTP(sp->gotslot_offset) = addend;
+ }
+
+ if (rrs_section_type == RRS_PARTIAL) {
+ /*
+ * Base address is known, gotslot should be fully
+ * relocated by now.
+ * NOTE: RRS_PARTIAL implies !SHAREABLE.
+ */
+ if (!sp->defined)
+ warnx("Cannot reduce symbol \"%s\" in %s",
+ demangle(sp->name), get_file_name(entry));
+ discarded_rrs_relocs++;
+ return sp->gotslot_offset;
+ }
+
+ /*
+ * Claim a relocation entry.
+ * If symbol is defined and in "main" (!SHAREABLE)
+ * we still put out a relocation as we cannot easily
+ * undo the allocation.
+ * `RELTYPE_RELATIVE' relocations have the external bit off
+ * as no symbol need be looked up at run-time.
+ */
+ r = rrs_next_reloc();
+ r->r_address = got_symbol->value + sp->gotslot_offset;
+ RELOC_SYMBOL(r) = sp->rrs_symbolnum;
+ RELOC_EXTERN_P(r) = !(reloc_type == RELTYPE_RELATIVE);
+ md_make_gotreloc(rp, r, reloc_type);
+
+ return sp->gotslot_offset;
+}
+
+/*
+ * Claim a GOT entry for a static symbol. Return offset of the
+ * allocated GOT entry. If RELOC_STATICS_THROUGH_GOT_P is in effect,
+ * return the offset of the symbol with respect to the *location* of
+ * the GOT.
+ */
+long
+claim_rrs_internal_gotslot(entry, rp, lsp, addend)
+ struct file_entry *entry;
+ struct relocation_info *rp;
+ struct localsymbol *lsp;
+ long addend;
+{
+ struct relocation_info *r;
+
+ addend += lsp->nzlist.nz_value;
+
+ if (!RELOC_STATICS_THROUGH_GOT_P(r))
+ return addend - got_symbol->value;
+
+ if (!(lsp->flags & LS_HASGOTSLOT))
+ errx(1, "internal error: "
+ "%s: claim_rrs_internal_gotslot at %#x: no reservation",
+ get_file_name(entry), RELOC_ADDRESS(rp));
+
+ if (lsp->gotslot_offset != -1) {
+ /* Already claimed */
+ if (*GOTP(lsp->gotslot_offset) != addend)
+ errx(1, "%s: gotslot at %#lx is multiple valued",
+ get_file_name(entry), lsp->gotslot_offset);
+ return lsp->gotslot_offset;
+ }
+
+ if (current_got_offset == 0)
+ /* GOT offset 0 is reserved */
+ current_got_offset += sizeof(got_t);
+
+ if (current_got_offset > max_got_offset)
+ errx(1, "%s: GOT overflow for relocation at %#x",
+ get_file_name(entry), RELOC_ADDRESS(rp));
+
+ lsp->gotslot_offset = current_got_offset;
+ current_got_offset += sizeof(got_t);
+
+ *GOTP(lsp->gotslot_offset) = addend;
+
+#ifdef DEBUG
+printf("claim_rrs_internal_gotslot: %s: slot offset %#x, addend = %#x\n",
+ get_file_name(entry), lsp->gotslot_offset, addend);
+#endif
+
+ if (rrs_section_type == RRS_PARTIAL) {
+ discarded_rrs_relocs++;
+ return lsp->gotslot_offset;
+ }
+
+ /*
+ * Relocation entry needed for this static GOT entry.
+ */
+ r = rrs_next_reloc();
+ r->r_address = got_symbol->value + lsp->gotslot_offset;
+ RELOC_EXTERN_P(r) = 0;
+ md_make_gotreloc(rp, r, RELTYPE_RELATIVE);
+ return lsp->gotslot_offset;
+}
+
+void
+claim_rrs_cpy_reloc(entry, rp, sp)
+ struct file_entry *entry;
+ struct relocation_info *rp;
+ symbol *sp;
+{
+ struct relocation_info *r;
+
+ if (sp->flags & GS_CPYRELOCCLAIMED)
+ return;
+
+ if (!(sp->flags & GS_CPYRELOCRESERVED))
+ errx(1, "internal error: "
+ "%s: claim_cpy_reloc: %s: no reservation",
+ get_file_name(entry), demangle(sp->name));
+
+#ifdef DEBUG
+printf("claim_rrs_copy: %s: %s -> %x\n",
+ get_file_name(entry), demangle(sp->name), sp->so_defined);
+#endif
+
+ r = rrs_next_reloc();
+ sp->flags |= GS_CPYRELOCCLAIMED;
+ r->r_address = rp->r_address;
+ RELOC_SYMBOL(r) = sp->rrs_symbolnum;
+ RELOC_EXTERN_P(r) = RELOC_EXTERN_P(rp);
+ md_make_cpyreloc(rp, r);
+}
+
+void
+claim_rrs_segment_reloc(entry, rp)
+ struct file_entry *entry;
+ struct relocation_info *rp;
+{
+ struct relocation_info *r = rrs_next_reloc();
+
+#ifdef DEBUG
+printf("claim_rrs_segment_reloc: %s at %#x\n",
+ get_file_name(entry), rp->r_address);
+#endif
+
+ r->r_address = rp->r_address;
+ RELOC_TYPE(r) = RELOC_TYPE(rp);
+ RELOC_EXTERN_P(r) = 0;
+ md_make_reloc(rp, r, RELTYPE_RELATIVE);
+
+}
+
+/*
+ * Fill the RRS hash table for the given symbol name.
+ * NOTE: the hash value computation must match the one in rtld.
+ */
+void
+rrs_insert_hash(cp, index)
+ char *cp;
+ int index;
+{
+ int hashval = 0;
+ struct rrs_hash *hp;
+
+ for (; *cp; cp++)
+ hashval = (hashval << 1) + *cp;
+
+ hashval = (hashval & 0x7fffffff) % rrs_sdt.sdt_buckets;
+
+ /* Get to the bucket */
+ hp = rrs_hashtab + hashval;
+ if (hp->rh_symbolnum == -1) {
+ /* Empty bucket, use it */
+ hp->rh_symbolnum = index;
+ hp->rh_next = 0;
+ return;
+ }
+
+ while (hp->rh_next != 0)
+ hp = rrs_hashtab + hp->rh_next;
+
+ hp->rh_next = current_hash_index++;
+ hp = rrs_hashtab + hp->rh_next;
+ hp->rh_symbolnum = index;
+ hp->rh_next = 0;
+}
+
+/*
+ * There are two interesting cases to consider here.
+ *
+ * 1) No shared objects were loaded, but there were PIC input rel files.
+ * In this case we must output a _GLOBAL_OFFSET_TABLE_ but no other
+ * RRS data. Also, the entries in the GOT must be fully resolved.
+ *
+ * 2) It's a genuine dynamically linked program, so the whole RRS scoop
+ * goes into a.out.
+ */
+void
+consider_rrs_section_lengths()
+{
+ int n;
+ struct shobj *shp;
+
+#ifdef notyet
+ struct shobj **shpp;
+/* We run into trouble with this as long as shared object symbols
+ are not checked for definitions */
+ /*
+ * First, determine the real number of shared objects we need.
+ */
+ for (shpp = &rrs_shobjs; *shpp; shpp = &(*shpp)->next) {
+ while (*shpp && !((*shpp)->entry->flags & E_SYMBOLS_USED)) {
+ if (--number_of_shobjs < 0)
+ errx(1, "internal error: number_of_shobjs < 0");
+ *shpp = (*shpp)->next;
+ }
+ if (*shpp == NULL)
+ break;
+ }
+#endif
+
+ /* First, determine what of the RRS we want */
+ if (relocatable_output)
+ rrs_section_type = RRS_NONE;
+ else if (link_mode & SHAREABLE)
+ rrs_section_type = RRS_FULL;
+ else if (number_of_shobjs == 0 && !(link_mode & FORCEDYNAMIC)) {
+ /*
+ * First slots in both tables are reserved
+ * hence the "> 1" condition
+ */
+ if (number_of_gotslots > 1 || number_of_jmpslots > 1)
+ rrs_section_type = RRS_PARTIAL;
+ else
+ rrs_section_type = RRS_NONE;
+ } else
+ rrs_section_type = RRS_FULL;
+
+ if (rrs_section_type == RRS_NONE) {
+ got_symbol->defined = 0;
+ if (reserved_rrs_relocs > 0)
+ errx(1, "internal error: empty RRS has reservations");
+ return;
+ }
+
+ rrs_symbol_size = LD_VERSION_NZLIST_P(soversion) ?
+ sizeof(struct nzlist) : sizeof(struct nlist);
+
+ /*
+ * If there is an entry point, __DYNAMIC must be referenced (usually
+ * from crt0), as this is the method used to determine whether the
+ * run-time linker must be called.
+ */
+ if (!(link_mode & SHAREABLE) && !(dynamic_symbol->flags & GS_REFERENCED))
+ errx(1, "No reference to __DYNAMIC");
+
+ dynamic_symbol->flags |= GS_REFERENCED;
+
+ if (number_of_gotslots > 1)
+ got_symbol->flags |= GS_REFERENCED;
+
+
+ /* Next, allocate relocs, got and plt */
+ n = reserved_rrs_relocs * sizeof(struct relocation_info);
+ rrs_reloc = (struct relocation_info *)xmalloc(n);
+ bzero(rrs_reloc, n);
+
+ n = number_of_gotslots * sizeof(got_t);
+ rrs_got = (got_t *)xmalloc(n);
+ bzero(rrs_got, n);
+
+ n = number_of_jmpslots * sizeof(jmpslot_t);
+ rrs_plt = (jmpslot_t *)xmalloc(n);
+ bzero(rrs_plt, n);
+
+ /* Initialize first jmpslot */
+ md_fix_jmpslot(rrs_plt, 0, 0);
+
+ if (rrs_section_type == RRS_PARTIAL) {
+ rrs_data_size = number_of_gotslots * sizeof(got_t);
+ rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
+ return;
+ }
+
+ /*
+ * Walk the symbol table, assign RRS symbol numbers
+ * and calculate string space.
+ * Assign number 0 to __DYNAMIC (!! Sun compatibility)
+ */
+ dynamic_symbol->rrs_symbolnum = number_of_rrs_symbols++;
+ FOR_EACH_SYMBOL(i ,sp) {
+ if ((link_mode & SHAREABLE) && sp->warning) {
+ /* Allocate N_WARNING & co */
+ rrs_strtab_size +=
+ 2 + strlen(sp->name) + strlen(sp->warning);
+ number_of_rrs_symbols += 2;
+ }
+
+ if (!(sp->flags & GS_REFERENCED))
+ continue;
+
+ rrs_strtab_size += 1 + strlen(sp->name);
+ if (sp != dynamic_symbol)
+ sp->rrs_symbolnum = number_of_rrs_symbols++;
+ if (sp->alias) {
+ /*
+ * (sigh) Always allocate space to hold the
+ * indirection. At this point there's not
+ * enough information to decide whether it's
+ * actually needed or not.
+ */
+ number_of_rrs_symbols++;
+ rrs_strtab_size += 1 + strlen(sp->alias->name);
+ }
+ } END_EACH_SYMBOL;
+
+ /*
+ * Now that we know how many RRS symbols there are going to be,
+ * allocate and initialize the RRS symbol hash table.
+ */
+ rrs_sdt.sdt_buckets = number_of_rrs_symbols/4;
+ if (rrs_sdt.sdt_buckets < 4)
+ rrs_sdt.sdt_buckets = 4;
+
+ number_of_rrs_hash_entries = rrs_sdt.sdt_buckets +
+ number_of_rrs_symbols;
+ rrs_hashtab = (struct rrs_hash *)xmalloc(
+ number_of_rrs_hash_entries * sizeof(struct rrs_hash));
+ for (n = 0; n < rrs_sdt.sdt_buckets; n++)
+ rrs_hashtab[n].rh_symbolnum = -1;
+ current_hash_index = rrs_sdt.sdt_buckets;
+
+ /*
+ * Get symbols into hash table now, so we can fine tune the size
+ * of the latter. We adjust the value of `number_of_rrs_hash_entries'
+ * to the number of hash link slots actually used.
+ */
+ FOR_EACH_SYMBOL(i ,sp) {
+ if (sp->flags & GS_REFERENCED)
+ rrs_insert_hash(sp->name, sp->rrs_symbolnum);
+ } END_EACH_SYMBOL;
+ number_of_rrs_hash_entries = current_hash_index;
+
+ /*
+ * Calculate RRS section sizes.
+ */
+ rrs_data_size = sizeof(struct _dynamic);
+ rrs_data_size += sizeof(struct so_debug);
+ rrs_data_size += sizeof(struct section_dispatch_table);
+ rrs_data_size += number_of_gotslots * sizeof(got_t);
+ rrs_data_size += number_of_jmpslots * sizeof(jmpslot_t);
+ rrs_data_size = MALIGN(rrs_data_size);
+
+ rrs_text_size = reserved_rrs_relocs * sizeof(struct relocation_info);
+ rrs_text_size += number_of_rrs_hash_entries * sizeof(struct rrs_hash);
+ rrs_text_size += number_of_rrs_symbols * rrs_symbol_size;
+ rrs_search_paths_size = rrs_search_paths
+ ? strlen(rrs_search_paths) + 1
+ : 0;
+ rrs_search_paths_size = MALIGN(rrs_search_paths_size);
+ rrs_text_size += rrs_search_paths_size;
+
+ /* Align strings size */
+ rrs_strtab_size = MALIGN(rrs_strtab_size);
+ rrs_text_size += rrs_strtab_size;
+
+ /* Process needed shared objects */
+ for (shp = rrs_shobjs; shp; shp = shp->next) {
+ char *name = shp->entry->local_sym_name;
+
+ if (*name == '-' && *(name+1) == 'l')
+ name += 2;
+
+ rrs_text_size += sizeof(struct sod);
+ rrs_text_size += 1 + strlen(name);
+ }
+
+ /* Finally, align size */
+ rrs_text_size = MALIGN(rrs_text_size);
+}
+
+void
+relocate_rrs_addresses()
+{
+ int gotsize;
+
+ dynamic_symbol->value = 0;
+
+ /*
+ * Get ready to allocate linkage table offsets.
+ * First jmpslot is reserved for the run-time binder
+ * GOT entry at offset 0 is reserved for `__DYNAMIC'.
+ */
+ current_jmpslot_offset = sizeof(jmpslot_t);
+ current_got_offset = 0;
+ max_got_offset = MAX_GOTOFF(pic_type);
+ min_got_offset = MIN_GOTOFF(pic_type);
+ gotsize = number_of_gotslots * sizeof(got_t);
+
+ if (gotsize + min_got_offset - (int)sizeof(got_t) > max_got_offset)
+ warnx("Global Offset Table overflow (use `-fPIC')");
+
+ if (gotsize > max_got_offset)
+ /* Position at "two-complements" origin */
+ current_got_offset += min_got_offset;
+
+ got_origin = -current_got_offset;
+
+ if (rrs_section_type == RRS_NONE)
+ return;
+
+ if (rrs_section_type == RRS_PARTIAL) {
+ rrs_sdt.sdt_got = rrs_data_start;
+ got_symbol->value = rrs_sdt.sdt_got + got_origin;
+ rrs_sdt.sdt_plt = rrs_sdt.sdt_got +
+ number_of_gotslots * sizeof(got_t);
+ return;
+ }
+
+ /*
+ * RRS data relocations.
+ */
+ rrs_dyn.d_version = soversion;
+ rrs_dyn.d_debug = (struct so_debug *)
+ (rrs_data_start + sizeof(struct _dynamic));
+ rrs_dyn.d_un.d_sdt = (struct section_dispatch_table *)
+ ((long)rrs_dyn.d_debug + sizeof(struct so_debug));
+
+ rrs_sdt.sdt_got = (long)rrs_dyn.d_un.d_sdt +
+ sizeof(struct section_dispatch_table);
+ rrs_sdt.sdt_plt = rrs_sdt.sdt_got + number_of_gotslots*sizeof(got_t);
+
+ /*
+ * RRS text relocations.
+ */
+ rrs_sdt.sdt_rel = rrs_text_start;
+ /*
+ * Sun BUG compatibility alert.
+ * Main program's RRS text values are relative to TXTADDR? WHY??
+ */
+#ifdef SUN_COMPAT
+ if (soversion == LD_VERSION_SUN && !(link_mode & SHAREABLE))
+ rrs_sdt.sdt_rel -= N_TXTADDR(outheader);
+#endif
+
+ rrs_sdt.sdt_hash = rrs_sdt.sdt_rel +
+ reserved_rrs_relocs * sizeof(struct relocation_info);
+ rrs_sdt.sdt_nzlist = rrs_sdt.sdt_hash +
+ number_of_rrs_hash_entries * sizeof(struct rrs_hash);
+ rrs_sdt.sdt_strings = rrs_sdt.sdt_nzlist +
+ number_of_rrs_symbols * rrs_symbol_size;
+ rrs_sdt.sdt_paths = rrs_search_paths
+ ? rrs_sdt.sdt_strings + rrs_strtab_size
+ : 0;
+ rrs_sdt.sdt_sods = rrs_shobjs
+ ? rrs_sdt.sdt_strings + rrs_strtab_size +
+ rrs_search_paths_size
+ : 0;
+ rrs_sdt.sdt_filler2 = 0;
+ rrs_sdt.sdt_str_sz = rrs_strtab_size;
+ rrs_sdt.sdt_text_sz = text_size;
+ rrs_sdt.sdt_plt_sz = number_of_jmpslots * sizeof(jmpslot_t);
+
+ /*
+ * Assign addresses to _GLOBAL_OFFSET_TABLE_ and __DYNAMIC.
+ * The value `&__DYNAMIC' is in the GOT table at offset 0.
+ */
+ got_symbol->value = rrs_sdt.sdt_got + got_origin;
+ *GOTP(0) = dynamic_symbol->value = rrs_data_start;
+
+}
+
+void
+write_rrs_data()
+{
+ long pos;
+
+ if (rrs_section_type == RRS_NONE)
+ return;
+
+ pos = rrs_data_start + N_TXTOFF(outheader) - text_start;
+ if (fseek(outstream, pos, SEEK_SET) != 0)
+ err(1, "write_rrs_data: fseek");
+
+ if (rrs_section_type == RRS_PARTIAL) {
+ /*
+ * Only a GOT and PLT are needed.
+ */
+ md_swapout_got(rrs_got, number_of_gotslots);
+ mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
+
+ md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
+ mywrite(rrs_plt, number_of_jmpslots,
+ sizeof(jmpslot_t), outstream);
+
+ return;
+ }
+
+ md_swapout__dynamic(&rrs_dyn);
+ mywrite(&rrs_dyn, 1, sizeof(struct _dynamic), outstream);
+
+ md_swapout_so_debug(&rrs_so_debug);
+ mywrite(&rrs_so_debug, 1, sizeof(struct so_debug), outstream);
+
+ md_swapout_section_dispatch_table(&rrs_sdt);
+ mywrite(&rrs_sdt, 1, sizeof(struct section_dispatch_table), outstream);
+
+ md_swapout_got(rrs_got, number_of_gotslots);
+ mywrite(rrs_got, number_of_gotslots, sizeof(got_t), outstream);
+
+ md_swapout_jmpslot(rrs_plt, number_of_jmpslots);
+ mywrite(rrs_plt, number_of_jmpslots, sizeof(jmpslot_t), outstream);
+}
+
+void
+write_rrs_text()
+{
+ long pos;
+ int i;
+ int symsize;
+ struct nzlist *nlp;
+ int offset = 0;
+ int aligned_offset;
+ struct shobj *shp;
+ struct sod *sodp;
+ int bind;
+
+ if (rrs_section_type == RRS_PARTIAL)
+ return;
+
+ pos = rrs_text_start + N_TXTOFF(outheader) - text_start;
+ if (fseek(outstream, pos, SEEK_SET) != 0)
+ err(1, "write_rrs_text: fseek");
+
+ /* Write relocation records */
+ md_swapout_reloc(rrs_reloc, reserved_rrs_relocs);
+ mywrite(rrs_reloc, reserved_rrs_relocs,
+ sizeof(struct relocation_info), outstream);
+
+ /* Write the RRS symbol hash tables */
+ md_swapout_rrs_hash(rrs_hashtab, number_of_rrs_hash_entries);
+ mywrite(rrs_hashtab, number_of_rrs_hash_entries,
+ sizeof(struct rrs_hash), outstream);
+
+ /*
+ * Determine size of an RRS symbol entry, allocate space
+ * to collect them in.
+ */
+ symsize = number_of_rrs_symbols * rrs_symbol_size;
+ nlp = rrs_symbols = (struct nzlist *)alloca(symsize);
+ rrs_strtab = (char *)alloca(rrs_strtab_size);
+
+#define INCR_NLP(p) ((p) = (struct nzlist *)((long)(p) + rrs_symbol_size))
+
+ /* __DYNAMIC symbol *must* be first for Sun compatibility */
+ nlp->nz_desc = nlp->nz_other = 0;
+ if (LD_VERSION_NZLIST_P(soversion))
+ nlp->nz_size = 0;
+ nlp->nz_type = dynamic_symbol->defined;
+ nlp->nz_value = dynamic_symbol->value;
+ nlp->nz_value = dynamic_symbol->value;
+ nlp->nz_strx = offset;
+ strcpy(rrs_strtab + offset, dynamic_symbol->name);
+ offset += 1 + strlen(dynamic_symbol->name);
+ INCR_NLP(nlp);
+
+ /*
+ * Now, for each global symbol, construct a nzlist element
+ * for inclusion in the RRS symbol table.
+ */
+ FOR_EACH_SYMBOL(i, sp) {
+
+ if (sp == dynamic_symbol)
+ continue;
+
+ if ((link_mode & SHAREABLE) && sp->warning) {
+ /*
+ * Write a N_WARNING duo.
+ */
+ nlp->nz_type = N_WARNING;
+ nlp->nz_un.n_strx = offset;
+ nlp->nz_value = 0;
+ nlp->nz_other = 0;
+ nlp->nz_desc = 0;
+ nlp->nz_size = 0;
+ strcpy(rrs_strtab + offset, sp->warning);
+ offset += 1 + strlen(sp->warning);
+ INCR_NLP(nlp);
+
+ nlp->nz_type = N_UNDF + N_EXT;
+ nlp->nz_un.n_strx = offset;
+ nlp->nz_value = 0;
+ nlp->nz_other = 0;
+ nlp->nz_desc = 0;
+ nlp->nz_size = 0;
+ strcpy(rrs_strtab + offset, sp->name);
+ offset += 1 + strlen(sp->name);
+ INCR_NLP(nlp);
+ }
+
+ if (!(sp->flags & GS_REFERENCED))
+ continue;
+
+ if ((long)nlp - (long)rrs_symbols >=
+ number_of_rrs_symbols * rrs_symbol_size)
+ errx(1, "internal error: "
+ "rrs symbols exceed allocation %d",
+ number_of_rrs_symbols);
+
+ nlp->nz_desc = 0;
+ nlp->nz_other = 0;
+ if (LD_VERSION_NZLIST_P(soversion))
+ nlp->nz_size = 0;
+
+ bind = (sp->flags & GS_WEAK) ? BIND_WEAK : 0;
+
+ if (sp->defined > 1) {
+ /* defined with known type */
+ if (!(link_mode & SHAREABLE) &&
+ sp->alias && sp->alias->defined > 1) {
+ /*
+ * If the target of an indirect symbol has
+ * been defined and we are outputting an
+ * executable, resolve the indirection; it's
+ * no longer needed.
+ */
+ nlp->nz_type = sp->alias->defined;
+ nlp->nz_value = sp->alias->value;
+ nlp->nz_other = N_OTHER(bind, sp->alias->aux);
+ } else if (sp->defined == N_SIZE) {
+ /*
+ * Make sure this symbol isn't going
+ * to define anything.
+ */
+ nlp->nz_type = N_UNDF;
+ nlp->nz_value = 0;
+ } else {
+ nlp->nz_type = sp->defined;
+ nlp->nz_value = sp->value;
+ nlp->nz_other = N_OTHER(bind, sp->aux);
+ }
+ if (LD_VERSION_NZLIST_P(soversion))
+ nlp->nz_size = sp->size;
+ } else if (sp->common_size) {
+ /*
+ * A common definition.
+ */
+ nlp->nz_type = N_UNDF | N_EXT;
+ nlp->nz_value = sp->common_size;
+ nlp->nz_other = N_OTHER(bind, 0);
+ } else if (!sp->defined) {
+ /* undefined */
+ nlp->nz_type = N_UNDF | N_EXT;
+ nlp->nz_value = 0;
+ if (sp->so_defined && sp->jmpslot_offset != -1) {
+ /*
+ * A PLT entry. The auxiliary type -- which
+ * must be AUX_FUNC -- is used by the run-time
+ * linker to unambiguously resolve function
+ * address references.
+ */
+ if (sp->aux != AUX_FUNC)
+ errx(1, "%s: non-function jmpslot",
+ demangle(sp->name));
+ nlp->nz_other = N_OTHER(bind, sp->aux);
+ nlp->nz_value =
+ rrs_sdt.sdt_plt + sp->jmpslot_offset;
+ }
+ } else
+ errx(1, "internal error: %s defined in mysterious way",
+ demangle(sp->name));
+
+ /* Set symbol's name */
+ nlp->nz_strx = offset;
+ strcpy(rrs_strtab + offset, sp->name);
+ offset += 1 + strlen(sp->name);
+
+ if (sp->alias) {
+ /*
+ * Write an extra symbol for indirections (possibly
+ * just a dummy).
+ */
+ int t = (nlp->nz_type == N_INDR + N_EXT);
+
+ INCR_NLP(nlp);
+ nlp->nz_type = N_UNDF + (t ? N_EXT : 0);
+ nlp->nz_un.n_strx = offset;
+ nlp->nz_value = 0;
+ nlp->nz_other = 0;
+ nlp->nz_desc = 0;
+ nlp->nz_size = 0;
+ strcpy(rrs_strtab + offset, sp->alias->name);
+ offset += 1 + strlen(sp->alias->name);
+ }
+
+ INCR_NLP(nlp);
+
+ } END_EACH_SYMBOL;
+
+ aligned_offset = MALIGN(offset);
+ while (offset < aligned_offset) /* Pad deterministically */
+ rrs_strtab[offset++] = '\0';
+ if (offset != rrs_strtab_size)
+ errx(1, "internal error: "
+ "inconsistent RRS string table length: %d, expected %d",
+ offset, rrs_strtab_size);
+
+ /* Write the symbol table */
+ if (rrs_symbol_size == sizeof(struct nlist))
+ md_swapout_symbols(rrs_symbols, number_of_rrs_symbols);
+ else
+ md_swapout_zsymbols(rrs_symbols, number_of_rrs_symbols);
+ mywrite(rrs_symbols, symsize, 1, outstream);
+
+ /* Write the strings */
+ mywrite(rrs_strtab, rrs_strtab_size, 1, outstream);
+
+ /* Write RT search path */
+ mywrite(rrs_search_paths, rrs_search_paths_size, 1, outstream);
+
+ /*
+ * Write the names of the shared objects needed at run-time
+ */
+ pos = rrs_sdt.sdt_sods + number_of_shobjs * sizeof(struct sod);
+ sodp = (struct sod *)alloca( number_of_shobjs * sizeof(struct sod));
+
+ for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
+ char *name = shp->entry->local_sym_name;
+
+ if (i >= number_of_shobjs)
+ errx(1, "internal error: # of link objects exceeds %d",
+ number_of_shobjs);
+
+ sodp[i].sod_name = pos;
+ sodp[i].sod_major = shp->entry->lib_major;
+ sodp[i].sod_minor = shp->entry->lib_minor;
+
+ if (*name == '-' && *(name+1) == 'l') {
+ name += 2;
+ sodp[i].sod_library = 1;
+ } else
+ sodp[i].sod_library = 0;
+ sodp[i].sod_reserved = 0;
+
+ pos += 1 + strlen(name);
+ sodp[i].sod_next = (i == number_of_shobjs - 1) ? 0 :
+ (rrs_sdt.sdt_sods + (i+1)*sizeof(struct sod));
+ }
+
+ if (i < number_of_shobjs)
+ errx(1, "internal error: "
+ "# of link objects less then expected %d",
+ number_of_shobjs);
+
+ md_swapout_sod(sodp, number_of_shobjs);
+ mywrite(sodp, number_of_shobjs, sizeof(struct sod), outstream);
+
+ for (i = 0, shp = rrs_shobjs; shp; i++, shp = shp->next) {
+ char *name = shp->entry->local_sym_name;
+
+ if (*name == '-' && *(name+1) == 'l') {
+ name += 2;
+ }
+
+ mywrite(name, strlen(name) + 1, 1, outstream);
+ }
+}
+
+void
+write_rrs()
+{
+
+ /*
+ * First, do some consistency checks on the RRS segment.
+ */
+ if (rrs_section_type == RRS_NONE) {
+ if (reserved_rrs_relocs > 1)
+ errx(1, "internal error: "
+ "RRS relocs in static program: %d",
+ reserved_rrs_relocs-1);
+ return;
+ }
+
+#ifdef DEBUG
+printf("rrs_relocs: reserved %d claimed %d discarded %d, gotslots %d jmpslots %d\n",
+ reserved_rrs_relocs, claimed_rrs_relocs, discarded_rrs_relocs,
+ number_of_gotslots-1, number_of_jmpslots-1);
+#endif
+
+ /* Final consistency check */
+ if (claimed_rrs_relocs + discarded_rrs_relocs != reserved_rrs_relocs) {
+ errx(1, "internal error: "
+ "reserved relocs(%d) != claimed(%d) + discarded(%d)",
+ reserved_rrs_relocs,
+ claimed_rrs_relocs,
+ discarded_rrs_relocs);
+ }
+
+ /* Write the RRS segments. */
+ write_rrs_text ();
+ write_rrs_data ();
+}
diff --git a/gnu/usr.bin/ld/sparc/md-static-funcs.c b/gnu/usr.bin/ld/sparc/md-static-funcs.c
new file mode 100644
index 0000000..04558ee
--- /dev/null
+++ b/gnu/usr.bin/ld/sparc/md-static-funcs.c
@@ -0,0 +1,37 @@
+
+/*
+ * $FreeBSD$
+ *
+ * Simple SPARC relocations for the benefit of self-relocation of ld.so
+ * avoiding the use of global variables (ie. reloc_bitshift[] et. al.).
+ * Only types supported are RELOC_32 and RELOC_RELATIVE.
+ *
+ * This *must* be a static function, so it is not called through a jmpslot.
+ */
+static void
+md_relocate_simple(r, relocation, addr)
+struct relocation_info *r;
+long relocation;
+char *addr;
+{
+ register unsigned long mask;
+ register unsigned long shift;
+
+ switch (r->r_type) {
+ case RELOC_32:
+ mask = 0xffffffff;
+ shift = 0;
+ break;
+ case RELOC_RELATIVE:
+ mask = 0x003fffff;
+ shift = 10;
+ break;
+ }
+ relocation += (*(long *)addr & mask) << shift;
+ relocation >>= shift;
+ relocation &= mask;
+
+ *(long *) (addr) &= ~mask;
+ *(long *) (addr) |= relocation;
+}
+
diff --git a/gnu/usr.bin/ld/sparc/md.c b/gnu/usr.bin/ld/sparc/md.c
new file mode 100644
index 0000000..20d2410
--- /dev/null
+++ b/gnu/usr.bin/ld/sparc/md.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <a.out.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stab.h>
+#include <string.h>
+
+#include "dynamic.h"
+
+/*
+ * Relocation masks and sizes for the Sparc architecture.
+ *
+ * Note that these are very dependent on the order of the enums in
+ * enum reloc_type (in a.out.h); if they change the following must be
+ * changed.
+ * Also, note that RELOC_RELATIVE is handled as if it were a RELOC_HI22.
+ * This should work provided that relocations values have zeroes in their
+ * least significant 10 bits. As RELOC_RELATIVE is used only to relocate
+ * with load address values - which are page aligned - this condition is
+ * fulfilled as long as the system's page size is > 1024 (and a power of 2).
+ */
+static int reloc_target_rightshift[] = {
+ 0, 0, 0, /* RELOC_8, _16, _32 */
+ 0, 0, 0, 2, 2, /* DISP8, DISP16, DISP32, WDISP30, WDISP22 */
+ 10, 0, /* HI22, _22 */
+ 0, 0, /* RELOC_13, _LO10 */
+ 0, 0, /* _SFA_BASE, _SFA_OFF13 */
+ 0, 0, 10, /* _BASE10, _BASE13, _BASE22 */
+ 0, 10, /* _PC10, _PC22 */
+ 2, 0, /* _JMP_TBL, _SEGOFF16 */
+ 0, 0, 0 /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
+};
+static int reloc_target_size[] = {
+ 0, 1, 2, /* RELOC_8, _16, _32 */
+ 0, 1, 2, 2, 2, /* DISP8, DISP16, DISP32, WDISP30, WDISP22 */
+ 2, 2, /* HI22, _22 */
+ 2, 2, /* RELOC_13, _LO10 */
+ 2, 2, /* _SFA_BASE, _SFA_OFF13 */
+ 2, 2, 2, /* _BASE10, _BASE13, _BASE22 */
+ 2, 2, /* _PC10, _PC22 */
+ 2, 0, /* _JMP_TBL, _SEGOFF16 */
+ 2, 0, 2 /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
+};
+static int reloc_target_bitsize[] = {
+ 8, 16, 32, /* RELOC_8, _16, _32 */
+ 8, 16, 32, 30, 22, /* DISP8, DISP16, DISP32, WDISP30, WDISP22 */
+ 22, 22, /* HI22, _22 */
+ 13, 10, /* RELOC_13, _LO10 */
+ 32, 32, /* _SFA_BASE, _SFA_OFF13 */
+ 10, 13, 22, /* _BASE10, _BASE13, _BASE22 */
+ 10, 22, /* _PC10, _PC22 */
+ 30, 0, /* _JMP_TBL, _SEGOFF16 */
+ 32, 0, 22 /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
+};
+
+
+/*
+ * Get relocation addend corresponding to relocation record RP
+ * ADDR unused by SPARC impl.
+ */
+long
+md_get_addend(r, addr)
+struct relocation_info *r;
+unsigned char *addr;
+{
+ return r->r_addend;
+}
+
+void
+md_relocate(r, relocation, addr, relocatable_output)
+struct relocation_info *r;
+long relocation;
+unsigned char *addr;
+int relocatable_output;
+{
+ register unsigned long mask;
+
+#ifndef RTLD
+ if (relocatable_output) {
+ /*
+ * Non-PC relative relocations which are absolute or
+ * which have become non-external now have fixed
+ * relocations. Set the ADD_EXTRA of this relocation
+ * to be the relocation we have now determined.
+ */
+ if (!RELOC_PCREL_P(r)) {
+ if ((int) r->r_type <= RELOC_32
+ || RELOC_EXTERN_P(r) == 0)
+ RELOC_ADD_EXTRA(r) = relocation;
+ } else if (RELOC_EXTERN_P(r))
+ /*
+ * External PC-relative relocations continue
+ * to move around; update their relocations
+ * by the amount they have moved so far.
+ */
+ RELOC_ADD_EXTRA(r) -= pc_relocation;
+ return;
+ }
+#endif
+
+ relocation >>= RELOC_VALUE_RIGHTSHIFT(r);
+
+ /* Unshifted mask for relocation */
+ mask = 1 << RELOC_TARGET_BITSIZE(r) - 1;
+ mask |= mask - 1;
+ relocation &= mask;
+
+ /* Shift everything up to where it's going to be used */
+ relocation <<= RELOC_TARGET_BITPOS(r);
+ mask <<= RELOC_TARGET_BITPOS(r);
+
+ switch (RELOC_TARGET_SIZE(r)) {
+ case 0:
+ if (RELOC_MEMORY_ADD_P(r))
+ relocation += (mask & *(u_char *) (addr));
+ *(u_char *) (addr) &= ~mask;
+ *(u_char *) (addr) |= relocation;
+ break;
+
+ case 1:
+ if (RELOC_MEMORY_ADD_P(r))
+ relocation += (mask & *(u_short *) (addr));
+ *(u_short *) (addr) &= ~mask;
+ *(u_short *) (addr) |= relocation;
+ break;
+
+ case 2:
+ if (RELOC_MEMORY_ADD_P(r))
+ relocation += (mask & *(u_long *) (addr));
+ *(u_long *) (addr) &= ~mask;
+ *(u_long *) (addr) |= relocation;
+ break;
+ default:
+ errx(1, "Unimplemented relocation field length: %d",
+ RELOC_TARGET_SIZE(r));
+ }
+}
+
+#ifndef RTLD
+/*
+ * Machine dependent part of claim_rrs_reloc().
+ * On the Sparc the relocation offsets are stored in the r_addend member.
+ */
+int
+md_make_reloc(rp, r, type)
+struct relocation_info *rp, *r;
+int type;
+{
+ r->r_type = rp->r_type;
+ r->r_addend = rp->r_addend;
+
+#if 1
+ /*
+ * This wouldn't be strictly necessary - we could record the
+ * relocation value "in situ" in stead of in the r_addend field -
+ * but we are being Sun compatible here. Besides, Sun's ld.so
+ * has a bug that prevents it from handling this alternate method.
+ *
+ * IT WOULD BE REALLY NICE TO HAVE CONSISTENCY THROUGHOUT THE ENTIRE
+ * RELOCATION PROCESS, ie. using `r_addend' for storing all partially
+ * completed relocations, in stead of mixing them in both relocation
+ * records and in the segment data.
+ */
+ if (RELOC_PCREL_P(rp))
+ r->r_addend -= pc_relocation;
+#endif
+
+ return 1;
+}
+#endif
+
+/*
+ * Set up a transfer from jmpslot at OFFSET (relative to the PLT table)
+ * to the binder slot (which is at offset 0 of the PLT).
+ */
+void
+md_make_jmpslot(sp, offset, index)
+jmpslot_t *sp;
+long offset;
+long index;
+{
+ u_long fudge = (u_long) -(sizeof(sp->opcode1) + offset);
+ sp->opcode1 = SAVE;
+ /* The following is a RELOC_WDISP30 relocation */
+ sp->opcode2 = CALL | ((fudge >> 2) & 0x3fffffff);
+ sp->reloc_index = NOP | index;
+}
+
+/*
+ * Set up a "direct" transfer (ie. not through the run-time binder) from
+ * jmpslot at OFFSET to ADDR. Used by `ld' when the SYMBOLIC flag is on,
+ * and by `ld.so' after resolving the symbol.
+ * On the i386, we use the JMP instruction which is PC relative, so no
+ * further RRS relocations will be necessary for such a jmpslot.
+ *
+ * OFFSET unused on Sparc.
+ */
+void
+md_fix_jmpslot(sp, offset, addr)
+jmpslot_t *sp;
+long offset;
+u_long addr;
+{
+ /*
+ * Here comes a RELOC_{LO10,HI22} relocation pair
+ * The resulting code is:
+ * sethi %hi(addr), %g1
+ * jmp %g1+%lo(addr)
+ * nop ! delay slot
+ */
+ sp->opcode1 = SETHI | ((addr >> 10) & 0x003fffff);
+ sp->opcode2 = JMP | (addr & 0x000003ff);
+ sp->reloc_index = NOP;
+}
+
+/*
+ * Update the relocation record for a jmpslot.
+ */
+void
+md_make_jmpreloc(rp, r, type)
+struct relocation_info *rp, *r;
+int type;
+{
+ if (type & RELTYPE_RELATIVE)
+ r->r_type = RELOC_RELATIVE;
+ else
+ r->r_type = RELOC_JMP_SLOT;
+
+ r->r_addend = rp->r_addend;
+}
+
+/*
+ * Set relocation type for a GOT RRS relocation.
+ */
+void
+md_make_gotreloc(rp, r, type)
+struct relocation_info *rp, *r;
+int type;
+{
+ /*
+ * GOT value resolved (symbolic or entry point): R_32
+ * GOT not resolved: GLOB_DAT
+ *
+ * NOTE: I don't think it makes a difference.
+ */
+ if (type & RELTYPE_RELATIVE)
+ r->r_type = RELOC_32;
+ else
+ r->r_type = RELOC_GLOB_DAT;
+
+ r->r_addend = 0;
+}
+
+/*
+ * Set relocation type for a RRS copy operation.
+ */
+void
+md_make_cpyreloc(rp, r)
+struct relocation_info *rp, *r;
+{
+ r->r_type = RELOC_COPY_DAT;
+ r->r_addend = 0;
+}
+
+void
+md_set_breakpoint(where, savep)
+long where;
+long *savep;
+{
+ *savep = *(long *)where;
+ *(long *)where = TRAP;
+}
+
+#ifndef RTLD
+/*
+ * Initialize (output) exec header such that useful values are
+ * obtained from subsequent N_*() macro evaluations.
+ */
+void
+md_init_header(hp, magic, flags)
+struct exec *hp;
+int magic, flags;
+{
+#ifdef NetBSD
+ N_SETMAGIC((*hp), magic, MID_MACHINE, flags);
+
+ /* TEXT_START depends on the value of outheader.a_entry. */
+ if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */
+ hp->a_entry = PAGSIZ;
+#else
+ hp->a_magic = magic;
+ hp->a_machtype = M_SPARC;
+ hp->a_toolversion = 1;
+ hp->a_dynamic = ((flags) & EX_DYNAMIC);
+
+ /* SunOS 4.1 N_TXTADDR depends on the value of outheader.a_entry. */
+ if (!(link_mode & SHAREABLE)) /*WAS: if (entry_symbol) */
+ hp->a_entry = N_PAGSIZ(*hp);
+#endif
+}
+
+/*
+ * Check for acceptable foreign machine Ids
+ */
+int
+md_midcompat(hp)
+struct exec *hp;
+{
+#ifdef NetBSD
+#define SUN_M_SPARC 3
+ return (((md_swap_long(hp->a_midmag)&0x00ff0000) >> 16) == SUN_M_SPARC);
+#else
+ return hp->a_machtype == M_SPARC;
+#endif
+}
+#endif /* RTLD */
diff --git a/gnu/usr.bin/ld/sparc/md.h b/gnu/usr.bin/ld/sparc/md.h
new file mode 100644
index 0000000..7c8a568
--- /dev/null
+++ b/gnu/usr.bin/ld/sparc/md.h
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * SPARC machine dependent definitions
+ */
+
+
+#define MAX_ALIGNMENT (sizeof (double))
+
+#ifdef NetBSD
+#define PAGSIZ __LDPGSZ
+
+#define N_SET_FLAG(ex,f) N_SETMAGIC(ex,N_GETMAGIC(ex), \
+ MID_MACHINE, N_GETFLAG(ex)|(f))
+#define N_IS_DYNAMIC(ex) ((N_GETFLAG(ex) & EX_DYNAMIC))
+
+/*
+ * Should be handled by a.out.h ?
+ */
+#define N_ADJUST(ex) (((ex).a_entry < PAGSIZ) ? -PAGSIZ : 0)
+#define TEXT_START(ex) (N_TXTADDR(ex) + N_ADJUST(ex))
+#define DATA_START(ex) (N_DATADDR(ex) + N_ADJUST(ex))
+
+#else
+
+/* Get the SunOS a.out and relocation nomenclature */
+#define EX_DYNAMIC 1
+
+#define N_IS_DYNAMIC(ex) ((ex).a_dynamic)
+
+#define N_SET_FLAG(ex, f) { \
+ (ex).a_dynamic = ((f) & EX_DYNAMIC); \
+}
+
+#undef relocation_info
+#define relocation_info reloc_info_sparc
+#define r_symbolnum r_index
+#endif /* NetBSD */
+
+#define N_BADMID(ex) \
+ (N_GETMID(ex) != 0 && N_GETMID(ex) != MID_MACHINE && \
+ !md_midcompat(&(ex)))
+
+/* Sparc (Sun 4) macros */
+#define RELOC_ADDRESS(r) ((r)->r_address)
+#define RELOC_EXTERN_P(r) ((r)->r_extern)
+#define RELOC_TYPE(r) ((r)->r_symbolnum)
+#define RELOC_SYMBOL(r) ((r)->r_symbolnum)
+#define RELOC_MEMORY_SUB_P(r) 0
+#ifdef RTLD
+/* XXX - consider this making SUN_COMPAT --> repercussions on rrs.c */
+#define RELOC_MEMORY_ADD_P(r) 1
+#else
+#define RELOC_MEMORY_ADD_P(r) 0
+#endif
+#define RELOC_ADD_EXTRA(r) ((r)->r_addend)
+#define RELOC_PCREL_P(r) \
+ (((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22) \
+ || ((r)->r_type == RELOC_PC10 || (r)->r_type == RELOC_PC22) \
+ || (r)->r_type == RELOC_JMP_TBL)
+#define RELOC_VALUE_RIGHTSHIFT(r) (reloc_target_rightshift[(r)->r_type])
+#define RELOC_TARGET_SIZE(r) (reloc_target_size[(r)->r_type])
+#define RELOC_TARGET_BITPOS(r) 0
+#define RELOC_TARGET_BITSIZE(r) (reloc_target_bitsize[(r)->r_type])
+
+#define RELOC_JMPTAB_P(r) ((r)->r_type == RELOC_JMP_TBL)
+
+#define RELOC_BASEREL_P(r) \
+ ((r)->r_type >= RELOC_BASE10 && (r)->r_type <= RELOC_BASE22)
+
+#define RELOC_RELATIVE_P(r) ((r)->r_type == RELOC_RELATIVE)
+#define RELOC_COPY_DAT (RELOC_RELATIVE+1) /*XXX*/
+#define RELOC_COPY_P(r) ((r)->r_type == RELOC_COPY_DAT)
+#define RELOC_LAZY_P(r) ((r)->r_type == RELOC_JMP_SLOT)
+
+#define RELOC_STATICS_THROUGH_GOT_P(r) (1)
+#define JMPSLOT_NEEDS_RELOC (1)
+
+/*
+ * Define the range of usable Global Offset Table offsets
+ * when using sparc 13 bit relocation types (-4096 - 4092).
+ */
+#define MAX_GOTSIZE (8192)
+#define MAX_GOTOFF (4092)
+#define MIN_GOTOFF (-4096)
+
+#define CHECK_GOT_RELOC(r) \
+ ((r)->r_type == RELOC_PC10 || (r)->r_type == RELOC_PC22)
+
+#define md_got_reloc(r) (-(r)->r_address)
+
+#define RELOC_INIT_SEGMENT_RELOC(r) ((r)->r_type = RELOC_32)
+
+#ifdef SUN_COMPAT
+/*
+ * Sun plays games with `r_addend'
+ */
+#define md_get_rt_segment_addend(r,a) (0)
+#endif
+
+/* Width of a Global Offset Table entry */
+typedef long got_t;
+
+typedef struct jmpslot {
+ u_long opcode1;
+ u_long opcode2;
+ u_long reloc_index;
+#define JMPSLOT_RELOC_MASK (0x003fffff) /* 22 bits */
+} jmpslot_t;
+
+#define SAVE 0x9de3bfa0 /* Build stack frame (opcode1) */
+#define SETHI 0x03000000 /* %hi(addr) -> %g1 (opcode1) */
+#define CALL 0x40000000 /* Call instruction (opcode2) */
+#define JMP 0x81c06000 /* Jump %g1 instruction (opcode2) */
+#define NOP 0x01000000 /* Delay slot NOP for (reloc_index) */
+#define TRAP 0x91d02001 /* ta 0x1 */
+
+
+/*
+ * Byte swap defs for cross linking
+ */
+
+#if !defined(NEED_SWAP)
+
+#define md_swapin_exec_hdr(h)
+#define md_swapout_exec_hdr(h)
+#define md_swapin_symbols(s,n)
+#define md_swapout_symbols(s,n)
+#define md_swapin_zsymbols(s,n)
+#define md_swapout_zsymbols(s,n)
+#define md_swapin_reloc(r,n)
+#define md_swapout_reloc(r,n)
+#define md_swapin__dynamic(l)
+#define md_swapout__dynamic(l)
+#define md_swapin_section_dispatch_table(l)
+#define md_swapout_section_dispatch_table(l)
+#define md_swapin_so_debug(d)
+#define md_swapout_so_debug(d)
+#define md_swapin_rrs_hash(f,n)
+#define md_swapout_rrs_hash(f,n)
+#define md_swapin_sod(l,n)
+#define md_swapout_sod(l,n)
+#define md_swapout_jmpslot(j,n)
+#define md_swapout_got(g,n)
+#define md_swapin_ranlib_hdr(h,n)
+#define md_swapout_ranlib_hdr(h,n)
+
+#endif /* NEED_SWAP */
+
+#ifdef CROSS_LINKER
+
+#ifdef NEED_SWAP
+
+/* Define IO byte swapping routines */
+
+void md_swapin_exec_hdr __P((struct exec *));
+void md_swapout_exec_hdr __P((struct exec *));
+void md_swapin_reloc __P((struct relocation_info *, int));
+void md_swapout_reloc __P((struct relocation_info *, int));
+void md_swapout_jmpslot __P((jmpslot_t *, int));
+
+#define md_swapin_symbols(s,n) swap_symbols(s,n)
+#define md_swapout_symbols(s,n) swap_symbols(s,n)
+#define md_swapin_zsymbols(s,n) swap_zsymbols(s,n)
+#define md_swapout_zsymbols(s,n) swap_zsymbols(s,n)
+#define md_swapin__dynamic(l) swap__dynamic(l)
+#define md_swapout__dynamic(l) swap__dynamic(l)
+#define md_swapin_section_dispatch_table(l) swap_section_dispatch_table(l)
+#define md_swapout_section_dispatch_table(l) swap_section_dispatch_table(l)
+#define md_swapin_so_debug(d) swap_so_debug(d)
+#define md_swapout_so_debug(d) swap_so_debug(d)
+#define md_swapin_rrs_hash(f,n) swap_rrs_hash(f,n)
+#define md_swapout_rrs_hash(f,n) swap_rrs_hash(f,n)
+#define md_swapin_sod(l,n) swapin_sod(l,n)
+#define md_swapout_sod(l,n) swapout_sod(l,n)
+#define md_swapout_got(g,n) swap_longs((long*)(g),n)
+#define md_swapin_ranlib_hdr(h,n) swap_ranlib_hdr(h,n)
+#define md_swapout_ranlib_hdr(h,n) swap_ranlib_hdr(h,n)
+
+#define md_swap_short(x) ( (((x) >> 8) & 0xff) | (((x) & 0xff) << 8) )
+
+#define md_swap_long(x) ( (((x) >> 24) & 0xff ) | (((x) >> 8 ) & 0xff00 ) | \
+ (((x) << 8 ) & 0xff0000) | (((x) << 24) & 0xff000000))
+
+#define get_byte(p) ( ((unsigned char *)(p))[0] )
+
+#define get_short(p) ( ( ((unsigned char *)(p))[1] << 8) | \
+ ( ((unsigned char *)(p))[0] ) \
+ )
+#define get_long(p) ( ( ((unsigned char *)(p))[3] << 24) | \
+ ( ((unsigned char *)(p))[2] << 16) | \
+ ( ((unsigned char *)(p))[1] << 8 ) | \
+ ( ((unsigned char *)(p))[0] ) \
+ )
+
+#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); }
+
+#define put_short(p, v) { ((unsigned char *)(p))[1] = \
+ ((((unsigned long)(v)) >> 8) & 0xff); \
+ ((unsigned char *)(p))[0] = \
+ ((((unsigned long)(v)) ) & 0xff); }
+
+#define put_long(p, v) { ((unsigned char *)(p))[3] = \
+ ((((unsigned long)(v)) >> 24) & 0xff); \
+ ((unsigned char *)(p))[2] = \
+ ((((unsigned long)(v)) >> 16) & 0xff); \
+ ((unsigned char *)(p))[1] = \
+ ((((unsigned long)(v)) >> 8) & 0xff); \
+ ((unsigned char *)(p))[0] = \
+ ((((unsigned long)(v)) ) & 0xff); }
+
+#else /* We need not swap, but must pay attention to alignment: */
+
+#define md_swap_short(x) (x)
+#define md_swap_long(x) (x)
+
+#define get_byte(p) ( ((unsigned char *)(p))[0] )
+
+#define get_short(p) ( ( ((unsigned char *)(p))[0] << 8) | \
+ ( ((unsigned char *)(p))[1] ) \
+ )
+
+#define get_long(p) ( ( ((unsigned char *)(p))[0] << 24) | \
+ ( ((unsigned char *)(p))[1] << 16) | \
+ ( ((unsigned char *)(p))[2] << 8 ) | \
+ ( ((unsigned char *)(p))[3] ) \
+ )
+
+
+#define put_byte(p, v) { ((unsigned char *)(p))[0] = ((unsigned long)(v)); }
+
+#define put_short(p, v) { ((unsigned char *)(p))[0] = \
+ ((((unsigned long)(v)) >> 8) & 0xff); \
+ ((unsigned char *)(p))[1] = \
+ ((((unsigned long)(v)) ) & 0xff); }
+
+#define put_long(p, v) { ((unsigned char *)(p))[0] = \
+ ((((unsigned long)(v)) >> 24) & 0xff); \
+ ((unsigned char *)(p))[1] = \
+ ((((unsigned long)(v)) >> 16) & 0xff); \
+ ((unsigned char *)(p))[2] = \
+ ((((unsigned long)(v)) >> 8) & 0xff); \
+ ((unsigned char *)(p))[3] = \
+ ((((unsigned long)(v)) ) & 0xff); }
+
+#endif /* NEED_SWAP */
+
+#else /* Not a cross linker: use native */
+
+#define md_swap_short(x) (x)
+#define md_swap_long(x) (x)
+
+#define get_byte(where) (*(char *)(where))
+#define get_short(where) (*(short *)(where))
+#define get_long(where) (*(long *)(where))
+
+#define put_byte(where,what) (*(char *)(where) = (what))
+#define put_short(where,what) (*(short *)(where) = (what))
+#define put_long(where,what) (*(long *)(where) = (what))
+
+#endif /* CROSS_LINKER */
+
+void md_init_header __P((struct exec *, int, int));
+long md_get_addend __P((struct relocation_info *, unsigned char *));
+void md_relocate __P((struct relocation_info *, long, unsigned char *, int));
+void md_make_jmpslot __P((jmpslot_t *, long, long));
+void md_fix_jmpslot __P((jmpslot_t *, long, u_long));
+int md_make_reloc __P((struct relocation_info *, struct relocation_info *, int));
+void md_make_jmpreloc __P((struct relocation_info *, struct relocation_info *, int));
+void md_make_gotreloc __P((struct relocation_info *, struct relocation_info *, int));
+void md_make_copyreloc __P((struct relocation_info *, struct relocation_info *));
+void md_set_breakpoint __P((long, long *));
diff --git a/gnu/usr.bin/ld/sparc/mdprologue.S b/gnu/usr.bin/ld/sparc/mdprologue.S
new file mode 100644
index 0000000..68140ae
--- /dev/null
+++ b/gnu/usr.bin/ld/sparc/mdprologue.S
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * SPARC run-time link editor entry points.
+ */
+
+#define CRT_VERSION_SUN 1
+
+ .seg "text" ! [internal]
+ .proc 16
+ .global _rtld_entry
+_rtld_entry:
+!#PROLOGUE# 0
+ save %sp,-96,%sp
+L.1B:
+ call L.2B
+ sethi %hi((__GLOBAL_OFFSET_TABLE_-(L.1B-.))),%l7
+L.2B:
+!#PROLOGUE# 1
+ or %l7,%lo((__GLOBAL_OFFSET_TABLE_-(L.1B-.))),%l7
+ add %l7,%o7,%l7
+
+ cmp %i0, CRT_VERSION_SUN ! is crtp passed in Sun style,
+ bne 1f ! ie. relative to stack frame ?
+ nop
+ add %i1, %fp, %i1 ! if so, adjust to absolute address
+1:
+ ld [%i1], %o3 ! load base address (crtp->crt_ba)
+ ld [%l7], %o2 ! get __DYNAMIC address
+ ! from 1st GOT entry
+ add %o2, %o3, %o2 ! relocate and make it 3rd arg.
+
+ ld [%l7 + _rtld], %g1 ! get address of rtld()
+ add %g1, %o3, %g1 ! relocate
+
+ mov %i1, %o1 ! set up args, #2: crtp
+ call %g1 ! rtld(version, crtp, dp)
+ mov %i0, %o0 ! arg #1: version
+
+ ret
+ restore
+ .seg "data" ! [internal]
+
+ .seg "text"
+ .global _binder_entry
+_binder_entry:
+!#PROLOGUE# 0
+ save %sp,-96,%sp
+!L.1C:
+! call L.2C
+! sethi %hi((__GLOBAL_OFFSET_TABLE_-(L.1C-.))),%l7
+!L.2C:
+! or %l7,%lo((__GLOBAL_OFFSET_TABLE_-(L.1C-.))),%l7
+!#PROLOGUE# 1
+
+ sub %i7, 4, %o0 ! get to jmpslot through pc
+ ld [%i7+4], %o1 ! get relocation index
+ sethi %hi(0x3fffff), %o2 ! -> reloc_index & 0x003fffff
+ or %o2, %lo(0x3fffff), %o2 ! [internal]
+ call _binder ! and call binder(jsp, reloc_index)
+ and %o1, %o2, %o1
+
+ mov %o0, %g1 ! return value == function address
+
+ restore ! get rid of our context
+ jmp %g1 ! and go.
+ restore ! and the jmpslot context
+ nop
+
+ .seg "data" ! [internal]
+
diff --git a/gnu/usr.bin/ld/symbol.c b/gnu/usr.bin/ld/symbol.c
new file mode 100644
index 0000000..350b23b
--- /dev/null
+++ b/gnu/usr.bin/ld/symbol.c
@@ -0,0 +1,194 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Modified 1993 by Paul Kranenburg, Erasmus University
+ */
+
+/* Derived from ld.c: "@(#)ld.c 6.10 (Berkeley) 5/22/91"; */
+
+/* Linker `ld' for GNU
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Richard Stallman with some help from Eric Albert.
+ Set, indirect, and warning symbol features added by Randy Smith. */
+
+/*
+ * symbol table routines
+ * $FreeBSD$
+ */
+
+/* Create the symbol table entries for `etext', `edata' and `end'. */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <a.out.h>
+#include <stab.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ld.h"
+#include "dynamic.h"
+
+symbol *symtab[SYMTABSIZE]; /* The symbol table. */
+int num_hash_tab_syms; /* Number of symbols in symbol hash table. */
+
+symbol *edata_symbol; /* the symbol _edata */
+symbol *etext_symbol; /* the symbol _etext */
+symbol *end_symbol; /* the symbol _end */
+symbol *got_symbol; /* the symbol __GLOBAL_OFFSET_TABLE_ */
+symbol *dynamic_symbol; /* the symbol __DYNAMIC */
+
+void
+symtab_init(relocatable_output)
+ int relocatable_output;
+{
+ /*
+ * Put linker reserved symbols into symbol table.
+ */
+#ifndef nounderscore
+#define ETEXT_SYM "_etext"
+#define EDATA_SYM "_edata"
+#define END_SYM "_end"
+#define DYN_SYM "__DYNAMIC"
+#define GOT_SYM "__GLOBAL_OFFSET_TABLE_"
+#else
+#define ETEXT_SYM "etext"
+#define EDATA_SYM "edata"
+#define END_SYM "end"
+#define DYN_SYM "_DYNAMIC"
+#define GOT_SYM "_GLOBAL_OFFSET_TABLE_"
+#endif
+
+ dynamic_symbol = getsym(DYN_SYM);
+ dynamic_symbol->defined = relocatable_output?N_UNDF:(N_DATA | N_EXT);
+
+ got_symbol = getsym(GOT_SYM);
+ got_symbol->defined = N_DATA | N_EXT;
+
+ if (relocatable_output)
+ return;
+
+ etext_symbol = getsym(ETEXT_SYM);
+ edata_symbol = getsym(EDATA_SYM);
+ end_symbol = getsym(END_SYM);
+
+ etext_symbol->defined = N_TEXT | N_EXT;
+ edata_symbol->defined = N_DATA | N_EXT;
+ end_symbol->defined = N_BSS | N_EXT;
+
+ etext_symbol->flags |= GS_REFERENCED;
+ edata_symbol->flags |= GS_REFERENCED;
+ end_symbol->flags |= GS_REFERENCED;
+}
+
+/*
+ * Compute the hash code for symbol name KEY.
+ */
+
+int
+hash_string (key)
+ char *key;
+{
+ register char *cp;
+ register int k;
+
+ cp = key;
+ k = 0;
+ while (*cp)
+ k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
+
+ return k;
+}
+
+/*
+ * Get the symbol table entry for the global symbol named KEY.
+ * Create one if there is none.
+ */
+
+symbol *
+getsym(key)
+ char *key;
+{
+ register int hashval;
+ register symbol *bp;
+
+ /* Determine the proper bucket. */
+ hashval = hash_string(key) % SYMTABSIZE;
+
+ /* Search the bucket. */
+ for (bp = symtab[hashval]; bp; bp = bp->link)
+ if (strcmp(key, bp->name) == 0)
+ return bp;
+
+ /* Nothing was found; create a new symbol table entry. */
+ bp = (symbol *)xmalloc(sizeof(symbol));
+ bp->name = (char *)xmalloc(strlen(key) + 1);
+ strcpy (bp->name, key);
+ bp->refs = 0;
+ bp->defined = 0;
+ bp->value = 0;
+ bp->common_size = 0;
+ bp->warning = 0;
+ bp->undef_refs = 0;
+ bp->mult_defs = 0;
+ bp->alias = 0;
+ bp->setv_count = 0;
+ bp->symbolnum = 0;
+ bp->rrs_symbolnum = 0;
+
+ bp->size = 0;
+ bp->aux = 0;
+ bp->sorefs = 0;
+ bp->so_defined = 0;
+ bp->def_lsp = 0;
+ bp->jmpslot_offset = -1;
+ bp->gotslot_offset = -1;
+ bp->flags = 0;
+
+ /* Add the entry to the bucket. */
+ bp->link = symtab[hashval];
+ symtab[hashval] = bp;
+
+ ++num_hash_tab_syms;
+
+ return bp;
+}
+
+/* Like `getsym' but return 0 if the symbol is not already known. */
+
+symbol *
+getsym_soft (key)
+ char *key;
+{
+ register int hashval;
+ register symbol *bp;
+
+ /* Determine which bucket. */
+ hashval = hash_string(key) % SYMTABSIZE;
+
+ /* Search the bucket. */
+ for (bp = symtab[hashval]; bp; bp = bp->link)
+ if (strcmp(key, bp->name) == 0)
+ return bp;
+
+ return 0;
+}
diff --git a/gnu/usr.bin/ld/symseg.h b/gnu/usr.bin/ld/symseg.h
new file mode 100644
index 0000000..fbe530f
--- /dev/null
+++ b/gnu/usr.bin/ld/symseg.h
@@ -0,0 +1,359 @@
+/*-
+ *
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * from: @(#)symseg.h 5.4 (Berkeley) 4/30/91
+ * $FreeBSD$
+ */
+
+/* GDB symbol table format definitions.
+ Copyright (C) 1987, 1988 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Format of GDB symbol table data.
+ There is one symbol segment for each source file or
+ independant compilation. These segments are simply concatenated
+ to form the GDB symbol table. A zero word where the beginning
+ of a segment is expected indicates there are no more segments.
+
+Format of a symbol segment:
+
+ The symbol segment begins with a word containing 1
+ if it is in the format described here. Other formats may
+ be designed, with other code numbers.
+
+ The segment contains many objects which point at each other.
+ The pointers are offsets in bytes from the beginning of the segment.
+ Thus, each segment can be loaded into core and its pointers relocated
+ to make valid in-core pointers.
+
+ All the data objects in the segment can be found indirectly from
+ one of them, the root object, of type `struct symbol_root'.
+ It appears at the beginning of the segment.
+
+ The total size of the segment, in bytes, appears as the `length'
+ field of this object. This size includes the size of the
+ root object.
+
+ All the object data types are defined here to contain pointer types
+ appropriate for in-core use on a relocated symbol segment.
+ Casts to and from type int are required for working with
+ unrelocated symbol segments such as are found in the file.
+
+ The ldsymaddr word is filled in by the loader to contain
+ the offset (in bytes) within the ld symbol table
+ of the first nonglobal symbol from this compilation.
+ This makes it possible to match those symbols
+ (which contain line number information) reliably with
+ the segment they go with.
+
+ Core addresses within the program that appear in the symbol segment
+ are not relocated by the loader. They are inserted by the assembler
+ and apply to addresses as output by the assembler, so GDB must
+ relocate them when it loads the symbol segment. It gets the information
+ on how to relocate from the textrel, datarel, bssrel, databeg and bssbeg
+ words of the root object.
+
+ The words textrel, datarel and bssrel
+ are filled in by ld with the amounts to relocate within-the-file
+ text, data and bss addresses by; databeg and bssbeg can be
+ used to tell which kind of relocation an address needs. */
+
+enum language {language_c};
+
+struct symbol_root
+{
+ int format; /* Data format version */
+ int length; /* # bytes in this symbol segment */
+ int ldsymoff; /* Offset in ld symtab of this file's syms */
+ int textrel; /* Relocation for text addresses */
+ int datarel; /* Relocation for data addresses */
+ int bssrel; /* Relocation for bss addresses */
+ char *filename; /* Name of main source file compiled */
+ char *filedir; /* Name of directory it was reached from */
+ struct blockvector *blockvector; /* Vector of all symbol-naming blocks */
+ struct typevector *typevector; /* Vector of all data types */
+ enum language language; /* Code identifying the language used */
+ char *version; /* Version info. Not fully specified */
+ char *compilation; /* Compilation info. Not fully specified */
+ int databeg; /* Address within the file of data start */
+ int bssbeg; /* Address within the file of bss start */
+ struct sourcevector *sourcevector; /* Vector of line-number info */
+};
+
+/* All data types of symbols in the compiled program
+ are represented by `struct type' objects.
+ All of these objects are pointed to by the typevector.
+ The type vector may have empty slots that contain zero. */
+
+struct typevector
+{
+ int length; /* Number of types described */
+ struct type *type[1];
+};
+
+/* Different kinds of data types are distinguished by the `code' field. */
+
+enum type_code
+{
+ TYPE_CODE_UNDEF, /* Not used; catches errors */
+ TYPE_CODE_PTR, /* Pointer type */
+ TYPE_CODE_ARRAY, /* Array type, lower bound zero */
+ TYPE_CODE_STRUCT, /* C struct or Pascal record */
+ TYPE_CODE_UNION, /* C union or Pascal variant part */
+ TYPE_CODE_ENUM, /* Enumeration type */
+ TYPE_CODE_FUNC, /* Function type */
+ TYPE_CODE_INT, /* Integer type */
+ TYPE_CODE_FLT, /* Floating type */
+ TYPE_CODE_VOID, /* Void type (values zero length) */
+ TYPE_CODE_SET, /* Pascal sets */
+ TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
+ TYPE_CODE_PASCAL_ARRAY, /* Array with explicit type of index */
+};
+
+/* This appears in a type's flags word for an unsigned integer type. */
+#define TYPE_FLAG_UNSIGNED 1
+
+/* Other flag bits are used with GDB. */
+
+struct type
+{
+ /* Code for kind of type */
+ enum type_code code;
+ /* Name of this type, or zero if none.
+ This is used for printing only.
+ Type names specified as input are defined by symbols. */
+ char *name;
+ /* Length in bytes of storage for a value of this type */
+ int length;
+ /* For a pointer type, describes the type of object pointed to.
+ For an array type, describes the type of the elements.
+ For a function type, describes the type of the value.
+ Unused otherwise. */
+ struct type *target_type;
+ /* Type that is a pointer to this type.
+ Zero if no such pointer-to type is known yet.
+ The debugger may add the address of such a type
+ if it has to construct one later. */
+ struct type *pointer_type;
+ /* Type that is a function returning this type.
+ Zero if no such function type is known here.
+ The debugger may add the address of such a type
+ if it has to construct one later. */
+ struct type *function_type;
+ /* Flags about this type. */
+ short flags;
+ /* Number of fields described for this type */
+ short nfields;
+ /* For structure and union types, a description of each field.
+ For set and pascal array types, there is one "field",
+ whose type is the domain type of the set or array.
+ For range types, there are two "fields",
+ the minimum and maximum values (both inclusive).
+ For enum types, each possible value is described by one "field".
+ For range types, there are two "fields", that record constant values
+ (inclusive) for the minimum and maximum.
+
+ Using a pointer to a separate array of fields
+ allows all types to have the same size, which is useful
+ because we can allocate the space for a type before
+ we know what to put in it. */
+ struct field
+ {
+ /* Position of this field, counting in bits from start of
+ containing structure. For a function type, this is the
+ position in the argument list of this argument.
+ For a range bound or enum value, this is the value itself. */
+ int bitpos;
+ /* Size of this field, in bits, or zero if not packed.
+ For an unpacked field, the field's type's length
+ says how many bytes the field occupies. */
+ int bitsize;
+ /* In a struct or enum type, type of this field.
+ In a function type, type of this argument.
+ In an array type, the domain-type of the array. */
+ struct type *type;
+ /* Name of field, value or argument.
+ Zero for range bounds and array domains. */
+ char *name;
+ } *fields;
+};
+
+/* All of the name-scope contours of the program
+ are represented by `struct block' objects.
+ All of these objects are pointed to by the blockvector.
+
+ Each block represents one name scope.
+ Each lexical context has its own block.
+
+ The first two blocks in the blockvector are special.
+ The first one contains all the symbols defined in this compilation
+ whose scope is the entire program linked together.
+ The second one contains all the symbols whose scope is the
+ entire compilation excluding other separate compilations.
+ In C, these correspond to global symbols and static symbols.
+
+ Each block records a range of core addresses for the code that
+ is in the scope of the block. The first two special blocks
+ give, for the range of code, the entire range of code produced
+ by the compilation that the symbol segment belongs to.
+
+ The blocks appear in the blockvector
+ in order of increasing starting-address,
+ and, within that, in order of decreasing ending-address.
+
+ This implies that within the body of one function
+ the blocks appear in the order of a depth-first tree walk. */
+
+struct blockvector
+{
+ /* Number of blocks in the list. */
+ int nblocks;
+ /* The blocks themselves. */
+ struct block *block[1];
+};
+
+struct block
+{
+ /* Addresses in the executable code that are in this block.
+ Note: in an unrelocated symbol segment in a file,
+ these are always zero. They can be filled in from the
+ N_LBRAC and N_RBRAC symbols in the loader symbol table. */
+ int startaddr, endaddr;
+ /* The symbol that names this block,
+ if the block is the body of a function;
+ otherwise, zero.
+ Note: In an unrelocated symbol segment in an object file,
+ this field may be zero even when the block has a name.
+ That is because the block is output before the name
+ (since the name resides in a higher block).
+ Since the symbol does point to the block (as its value),
+ it is possible to find the block and set its name properly. */
+ struct symbol *function;
+ /* The `struct block' for the containing block, or 0 if none. */
+ /* Note that in an unrelocated symbol segment in an object file
+ this pointer may be zero when the correct value should be
+ the second special block (for symbols whose scope is one compilation).
+ This is because the compiler ouptuts the special blocks at the
+ very end, after the other blocks. */
+ struct block *superblock;
+ /* Number of local symbols. */
+ int nsyms;
+ /* The symbols. */
+ struct symbol *sym[1];
+};
+
+/* Represent one symbol name; a variable, constant, function or typedef. */
+
+/* Different name spaces for symbols. Looking up a symbol specifies
+ a namespace and ignores symbol definitions in other name spaces.
+
+ VAR_NAMESPACE is the usual namespace.
+ In C, this contains variables, function names, typedef names
+ and enum type values.
+
+ STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
+ Thus, if `struct foo' is used in a C program,
+ it produces a symbol named `foo' in the STRUCT_NAMESPACE.
+
+ LABEL_NAMESPACE may be used for names of labels (for gotos);
+ currently it is not used and labels are not recorded at all. */
+
+/* For a non-global symbol allocated statically,
+ the correct core address cannot be determined by the compiler.
+ The compiler puts an index number into the symbol's value field.
+ This index number can be matched with the "desc" field of
+ an entry in the loader symbol table. */
+
+enum namespace
+{
+ UNDEF_NAMESPACE, VAR_NAMESPACE, STRUCT_NAMESPACE, LABEL_NAMESPACE,
+};
+
+/* An address-class says where to find the value of the symbol in core. */
+
+enum address_class
+{
+ LOC_UNDEF, /* Not used; catches errors */
+ LOC_CONST, /* Value is constant int */
+ LOC_STATIC, /* Value is at fixed address */
+ LOC_REGISTER, /* Value is in register */
+ LOC_ARG, /* Value is at spec'd position in arglist */
+ LOC_LOCAL, /* Value is at spec'd pos in stack frame */
+ LOC_TYPEDEF, /* Value not used; definition in SYMBOL_TYPE
+ Symbols in the namespace STRUCT_NAMESPACE
+ all have this class. */
+ LOC_LABEL, /* Value is address in the code */
+ LOC_BLOCK, /* Value is address of a `struct block'.
+ Function names have this class. */
+ LOC_EXTERNAL, /* Value is at address not in this compilation.
+ This is used for .comm symbols
+ and for extern symbols within functions.
+ Inside GDB, this is changed to LOC_STATIC once the
+ real address is obtained from a loader symbol. */
+ LOC_CONST_BYTES /* Value is a constant byte-sequence. */
+};
+
+struct symbol
+{
+ /* Symbol name */
+ char *name;
+ /* Name space code. */
+ enum namespace namespace;
+ /* Address class */
+ enum address_class class;
+ /* Data type of value */
+ struct type *type;
+ /* constant value, or address if static, or register number,
+ or offset in arguments, or offset in stack frame. */
+ union
+ {
+ long value;
+ struct block *block; /* for LOC_BLOCK */
+ char *bytes; /* for LOC_CONST_BYTES */
+ }
+ value;
+};
+
+/* Source-file information.
+ This describes the relation between source files and line numbers
+ and addresses in the program text. */
+
+struct sourcevector
+{
+ int length; /* Number of source files described */
+ struct source *source[1]; /* Descriptions of the files */
+};
+
+/* Line number and address of one line. */
+
+struct line
+{
+ int linenum;
+ int address;
+};
+
+/* All the information on one source file. */
+
+struct source
+{
+ char *name; /* Name of file */
+ int nlines; /* Number of lines that follow */
+ struct line lines[1]; /* Information on each line */
+};
diff --git a/gnu/usr.bin/ld/warnings.c b/gnu/usr.bin/ld/warnings.c
new file mode 100644
index 0000000..2c988d5
--- /dev/null
+++ b/gnu/usr.bin/ld/warnings.c
@@ -0,0 +1,810 @@
+/*-
+ * This code is derived from software copyrighted by the Free Software
+ * Foundation.
+ *
+ * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Modified 1993 by Paul Kranenburg, Erasmus University
+ */
+
+/* Derived from ld.c: "@(#)ld.c 6.10 (Berkeley) 5/22/91"; */
+
+/* Linker `ld' for GNU
+ Copyright (C) 1988 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Richard Stallman with some help from Eric Albert.
+ Set, indirect, and warning symbol features added by Randy Smith. */
+
+/*
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <ar.h>
+#include <ranlib.h>
+#include <a.out.h>
+#include <stab.h>
+#include <string.h>
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "ld.h"
+#include "dynamic.h"
+
+static int reported_undefineds;
+
+#ifdef DEMANGLE_CPLUSPLUS
+#include "demangle.h"
+
+char *demangle(name)
+ char *name;
+{
+ static char* saved_result = NULL;
+
+ if (saved_result)
+ free (saved_result);
+
+ saved_result = cplus_demangle (name[0] == '_' ? name + 1 : name, DMGL_PARAMS | DMGL_ANSI);
+
+ if (saved_result)
+ return saved_result;
+ else
+ return name;
+}
+#endif
+
+/*
+ * Print the filename of ENTRY on OUTFILE (a stdio stream),
+ * and then a newline.
+ */
+
+void
+prline_file_name (entry, outfile)
+ struct file_entry *entry;
+ FILE *outfile;
+{
+ print_file_name (entry, outfile);
+ fprintf (outfile, "\n");
+}
+
+/*
+ * Print the filename of ENTRY on OUTFILE (a stdio stream).
+ */
+
+void
+print_file_name (entry, outfile)
+ struct file_entry *entry;
+ FILE *outfile;
+{
+ if (entry == NULL) {
+ fprintf (outfile, "NULL");
+ }
+
+ if (entry->superfile) {
+ print_file_name (entry->superfile, outfile);
+ fprintf (outfile, "(%s)", entry->filename);
+ } else
+ fprintf (outfile, "%s", entry->filename);
+}
+
+/*
+ * Return the filename of entry as a string (malloc'd for the purpose)
+ */
+
+char *
+get_file_name (entry)
+ struct file_entry *entry;
+{
+ char *result, *supfile;
+
+ if (entry == NULL) {
+ return (char *)strdup("NULL");
+ }
+
+ if (entry->superfile) {
+ supfile = get_file_name(entry->superfile);
+ result = (char *)
+ xmalloc(strlen(supfile) + strlen(entry->filename) + 3);
+ (void)sprintf(result, "%s(%s)", supfile, entry->filename);
+ free(supfile);
+
+ } else {
+ result = (char *)xmalloc(strlen(entry->filename) + 1);
+ strcpy(result, entry->filename);
+ }
+ return result;
+}
+
+/* Print a complete or partial map of the output file. */
+
+static void describe_file_sections __P((struct file_entry *, FILE *));
+static void list_file_locals __P((struct file_entry *, FILE *));
+
+void
+print_symbols(outfile)
+ FILE *outfile;
+{
+ fprintf(outfile, "\nFiles:\n\n");
+ each_file(describe_file_sections, (void *)outfile);
+
+ fprintf(outfile, "\nGlobal symbols:\n\n");
+ FOR_EACH_SYMBOL(i, sp) {
+ fprintf(outfile, " %s: ", demangle(sp->name));
+ if (!(sp->flags & GS_REFERENCED))
+ fprintf(outfile, "unreferenced");
+ else if (sp->so_defined)
+ fprintf(outfile, "sodefined");
+ else if (!sp->defined)
+ fprintf(outfile, "undefined");
+ else if (sp->defined == (N_UNDF|N_EXT))
+ fprintf(outfile, "common: size %#x", sp->common_size);
+ else
+ fprintf(outfile, "type %d, value %#lx, size %#x",
+ sp->defined, sp->value, sp->size);
+ if (sp->alias)
+ fprintf(outfile, ", aliased to %s", demangle(sp->alias->name));
+ fprintf(outfile, "\n");
+ } END_EACH_SYMBOL;
+
+ each_file(list_file_locals, (void *)outfile);
+}
+
+static void
+describe_file_sections(entry, outfile)
+ struct file_entry *entry;
+ FILE *outfile;
+{
+ fprintf(outfile, " ");
+ print_file_name(entry, outfile);
+ if (entry->flags & (E_JUST_SYMS | E_DYNAMIC))
+ fprintf(outfile, " symbols only\n");
+ else
+ fprintf(outfile,
+ " text %x(%lx), data %x(%lx), bss %x(%lx) hex\n",
+ entry->text_start_address,
+ (unsigned long)entry->header.a_text,
+ entry->data_start_address,
+ (unsigned long)entry->header.a_data,
+ entry->bss_start_address,
+ (unsigned long)entry->header.a_bss);
+}
+
+static void
+list_file_locals (entry, outfile)
+ struct file_entry *entry;
+ FILE *outfile;
+{
+ struct localsymbol *lsp, *lspend;
+
+ entry->strings = (char *)alloca(entry->string_size);
+ read_entry_strings (file_open(entry), entry);
+
+ fprintf (outfile, "\nLocal symbols of ");
+ print_file_name (entry, outfile);
+ fprintf (outfile, ":\n\n");
+
+ lspend = entry->symbols + entry->nsymbols;
+ for (lsp = entry->symbols; lsp < lspend; lsp++) {
+ register struct nlist *p = &lsp->nzlist.nlist;
+ /*
+ * If this is a definition,
+ * update it if necessary by this file's start address.
+ */
+ if (!(p->n_type & (N_STAB | N_EXT)))
+ fprintf(outfile, " %s: 0x%lx\n",
+ entry->strings + p->n_un.n_strx, p->n_value);
+ }
+
+ entry->strings = 0; /* All done with them. */
+}
+
+
+/* Static vars for do_warnings and subroutines of it */
+static int list_unresolved_refs; /* List unresolved refs */
+static int list_multiple_defs; /* List multiple definitions */
+
+static struct line_debug_entry *init_debug_scan __P((int, struct file_entry *));
+static int next_debug_entry __P((int, struct line_debug_entry *));
+static int address_to_line __P((unsigned long, struct line_debug_entry *));
+
+/*
+ * Structure for communication between do_file_warnings and it's
+ * helper routines. Will in practice be an array of three of these:
+ * 0) Current line, 1) Next line, 2) Source file info.
+ */
+struct line_debug_entry
+{
+ int line;
+ char *filename;
+ struct localsymbol *sym;
+};
+
+/*
+ * Helper routines for do_file_warnings.
+ */
+
+/*
+ * Return an integer less than, equal to, or greater than 0 as per the
+ * relation between the two relocation entries. Used by qsort.
+ */
+
+static int
+reloc_cmp(rel1, rel2)
+ struct relocation_info *rel1, *rel2;
+{
+ return RELOC_ADDRESS(rel1) - RELOC_ADDRESS(rel2);
+}
+
+/*
+ * Moves to the next debugging symbol in the file. USE_DATA_SYMBOLS
+ * determines the type of the debugging symbol to look for (DSLINE or
+ * SLINE). STATE_POINTER keeps track of the old and new locatiosn in
+ * the file. It assumes that state_pointer[1] is valid; ie
+ * that it.sym points into some entry in the symbol table. If
+ * state_pointer[1].sym == 0, this routine should not be called.
+ */
+
+static int
+next_debug_entry(use_data_symbols, state_pointer)
+ register int use_data_symbols;
+ /* Next must be passed by reference! */
+ struct line_debug_entry state_pointer[3];
+{
+ register struct line_debug_entry
+ *current = state_pointer,
+ *next = state_pointer + 1,
+ /* Used to store source file */
+ *source = state_pointer + 2;
+
+ struct file_entry *entry = (struct file_entry *)source->sym;
+ struct localsymbol *lspend = entry->symbols + entry->nsymbols;
+
+
+ current->sym = next->sym;
+ current->line = next->line;
+ current->filename = next->filename;
+
+ while (++(next->sym) < lspend) {
+
+ struct nlist *np = &next->sym->nzlist.nlist;
+
+ /*
+ * n_type is a char, and N_SOL, N_EINCL and N_BINCL are > 0x80,
+ * so may look negative...therefore, must mask to low bits
+ */
+ switch (np->n_type & 0xff) {
+ case N_SLINE:
+ if (use_data_symbols)
+ continue;
+ next->line = np->n_desc;
+ return 1;
+ case N_DSLINE:
+ if (!use_data_symbols)
+ continue;
+ next->line = np->n_desc;
+ return 1;
+#ifdef HAVE_SUN_STABS
+ case N_EINCL:
+ next->filename = source->filename;
+ continue;
+#endif
+ case N_SO:
+ source->filename = np->n_un.n_strx + entry->strings;
+ source->line++;
+#ifdef HAVE_SUN_STABS
+ case N_BINCL:
+#endif
+ case N_SOL:
+ next->filename = np->n_un.n_strx + entry->strings;
+ default:
+ continue;
+ }
+ }
+ next->sym = (struct localsymbol *)0;
+ return 0;
+}
+
+/*
+ * Create a structure to save the state of a scan through the debug symbols.
+ * USE_DATA_SYMBOLS is set if we should be scanning for DSLINE's instead of
+ * SLINE's. ENTRY is the file entry which points at the symbols to use.
+ */
+
+static struct line_debug_entry *
+init_debug_scan(use_data_symbols, entry)
+ int use_data_symbols;
+ struct file_entry *entry;
+{
+ register struct localsymbol *lsp, *lspend;
+ struct line_debug_entry *state_pointer, *current, *next, *source;
+
+ state_pointer = (struct line_debug_entry *)
+ xmalloc(3 * sizeof(*state_pointer));
+
+ current = state_pointer,
+ next = state_pointer + 1,
+ source = state_pointer + 2; /* Used to store source file */
+
+ lspend = entry->symbols+entry->nsymbols;
+
+ for (lsp = entry->symbols; lsp < lspend; lsp++)
+ if (lsp->nzlist.nlist.n_type == N_SO)
+ break;
+
+ if (lsp >= lspend) {
+ /* I believe this translates to "We lose" */
+ current->filename = next->filename = entry->filename;
+ current->line = next->line = -1;
+ current->sym = next->sym = (struct localsymbol *)0;
+ return state_pointer;
+ }
+ next->line = source->line = 0;
+ next->filename = source->filename
+ = (lsp->nzlist.nlist.n_un.n_strx + entry->strings);
+ source->sym = (struct localsymbol *)entry;
+ next->sym = lsp;
+
+ /* To setup next */
+ next_debug_entry(use_data_symbols, state_pointer);
+
+ if (!next->sym) { /* No line numbers for this section; */
+ /* setup output results as appropriate */
+ if (source->line) {
+ current->filename = source->filename = entry->filename;
+ current->line = -1; /* Don't print lineno */
+ } else {
+ current->filename = source->filename;
+ current->line = 0;
+ }
+ return state_pointer;
+ }
+ /* To setup current */
+ next_debug_entry(use_data_symbols, state_pointer);
+
+ return state_pointer;
+}
+
+/*
+ * Takes an ADDRESS (in either text or data space) and a STATE_POINTER which
+ * describes the current location in the implied scan through the debug
+ * symbols within the file which ADDRESS is within, and returns the source
+ * line number which corresponds to ADDRESS.
+ */
+
+static int
+address_to_line(address, state_pointer)
+ unsigned long address;
+/* Next must be passed by reference! */
+ struct line_debug_entry state_pointer[3];
+{
+ struct line_debug_entry *current, *next, *tmp_pointer;
+ int use_data_symbols;
+
+ current = state_pointer;
+ next = state_pointer + 1;
+
+ if (next->sym)
+ use_data_symbols =
+ (next->sym->nzlist.nlist.n_type & N_TYPE) == N_DATA;
+ else
+ return current->line;
+
+ /* Go back to the beginning if we've already passed it. */
+ if (current->sym->nzlist.nlist.n_value > address) {
+ tmp_pointer = init_debug_scan(use_data_symbols,
+ (struct file_entry *)
+ ((state_pointer + 2)->sym));
+ state_pointer[0] = tmp_pointer[0];
+ state_pointer[1] = tmp_pointer[1];
+ state_pointer[2] = tmp_pointer[2];
+ free(tmp_pointer);
+ }
+
+ /* If we're still in a bad way, return -1, meaning invalid line. */
+ if (current->sym->nzlist.nlist.n_value > address)
+ return -1;
+
+ while (next->sym
+ && next->sym->nzlist.nlist.n_value <= address
+ && next_debug_entry(use_data_symbols, state_pointer));
+
+ return current->line;
+}
+
+
+/* Macros for manipulating bitvectors. */
+#define BIT_SET_P(bv, index) ((bv)[(index) >> 3] & 1 << ((index) & 0x7))
+#define SET_BIT(bv, index) ((bv)[(index) >> 3] |= 1 << ((index) & 0x7))
+
+/*
+ * This routine will scan through the relocation data of file ENTRY, printing
+ * out references to undefined symbols and references to symbols defined in
+ * files with N_WARNING symbols. If DATA_SEGMENT is non-zero, it will scan
+ * the data relocation segment (and use N_DSLINE symbols to track line
+ * number); otherwise it will scan the text relocation segment. Warnings
+ * will be printed on the output stream OUTFILE. Eventually, every nlist
+ * symbol mapped through will be marked in the NLIST_BITVECTOR, so we don't
+ * repeat ourselves when we scan the nlists themselves.
+ */
+
+static void
+do_relocation_warnings(entry, data_segment, outfile, nlist_bitvector)
+ struct file_entry *entry;
+ int data_segment;
+ FILE *outfile;
+ unsigned char *nlist_bitvector;
+{
+ struct relocation_info *rp, *erp;
+ int start_of_segment;
+ struct localsymbol *start_of_syms;
+ struct line_debug_entry *state_pointer, *current;
+ /* Assigned to generally static values; should not be written into. */
+ char *errfmt;
+ /*
+ * Assigned to alloca'd values cand copied into; should be freed when
+ * done.
+ */
+ char *errmsg;
+ int invalidate_line_number;
+
+ rp = data_segment ? entry->datarel : entry->textrel;
+ erp = data_segment ? (rp + entry->ndatarel) : (rp + entry->ntextrel);
+ start_of_syms = entry->symbols;
+ start_of_segment = (data_segment ?
+ entry->data_start_address :
+ entry->text_start_address);
+ state_pointer = init_debug_scan(data_segment != 0, entry);
+ current = state_pointer;
+
+ /*
+ * We need to sort the relocation info here. Sheesh, so much effort
+ * for one lousy error optimization.
+ */
+ qsort(rp, erp - rp, sizeof(rp[0]), reloc_cmp);
+
+ for (; rp < erp; rp++) {
+ register struct localsymbol *lsp;
+ register symbol *g;
+
+ /*
+ * If the relocation isn't resolved through a symbol, continue.
+ */
+ if (!RELOC_EXTERN_P(rp))
+ continue;
+
+ lsp = &entry->symbols[RELOC_SYMBOL(rp)];
+
+ /*
+ * Local symbols shouldn't ever be used by relocation info,
+ * so the next should be safe. This is, of course, wrong.
+ * References to local BSS symbols can be the targets of
+ * relocation info, and they can (must) be resolved through
+ * symbols. However, these must be defined properly, (the
+ * assembler would have caught it otherwise), so we can
+ * ignore these cases.
+ */
+
+ if ((g = lsp->symbol) == NULL)
+ continue;
+
+ if (!(lsp->nzlist.nz_type & N_EXT) &&
+ !SET_ELEMENT_P(lsp->nzlist.nz_type)) {
+ warnx("internal error: `%s' N_EXT not set", demangle(g->name));
+ continue;
+ }
+
+ errmsg = 0;
+
+ if (!g->defined && !g->so_defined && list_unresolved_refs) {
+ /* Mark as being noted by relocation warning pass. */
+ SET_BIT(nlist_bitvector, lsp - start_of_syms);
+
+ if (g->undef_refs == 0)
+ reported_undefineds++;
+ if (g->undef_refs >= MAX_UREFS_PRINTED)
+ /* Listed too many */
+ continue;
+ /* Undefined symbol which we should mention */
+
+ if (++(g->undef_refs) == MAX_UREFS_PRINTED) {
+ errfmt = "More undefined symbol %s refs follow";
+ invalidate_line_number = 1;
+ } else {
+ errfmt =
+ "Undefined symbol `%s' referenced from %s segment";
+ invalidate_line_number = 0;
+ }
+ } else { /* Defined */
+ /* Potential symbol warning here */
+ if (!g->warning)
+ continue;
+
+ if (BIT_SET_P(nlist_bitvector, lsp - start_of_syms))
+ continue;
+
+ /* Mark as being noted by relocation warning pass. */
+ SET_BIT(nlist_bitvector, lsp - start_of_syms);
+
+ errfmt = 0;
+ errmsg = g->warning;
+ invalidate_line_number = 0;
+ }
+
+
+ /* If errfmt == 0, errmsg has already been defined. */
+ if (errfmt != 0) {
+ char *nm = demangle(g->name);
+ errmsg = (char *)
+ xmalloc(strlen(errfmt) + strlen(nm) + 1);
+ sprintf(errmsg, errfmt, nm, data_segment?"data":"text");
+ }
+ address_to_line(RELOC_ADDRESS(rp) + start_of_segment,
+ state_pointer);
+
+ if (current->line >= 0)
+ fprintf(outfile, "%s:%d: %s\n",
+ current->filename,
+ invalidate_line_number ? 0 : current->line,
+ errmsg);
+ else
+ fprintf(outfile, "%s: %s\n", current->filename, errmsg);
+
+ if (errfmt != 0)
+ free(errmsg);
+ }
+
+ free(state_pointer);
+}
+
+/*
+ * Print on OUTFILE a list of all warnings generated by references and/or
+ * definitions in the file ENTRY. List source file and line number if
+ * possible, just the .o file if not.
+ */
+
+void
+do_file_warnings (entry, outfile)
+ struct file_entry *entry;
+ FILE *outfile;
+{
+ int nsym;
+ int i;
+ char *errfmt, *file_name;
+ int line_number;
+ int dont_allow_symbol_name;
+ u_char *nlist_bitvector;
+ struct line_debug_entry *text_scan, *data_scan;
+
+ nsym = entry->nsymbols;
+ nlist_bitvector = (u_char *)alloca((nsym >> 3) + 1);
+ bzero(nlist_bitvector, (nsym >> 3) + 1);
+
+ /* Read in the strings */
+ entry->strings = (char *)alloca(entry->string_size);
+ read_entry_strings(file_open(entry), entry);
+
+ if (!(entry->flags & E_DYNAMIC)) {
+ /* Do text warnings based on a scan through the reloc info. */
+ do_relocation_warnings(entry, 0, outfile, nlist_bitvector);
+
+ /* Do data warnings based on a scan through the reloc info. */
+ do_relocation_warnings(entry, 1, outfile, nlist_bitvector);
+ }
+
+ /*
+ * Scan through all of the nlist entries in this file and pick up
+ * anything that the scan through the relocation stuff didn't.
+ */
+ text_scan = init_debug_scan(0, entry);
+ data_scan = init_debug_scan(1, entry);
+
+ for (i = 0; i < nsym; i++) {
+ struct nlist *np;
+ symbol *g;
+
+ g = entry->symbols[i].symbol;
+ np = &entry->symbols[i].nzlist.nlist;
+
+ if (g == NULL)
+ continue;
+
+ if (!(np->n_type & N_EXT) && !SET_ELEMENT_P(np->n_type)) {
+ warnx("internal error: `%s' N_EXT not set", demangle(g->name));
+ continue;
+ }
+
+ if (!(g->flags & GS_REFERENCED)) {
+#if 0
+ /* Check for undefined shobj symbols */
+ struct localsymbol *lsp;
+ register int type;
+
+ for (lsp = g->sorefs; lsp; lsp = lsp->next) {
+ type = lsp->nzlist.nz_type;
+ if ((type & N_EXT) &&
+ type != (N_UNDF | N_EXT)) {
+ break;
+ }
+ }
+ if (type == (N_UNDF | N_EXT)) {
+ fprintf(stderr,
+ "Undefined symbol %s referenced from %s\n",
+ demangle(g->name),
+ get_file_name(entry));
+ }
+#endif
+ continue;
+ }
+
+ dont_allow_symbol_name = 0;
+
+ if (list_multiple_defs && g->mult_defs) {
+
+ errfmt = "Definition of symbol `%s' (multiply defined)";
+ switch (np->n_type) {
+ case N_TEXT | N_EXT:
+ line_number =
+ address_to_line(np->n_value, text_scan);
+ file_name = text_scan[0].filename;
+ break;
+
+ case N_DATA | N_EXT:
+ line_number =
+ address_to_line(np->n_value, data_scan);
+ file_name = data_scan[0].filename;
+ break;
+
+ case N_SETA | N_EXT:
+ case N_SETT | N_EXT:
+ case N_SETD | N_EXT:
+ case N_SETB | N_EXT:
+ if (g->mult_defs == 2)
+ continue;
+ errfmt =
+ "First set element definition of symbol `%s' (multiply defined)";
+ line_number = -1;
+ break;
+
+ case N_SIZE | N_EXT:
+ errfmt =
+ "Size element definition of symbol `%s' (multiply defined)";
+ line_number = -1;
+ break;
+
+ case N_INDR | N_EXT:
+ errfmt =
+ "Alias definition of symbol `%s' (multiply defined)";
+ line_number = -1;
+ break;
+
+ case N_UNDF | N_EXT:
+ /* Don't print out multiple defs at references.*/
+ continue;
+
+ default:
+ warnx("%s: unexpected multiple definitions "
+ "of symbol `%s', type %#x",
+ get_file_name(entry),
+ demangle(g->name), np->n_type);
+ break;
+ }
+
+ } else if (BIT_SET_P(nlist_bitvector, i)) {
+ continue;
+ } else if (list_unresolved_refs &&
+ !g->defined && !g->so_defined) {
+
+ if (g->undef_refs == 0)
+ reported_undefineds++;
+ if (g->undef_refs >= MAX_UREFS_PRINTED)
+ continue;
+ if (++(g->undef_refs) == MAX_UREFS_PRINTED)
+ errfmt = "More undefined `%s' refs follow";
+ else
+ errfmt = "Undefined symbol `%s' referenced";
+ line_number = -1;
+ } else if (g->def_lsp && g->def_lsp->entry != entry &&
+ !(entry->flags & E_DYNAMIC) &&
+ g->def_lsp->entry->flags & E_SECONDCLASS) {
+ fprintf(outfile,
+ "%s: Undefined symbol `%s' referenced (use %s ?)\n",
+ get_file_name(entry),
+ demangle(g->name),
+ g->def_lsp->entry->local_sym_name);
+ continue;
+ } else if (g->warning) {
+ /*
+ * There are two cases in which we don't want to do
+ * this. The first is if this is a definition instead
+ * of a reference. The second is if it's the reference
+ * used by the warning stabs itself.
+ */
+ if (np->n_type != (N_EXT | N_UNDF) ||
+ (entry->symbols[i].flags & LS_WARNING))
+ continue;
+
+ errfmt = g->warning;
+ line_number = -1;
+ dont_allow_symbol_name = 1;
+ } else
+ continue;
+
+ if (line_number == -1)
+ fprintf(outfile, "%s: ", get_file_name(entry));
+ else
+ fprintf(outfile, "%s:%d: ", file_name, line_number);
+
+ if (dont_allow_symbol_name)
+ fprintf(outfile, "%s", errfmt);
+ else
+ fprintf(outfile, errfmt, demangle(g->name));
+
+ fputc('\n', outfile);
+ }
+ free(text_scan);
+ free(data_scan);
+ entry->strings = 0; /* Since it will disappear anyway. */
+}
+
+int
+do_warnings(outfile)
+ FILE *outfile;
+{
+
+ list_unresolved_refs = !relocatable_output &&
+ ( (undefined_global_sym_count - undefined_weak_sym_count) > 0
+ || undefined_shobj_sym_count
+ );
+ list_multiple_defs = multiple_def_count != 0;
+
+ if (!(list_unresolved_refs ||
+ list_warning_symbols ||
+ list_multiple_defs))
+ /* No need to run this routine */
+ return 1;
+
+ if (entry_symbol && !entry_symbol->defined)
+ fprintf(outfile, "Undefined entry symbol `%s'\n",
+ demangle(entry_symbol->name));
+
+ each_file(do_file_warnings, (void *)outfile);
+
+ if (list_unresolved_refs &&
+ reported_undefineds !=
+ (undefined_global_sym_count - undefined_weak_sym_count))
+ warnx("Spurious undefined symbols: "
+ "# undefined symbols %d, reported %d",
+ (undefined_global_sym_count - undefined_weak_sym_count),
+ reported_undefineds);
+
+ if (list_unresolved_refs || list_multiple_defs)
+ return 0;
+
+ return 1;
+}
diff --git a/gnu/usr.bin/ld/xbits.c b/gnu/usr.bin/ld/xbits.c
new file mode 100644
index 0000000..f5a2740
--- /dev/null
+++ b/gnu/usr.bin/ld/xbits.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1993 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * "Generic" byte-swap routines.
+ */
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <ar.h>
+#include <ranlib.h>
+#include <a.out.h>
+#include <stab.h>
+#include <string.h>
+
+#include "ld.h"
+#include "dynamic.h"
+
+void
+swap_longs(lp, n)
+int n;
+long *lp;
+{
+ for (; n > 0; n--, lp++)
+ *lp = md_swap_long(*lp);
+}
+
+void
+swap_symbols(s, n)
+struct nlist *s;
+int n;
+{
+ for (; n; n--, s++) {
+ s->n_un.n_strx = md_swap_long(s->n_un.n_strx);
+ s->n_desc = md_swap_short(s->n_desc);
+ s->n_value = md_swap_long(s->n_value);
+ }
+}
+
+void
+swap_zsymbols(s, n)
+struct nzlist *s;
+int n;
+{
+ for (; n; n--, s++) {
+ s->nz_strx = md_swap_long(s->nz_strx);
+ s->nz_desc = md_swap_short(s->nz_desc);
+ s->nz_value = md_swap_long(s->nz_value);
+ s->nz_size = md_swap_long(s->nz_size);
+ }
+}
+
+
+void
+swap_ranlib_hdr(rlp, n)
+struct ranlib *rlp;
+int n;
+{
+ for (; n; n--, rlp++) {
+ rlp->ran_un.ran_strx = md_swap_long(rlp->ran_un.ran_strx);
+ rlp->ran_off = md_swap_long(rlp->ran_off);
+ }
+}
+
+void
+swap__dynamic(dp)
+struct _dynamic *dp;
+{
+ dp->d_version = md_swap_long(dp->d_version);
+ dp->d_debug = (struct so_debug *)md_swap_long((long)dp->d_debug);
+ dp->d_un.d_sdt = (struct section_dispatch_table *)
+ md_swap_long((long)dp->d_un.d_sdt);
+ dp->d_entry = (struct ld_entry *)md_swap_long((long)dp->d_entry);
+}
+
+void
+swap_section_dispatch_table(sdp)
+struct section_dispatch_table *sdp;
+{
+ swap_longs((long *)sdp, sizeof(*sdp)/sizeof(long));
+}
+
+void
+swap_so_debug(ddp)
+struct so_debug *ddp;
+{
+ swap_longs((long *)ddp, sizeof(*ddp)/sizeof(long));
+}
+
+void
+swapin_sod(sodp, n)
+struct sod *sodp;
+int n;
+{
+ unsigned long bits;
+
+ for (; n; n--, sodp++) {
+ sodp->sod_name = md_swap_long(sodp->sod_name);
+ sodp->sod_major = md_swap_short(sodp->sod_major);
+ sodp->sod_minor = md_swap_short(sodp->sod_minor);
+ sodp->sod_next = md_swap_long(sodp->sod_next);
+ bits = ((unsigned long *)sodp)[1];
+ sodp->sod_library = ((bits >> 24) & 1);
+ }
+}
+
+void
+swapout_sod(sodp, n)
+struct sod *sodp;
+int n;
+{
+ unsigned long bits;
+
+ for (; n; n--, sodp++) {
+ sodp->sod_name = md_swap_long(sodp->sod_name);
+ sodp->sod_major = md_swap_short(sodp->sod_major);
+ sodp->sod_minor = md_swap_short(sodp->sod_minor);
+ sodp->sod_next = md_swap_long(sodp->sod_next);
+ bits = (unsigned long)(sodp->sod_library) << 24;
+ ((unsigned long *)sodp)[1] = bits;
+ }
+}
+
+void
+swap_rrs_hash(fsp, n)
+struct rrs_hash *fsp;
+int n;
+{
+ for (; n; n--, fsp++) {
+ fsp->rh_symbolnum = md_swap_long(fsp->rh_symbolnum);
+ fsp->rh_next = md_swap_long(fsp->rh_next);
+ }
+}
+
diff --git a/gnu/usr.bin/man/COPYING b/gnu/usr.bin/man/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/gnu/usr.bin/man/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/man/Makefile b/gnu/usr.bin/man/Makefile
new file mode 100644
index 0000000..7b0ba5b
--- /dev/null
+++ b/gnu/usr.bin/man/Makefile
@@ -0,0 +1,12 @@
+# Master Makefile for man, manpath, apropos, whatis, and makewhatis
+#
+# You may distribute under the terms of the GNU General Public
+# License as specified in the README file that comes with the man 1.0
+# distribution.
+#
+# $FreeBSD$
+#
+
+SUBDIR = lib man manpath apropos
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/man/Makefile.inc b/gnu/usr.bin/man/Makefile.inc
new file mode 100644
index 0000000..7da63dc
--- /dev/null
+++ b/gnu/usr.bin/man/Makefile.inc
@@ -0,0 +1,36 @@
+# $FreeBSD$
+#
+# Set a bunch of things to hardcoded paths so that we don't accidently
+# pick up a user's own version of some utility and hose ourselves.
+#
+libdir= /etc
+bindir= ${BINDIR}
+pager= more -s
+manpath_config_file= /etc/manpath.config
+troff= /usr/bin/groff -S -man
+# -Tascii or localized encoding added automatically
+nroff= /usr/bin/groff -S -Wall -mtty-char -man
+apropos= /usr/bin/apropos
+whatis= /usr/bin/whatis
+eqn= /usr/bin/eqn
+# -Tascii or localized encoding added automatically
+neqn= /usr/bin/eqn
+tbl= /usr/bin/tbl
+col= /usr/bin/col
+vgrind= /usr/bin/vgrind
+refer= /usr/bin/refer
+grap= # no grap
+pic= /usr/bin/pic
+zcat= /usr/bin/zcat
+compress= /usr/bin/gzip -c
+compext= .gz
+
+.if exists(${.OBJDIR}/../lib)
+LIBDESTDIR= ${.OBJDIR}/../lib
+.else
+LIBDESTDIR= ${.CURDIR}/../lib
+.endif
+
+LIBMAN= ${LIBDESTDIR}/libman.a
+
+.include "../Makefile.inc"
diff --git a/gnu/usr.bin/man/README b/gnu/usr.bin/man/README
new file mode 100644
index 0000000..d8fc4d4
--- /dev/null
+++ b/gnu/usr.bin/man/README
@@ -0,0 +1,134 @@
+README file for man(1).
+
+This is a replacement for Un*x man(1), apropos(1), whatis(1), and
+manpath(1). It has all kinds of neat features that other versions of
+man don't, including support for multiple man page directory trees,
+preformatted man pages, and troff. It is provided without any
+warranty whatever. I hope you find it useful.
+
+This program is not a GNU product but it is distributed under the
+terms of the GNU copyleft which is described in the file COPYING.
+
+There is a solution written in perl which is probably superior in
+every way, but, like me, you may prefer this one anyway.
+:-)
+
+If you compile with support for preformatted man pages, man(1) will
+try to update the preformatted page if the man page source is newer.
+
+If you compile with support for troff, you can say things like
+`man -t foo | psdit > foo.ps' and have fabulous printed documentation
+as well.
+
+I have resisted the temptation to handle all the bizarre ways various
+vendors have of organizing man pages. This version of man assumes
+that directory trees have the structure:
+
+ .../man
+ /manSect
+ /foo.Sect*
+ ...
+ /catSect
+ /foo.Sect*
+ ...
+
+where Sect is some number or string and should be listed in the set of
+sections to be searched. It is not necessary to have both the cat*
+and man* subdirectories, but you must have at least one. :-)
+
+
+INSTALLATION
+
+1. Run configure. This will grope around your system a bit and then
+ ask you a number of questions. It will create a Makefile from the
+ file Makefile.in, and a config.h file from config.h.in. You may
+ have to do some fine tuning to get things to work exactly right on
+ your system. If you do, I'd like to know what changes you had to
+ make to get things working.
+
+2. Edit the manpath.config file. This determines the system-wide
+ mappings for bin directories and man page directories.
+
+3. Do a `make all', try it out, and then if you're happy with that, do
+ a `make install'. You don't need to be root to use this set of
+ programs.
+
+4. Install the whatis database(s) by running makewhatis. If you want
+ to keep things absolutely current, you'll need to run this whenever
+ you add new man pages. You might want to add an entry in your
+ crontab.
+
+BUGS
+
+If you find one of these, please tell me about it. If you have a fix,
+that's even better. If not, I can't guarantee that I'll fix it, but I
+would like to know about them.
+
+John Eaton
+jwe@che.utexas.edu
+Department of Chemical Engineering
+The University of Texas at Austin
+Austin, Texas 78712
+
+
+CHANGES
+
+Partial list of changes since version 1.0:
+
+Installation made easier (this was the intent anyway) with the
+introduction of a configure script.
+
+Commands like `man 3f intro' handled properly when the name of the
+file we want is something like .../man3/intro.3f.
+
+Man can now run set uid to a special user so formatted man pages don't
+have to be world writable.
+
+Man now works with compressed (.Z) frozen (.F) and yabba (.Y) cat
+files. Frozen files are compressed files using freeze/melt, some
+combination of LZW and tree coding. Sources for it came out on
+comp.sources.misc or alt.sources or ... a few months ago. Yabba files
+are compressed using yabba/unyabba, a data compression scheme posted
+to alt.sources by Dan Bernstein.
+
+Man now uses a more reasonable default for the search order:
+1, n, l, 6, 8, 2, 3, 4, 5, 7, p, o
+
+Man now allows for user-definable section search order via -S or
+MANSECT.
+
+Glob.c can work even if you don't have alloca, and works properly on
+Suns with the Sun C compiler.
+
+There is now a way to automatically to run preprocessors like the Sun
+man program. The first line of the man page indicates which
+preprocessors should be run:
+
+ If the first line is a string of the form:
+
+ '\" X
+
+ where X is separated from the the `"' by a single SPACE and
+ consists of any combination of characters in the following
+ list, man pipes its input to troff(1) or nroff(1) through
+ the corresponding preprocessors.
+
+ e eqn(1), or neqn for nroff
+ g grap(1)
+ p pic(1)
+ r refer(1)
+ t tbl(1), and col(1V) for nroff
+ v vgrind(1)
+
+Preprocessors may also be set on the command line with -p or from the
+environment with MANROFFSEQ.
+
+The tbl preprocessor is run by default.
+
+Manpath now stat()'s the directories in MANPATH to avoid including
+directories that don't exist.
+
+The output of apropos and whatis are now piped through PAGER.
+
+There is a new option to show where you would find a man page
+(-w option) and in what order (-w with -a).
diff --git a/gnu/usr.bin/man/TODO b/gnu/usr.bin/man/TODO
new file mode 100644
index 0000000..19060ad
--- /dev/null
+++ b/gnu/usr.bin/man/TODO
@@ -0,0 +1,123 @@
+Things that would be nice but aren't really necessary:
+
+0. Update the documentation.
+
+XX Come up with an easier way to install this thing. There are now
+ lots of options and dependent flags to set. Should I worry too
+ much about this?
+
+XX Properly handle commands like `man 3f intro' when the name of the
+ file we want is something like .../man3/intro.3f. The way this is
+ done right now seems sort of kludgey but it mostly works. See
+ man.c for details.
+
+2. Malloc everything instead of having fixed limits... Or at least
+ check the limits everywhere. If you're paranoid about this, make
+ the limits big (famous last words: really, there aren't that many
+ things that could go wrong :-).
+
+3. Try to do a little better job of memory management. There are a
+ lot of little temporary strings that are malloc'd and never freed.
+ This is probably ok for a standalone program but not so good if
+ you wanted to call man() from another program.
+
+XX Come up with a clear view of the cat directory file permissions
+ problem. What's a good solution, other than having man run setuid
+ to some special user? (Make directories writable by all, cat
+ files 666.)
+
+XX Allow a compile time option that makes man run setuid to some
+ other user that owns all the cat pages, so that they don't have to
+ be world writable.
+
+XX Allow man to deal with compressed (.Z) frozen (.F) and yabba (.Y)
+ cat files. Frozen files are compressed files using freeze/melt,
+ some combination of LZW and tree coding. Sources for it came out
+ on comp.sources.misc or alt.sources or ... a few months ago.
+ Yabba files are compressed using yabba/unyabba, a data compression
+ scheme posted to alt.sources by Dan Bernstein.
+
+XX Choose a more reasonable default for the search order. Perhaps
+ this: 1, n, l, 6, 8, 2, 3, 4, 5, 7, p, o
+
+XX Fix glob.c so it doesn't need alloca, and/or fix it so that it can
+ work on a Sun:
+
+ #ifdef __GNUC__
+ #define alloca __builtin_alloca
+ #else /* !__GNUC__ */
+ #ifdef sparc
+ #include <alloca.h>
+ #endif /* sparc */
+ #endif /* __GNUC__ */
+
+XX Add some way to automatically to run preprocessors. The Sun man
+ program has a convention that the first line of the man page can
+ indicate which preprocessors should be run. Here's an excerpt from
+ its man page:
+
+ Preprocessing Manual Pages
+ If the first line is a string of the form:
+
+ '\" X
+
+ where X is separated from the the `"' by a single SPACE and
+ consists of any combination of characters in the following
+ list, man pipes its input to troff(1) or nroff(1) through
+ the corresponding preprocessors.
+
+ e eqn(1), or neqn for nroff
+ r refer(1)
+ t tbl(1), and col(1V) for nroff
+ v vgrind(1)
+
+ If eqn or neqn is invoked, it will automatically read the
+ file /usr/pub/eqnchar (see eqnchar(7)).
+
+XX Have manpath stat() the directories in MANPATH to avoid including
+ directories that don't exist. Some versions of man and whatis
+ complain when the directories (like /usr/new/man) don't exist.
+
+XX Pipe the output of apropos and whatis through a pager.
+
+XX I've been using your man(1) package for a while now and I ran into
+ a problem with the X man pages that use tbl commands. Is it
+ possible to configure your man(1) package to use a general command
+ string. For example, a user could set an environment variable:
+
+ setenv ROFFLINE 'pic $* | tbl | nroff -man'
+
+13. Fix makewhatis so that it can handle stuff like this (from the
+ Motif 1.1 man pages):
+
+ .TH XmRowColumn 3X "" "" "" ""
+ .SH NAME
+ .mc |
+ \fBXmRowColumn \(em the RowColumn widget class.\fP
+ .mc
+ .iX "XmRowColumn"
+ .iX "widget class" "RowColumn"
+ .sp 1
+ .SH SYNOPSIS
+
+14. Consider changing the format of the awk command's printf to use
+ "%s" instead of the standard 20.20s to accomodate the extra long
+ file names used by Motif. Maybe there's a better way to handle
+ this?
+
+15. Add ability to run man on a local file
+
+16. Handle per-tree tmac macros
+
+XX Allow user-definable section search order via -S or $MANSECT.
+ Thus programmers can get stty(3) before stty(1).
+
+XX Show all the places you would find a man page (-w option) and in
+ what order.
+
+19. Support for multi-char sections like man1m/*.1m or manavs/*.avs
+ (can I have a section that doesn't start with a numeral?)
+
+20. Implement man -K for regexp apropos
+
+21. An option to grep through all the man pages in $MANPATH
diff --git a/gnu/usr.bin/man/apropos/Makefile b/gnu/usr.bin/man/apropos/Makefile
new file mode 100644
index 0000000..2f5244b
--- /dev/null
+++ b/gnu/usr.bin/man/apropos/Makefile
@@ -0,0 +1,22 @@
+# $FreeBSD$
+MAINTAINER= wosch
+
+SCRIPTS=apropos
+MAN= apropos.1
+CLEANFILES+= ${SCRIPTS} ${MAN}
+
+LINKS= ${BINDIR}/apropos ${BINDIR}/whatis
+MLINKS= apropos.1 whatis.1
+
+.sh:
+ sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \
+ -e 's,%pager%,${pager},' \
+ ${.ALLSRC} > ${.TARGET}
+
+apropos.1: apropos.man
+ sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \
+ -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \
+ -e 's,%manpath_config_file%,${manpath_config_file},' \
+ ${.ALLSRC} > ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/man/apropos/apropos.man b/gnu/usr.bin/man/apropos/apropos.man
new file mode 100644
index 0000000..1472f30
--- /dev/null
+++ b/gnu/usr.bin/man/apropos/apropos.man
@@ -0,0 +1,47 @@
+.\" Man page for apropos an whatis
+.\"
+.\" Copyright (c) 1990, 1991, John W. Eaton.
+.\"
+.\" You may distribute under the terms of the GNU General Public
+.\" License as specified in the README file that comes with the man 1.0
+.\" distribution.
+.\"
+.\" John W. Eaton
+.\" jwe@che.utexas.edu
+.\" Department of Chemical Engineering
+.\" The University of Texas at Austin
+.\" Austin, Texas 78712
+.\"
+.\" $FreeBSD$
+.Dd January 15, 1991
+.Dt APROPOS 1
+.Os
+.Sh NAME
+.Nm apropos ,
+.Nm whatis
+.Nd search the whatis database
+.Sh SYNOPSIS
+.Nm apropos
+.Ar keyword ...
+.Nm whatis
+.Ar keyword ...
+.Sh DESCRIPTION
+.Nm
+searches a set of database files containing short descriptions
+of system commands for keywords and displays the result on the
+standard output.
+.Nm whatis
+displays only complete word matches.
+.Pp
+.Ar keyword
+really is a regular expression, please read
+.Xr grep 1
+manual page for more information about its format.
+.Sh DIAGNOSTICS
+The
+.Nm
+utility exits 0 on success, and 1 if no keyword matched.
+.Sh SEE ALSO
+.Xr grep 1 ,
+.Xr makewhatis 1 ,
+.Xr man 1
diff --git a/gnu/usr.bin/man/apropos/apropos.sh b/gnu/usr.bin/man/apropos/apropos.sh
new file mode 100644
index 0000000..f6be26b
--- /dev/null
+++ b/gnu/usr.bin/man/apropos/apropos.sh
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# apropos -- search the whatis database for keywords.
+#
+# Copyright (c) February 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+# Copyright (c) 1990, 1991, John W. Eaton.
+#
+# You may distribute under the terms of the GNU General Public
+# License as specified in the README file that comes with the man
+# distribution.
+#
+# John W. Eaton
+# jwe@che.utexas.edu
+# Department of Chemical Engineering
+# The University of Texas at Austin
+# Austin, Texas 78712
+#
+# $FreeBSD$
+
+
+PATH=/bin:/usr/bin:$PATH
+db=whatis # name of whatis data base
+grepopt=''
+
+# man -k complain if exit_nomatch=1 and no keyword matched
+: ${exit_nomatch=0}
+exit_error=2
+
+# argument test
+case $# in 0)
+ echo "usage: `basename $0` keyword ..." >&2
+ exit $exit_error
+ ;;
+esac
+
+case "$0" in
+ *whatis) grepopt='-w';; # run as whatis(1)
+ *) grepopt='';; # otherwise run as apropos(1)
+esac
+
+# test manpath
+manpath=`%bindir%/manpath -q | tr : '\040'`
+case X"$manpath" in X)
+ echo "`basename $0`: manpath is null, use \"/usr/share/man\"" >&2
+ manpath=/usr/share/man
+ ;;
+esac
+
+
+# reset $PAGER if $PAGER is empty
+case X"$PAGER" in X)
+ PAGER="%pager%"
+ ;;
+esac
+
+man_locales=`%bindir%/manpath -qL`
+
+# search for existing */whatis databases
+mandir=''
+for d in $manpath
+do
+ if [ -f "$d/$db" -a -r "$d/$db" ]
+ then
+ mandir="$mandir $d/$db"
+ fi
+
+ # Check for localized manpage subdirectories
+ if [ X"$man_locales" != X ]; then
+ for l in $man_locales
+ do
+ if [ -f "$d/$l/$db" -a -r "$d/$l/$db" ];
+ then
+ mandir="$mandir $d/$l/$db"
+ fi
+ done
+ fi
+done
+
+case X"$mandir" in X)
+ echo "`basename $0`: no whatis databases in $manpath" >&2
+ exit $exit_error
+esac
+
+
+for manpage
+do
+ if grep -hi $grepopt -- "$manpage" $mandir; then :
+ else
+ echo "$manpage: nothing appropriate"
+ fi
+done |
+
+( # start $PAGER only if we find a manual page
+ while read line
+ do
+ case $line in
+ # collect error(s)
+ *": nothing appropriate") line2="$line2$line\n";;
+ # matched line or EOF
+ *) break;;
+ esac
+ done
+
+ # nothing found, exit
+ if [ -z "$line" -a ! -z "$line2" ]; then
+ printf -- "$line2"
+ exit $exit_nomatch
+ else
+ ( printf -- "$line2"; echo "$line"; cat ) | $PAGER
+ fi
+)
diff --git a/gnu/usr.bin/man/catman/Makefile b/gnu/usr.bin/man/catman/Makefile
new file mode 100644
index 0000000..047cc79
--- /dev/null
+++ b/gnu/usr.bin/man/catman/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+MAINTAINER= wosch
+
+SCRIPTS= catman.perl
+MAN= catman.1
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/man/catman/catman.1 b/gnu/usr.bin/man/catman/catman.1
new file mode 100644
index 0000000..6a90d6c
--- /dev/null
+++ b/gnu/usr.bin/man/catman/catman.1
@@ -0,0 +1,132 @@
+.\" Copyright (c) March 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" /usr/bin/catman - preformat man pages
+.\"
+.\" $FreeBSD$
+.Dd March 12, 1995
+.Dt CATMAN 1
+.Os
+.Sh NAME
+.Nm catman
+.Nd preformat man pages
+.Sh SYNOPSIS
+.Nm
+.Op Fl f | Fl force
+.Op Fl h | Fl help
+.Op Fl L | Fl locale
+.Op Fl p | Fl print
+.Op Fl r | Fl remove
+.Op Fl v | Fl verbose
+.Op Ar directories ...
+.Sh DESCRIPTION
+.Nm Catman
+format man pages to ASCII. It's like typing
+.Sq man program
+for all man pages in
+.Ar directories .
+.Ar Directories
+is a list of man directories or subdirectories separated
+by spaces or colons.
+Use
+.Ar /usr/share/man
+if no
+.Ar directories
+defined.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl f , Fl force
+Force overwriting old cat pages. Normally only those pages will be formatted
+which are not up to date. This option is a waste of time, CPU and RAM.
+.It Fl h , Fl help
+Print options and exit.
+.It Fl L , Fl locale
+Sense locale environment variables for possible localized man subdirectories
+and process these entries only.
+.It Fl p , Fl print
+Don't actually format man pages. Show what would be done.
+.It Fl r , Fl remove
+Remove garbage, e.\& g. catpage without manpage, uncompressed catpage but
+a compressed catpage exist, filenames with non-alphanumeric
+characters, uncompressed manpage but a compressed manpage exist.
+.It Fl v , Fl verbose
+More warnings.
+.El
+.Sh EXAMPLES
+.Dl $ catman
+.Pp
+Format man pages in
+.Ar /usr/share/man
+if necessary.
+.Pp
+.Dl $ catman $MANPATH
+.Pp
+Format all your man pages if necessary.
+.Pp
+.Dl $ catman -f /usr/local/man/man1 /usr/local/man/manl
+.Pp
+Force reformatting of all man pages in
+.Pa /usr/local/man/man1
+and
+.Pa /usr/local/man/manl .
+.Pp
+.Dl $ catman -p /usr/X11/man
+.Pp
+Show only.
+.Sh FILES
+.Bl -tag -width /etc/periodic/weekly/330.catman
+.It Pa /etc/periodic/weekly/330.catman
+Starts this program
+.El
+.Sh FEATURES
+Very fast if all man pages already formatted.
+Does not support the
+.Fl w
+option as some other systems do. Use
+.Xr makewhatis 1
+to rebuild the
+.Ql whatis
+database.
+.Sh BUGS
+.Xr man 1
+is a setuid program. Be careful that user
+.Sq man
+has write permissions to the catman directories.
+.Nm Catman
+does not check for any
+.Sq .so
+in man page sources. Use hard or symlinks
+to avoid redundant formatted man pages.
+.Sh SEE ALSO
+.Xr makewhatis 1 ,
+.Xr man 1 ,
+.Xr manpath 1
+.Sh HISTORY
+This version of
+.Nm
+command appeared in
+.Fx 2.1 .
+.Sh AUTHORS
+.An Wolfram Schneider Aq wosch@FreeBSD.org ,
+Berlin.
diff --git a/gnu/usr.bin/man/catman/catman.perl b/gnu/usr.bin/man/catman/catman.perl
new file mode 100644
index 0000000..0bd3372
--- /dev/null
+++ b/gnu/usr.bin/man/catman/catman.perl
@@ -0,0 +1,439 @@
+#!/usr/bin/perl
+#
+# Copyright (c) March 1995 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# /usr/bin/catman - preformat man pages
+#
+# $FreeBSD$
+
+
+sub usage {
+
+warn <<EOF;
+usage: catman [-f|-force] [-h|-help] [-L|-locale] [-p|-print] [-r|remove]
+ [-v|-verbose] [directories ...]
+EOF
+
+exit 1;
+}
+
+sub variables {
+ $force = 0; # force overwriting existing catpages
+ $verbose = 0; # more warnings
+ $print = 0; # show only, do nothing
+ $remove = 0; # unlink forgotten man/catpages
+ $locale = 0; # go through localized man directories only
+
+ # choose localized man directories suffix.
+ $local_suffix = $ENV{'LC_ALL'} || $ENV{'LC_CTYPE'} || $ENV{'LANG'};
+
+ # if no argument for directories given
+ @defaultmanpath = ( '/usr/share/man' );
+
+ $exit = 0; # exit code
+ $ext = ".gz"; # extension
+ umask(022);
+
+ # Signals
+ $SIG{'INT'} = 'Exit';
+ $SIG{'HUP'} = 'Exit';
+ $SIG{'TRAP'} = 'Exit';
+ $SIG{'QUIT'} = 'Exit';
+ $SIG{'TERM'} = 'Exit';
+ $tmp = ''; # tmp file
+
+ $ENV{'PATH'} = '/bin:/usr/bin';
+}
+
+sub Exit {
+ unlink($tmp) if $tmp ne ""; # unlink if a filename
+ die "$0: die on signal SIG@_\n";
+}
+
+sub parse {
+ local(@argv) = @_;
+
+ while($_ = $argv[0], /^-/) {
+ shift @argv;
+ last if /^--$/;
+ if (/^--?(f|force)$/) { $force = 1 }
+ elsif (/^--?(p|print)$/) { $print = 1 }
+ elsif (/^--?(r|remove)$/) { $remove = 1 }
+ elsif (/^--?(v|verbose)$/) { $verbose = 1 }
+ elsif (/^--?(L|locale)$/) { $locale = 1 }
+ else { &usage }
+ }
+ warn "Localized man directory suffix is $local_suffix\n"
+ if $verbose && $locale;
+
+ return &absolute_path(@argv) if $#argv >= 0;
+ return @defaultmanpath if $#defaultmanpath >= 0;
+
+ warn "Missing directories\n"; &usage;
+}
+
+# make relative path to absolute path
+sub absolute_path {
+ local(@dirlist) = @_;
+ local($pwd, $dir, @a);
+
+ $pwd = $ENV{'PWD'};
+
+ foreach $dir (@dirlist) {
+ if ($dir !~ "^/") {
+ chop($pwd = `pwd`) if (!$pwd || $pwd !~ /^\//);
+ push(@a, "$pwd/$dir");
+ } else {
+ push(@a, $dir);
+ }
+ }
+ return @a;
+}
+
+# strip unused '/'
+# e.g.: //usr///home// -> /usr/home
+sub stripdir {
+ local($dir) = @_;
+
+ $dir =~ s|/+|/|g; # delete double '/'
+ $dir =~ s|/$||; # delete '/' at end
+ $dir =~ s|/(\.\/)+|/|g; # delete ././././
+
+ $dir =~ s|/+|/|g; # delete double '/'
+ $dir =~ s|/$||; # delete '/' at end
+ $dir =~ s|/\.$||; # delete /. at end
+ return $dir if $dir ne "";
+ return '/';
+}
+
+# read man directory
+sub parse_dir {
+ local($dir) = @_;
+ local($subdir, $catdir);
+ local($dev,$ino) = (stat($dir))[01];
+
+ # already visit
+ if ($dir_visit{$dev,$ino}) {
+ warn "$dir already parsed: $dir_visit{$dev,$ino}\n";
+ return 1;
+ }
+ $dir_visit{$dev,$ino} = $dir;
+
+ # Manpath, /usr/local/man or
+ # localized manpath /usr/local/man/{$LC_CTYPE|$LANG}
+ if (($dir =~ /man$/) ||
+ (($locale) && ($dir =~ /man/) && ($dir =~ $local_suffix))) {
+ warn "open manpath directory ``$dir''\n" if $verbose;
+ if (!opendir(DIR, $dir)) {
+ warn "opendir ``$dir'':$!\n"; $exit = 1; return 0;
+ }
+
+ warn "chdir to: $dir\n" if $verbose;
+ chdir($dir) || do { warn "$dir: $!\n"; $exit = 1; return 0 };
+
+ foreach $subdir (sort(readdir(DIR))) {
+ if ($subdir =~ /^man\w+$/) {
+ $subdir = "$dir/$subdir";
+ &catdir_create($subdir) && &parse_subdir($subdir);
+ }
+ }
+ closedir DIR
+
+ # subdir, /usr/local/man/man1
+ } elsif ($dir =~ /man\w+$/) {
+ local($parentdir) = $dir;
+ $parentdir =~ s|/[^/]+$||;
+ warn "chdir to: $parentdir\n" if $verbose;
+ chdir($parentdir) || do {
+ warn "$parentdir: $!\n"; $exit = 1; return 0 };
+
+ &catdir_create($dir) && &parse_subdir($dir);
+ } else {
+ warn "Assume ``$dir'' is not a man directory.\n";
+ $exit = 1;
+ }
+}
+
+# create cat subdirectory if neccessary
+# e.g.: man9 exist, but cat9 not
+sub catdir_create {
+ local($subdir) = @_;
+ local($catdir) = $subdir;
+
+ $catdir = &man2cat($subdir);
+ if (-d $catdir) {
+ return 1 if -w _;
+ if (!chmod(0755, $catdir)) {
+ warn "Cannot write $catdir, chmod: $!\n";
+ $exit = 1;
+ return 0;
+ }
+ return 1;
+ }
+
+ warn "mkdir ``$catdir''\n" if $verbose || $print;
+ unless ($print) {
+ unlink($catdir); # be paranoid
+ if (!mkdir($catdir, 0755)) {
+ warn "Cannot make $catdir: $!\n";
+ $exit = 1;
+ return 0;
+ }
+ return 1;
+ }
+}
+
+# I: /usr/share/man/man9
+# O: /usr/share/man/cat9
+sub man2cat {
+ local($man) = @_;
+
+ $man =~ s/man(\w+)$/cat$1/;
+ return $man;
+}
+
+sub parse_subdir {
+ local($subdir) = @_;
+ local($file, $f, $catdir, $catdir_short, $mandir, $mandir_short);
+ local($mtime_man, $mtime_cat);
+ local(%read);
+
+ $mandir = $subdir;
+ $catdir = &man2cat($mandir);
+
+ ($mandir_short = $mandir) =~ s|.*/(.*)|$1|;
+ ($catdir_short = $catdir) =~ s|.*/(.*)|$1|;
+
+ warn "open man directory: ``$mandir''\n" if $verbose;
+ if (!opendir(D, $mandir)) {
+ warn "opendir ``$mandir'': $!\n"; $exit = 1; return 0;
+ }
+
+ foreach $file (readdir(D)) {
+ # skip current and parent directory
+ next if $file eq "." || $file eq "..";
+
+ # fo_09-o.bar0
+ if ($file !~ /^[\w\-\+\[\.:]+\.\w+$/) {
+ &garbage("$mandir/$file", "Assume garbage")
+ unless -d "$mandir/$file";
+ next;
+ }
+
+ if ($file !~ /\.gz$/) {
+ if (-e "$mandir/$file.gz") {
+ &garbage("$mandir/$file",
+ "Manpage unused, see compressed version");
+ next;
+ }
+ warn "$mandir/$file is uncompressed\n" if $verbose;
+ $cfile = "$file.gz";
+ } else {
+ $cfile = "$file";
+ }
+
+ if (!(($mtime_man = ((stat("$mandir_short/$file"))[9])) && -r _ && -f _)) {
+ if (! -d _) {
+ warn "Cannot read file: ``$mandir/$file''\n";
+ $exit = 1;
+ if ($remove && -l "$mandir/$file") {
+ &garbage("$mandir/$file", "Assume wrong symlink");
+ }
+ next;
+ }
+ warn "Ignore subsubdirectory: ``$mandir/$file''\n"
+ if $verbose;
+ next;
+ }
+
+ $read{$file} = 1;
+
+ # Assume catpages always compressed
+ if (($mtime_cat = ((stat("$catdir_short/$cfile"))[9]))
+ && -r _ && -f _) {
+ if ($mtime_man > $mtime_cat || $force) {
+ &nroff("$mandir/$file", "$catdir/$cfile");
+ } else {
+ warn "up to date: $mandir/$file\n" if $verbose;
+ #print STDERR "." if $verbose;
+ }
+ } else {
+ &nroff("$mandir/$file", "$catdir/$cfile");
+ }
+ }
+ closedir D;
+
+ if (!opendir(D, $catdir)) {
+ warn "opendir ``$catdir'': $!\n"; return 0;
+ }
+
+ warn "open cat directory: ``$catdir''\n" if $verbose;
+ foreach $file (readdir(D)) {
+ next if $file =~ /^(\.|\.\.)$/; # skip current and parent directory
+
+ if ($file !~ /^[\w\-\+\[\.:]+\.\w+$/) {
+ &garbage("$catdir/$file", "Assume garbage")
+ unless -d "$catdir/$file";
+ next;
+ }
+
+ if ($file !~ /\.gz$/ && $read{"$file.gz"}) {
+ &garbage("$catdir/$file",
+ "Catpage unused, see compressed version");
+ } elsif (!$read{$file}) {
+ # maybe a bug in man(1)
+ # if both manpage and catpage are uncompressed, man reformats
+ # the manpage and puts a compressed catpage to the
+ # already existing uncompressed catpage
+ ($f = $file) =~ s/\.gz$//;
+
+ # man page is uncompressed, catpage is compressed
+ next if $read{$f};
+ &garbage("$catdir/$file", "Catpage without manpage");
+ }
+ }
+ closedir D;
+}
+
+sub garbage {
+ local($file, @text) = @_;
+
+ warn "@text: ``$file''\n";
+ if ($remove) {
+ warn "unlink $file\n";
+ unless ($print) {
+ unlink($file) || warn "unlink $file: $!\n" ;
+ }
+ }
+}
+
+sub nroff {
+ local($man,$cat) = @_;
+ local($nroff) = "nroff -T" . $dev_name . " -man | col";
+ local($dev, $ino) = (stat($man))[01];
+
+ # It's a link
+ if ($link{"$dev.$ino"}) {
+ warn "Link: $link{\"$dev.$ino\"} -> $cat\n" if $verbose || $print;
+
+ return if $print; # done
+ unlink($cat); # remove possible old link
+
+ unless (link($link{"$dev.$ino"}, $cat)) {
+ warn "Link $cat: $!\n";
+ $exit = 1;
+ }
+ return;
+ } else {
+ $cat = "$cat$ext" if $cat !~ /$ext$/;
+ warn "Format: $man -> $cat\n" if $verbose || $print;
+
+ unless($print) {
+ # man page is compressed
+ if ($man =~ /$ext$/) {
+ $nroff = "zcat $man | tbl | $nroff";
+ } else {
+ $nroff = "tbl $man | $nroff";
+ }
+
+ # start formatting
+ $tmp = "$cat.$tmp"; # for cleanup after signals
+ system("$nroff | gzip > $cat.tmp");
+ if ($?) {
+ # assume a fatal signal to nroff
+ &Exit("INT to system() function") if ($? == 2);
+ } else {
+ rename("$cat.tmp", $cat);
+ }
+ }
+ }
+
+ # dev/ino from manpage, path from catpage
+ $link{"$dev.$ino"} = $cat;
+}
+
+# Set correct [gn]roff output device name ([ng]roff's "-T" option)
+sub nroff_device {
+ # Choose default output device name.
+ $dev_name = "ascii";
+
+ if ($locale) {
+ # Use "nroff -Tkoi8-r -man" to format russian manpages (if catman "-L"
+ # option specified only).
+ if ($local_suffix =~ '\.KOI8-R$') {
+ $dev_name = "koi8-r";
+ }
+ # Use "nroff -Tlatin1 -man" to format ISO 8859-1 manpages
+ elsif ($local_suffix =~ '\.ISO_?8859-15?$') {
+ $dev_name = "latin1";
+ }
+ }
+ warn "nroff output device name is $dev_name\n" if $verbose;
+}
+
+# process directory
+sub process_dir {
+ local($dir) = @_;
+
+ if (-e $dir && -d _ && -r _ && -x _) {
+ warn "``$dir'' is not writable for you,\n" .
+ "can only write to existing cat subdirs (if any)\n"
+ if ! -w _ && $verbose;
+ &parse_dir(&stripdir($dir));
+ } else {
+ warn "``$dir'' is not a directory or not read-/searchable for you\n";
+ $exit = 1;
+ }
+}
+
+# convert locale name to short notation (ru_RU.KOI8-R -> ru.KOI8-R)
+sub short_locale_name {
+ local($lname) = @_;
+
+ $lname =~ s|_[A-Z][A-Z]||;
+ warn "short locale name is $lname\n" if $verbose && $locale;
+
+ return $lname;
+}
+
+#############
+# main
+warn "Don't start this program as root, use:\n" .
+ "echo $0 @ARGV | nice -5 su -m man\n" unless $>;
+
+&variables;
+@argv = &parse(split(/[ :]/, join($", @ARGV)));
+&nroff_device;
+foreach $dir (@argv) {
+ if ($locale) {
+ if ($local_suffix ne "") {
+ &process_dir($dir.'/'.$local_suffix);
+ &process_dir($dir.'/'.&short_locale_name($local_suffix));
+ }
+ } else {
+ &process_dir($dir);
+ }
+}
+exit($exit);
diff --git a/gnu/usr.bin/man/lib/Makefile b/gnu/usr.bin/man/lib/Makefile
new file mode 100644
index 0000000..243d141
--- /dev/null
+++ b/gnu/usr.bin/man/lib/Makefile
@@ -0,0 +1,27 @@
+# $FreeBSD$
+
+LIB= man
+INTERNALLIB= true
+
+CFLAGS+= -DSTDC_HEADERS
+CLEANFILES+= config.h
+SRCS= gripes.c util.c
+
+# Kludge to create config.h for other modules. The library itself doesn't
+# depend on config.h.
+SRCS+= config.h
+
+config.h: ${.CURDIR}/config.h_dist ${.CURDIR}/../Makefile.inc
+ sed -e 's,%apropos%,${apropos},' -e 's,%whatis%,${whatis},' \
+ -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \
+ -e 's,%nroff%,${nroff},' -e 's,%tbl%,${tbl},' \
+ -e 's,%col%,${col},' -e 's,%pic%,${pic},' \
+ -e 's,%eqn%,${eqn},' -e 's,%neqn%,${neqn},' \
+ -e 's,%vgrind%,${vgrind},' -e 's,%refer%,${refer},' \
+ -e 's,%grap%,${grap},' -e 's,%zcat%,${zcat},' \
+ -e 's,%manpath_config_file%,${manpath_config_file},' \
+ -e 's,%compress%,${compress},' \
+ -e 's,%compext%,${compext},' \
+ ${.CURDIR}/config.h_dist > ${.TARGET}
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/man/lib/config.h_dist b/gnu/usr.bin/man/lib/config.h_dist
new file mode 100644
index 0000000..e764933
--- /dev/null
+++ b/gnu/usr.bin/man/lib/config.h_dist
@@ -0,0 +1,210 @@
+/*
+ * config.h
+ *
+ * If you haven't read the README file, now might be a good time.
+ *
+ * This file is edited by configure, so you shouldn't have to.
+ * If that doesn't work, edit this file to match your site.
+ *
+ * Sorry it's so long, but there are lots of things you might want to
+ * customize for your site.
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ */
+
+/*
+ * This is the size of a number of internal buffers. It should
+ * probably not be less than 512.
+ */
+#ifndef BUFSIZ
+#define BUFSIZ 1024
+#endif
+
+/*
+ * This should be at least the size of the longest path.
+ */
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+/*
+ * This is the maximum number of directories expected in the manpath.
+ */
+#ifndef MAXDIRS
+#define MAXDIRS 64
+#endif
+
+/*
+ * This is the name of the group that owns the preformatted man pages.
+ * If you are running man as a setgid program, you should make sure
+ * that all of the preformatted man pages and the directories that
+ * they live in are readable and writeable and owned by this group.
+ */
+#ifdef SECURE_MAN_UID
+#define MAN_USER ""
+#endif
+
+/*
+ * It's probably best to define absolute paths to all of these. If
+ * you don't, you'll be depending on the user's path to be correct
+ * when system () is called. This can result in weird behavior that's
+ * hard to track down, especially after you forget how this program
+ * works... If you don't have some of these programs, simply define
+ * them to be empty strings (i.e. ""). As a minimum, you must have
+ * nroff installed.
+ */
+#ifndef APROPOS
+#define APROPOS "%apropos%"
+#endif
+
+#ifndef WHATIS
+#define WHATIS "%whatis%"
+#endif
+
+#ifndef PAGER
+#define PAGER "%pager%"
+#endif
+
+#ifdef HAS_TROFF
+#ifndef TROFF
+#define TROFF "%troff%"
+#endif
+#endif
+
+#ifndef NROFF
+#define NROFF "%nroff%"
+#endif
+
+#ifndef EQN
+#define EQN "%eqn%"
+#endif
+
+#ifndef NEQN
+#define NEQN "%neqn%"
+#endif
+
+#ifndef TBL
+#define TBL "%tbl%"
+#endif
+
+#ifndef COL
+#define COL "%col%"
+#endif
+
+#ifndef VGRIND
+#define VGRIND "%vgrind%"
+#endif
+
+#ifndef REFER
+#define REFER "%refer%"
+#endif
+
+#ifndef GRAP
+#define GRAP "%grap%"
+#endif
+
+#ifndef PIC
+#define PIC "%pic%"
+#endif
+
+/*
+ * Define the absolute path to the configuration file.
+ */
+#ifndef MAN_MAIN
+ static char config_file[] = "%manpath_config_file%" ;
+#endif
+
+/*
+ * Define the uncompression program(s) to use for those preformatted
+ * pages that end in the given character. If you add extras here, you
+ * may need to change man.c. [I have no idea what FCAT and YCAT files
+ * are! - I will leave them in for now.. -jkh]
+ */
+/* .F files */
+#define FCAT ""
+/* .Y files */
+#define YCAT ""
+/* .Z files */
+#define ZCAT "%zcat%"
+
+/*
+ * This is the standard program to use on this system for compressing
+ * pages once they have been formatted, and the character to tack on
+ * to the end of those files. The program listed is expected to read
+ * from the standard input and write compressed output to the standard
+ * output. These won't actually be used unless compression is enabled.
+ */
+#ifdef DO_COMPRESS
+#define COMPRESSOR "%compress%"
+#define COMPRESS_EXT "%compext%"
+#endif
+
+/*
+ * Define the standard manual sections. For example, if your man
+ * directory tree has subdirectories man1, man2, man3, mann,
+ * and man3foo, std_sections[] would have "1", "2", "3", "n", and
+ * "3foo". Directories are searched in the order they appear. Having
+ * extras isn't fatal, it just slows things down a bit.
+ *
+ * Note that this is just for directories to search. If you have
+ * files like .../man3/foobar.3Xtc, you don't need to have "3Xtc" in
+ * the list below -- this is handled separately, so that `man 3Xtc foobar',
+ * `man 3 foobar', and `man foobar' should find the file .../man3/foo.3Xtc,
+ * (assuming, of course, that there isn't a .../man1/foo.1 or somesuch
+ * that we would find first).
+ *
+ * Note that this list should be in the order that you want the
+ * directories to be searched. Is there a standard for this? What is
+ * the normal order? If anyone knows, please tell me!
+ */
+#ifndef MANPATH_MAIN
+ static char *std_sections[] =
+ {
+ "1", "1aout", "8", "2", "3", "n", "4", "5", "6", "7", "9", "l", NULL
+ };
+#endif
+
+/*
+ * Not all systems define these in stat.h.
+ */
+#ifndef S_IRUSR
+#define S_IRUSR 00400 /* read permission: owner */
+#endif
+#ifndef S_IWUSR
+#define S_IWUSR 00200 /* write permission: owner */
+#endif
+#ifndef S_IRGRP
+#define S_IRGRP 00040 /* read permission: group */
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP 00020 /* write permission: group */
+#endif
+#ifndef S_IROTH
+#define S_IROTH 00004 /* read permission: other */
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH 00002 /* write permission: other */
+#endif
+
+/*
+ * This is the mode used for formatted pages that we create. If you
+ * are using the setgid option, you should use 664. If you are not,
+ * you should use 666 and make the cat* directories mode 777.
+ */
+#ifndef CATMODE
+#ifdef SECURE_MAN_UID
+#define CATMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
+#else
+#define CATMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
+#endif
+#endif
diff --git a/gnu/usr.bin/man/lib/gripes.c b/gnu/usr.bin/man/lib/gripes.c
new file mode 100644
index 0000000..466f0bc
--- /dev/null
+++ b/gnu/usr.bin/man/lib/gripes.c
@@ -0,0 +1,180 @@
+/*
+ * gripes.c
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ */
+
+#include <stdio.h>
+#include "gripes.h"
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern int fprintf ();
+extern int fflush ();
+extern int exit ();
+#endif
+
+extern char *prognam;
+
+void
+gripe_no_name (section)
+ char *section;
+{
+ if (section)
+ fprintf (stderr, "What manual page do you want from section %s?\n",
+ section);
+ else
+ fprintf (stderr, "What manual page do you want?\n");
+
+ fflush (stderr);
+}
+
+void
+gripe_reading_man_file (name)
+ char *name;
+{
+ fprintf (stderr, "Read access denied for file %s\n", name);
+
+ fflush (stderr);
+}
+
+void
+gripe_converting_name (name, to_cat)
+ char *name;
+ int to_cat;
+{
+ if (to_cat)
+ fprintf (stderr, "Error converting %s to cat name\n", name);
+ else
+ fprintf (stderr, "Error converting %s to man name\n", name);
+
+ fflush (stderr);
+
+ exit (1);
+}
+
+void
+gripe_system_command (status)
+ int status;
+{
+ fprintf (stderr, "Error executing formatting or display command.\n");
+ fprintf (stderr, "system command exited with status %d\n", status);
+
+ fflush (stderr);
+}
+
+void
+gripe_not_found (name, section)
+ char *name, *section;
+{
+ if (section)
+ fprintf (stderr, "No entry for %s in section %s of the manual\n",
+ name, section);
+ else
+ fprintf (stderr, "No manual entry for %s\n", name);
+
+ fflush (stderr);
+}
+
+void
+gripe_incompatible (s)
+ char *s;
+{
+ fprintf (stderr, "%s: incompatible options %s\n", prognam, s);
+
+ fflush (stderr);
+
+ exit (1);
+}
+
+void
+gripe_getting_mp_config (file)
+ char *file;
+{
+ fprintf (stderr, "%s: unable to find the file %s\n", prognam, file);
+
+ fflush (stderr);
+
+ exit (1);
+}
+
+void
+gripe_reading_mp_config (file)
+ char *file;
+{
+ fprintf (stderr, "%s: unable to make sense of the file %s\n", prognam, file);
+
+ fflush (stderr);
+
+ exit (1);
+}
+
+void
+gripe_invalid_section (section)
+ char *section;
+{
+ fprintf (stderr, "%s: invalid section (%s) selected\n", prognam, section);
+
+ fflush (stderr);
+
+ exit (1);
+}
+
+void
+gripe_manpath ()
+{
+ fprintf (stderr, "%s: manpath is null\n", prognam);
+
+ fflush (stderr);
+
+ exit (1);
+}
+
+void
+gripe_alloc (bytes, object)
+ int bytes;
+ char *object;
+{
+ fprintf (stderr, "%s: can't malloc %d bytes for %s\n",
+ prognam, bytes, object);
+
+ fflush (stderr);
+
+ exit (1);
+}
+
+void
+gripe_roff_command_from_file (file)
+ char *file;
+{
+ fprintf (stderr, "Error parsing *roff command from file %s\n", file);
+
+ fflush (stderr);
+}
+
+void
+gripe_roff_command_from_env ()
+{
+ fprintf (stderr, "Error parsing MANROFFSEQ. Using system defaults.\n");
+
+ fflush (stderr);
+}
+
+void
+gripe_roff_command_from_command_line ()
+{
+ fprintf (stderr, "Error parsing *roff command from command line.\n");
+
+ fflush (stderr);
+}
diff --git a/gnu/usr.bin/man/lib/gripes.h b/gnu/usr.bin/man/lib/gripes.h
new file mode 100644
index 0000000..5fd59b2
--- /dev/null
+++ b/gnu/usr.bin/man/lib/gripes.h
@@ -0,0 +1,30 @@
+/*
+ * gripes.h
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ */
+
+extern void gripe_no_name ();
+extern void gripe_converting_name ();
+extern void gripe_system_command ();
+extern void gripe_reading_man_file ();
+extern void gripe_not_found ();
+extern void gripe_invalid_section ();
+extern void gripe_manpath ();
+extern void gripe_alloc ();
+extern void gripe_incompatible ();
+extern void gripe_getting_mp_config ();
+extern void gripe_reading_mp_config ();
+extern void gripe_roff_command_from_file ();
+extern void gripe_roff_command_from_env ();
+extern void gripe_roff_command_from_command_line ();
diff --git a/gnu/usr.bin/man/lib/util.c b/gnu/usr.bin/man/lib/util.c
new file mode 100644
index 0000000..70d57b5
--- /dev/null
+++ b/gnu/usr.bin/man/lib/util.c
@@ -0,0 +1,160 @@
+/*
+ * util.c
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern int fprintf ();
+extern int tolower ();
+#endif
+
+extern char *strdup ();
+extern int system ();
+
+#include "gripes.h"
+
+/*
+ * Extract last element of a name like /foo/bar/baz.
+ */
+char *
+mkprogname (s)
+ register char *s;
+{
+ char *t;
+
+ t = strrchr (s, '/');
+ if (t == (char *)NULL)
+ t = s;
+ else
+ t++;
+
+ return strdup (t);
+}
+
+void
+downcase (s)
+ unsigned char *s;
+{
+ register unsigned char c;
+ while ((c = *s) != '\0')
+ {
+ if (isalpha (c))
+ *s = tolower (c);
+ s++;
+ }
+}
+
+/*
+ * Is file a newer than file b?
+ *
+ * case:
+ *
+ * a newer than b returns 1
+ * a older than b returns 0
+ * stat on a fails returns -1
+ * stat on b fails returns -2
+ * stat on a and b fails returns -3
+ */
+int
+is_newer (fa, fb)
+ register char *fa;
+ register char *fb;
+{
+ struct stat fa_sb;
+ struct stat fb_sb;
+ register int fa_stat;
+ register int fb_stat;
+ register int status = 0;
+
+ fa_stat = stat (fa, &fa_sb);
+ if (fa_stat != 0)
+ status = 1;
+
+ fb_stat = stat (fb, &fb_sb);
+ if (fb_stat != 0)
+ status |= 2;
+
+ if (status != 0)
+ return -status;
+
+ return (fa_sb.st_mtime > fb_sb.st_mtime);
+}
+
+/*
+ * Is path a directory?
+ */
+int
+is_directory (path)
+ char *path;
+{
+ struct stat sb;
+ register int status;
+
+ status = stat (path, &sb);
+
+ if (status != 0)
+ return -1;
+
+ return ((sb.st_mode & S_IFDIR) == S_IFDIR);
+
+}
+
+/*
+ * Attempt a system () call. Return 1 for success and 0 for failure
+ * (handy for counting successes :-).
+ */
+int
+do_system_command (command)
+ char *command;
+{
+ int status = 0;
+ extern int debug;
+
+ /*
+ * If we're debugging, don't really execute the command -- you never
+ * know what might be in that mangled string :-O.
+ */
+ if (debug)
+ fprintf (stderr, "\ntrying command: %s\n", command);
+ else
+ status = system (command);
+
+ /* check return value from system() function first */
+ if (status == -1) {
+ fprintf(stderr,
+ "wait() for exit status of shell failed in function system()\n");
+ return 0;
+ } else if (status == 127 || status == (127 << 8)) {
+ fprintf(stderr, "execution of the shell failed in function system()\n");
+ return 0;
+ }
+
+ if (WIFSIGNALED(status))
+ return -1;
+ else if (WEXITSTATUS(status)) {
+ gripe_system_command (status);
+ return 0;
+ }
+ else
+ return 1;
+}
diff --git a/gnu/usr.bin/man/makewhatis/Makefile b/gnu/usr.bin/man/makewhatis/Makefile
new file mode 100644
index 0000000..73eb9e0
--- /dev/null
+++ b/gnu/usr.bin/man/makewhatis/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+MAINTAINER= wosch
+
+SCRIPTS=makewhatis.perl makewhatis.local.sh
+MAN= makewhatis.1 makewhatis.local.8
+
+libexecdir=/usr/libexec
+LINKS=${libexecdir}/makewhatis.local ${libexecdir}/catman.local
+SCRIPTSDIR_makewhatis.local.sh= ${libexecdir}
+MLINKS= makewhatis.local.8 catman.local.8
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/man/makewhatis/makewhatis.1 b/gnu/usr.bin/man/makewhatis/makewhatis.1
new file mode 100644
index 0000000..75c2f29
--- /dev/null
+++ b/gnu/usr.bin/man/makewhatis/makewhatis.1
@@ -0,0 +1,148 @@
+.\" Copyright (c) 1994-1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd January 12, 1995
+.Dt MAKEWHATIS 1
+.Os
+.Sh NAME
+.Nm makewhatis
+.Nd create whatis database
+.Sh SYNOPSIS
+.Nm
+.Op Fl a | Fl append
+.Op Fl h | Fl help
+.Op Fl i | Fl indent Ar column
+.Op Fl L | Fl locale
+.Op Fl n | Fl name Ar name
+.Op Fl o | Fl outfile Ar file
+.Op Fl v | Fl verbose
+.Op Ar directories ...
+.Sh DESCRIPTION
+.Nm
+extracts the name and a short description from unformatted manpages
+and creates the
+.Xr whatis 1
+database.
+.Nm
+can read gzip'ed manpages.
+.Ar Directory
+names a directory containing manpage subdirectories
+(named
+.Pa man.+ ) .
+Colons are treated as spaces, hence
+.Ic makewhatis $MANPATH
+or
+.Ic makewhatis `manpath`
+are allowed.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl a , Fl append
+Append mode. Don't delete old entries in whatis database. Note:
+the new database will be sorted without repeated lines and
+.Nm
+does not check if old entries are valid.
+.It Fl h , Fl help
+Print options and exit.
+.It Fl i , Fl indent Ar column
+Justify description strings to
+.Ar column
+(default 24).
+.It Fl L , Fl locale
+Sense locale environment variables for possible localized man subdirectories
+and process this entries only.
+.It Fl n , Fl name Ar name
+Use
+.Ar name
+instead of
+.Pa whatis Ns .
+.It Fl o , Fl outfile Ar file
+Write all output to
+.Ar file
+instead of
+.Pa dirname/whatis Ns .
+.It Fl v , Fl verbose
+Issue more warnings
+(to stderr).
+For every parsed man page write a single char:
+.Ql .\&
+for an uncompressed page,
+.Ql *
+for a compressed page, and
+.Ql +
+for a link.
+.El
+.Sh EXAMPLES
+.Ic makewhatis $MANPATH
+.Pp
+Create whatis database for all directories in your
+.Pa $MANPATH Ns .
+.Pp
+.Ic makewhatis -outfile /tmp/mywhatis /usr/local/man $HOME/man
+.Pp
+Create whatis database
+.Pa /tmp/mywhatis .
+Traverse directories
+.Pa /usr/local/man
+and
+.Pa $HOME/man Ns .
+Don't create
+.Pa /usr/local/man/whatis
+or
+.Pa $HOME/man/whatis Ns .
+.Pp
+.Ic makewhatis -name windex $HOME/man
+.Pp
+Create whatis database
+.Pa windex
+instead of
+.Pa whatis Ns .
+May be useful for Solaris.
+.Sh FILES
+.Bl -tag -width /etc/master.passwdxx -compact
+.It Pa */man/whatis
+whatis database
+.It Pa /etc/periodic/weekly/320.whatis
+run
+.Nm makewhatis.local
+every week
+.El
+.Sh SEE ALSO
+.Xr apropos 1 ,
+.Xr catman 1 ,
+.Xr getNAME 1 ,
+.Xr man 1 ,
+.Xr manpath 1 ,
+.Xr sort 1 ,
+.Xr uniq 1 ,
+.Xr whatis 1 ,
+.Xr makewhatis.local 8
+.Sh HISTORY
+This
+.Nm
+command appeared in
+.Fx 2.1 .
+.Sh AUTHORS
+.An Wolfram Schneider ,
+Berlin.
diff --git a/gnu/usr.bin/man/makewhatis/makewhatis.local.8 b/gnu/usr.bin/man/makewhatis/makewhatis.local.8
new file mode 100644
index 0000000..9a721bd
--- /dev/null
+++ b/gnu/usr.bin/man/makewhatis/makewhatis.local.8
@@ -0,0 +1,80 @@
+.\" Copyright (c) April 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd April 26, 1996
+.Dt MAKEWHATIS.LOCAL 8
+.Os
+.Sh NAME
+.Nm makewhatis.local , catman.local
+.Nd start makewhatis or catman for local file systems
+.Sh SYNOPSIS
+.Nm /usr/libexec/makewhatis.local
+.Op options
+.Ar directories ...
+.Nm /usr/libexec/catman.local
+.Op options
+.Ar directories ...
+.Sh DESCRIPTION
+.Nm
+start
+.Xr makewhatis 1
+only for file systems physically mounted on the system
+where the
+.Nm
+is being executed. Running makewhatis
+by
+.Pa periodic weekly
+for rw nfs-mounted /usr may kill
+your NFS server -- all NFS clients start makewhatis at the same time!
+So use this wrapper for
+.Xr cron 8
+instead of calling makewhatis directly.
+.Nm catman.local
+is using for same purposes as
+.Nm
+but for
+.Xr catman 1 .
+.Sh FILES
+.Bl -tag -width /etc/periodic/weekly/320.whatis.XXX -compact
+.It Pa /etc/periodic/weekly/320.whatis
+run
+.Nm
+every week
+.It Pa /etc/periodic/weekly/330.catman
+run
+.Nm catman.local
+every week
+.El
+.Sh SEE ALSO
+.Xr catman 1 ,
+.Xr find 1 ,
+.Xr makewhatis 1 ,
+.Xr cron 8 ,
+.Xr periodic 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 2.2 .
diff --git a/gnu/usr.bin/man/makewhatis/makewhatis.local.sh b/gnu/usr.bin/man/makewhatis/makewhatis.local.sh
new file mode 100644
index 0000000..8be2530
--- /dev/null
+++ b/gnu/usr.bin/man/makewhatis/makewhatis.local.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# Copyright (c) April 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# makewhatis.local - start makewhatis(1) only for file systems
+# physically mounted on the system
+#
+# Running makewhatis from /etc/periodic/weekly/320.whatis for rw nfs-mounted
+# /usr may kill your NFS server -- all clients start makewhatis at the same
+# time! So use this wrapper instead calling makewhatis directly.
+#
+# PS: this wrapper works also for catman(1)
+#
+# $FreeBSD$
+
+PATH=/bin:/usr/bin:$PATH; export PATH
+opt= dirs= localdirs=
+
+for arg
+do
+ case "$arg" in
+ -*) opt="$opt $arg";;
+ *) dirs="$dirs $arg";;
+ esac
+done
+
+dirs=`echo $dirs | sed 's/:/ /g'`
+case X"$dirs" in X) echo "usage: $0 [options] directories ..."; exit 1;; esac
+
+localdirs=`find -H $dirs -fstype local -type d -prune -print`
+
+case X"$localdirs" in
+ X) echo "$0: no local-mounted manual directories found: $dirs"
+ exit 1;;
+ *) exec `basename $0 .local` $opt $localdirs;;
+esac
diff --git a/gnu/usr.bin/man/makewhatis/makewhatis.perl b/gnu/usr.bin/man/makewhatis/makewhatis.perl
new file mode 100644
index 0000000..33cee65
--- /dev/null
+++ b/gnu/usr.bin/man/makewhatis/makewhatis.perl
@@ -0,0 +1,574 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 1994-1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# makewhatis -- update the whatis database in the man directories.
+#
+# $FreeBSD$
+
+
+sub usage {
+
+ warn <<EOF;
+usage: makewhatis [-a|-append] [-h|-help] [-i|-indent column] [-L|-locale]
+ [-n|-name name] [-o|-outfile file] [-v|-verbose]
+ [directories ...]
+EOF
+ exit 1;
+}
+
+
+# Format output
+sub open_output {
+ local($dir) = @_;
+
+ die "Name for whatis is empty\n" if $whatis_name eq "";
+
+ if ($outfile) { # Write all Output to $outfile
+ $whatisdb = $outfile;
+ } else { # Use man/whatis
+ $whatisdb = $dir . "/$whatis_name.tmp";
+ }
+ $tmp = $whatisdb; # for signals
+
+ # Array of all entries
+ @a = ();
+
+ # Append mode
+ if ($append) {
+ local($file) = $whatisdb;
+ $file =~ s/\.tmp$// if !$outfile;
+
+ if (open(A, "$file")) {
+ warn "Open $file for append mode\n" if $verbose;
+ while(<A>) {
+ push(@a, $_);
+ }
+ close A;
+ }
+
+ else {
+ warn "$whatisdb: $!\n" if lstat($file) && $verbose; #
+ }
+ undef $file;
+ }
+
+
+ warn "Open $whatisdb\n" if $verbose;
+ if (!open(A, "> $whatisdb")) {
+ die "$whatisdb: $!\n" if $outfile;
+
+ warn "$whatisdb: $!\n"; $err++; return 0;
+ }
+
+ select A;
+ return 1;
+}
+
+sub close_output {
+ local($success) = @_;
+ local($w) = $whatisdb;
+ local($counter) = 0;
+ local($i, $last,@b);
+
+ $w =~ s/\.tmp$//;
+ if ($success) { # success
+ # uniq
+ warn "\n" if $verbose && $pointflag;
+ warn "sort -u > $whatisdb\n" if $verbose;
+ foreach $i (sort @a) {
+ if ($i ne $last) {
+ push(@b, $i);
+ }
+ $last =$i;
+ }
+
+ $counter = $#b + 1;
+ print @b; close A; select STDOUT;
+
+ if (!$outfile) {
+ warn "Rename $whatisdb to $w\n" if $verbose;
+ rename($whatisdb, $w) || warn "rename $whatisdb $w\n";
+ $counter_all += $counter;
+ warn "$counter entries in $w\n" if $verbose;
+ } else {
+ $counter_all = $counter;
+ }
+ } else { # building whatisdb failed
+ unlink($whatisdb);
+ warn "building whatisdb: $whatisdb failed\n" if $verbose;
+ }
+ return 1;
+}
+
+sub parse_subdir {
+ local($dir) = @_;
+ local($file, $dev,$ino);
+
+ warn "\n" if $pointflag;
+ warn "traverse $dir\n" if $verbose;
+ $pointflag = 0;
+
+ if (!opendir(M, $dir)) {
+ warn "$dir: $!\n"; $err++; return 0;
+ }
+
+ $| = 1 if $verbose;
+ foreach $file (readdir(M)) {
+ next if $file =~ /^(\.|\.\.)$/;
+
+ ($dev, $ino) = ((stat("$dir/$file"))[01]);
+ if (-f _) {
+ if ($man_red{"$dev.$ino"}) {
+ # Link
+ print STDERR "+" if $verbose;
+ $pointflag++ if $verbose;
+ } else {
+ &manual("$dir/$file");
+ }
+ $man_red{"$dev.$ino"} = 1;
+ } elsif (! -d _) {
+ warn "Cannot find file: $dir/$file\n"; $err++;
+ }
+ }
+ closedir M;
+ return 1;
+}
+
+# read man directory
+sub parse_dir {
+ local($dir) = @_;
+ local($subdir, $file);
+
+ # clean up, in case mandir and subdirs are called simultaneously
+ # e. g.: ~/man/man1 ~/man/man2 ~/man
+ #~/man/ man1 and ~/man/man2 are a subset of ~/man
+ foreach $file (keys %man_red) {
+ delete $man_red{$file};
+ }
+
+ if ($dir =~ /man/) {
+ warn "\n" if $verbose && $pointflag;
+ warn "open manpath directory ``$dir''\n" if $verbose;
+ $pointflag = 0;
+ if (!opendir(DIR, $dir)) {
+ warn "opendir ``$dir'':$!\n"; $err = 1; return 0;
+ }
+ foreach $subdir (sort(readdir(DIR))) {
+ if ($subdir =~ /^man\w+$/) {
+ $subdir = "$dir/$subdir";
+ &parse_subdir($subdir);
+ &parse_subdir($subdir) if -d ($subdir .= "/${machine}");
+ }
+ }
+ closedir DIR
+
+ } elsif ($dir =~ /man\w+$/) {
+ &parse_subdir($dir);
+ } else {
+ warn "Assume ``$dir'' is not a man directory.\n";
+ $err = 1; return 0;
+ }
+ return 1;
+}
+
+sub dir_redundant {
+ local($dir) = @_;
+
+ local($dev,$ino) = (stat($dir))[0..1];
+
+ if ($dir_redundant{"$dev.$ino"}) {
+ warn "$dir is equal to: $dir_redundant{\"$dev.$ino\"}\n" if $verbose;
+ return 0;
+ }
+ $dir_redundant{"$dev.$ino"} = $dir;
+ return 1;
+}
+
+
+# ``/usr/man/man1/foo.l'' -> ``l''
+sub ext {
+ local($filename) = @_;
+ local($extension) = $filename;
+
+ $extension =~ s/$ext$//g; # strip .gz
+ $extension =~ s/.*\///g; # basename
+
+ if ($extension !~ m%[^/]+\.[^.]+$%) { # no dot
+ $extension = $filename;
+ #$extension =~ s|/[^/]+$||;
+ $extension =~ s%.*man([^/]+)/[^/]+%$1%; # last character
+ warn "\n" if $verbose && $pointflag;
+ warn "$filename has no extension, try section ``$extension''\n"
+ if $verbose;
+ $pointflag = 0;
+ } else {
+ $extension =~ s/.*\.//g; # foo.bla.1 -> 1
+ }
+ return "$extension";
+}
+
+# ``/usr/man/man1/foo.1'' -> ``foo''
+sub name {
+ local($name) = @_;
+
+ $name =~ s=.*/==;
+ $name =~ s=$ext$==o;
+ $name =~ s=\.[^\.]+$==;
+
+ return "$name";
+}
+
+# output
+sub out {
+ local($list) = @_;
+ local($delim) = " - ";
+ $_ = $list;
+
+ # delete italic etc.
+ s/^\.[^ -]+[ -]+//;
+ s/\\\((em|mi)//;
+ s/\\f[IRBP]//g;
+ s/\\\*p//g;
+ s/\(OBSOLETED\)[ ]?//;
+ s/\\&//g;
+ s/^\@INDOT\@//;
+ s/[\"\\]//g; #"
+ s/[. \t-]+$//;
+
+ s/ / - / unless / - /;
+ ($man,$desc) = split(/ - /);
+
+ $man = $name unless $man;
+ $man =~ s/[,. ]+$//;
+ $man =~ s/,/($extension),/g;
+ $man .= "($extension)";
+
+ &manpagename;
+
+ $desc =~ s/^[ \t]+//;
+
+ for($i = length($man); $i < $indent && $desc; $i++) {
+ $man .= ' ';
+ }
+ if ($desc) {
+ push(@a, "$man$delim$desc\n");
+ } else {
+ push(@a, "$man\n");
+ }
+}
+
+# The filename of manual page is not a keyword.
+# This is bad, because you don't find the manpage
+# whith: $ man <section> <keyword>
+#
+# Add filename if a) filename is not a keyword and b) no keyword(s)
+# exist as file in same mansection
+#
+sub manpagename {
+ foreach (split(/,\s+/, $man)) {
+ s/\(.+//;
+ # filename is keyword
+ return if $name eq $_;
+ }
+
+ local($f) = $file; $f =~ s%/*[^/]+$%%; # dirname
+ local($e) = $file; $e =~ s/$ext$//; $e =~ s%.*(\.[^.]+)$%$1%; # .1
+
+ foreach (split(/,\s+/, $man)) {
+ s/\(.+//;
+
+ # a keyword exist as file
+ return if -e "$f/$_$e" || -e "$f/$_$e$ext";
+ }
+
+ $man = "$name($extension), $man";
+}
+
+# looking for NAME
+sub manual {
+ local($file) = @_;
+ local($list, $desc, $extension);
+ local($ofile) = $file;
+
+ # Compressed man pages
+ if ($ofile =~ /$ext$/) {
+ $ofile = "gzcat $file |";
+ print STDERR "*" if $verbose;
+ } else {
+ print STDERR "." if $verbose;
+ }
+ $pointflag++ if $verbose;
+
+ if (!open(F, "$ofile")) {
+ warn "Cannot open file: $ofile\n"; $err++;
+ return 0;
+ }
+ # extension/section
+ $extension = &ext($file);
+ $name = &name($file);
+
+ $section_name = "NAME|Name|NAMN|BEZEICHNUNG|̾¾Î|îáú÷áîéå";
+
+ local($source) = 0;
+ local($list);
+ while(<F>) {
+ # ``man'' style pages
+ # &&: it takes you only half the user time, regexp is slow!!!
+ if (/^\.SH/ && /^\.SH[ \t]+["]?($section_name)["]?/) {
+ #while(<F>) { last unless /^\./ } # Skip
+ #chop; $list = $_;
+ while(<F>) {
+ last if /^\.SH[ \t]/;
+ chop;
+ s/^\.IX\s.*//; # delete perlpod garbage
+ s/^\.[A-Z]+[ ]+[0-9]+$//; # delete commands
+ s/^\.[A-Za-z]*[ \t]*//; # delete commands
+ s/^\.\\".*$//; #" delete comments
+ s/^[ \t]+//;
+ if ($_) {
+ $list .= $_;
+ $list .= ' ';
+ }
+ }
+ while(<F>) { } # skip remaining input to avoid pipe errors
+ &out($list); close F; return 1;
+ } elsif (/^\.Sh/ && /^\.Sh[ \t]+["]?($section_name)["]?/) {
+ # ``doc'' style pages
+ local($flag) = 0;
+ while(<F>) {
+ last if /^\.Sh/;
+ chop;
+ s/^\.\\".*$//; #" delete comments
+ next if /^\.[ \t]*$/; # skip empty calls
+ if (/^\.Nm/) {
+ s/^\.Nm[ \t]*//;
+ s/ ,/,/g;
+ s/[ \t]+$//;
+ $list .= $_;
+ $list .= ' ';
+ } else {
+ $list .= '- ' if (!$flag && !/^- /);
+ $flag++;
+ if (/^\.Xr/) {
+ split;
+ $list .= @_[1];
+ $list .= "(@_[2])" if @_[2];
+ } else {
+ s/^\.([A-Z][a-z])?[ \t]*//;
+ s/[ \t]+$//;
+ $list .= $_;
+ }
+ $list .= ' ';
+ }
+ }
+ while(<F>) { } # skip remaining input to avoid pipe errors
+ &out($list); close F; return 1;
+
+ } elsif(/^\.so/ && /^\.so[ \t]+man/) {
+ while(<F>) { } # skip remaining input to avoid pipe errors
+ close F; return 1;
+ }
+ }
+ if (!$source && $verbose) {
+ warn "\n" if $pointflag;
+ warn "Maybe $file is not a manpage\n" ;
+ $pointflag = 0;
+ }
+ return 0;
+}
+
+# make relative path to absolute path
+sub absolute_path {
+ local(@dirlist) = @_;
+ local($pwd, $dir, @a);
+
+ $pwd = $ENV{'PWD'};
+ foreach $dir (@dirlist) {
+ if ($dir !~ "^/") {
+ chop($pwd = `pwd`) if (!$pwd || $pwd !~ /^\//);
+ push(@a, "$pwd/$dir");
+ } else {
+ push(@a, $dir);
+ }
+ }
+ return @a;
+}
+
+# strip unused '/'
+# e.g.: //usr///home// -> /usr/home
+sub stripdir {
+ local($dir) = @_;
+
+ $dir =~ s|/+|/|g; # delete double '/'
+ $dir =~ s|/$||; # delete '/' at end
+ $dir =~ s|/(\.\/)+|/|g; # delete ././././
+
+ $dir =~ s|/+|/|g; # delete double '/'
+ $dir =~ s|/$||; # delete '/' at end
+ $dir =~ s|/\.$||; # delete /. at end
+ return $dir if $dir ne "";
+ return '/';
+}
+
+sub variables {
+ $verbose = 0; # Verbose
+ $indent = 24; # Indent for description
+ $outfile = 0; # Don't write to ./whatis
+ $whatis_name = "whatis"; # Default name for DB
+ $append = 0; # Don't delete old entries
+ $locale = 0; # Build DB only for localized man directories
+ chomp($machine = $ENV{'MACHINE'} || `uname -m`);
+
+ # choose localized man directories suffix.
+ $local_suffix = $ENV{'LC_ALL'} || $ENV{'LC_CTYPE'} || $ENV{'LANG'};
+
+ # if no argument for directories given
+ @defaultmanpath = ( '/usr/share/man' );
+
+ $ext = '.gz'; # extension
+ umask(022);
+
+ $err = 0; # exit code
+ $whatisdb = '';
+ $counter_all = 0;
+ $dir_redundant = ''; # redundant directories
+ $man_red = ''; # redundant man pages
+ @a = (); # Array for output
+
+ # Signals
+ $SIG{'INT'} = 'Exit';
+ $SIG{'HUP'} = 'Exit';
+ $SIG{'TRAP'} = 'Exit';
+ $SIG{'QUIT'} = 'Exit';
+ $SIG{'TERM'} = 'Exit';
+ $tmp = ''; # tmp file
+
+ $ENV{'PATH'} = "/bin:/usr/bin:$ENV{'PATH'}";
+}
+
+sub Exit {
+ unlink($tmp) if $tmp ne ""; # unlink if a filename
+ die "$0: die on signal SIG@_\n";
+}
+
+sub parse {
+ local(@argv) = @_;
+ local($i);
+
+ while ($_ = $argv[0], /^-/) {
+ shift @argv;
+ last if /^--$/;
+ if (/^--?(v|verbose)$/) { $verbose = 1 }
+ elsif (/^--?(h|help|\?)$/) { &usage }
+ elsif (/^--?(o|outfile)$/) { $outfile = $argv[0]; shift @argv }
+ elsif (/^--?(f|format|i|indent)$/) { $i = $argv[0]; shift @argv }
+ elsif (/^--?(n|name)$/) { $whatis_name = $argv[0];shift @argv }
+ elsif (/^--?(a|append)$/) { $append = 1 }
+ elsif (/^--?(L|locale)$/) { $locale = 1 }
+ else { &usage }
+ }
+ warn "Localized man directory suffix is ``$local_suffix''\n"
+ if $verbose && $locale;
+
+ if ($i ne "") {
+ if ($i =~ /^[0-9]+$/) {
+ $indent = $i;
+ } else {
+ warn "Ignoring wrong indent value: ``$i''\n";
+ }
+ }
+
+ return &absolute_path(@argv) if $#argv >= 0;
+ return @defaultmanpath if $#defaultmanpath >= 0;
+
+ warn "Missing directories\n"; &usage;
+}
+
+# Process man directory
+sub process_dir {
+ local($dir) = @_;
+
+ $dir = &stripdir($dir);
+ &dir_redundant($dir) && &parse_dir($dir);
+}
+
+# Process man directory and store output to file
+sub process_dir_to_file {
+ local($dir) = @_;
+
+ $dir = &stripdir($dir);
+ &dir_redundant($dir) &&
+ &close_output(&open_output($dir) && &parse_dir($dir));
+}
+
+# convert locale name to short notation (ru_RU.KOI8-R -> ru.KOI8-R)
+sub short_locale_name {
+ local($lname) = @_;
+
+ $lname =~ s|_[A-Z][A-Z]||;
+ warn "short locale name is $lname\n" if $verbose && $locale;
+ return $lname;
+}
+
+##
+## Main
+##
+
+&variables;
+# allow colons in dir: ``makewhatis dir1:dir2:dir3''
+@argv = &parse(split(/[: ]/, join($", @ARGV))); # "
+
+if ($outfile) {
+ if(&open_output($outfile)){
+ foreach $dir (@argv) {
+ # "Local only" flag set ? Yes ...
+ if ($locale) {
+ if ($local_suffix ne "") {
+ &process_dir($dir.'/'.$local_suffix);
+ &process_dir($dir.'/'.&short_locale_name($local_suffix));
+ }
+ } else {
+ &process_dir($dir);
+ }
+ }
+ }
+ &close_output(1);
+} else {
+ foreach $dir (@argv) {
+ # "Local only" flag set ? Yes ...
+ if ($locale) {
+ if ($local_suffix ne "") {
+ &process_dir_to_file($dir.'/'.$local_suffix);
+ &process_dir_to_file($dir.'/'.&short_locale_name($local_suffix));
+ }
+ } else {
+ &process_dir_to_file($dir);
+ }
+ }
+}
+
+warn "Total entries: $counter_all\n" if $verbose && ($#argv > 0 || $outfile);
+exit $err;
diff --git a/gnu/usr.bin/man/man/Makefile b/gnu/usr.bin/man/man/Makefile
new file mode 100644
index 0000000..905d4db
--- /dev/null
+++ b/gnu/usr.bin/man/man/Makefile
@@ -0,0 +1,33 @@
+# $FreeBSD$
+#
+
+MAN_LIBZ=YES
+
+PROG= man
+SRCS= man.c manpath.c glob.c
+
+CFLAGS+= -I${LIBDESTDIR}
+DPADD= ${LIBMAN}
+LDADD= ${LIBMAN}
+
+.if defined(MAN_LIBZ) && !empty(MAN_LIBZ)
+DPADD+= ${LIBZ}
+LDADD+= -lz
+CFLAGS+=-DHAVE_LIBZ=1
+.endif
+
+CFLAGS+= -I${.CURDIR}/../lib -DSTDC_HEADERS -DPOSIX -DHAS_TROFF
+CFLAGS+= -DDO_COMPRESS -DCATMODE=0644
+CLEANFILES+= man.1
+
+.PATH: ${.CURDIR}/../manpath
+
+man.1: ${.CURDIR}/man.man
+ @${ECHO} echo Making ${.TARGET:T} from ${.ALLSRC:T}; \
+ sed -e 's,%libdir%,${libdir},' -e 's,%bindir%,${bindir},' \
+ -e 's,%pager%,${pager},' -e 's,%troff%,${troff},' \
+ -e 's,%manpath_config_file%,${manpath_config_file},' \
+ -e 's,%compress%,${compress},' \
+ ${.ALLSRC} > ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/man/man/glob.c b/gnu/usr.bin/man/man/glob.c
new file mode 100644
index 0000000..65eb1fa
--- /dev/null
+++ b/gnu/usr.bin/man/man/glob.c
@@ -0,0 +1,712 @@
+/* File-name wildcard pattern matching for GNU.
+ Copyright (C) 1985, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* To whomever it may concern: I have never seen the code which most
+ Unix programs use to perform this function. I wrote this from scratch
+ based on specifications for the pattern matching. --RMS. */
+
+#ifdef SHELL
+#include "config.h"
+#endif /* SHELL */
+
+#include <sys/types.h>
+
+#if defined (USGr3) && !defined (DIRENT)
+#define DIRENT
+#endif /* USGr3 */
+#if defined (Xenix) && !defined (SYSNDIR)
+#define SYSNDIR
+#endif /* Xenix */
+
+#if defined (POSIX) || defined (DIRENT) || defined (__GNU_LIBRARY__)
+#include <dirent.h>
+#define direct dirent
+#define D_NAMLEN(d) strlen((d)->d_name)
+#else /* not POSIX or DIRENT or __GNU_LIBRARY__ */
+#define D_NAMLEN(d) ((d)->d_namlen)
+#ifdef USG
+#if defined (SYSNDIR)
+#include <sys/ndir.h>
+#else /* SYSNDIR */
+#include "ndir.h"
+#endif /* not SYSNDIR */
+#else /* not USG */
+#include <sys/dir.h>
+#endif /* USG */
+#endif /* POSIX or DIRENT or __GNU_LIBRARY__ */
+
+#if defined (_POSIX_SOURCE)
+/* Posix does not require that the d_ino field be present, and some
+ systems do not provide it. */
+#define REAL_DIR_ENTRY(dp) 1
+#else
+#define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif /* _POSIX_SOURCE */
+
+#if defined (STDC_HEADERS) || defined (__GNU_LIBRARY__)
+#include <stdlib.h>
+#include <string.h>
+#define STDC_STRINGS
+#else /* STDC_HEADERS or __GNU_LIBRARY__ */
+
+#if defined (USG)
+#include <string.h>
+#ifndef POSIX
+#include <memory.h>
+#endif /* POSIX */
+#define STDC_STRINGS
+#else /* not USG */
+#ifdef NeXT
+#include <string.h>
+#else /* NeXT */
+#include <strings.h>
+#endif /* NeXT */
+/* Declaring bcopy causes errors on systems whose declarations are different.
+ If the declaration is omitted, everything works fine. */
+#endif /* not USG */
+
+extern char *malloc ();
+extern char *realloc ();
+extern void free ();
+
+#ifndef NULL
+#define NULL 0
+#endif
+#endif /* Not STDC_HEADERS or __GNU_LIBRARY__. */
+
+#ifdef STDC_STRINGS
+#define bcopy(s, d, n) memcpy ((d), (s), (n))
+#define index strchr
+#define rindex strrchr
+#endif /* STDC_STRINGS */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* Not GCC. */
+#ifdef sparc
+#include <alloca.h>
+#else /* Not sparc. */
+extern char *alloca ();
+#endif /* sparc. */
+#endif /* GCC. */
+#endif
+
+/* Nonzero if '*' and '?' do not match an initial '.' for glob_filename. */
+int noglob_dot_filenames = 1;
+
+static int glob_match_after_star ();
+
+#ifdef __FreeBSD__
+static int collate_range_cmp (a, b)
+ int a, b;
+{
+ int r;
+ static char s[2][2];
+
+ if ((unsigned char)a == (unsigned char)b)
+ return 0;
+ s[0][0] = a;
+ s[1][0] = b;
+ if ((r = strcoll(s[0], s[1])) == 0)
+ r = (unsigned char)a - (unsigned char)b;
+ return r;
+}
+#endif
+
+/* Return nonzero if PATTERN has any special globbing chars in it. */
+
+int
+glob_pattern_p (pattern)
+ char *pattern;
+{
+ register char *p = pattern;
+ register char c;
+ int open = 0;
+
+ while ((c = *p++) != '\0')
+ switch (c)
+ {
+ case '?':
+ case '*':
+ return 1;
+
+ case '[': /* Only accept an open brace if there is a close */
+ open++; /* brace to match it. Bracket expressions must be */
+ continue; /* complete, according to Posix.2 */
+ case ']':
+ if (open)
+ return 1;
+ continue;
+
+ case '\\':
+ if (*p++ == '\0')
+ return 0;
+ }
+
+ return 0;
+}
+
+
+/* Match the pattern PATTERN against the string TEXT;
+ return 1 if it matches, 0 otherwise.
+
+ A match means the entire string TEXT is used up in matching.
+
+ In the pattern string, `*' matches any sequence of characters,
+ `?' matches any character, [SET] matches any character in the specified set,
+ [!SET] matches any character not in the specified set.
+
+ A set is composed of characters or ranges; a range looks like
+ character hyphen character (as in 0-9 or A-Z).
+ [0-9a-zA-Z_] is the set of characters allowed in C identifiers.
+ Any other character in the pattern must be matched exactly.
+
+ To suppress the special syntactic significance of any of `[]*?!-\',
+ and match the character exactly, precede it with a `\'.
+
+ If DOT_SPECIAL is nonzero,
+ `*' and `?' do not match `.' at the beginning of TEXT. */
+
+int
+glob_match (pattern, text, dot_special)
+ char *pattern, *text;
+ int dot_special;
+{
+ register char *p = pattern, *t = text;
+ register char c;
+
+ while ((c = *p++) != '\0')
+ switch (c)
+ {
+ case '?':
+ if (*t == '\0' || (dot_special && t == text && *t == '.'))
+ return 0;
+ else
+ ++t;
+ break;
+
+ case '\\':
+ if (*p++ != *t++)
+ return 0;
+ break;
+
+ case '*':
+ if (dot_special && t == text && *t == '.')
+ return 0;
+ return glob_match_after_star (p, t);
+
+ case '[':
+ {
+ register char c1 = *t++;
+ int invert;
+ char *cp1 = p;
+
+ if (c1 == '\0')
+ return 0;
+
+ invert = (*p == '!');
+
+ if (invert)
+ p++;
+
+ c = *p++;
+ while (1)
+ {
+ register char cstart = c, cend = c;
+
+ if (c == '\\')
+ {
+ cstart = *p++;
+ cend = cstart;
+ }
+
+ if (cstart == '\0')
+ {
+ /* Missing ']'. */
+ if (c1 != '[')
+ return 0;
+ /* matched a single bracket */
+ p = cp1;
+ goto breakbracket;
+ }
+
+ c = *p++;
+
+ if (c == '-')
+ {
+ cend = *p++;
+ if (cend == '\\')
+ cend = *p++;
+ if (cend == '\0')
+ return 0;
+ c = *p++;
+ }
+#ifdef __FreeBSD__
+ if ( collate_range_cmp (c1, cstart) >= 0
+ && collate_range_cmp (c1, cend) <= 0
+ )
+#else
+ if (c1 >= cstart && c1 <= cend)
+#endif
+ goto match;
+ if (c == ']')
+ break;
+ }
+ if (!invert)
+ return 0;
+ break;
+
+ match:
+ /* Skip the rest of the [...] construct that already matched. */
+ while (c != ']')
+ {
+ if (c == '\0')
+ return 0;
+ c = *p++;
+ if (c == '\0')
+ return 0;
+ if (c == '\\')
+ p++;
+ }
+ if (invert)
+ return 0;
+ breakbracket:
+ break;
+ }
+
+ default:
+ if (c != *t++)
+ return 0;
+ }
+
+ return *t == '\0';
+}
+
+/* Like glob_match, but match PATTERN against any final segment of TEXT. */
+
+static int
+glob_match_after_star (pattern, text)
+ char *pattern, *text;
+{
+ register char *p = pattern, *t = text;
+ register char c, c1;
+
+ while ((c = *p++) == '?' || c == '*')
+ if (c == '?' && *t++ == '\0')
+ return 0;
+
+ if (c == '\0')
+ return 1;
+
+ if (c == '\\')
+ c1 = *p;
+ else
+ c1 = c;
+
+ --p;
+ while (1)
+ {
+ if ((c == '[' || *t == c1) && glob_match (p, t, 0))
+ return 1;
+ if (*t++ == '\0')
+ return 0;
+ }
+}
+
+/* Return a vector of names of files in directory DIR
+ whose names match glob pattern PAT.
+ The names are not in any particular order.
+ Wildcards at the beginning of PAT do not match an initial period
+ if noglob_dot_filenames is nonzero.
+
+ The vector is terminated by an element that is a null pointer.
+
+ To free the space allocated, first free the vector's elements,
+ then free the vector.
+
+ Return NULL if cannot get enough memory to hold the pointer
+ and the names.
+
+ Return -1 if cannot access directory DIR.
+ Look in errno for more information. */
+
+char **
+glob_vector (pat, dir)
+ char *pat;
+ char *dir;
+{
+ struct globval
+ {
+ struct globval *next;
+ char *name;
+ };
+
+ DIR *d;
+ register struct direct *dp;
+ struct globval *lastlink;
+ register struct globval *nextlink;
+ register char *nextname;
+ unsigned int count;
+ int lose;
+ register char **name_vector;
+ register unsigned int i;
+#ifdef ALLOCA_MISSING
+ struct globval *templink;
+#endif
+
+ d = opendir (dir);
+ if (d == NULL)
+ return (char **) -1;
+
+ lastlink = NULL;
+ count = 0;
+ lose = 0;
+
+ /* Scan the directory, finding all names that match.
+ For each name that matches, allocate a struct globval
+ on the stack and store the name in it.
+ Chain those structs together; lastlink is the front of the chain. */
+ while (1)
+ {
+#if defined (SHELL)
+ /* Make globbing interruptible in the bash shell. */
+ extern int interrupt_state;
+
+ if (interrupt_state)
+ {
+ closedir (d);
+ lose = 1;
+ goto lost;
+ }
+#endif /* SHELL */
+
+ dp = readdir (d);
+ if (dp == NULL)
+ break;
+ if (REAL_DIR_ENTRY (dp)
+ && glob_match (pat, dp->d_name, noglob_dot_filenames))
+ {
+#ifdef ALLOCA_MISSING
+ nextlink = (struct globval *) malloc (sizeof (struct globval));
+#else
+ nextlink = (struct globval *) alloca (sizeof (struct globval));
+#endif
+ nextlink->next = lastlink;
+ i = D_NAMLEN (dp) + 1;
+ nextname = (char *) malloc (i);
+ if (nextname == NULL)
+ {
+ lose = 1;
+ break;
+ }
+ lastlink = nextlink;
+ nextlink->name = nextname;
+ bcopy (dp->d_name, nextname, i);
+ count++;
+ }
+ }
+ closedir (d);
+
+ if (!lose)
+ {
+ name_vector = (char **) malloc ((count + 1) * sizeof (char *));
+ lose |= name_vector == NULL;
+ }
+
+ /* Have we run out of memory? */
+#ifdef SHELL
+ lost:
+#endif
+ if (lose)
+ {
+ /* Here free the strings we have got. */
+ while (lastlink)
+ {
+ free (lastlink->name);
+#ifdef ALLOCA_MISSING
+ templink = lastlink->next;
+ free ((char *) lastlink);
+ lastlink = templink;
+#else
+ lastlink = lastlink->next;
+#endif
+ }
+ return NULL;
+ }
+
+ /* Copy the name pointers from the linked list into the vector. */
+ for (i = 0; i < count; ++i)
+ {
+ name_vector[i] = lastlink->name;
+#ifdef ALLOCA_MISSING
+ templink = lastlink->next;
+ free ((char *) lastlink);
+ lastlink = templink;
+#else
+ lastlink = lastlink->next;
+#endif
+ }
+
+ name_vector[count] = NULL;
+ return name_vector;
+}
+
+/* Return a new array, replacing ARRAY, which is the concatenation
+ of each string in ARRAY to DIR.
+ Return NULL if out of memory. */
+
+static char **
+glob_dir_to_array (dir, array)
+ char *dir, **array;
+{
+ register unsigned int i, l;
+ int add_slash = 0;
+ char **result;
+
+ l = strlen (dir);
+ if (l == 0)
+ return array;
+
+ if (dir[l - 1] != '/')
+ add_slash++;
+
+ for (i = 0; array[i] != NULL; i++)
+ ;
+
+ result = (char **) malloc ((i + 1) * sizeof (char *));
+ if (result == NULL)
+ return NULL;
+
+ for (i = 0; array[i] != NULL; i++)
+ {
+ result[i] = (char *) malloc (1 + l + add_slash + strlen (array[i]));
+ if (result[i] == NULL)
+ return NULL;
+ strcpy (result[i], dir);
+ if (add_slash)
+ result[i][l] = '/';
+ strcpy (result[i] + l + add_slash, array[i]);
+ }
+ result[i] = NULL;
+
+ /* Free the input array. */
+ for (i = 0; array[i] != NULL; i++)
+ free (array[i]);
+ free ((char *) array);
+ return result;
+}
+
+/* Do globbing on PATHNAME. Return an array of pathnames that match,
+ marking the end of the array with a null-pointer as an element.
+ If no pathnames match, then the array is empty (first element is null).
+ If there isn't enough memory, then return NULL.
+ If a file system error occurs, return -1; `errno' has the error code.
+
+ Wildcards at the beginning of PAT, or following a slash,
+ do not match an initial period if noglob_dot_filenames is nonzero. */
+
+char **
+glob_filename (pathname)
+ char *pathname;
+{
+ char **result;
+ unsigned int result_size;
+ char *directory_name, *filename;
+ unsigned int directory_len;
+
+ result = (char **) malloc (sizeof (char *));
+ result_size = 1;
+ if (result == NULL)
+ return NULL;
+
+ result[0] = NULL;
+
+ /* Find the filename. */
+ filename = rindex (pathname, '/');
+ if (filename == NULL)
+ {
+ filename = pathname;
+ directory_name = "";
+ directory_len = 0;
+ }
+ else
+ {
+ directory_len = (filename - pathname) + 1;
+#ifdef ALLOCA_MISSING
+ directory_name = (char *) malloc (directory_len + 1);
+#else
+ directory_name = (char *) alloca (directory_len + 1);
+#endif
+ bcopy (pathname, directory_name, directory_len);
+ directory_name[directory_len] = '\0';
+ ++filename;
+ }
+
+ /* If directory_name contains globbing characters, then we
+ have to expand the previous levels. Just recurse. */
+ if (glob_pattern_p (directory_name))
+ {
+ char **directories;
+ register unsigned int i;
+
+ if (directory_name[directory_len - 1] == '/')
+ directory_name[directory_len - 1] = '\0';
+
+ directories = glob_filename (directory_name);
+#ifdef ALLOCA_MISSING
+ free ((char *) directory_name);
+#endif
+ if (directories == NULL)
+ goto memory_error;
+ else if (directories == (char **) -1)
+ return (char **) -1;
+ else if (*directories == NULL)
+ {
+ free ((char *) directories);
+ return (char **) -1;
+ }
+
+ /* We have successfully globbed the preceding directory name.
+ For each name in DIRECTORIES, call glob_vector on it and
+ FILENAME. Concatenate the results together. */
+ for (i = 0; directories[i] != NULL; i++)
+ {
+ char **temp_results = glob_vector (filename, directories[i]);
+ if (temp_results == NULL)
+ goto memory_error;
+ else if (temp_results == (char **) -1)
+ /* This filename is probably not a directory. Ignore it. */
+ ;
+ else
+ {
+ char **array = glob_dir_to_array (directories[i], temp_results);
+ register unsigned int l;
+
+ l = 0;
+ while (array[l] != NULL)
+ ++l;
+
+ result = (char **) realloc (result,
+ (result_size + l) * sizeof (char *));
+ if (result == NULL)
+ goto memory_error;
+
+ for (l = 0; array[l] != NULL; ++l)
+ result[result_size++ - 1] = array[l];
+ result[result_size - 1] = NULL;
+ free ((char *) array);
+ }
+ }
+ /* Free the directories. */
+ for (i = 0; directories[i] != NULL; i++)
+ free (directories[i]);
+ free ((char *) directories);
+
+ return result;
+ }
+
+ /* If there is only a directory name, return it. */
+ if (*filename == '\0')
+ {
+ result = (char **) realloc ((char *) result, 2 * sizeof (char *));
+ if (result != NULL)
+ {
+ result[0] = (char *) malloc (directory_len + 1);
+ if (result[0] == NULL)
+ {
+#ifdef ALLOCA_MISSING
+ free ((char *) directory_name);
+#endif
+ goto memory_error;
+ }
+ bcopy (directory_name, result[0], directory_len + 1);
+ result[1] = NULL;
+ }
+#ifdef ALLOCA_MISSING
+ free ((char *) directory_name);
+#endif
+ return result;
+ }
+ else
+ {
+ /* Otherwise, just return what glob_vector
+ returns appended to the directory name. */
+ char **temp_results = glob_vector (filename,
+ (directory_len == 0
+ ? "." : directory_name));
+
+ if (temp_results == NULL || temp_results == (char **) -1)
+ {
+#ifdef NO_ALLOCA
+ free ((char *) directory_name);
+#endif
+ return temp_results;
+ }
+
+ temp_results = glob_dir_to_array (directory_name, temp_results);
+#ifdef NO_ALLOCA
+ free ((char *) directory_name);
+#endif
+ return temp_results;
+ }
+
+ /* We get to memory error if the program has run out of memory, or
+ if this is the shell, and we have been interrupted. */
+ memory_error:
+ if (result != NULL)
+ {
+ register unsigned int i;
+ for (i = 0; result[i] != NULL; ++i)
+ free (result[i]);
+ free ((char *) result);
+ }
+#if defined (SHELL)
+ {
+ extern int interrupt_state;
+
+ if (interrupt_state)
+ throw_to_top_level ();
+ }
+#endif /* SHELL */
+ return NULL;
+}
+
+#ifdef TEST
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char **value;
+ int i, optind;
+
+ for (optind = 1; optind < argc; optind++)
+ {
+ value = glob_filename (argv[optind]);
+ if (value == NULL)
+ puts ("virtual memory exhausted");
+ else if (value == (char **) -1)
+ perror (argv[optind]);
+ else
+ for (i = 0; value[i] != NULL; i++)
+ puts (value[i]);
+ }
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/man/man/man.c b/gnu/usr.bin/man/man/man.c
new file mode 100644
index 0000000..77165d2
--- /dev/null
+++ b/gnu/usr.bin/man/man/man.c
@@ -0,0 +1,1708 @@
+/*
+ * man.c
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#define MAN_MAIN
+
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef __FreeBSD__
+#include <locale.h>
+#include <langinfo.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#if HAVE_LIBZ > 0
+#include <zlib.h>
+#endif
+#include "config.h"
+#include "gripes.h"
+#include "version.h"
+
+#ifdef POSIX
+#include <unistd.h>
+#else
+#ifndef R_OK
+#define R_OK 4
+#endif
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern char *malloc ();
+extern char *getenv ();
+extern void free ();
+extern int system ();
+extern int strcmp ();
+extern int strncmp ();
+extern int exit ();
+extern int fflush ();
+extern int printf ();
+extern int fprintf ();
+extern FILE *fopen ();
+extern int fclose ();
+extern char *sprintf ();
+#endif
+
+extern char **glob_filename ();
+extern int is_newer ();
+extern int is_directory ();
+extern int do_system_command ();
+
+char *prognam;
+static char *pager;
+static char *machine;
+static char *manp;
+static char *manpathlist[MAXDIRS];
+static char *shortsec;
+static char *longsec;
+static char *colon_sep_section_list;
+static char **section_list;
+static char *roff_directive;
+static int apropos;
+static int whatis;
+static int findall;
+static int print_where;
+
+#ifdef __FreeBSD__
+static char *locale, *locale_opts, *locale_nroff, *locale_codeset;
+static char locale_terr[3], locale_lang[3];
+static int use_original;
+struct ltable {
+ char *lcode;
+ char *nroff;
+};
+static struct ltable ltable[] = {
+ {"KOI8-R", "koi8-r"},
+ {"ISO8859-1", "latin1"},
+ {"ISO8859-15", "latin1"},
+ {NULL}
+};
+#endif
+
+static int troff = 0;
+
+int debug;
+
+#ifdef HAS_TROFF
+#ifdef __FreeBSD__
+static char args[] = "M:P:S:adfhkm:op:tw?";
+#else
+static char args[] = "M:P:S:adfhkm:p:tw?";
+#endif
+#else
+#ifdef __FreeBSD__
+static char args[] = "M:P:S:adfhkm:op:w?";
+#else
+static char args[] = "M:P:S:adfhkm:p:w?";
+#endif
+#endif
+
+#ifdef SETUID
+uid_t ruid;
+uid_t euid;
+#endif
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int status = 0;
+ char *nextarg;
+ char *tmp;
+ extern char *mkprogname ();
+ char *is_section ();
+ char **get_section_list ();
+ void man_getopt ();
+ void do_apropos ();
+ void do_whatis ();
+ int man ();
+
+ prognam = mkprogname (argv[0]);
+ longsec = NULL;
+
+ unsetenv("IFS");
+#ifdef __FreeBSD__
+ (void) setlocale(LC_ALL, "");
+#endif
+ man_getopt (argc, argv);
+
+ if (optind == argc)
+ gripe_no_name ((char *)NULL);
+
+ section_list = get_section_list ();
+
+ if (optind == argc - 1)
+ {
+ tmp = is_section (argv[optind], manp);
+
+ if (tmp != NULL)
+ gripe_no_name (tmp);
+ }
+
+#ifdef SETUID
+ ruid = getuid();
+ euid = geteuid();
+ seteuid(ruid);
+#endif
+
+ while (optind < argc)
+ {
+ nextarg = argv[optind++];
+
+ /*
+ * See if this argument is a valid section name. If not,
+ * is_section returns NULL.
+ */
+ tmp = is_section (nextarg, manp);
+
+ if (tmp != NULL)
+ {
+ shortsec = tmp;
+
+ if (debug)
+ fprintf (stderr, "\nsection: %s\n", shortsec);
+
+ continue;
+ }
+
+ if (apropos) {
+ do_apropos (nextarg);
+ status = (status ? 0 : 1); /* reverts status, see below */
+ }
+ else if (whatis) {
+ do_whatis (nextarg);
+ status = (status ? 0 : 1); /* reverts status, see below */
+ }
+ else
+ {
+ status = man (nextarg);
+
+ if (status == 0)
+ gripe_not_found (nextarg, longsec);
+ }
+ }
+ return (status==0); /* status==1 --> exit(0),
+ status==0 --> exit(1) */
+}
+
+void
+usage ()
+{
+ static char usage_string[1024] = "%s, version %s\n\n";
+
+#ifdef HAS_TROFF
+#ifdef __FreeBSD__
+ static char s1[] =
+ "usage: %s [-adfhkotw] [section] [-M path] [-P pager] [-S list]\n\
+ [-m machine] [-p string] name ...\n\n";
+#else
+ static char s1[] =
+ "usage: %s [-adfhktw] [section] [-M path] [-P pager] [-S list]\n\
+ [-m machine] [-p string] name ...\n\n";
+#endif
+#else
+#ifdef __FreeBSD__
+ static char s1[] =
+ "usage: %s [-adfhkow] [section] [-M path] [-P pager] [-S list]\n\
+ [-m machine] [-p string] name ...\n\n";
+#else
+ static char s1[] =
+ "usage: %s [-adfhkw] [section] [-M path] [-P pager] [-S list]\n\
+ [-m machine] [-p string] name ...\n\n";
+#endif
+#endif
+
+static char s2[] = " a : find all matching entries\n\
+ d : print gobs of debugging information\n\
+ f : same as whatis(1)\n\
+ h : print this help message\n\
+ k : same as apropos(1)\n";
+
+#ifdef __FreeBSD__
+ static char s3[] = " o : use original, non-localized manpages\n";
+#endif
+
+#ifdef HAS_TROFF
+ static char s4[] = " t : use troff to format pages for printing\n";
+#endif
+
+ static char s5[] = " w : print location of man page(s) that would be displayed\n\n\
+ M path : set search path for manual pages to `path'\n\
+ P pager : use program `pager' to display pages\n\
+ S list : colon separated section list\n\
+ m machine : search for alternate architecture man pages\n";
+
+ static char s6[] = " p string : string tells which preprocessors to run\n\
+ e - [n]eqn(1) p - pic(1) t - tbl(1)\n\
+ g - grap(1) r - refer(1) v - vgrind(1)\n";
+
+ strcat (usage_string, s1);
+ strcat (usage_string, s2);
+#ifdef __FreeBSD__
+ strcat (usage_string, s3);
+#endif
+
+#ifdef HAS_TROFF
+ strcat (usage_string, s4);
+#endif
+
+ strcat (usage_string, s5);
+
+ strcat (usage_string, s6);
+
+ fprintf (stderr, usage_string, prognam, version, prognam);
+ exit(1);
+}
+
+char **
+add_dir_to_mpath_list (mp, p)
+ char **mp;
+ char *p;
+{
+ int status;
+
+ status = is_directory (p);
+
+ if (status < 0 && debug)
+ {
+ fprintf (stderr, "Warning: couldn't stat file %s!\n", p);
+ }
+ else if (status == 0 && debug)
+ {
+ fprintf (stderr, "Warning: %s isn't a directory!\n", p);
+ }
+ else if (status == 1)
+ {
+ if (debug)
+ fprintf (stderr, "adding %s to manpathlist\n", p);
+
+ *mp++ = strdup (p);
+ }
+ return mp;
+}
+
+/*
+ * Get options from the command line and user environment.
+ */
+void
+man_getopt (argc, argv)
+ register int argc;
+ register char **argv;
+{
+ register int c;
+ register char *p;
+ register char *end;
+ register char **mp;
+ extern void downcase ();
+ extern char *manpath ();
+
+ while ((c = getopt (argc, argv, args)) != EOF)
+ {
+ switch (c)
+ {
+ case 'M':
+ manp = strdup (optarg);
+ break;
+ case 'P':
+ pager = strdup (optarg);
+ if (setenv("PAGER", pager, 1) != 0)
+ (void)fprintf(stderr, "setenv PAGER=%s\n", pager);
+ break;
+ case 'S':
+ colon_sep_section_list = strdup (optarg);
+ break;
+ case 'a':
+ findall++;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'f':
+ if (troff)
+ gripe_incompatible ("-f and -t");
+ if (apropos)
+ gripe_incompatible ("-f and -k");
+ if (print_where)
+ gripe_incompatible ("-f and -w");
+ whatis++;
+ break;
+ case 'k':
+ if (troff)
+ gripe_incompatible ("-k and -t");
+ if (whatis)
+ gripe_incompatible ("-k and -f");
+ if (print_where)
+ gripe_incompatible ("-k and -w");
+ apropos++;
+ break;
+ case 'm':
+ machine = optarg;
+ break;
+#ifdef __FreeBSD__
+ case 'o':
+ use_original++;
+ break;
+#endif
+ case 'p':
+ roff_directive = strdup (optarg);
+ break;
+#ifdef HAS_TROFF
+ case 't':
+ if (apropos)
+ gripe_incompatible ("-t and -k");
+ if (whatis)
+ gripe_incompatible ("-t and -f");
+ if (print_where)
+ gripe_incompatible ("-t and -w");
+ troff++;
+ break;
+#endif
+ case 'w':
+ if (apropos)
+ gripe_incompatible ("-w and -k");
+ if (whatis)
+ gripe_incompatible ("-w and -f");
+ if (troff)
+ gripe_incompatible ("-w and -t");
+ print_where++;
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage();
+ break;
+ }
+ }
+
+#ifdef __FreeBSD__
+ /* "" intentionally used to catch error */
+ if ((locale = setlocale(LC_CTYPE, "")) != NULL)
+ locale_codeset = nl_langinfo(CODESET);
+ if (!use_original && locale != NULL && *locale_codeset != '\0' &&
+ strcmp(locale_codeset, "US-ASCII") != 0
+ ) {
+ char *tmp, *short_locale;
+ struct ltable *pltable;
+
+ *locale_lang = '\0';
+ *locale_terr = '\0';
+
+ if ((short_locale = strdup(locale)) == NULL) {
+ perror ("ctype locale strdup");
+ exit (1);
+ }
+ if ((tmp = strchr(short_locale, '.')) != NULL)
+ *tmp = '\0';
+
+ if (strlen(short_locale) == 2)
+ strcpy(locale_lang, short_locale);
+ else if ((tmp = strchr(short_locale, '_')) == NULL ||
+ tmp != short_locale + 2 ||
+ strlen(tmp + 1) != 2
+ ) {
+ errno = EINVAL;
+ perror ("ctype locale format");
+ locale = NULL;
+ } else {
+ strncpy(locale_terr, short_locale + 3, 2);
+ locale_terr[2] = '\0';
+ strncpy(locale_lang, short_locale, 2);
+ locale_lang[2] = '\0';
+ }
+
+ free(short_locale);
+
+ if (locale != NULL) {
+ for (pltable = ltable; pltable->lcode != NULL; pltable++) {
+ if (strcmp(pltable->lcode, locale_codeset) == 0) {
+ locale_nroff = pltable->nroff;
+ break;
+ }
+ }
+ }
+ } else {
+ if (locale == NULL) {
+ errno = EINVAL;
+ perror ("ctype locale");
+ } else {
+ locale = NULL;
+ if (*locale_codeset == '\0') {
+ errno = EINVAL;
+ perror ("ctype codeset");
+ }
+ }
+ }
+#endif /* __FreeBSD__ */
+
+ if (pager == NULL || *pager == '\0')
+ if ((pager = getenv ("PAGER")) == NULL)
+ pager = strdup (PAGER);
+
+ if (debug)
+ fprintf (stderr, "\nusing %s as pager\n", pager);
+
+ if (machine == NULL && (machine = getenv ("MACHINE")) == NULL)
+ machine = MACHINE;
+
+ if (debug)
+ fprintf (stderr, "\nusing %s architecture\n", machine);
+
+ if (manp == NULL)
+ {
+ if ((manp = manpath (0)) == NULL)
+ gripe_manpath ();
+
+ if (debug)
+ fprintf (stderr,
+ "\nsearch path for pages determined by manpath is\n%s\n\n",
+ manp);
+ }
+
+ /*
+ * Expand the manpath into a list for easier handling.
+ */
+ mp = manpathlist;
+ for (p = manp; ; p = end+1)
+ {
+ if (mp == manpathlist + MAXDIRS - 1) {
+ fprintf (stderr, "Warning: too many directories in manpath, truncated!\n");
+ break;
+ }
+ if ((end = strchr (p, ':')) != NULL)
+ *end = '\0';
+
+ mp = add_dir_to_mpath_list (mp, p);
+ if (end == NULL)
+ break;
+
+ *end = ':';
+ }
+ *mp = NULL;
+}
+
+/*
+ * Check to see if the argument is a valid section number. If the
+ * first character of name is a numeral, or the name matches one of
+ * the sections listed in section_list, we'll assume that it's a section.
+ * The list of sections in config.h simply allows us to specify oddly
+ * named directories like .../man3f. Yuk.
+ */
+char *
+is_section (name, path)
+ char *name;
+ char *path;
+{
+ register char **vs;
+ char *temp, *end, *loc;
+ char **plist;
+ int x;
+
+ for (vs = section_list; *vs != NULL; vs++)
+ if ((strcmp (*vs, name) == 0)
+ || (isdigit ((unsigned char)name[0]) && strlen(name) == 1))
+ return (longsec = strdup(name));
+
+ plist = manpathlist;
+ if (isdigit ((unsigned char)name[0]))
+ {
+ while (*plist != NULL)
+ {
+ asprintf (&temp, "%s/man%c/*", *plist, name[0]);
+ plist++;
+
+ x = 0;
+ vs = glob_filename (temp);
+ if ((int)vs == -1)
+ {
+ free (temp);
+ return NULL;
+ }
+ for ( ; *vs != NULL; vs++)
+ {
+ end = strrchr (*vs, '/');
+ if ((loc = strstr (end, name)) != NULL && loc - end > 2
+ && *(loc-1) == '.'
+ && (*(loc+strlen(name)) == '\0' || *(loc+strlen(name)) == '.'))
+ {
+ x = 1;
+ break;
+ }
+ }
+ free (temp);
+ if (x == 1)
+ {
+ asprintf (&temp, "%c", name[0]);
+ longsec = strdup (name);
+ return (temp);
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Handle the apropos option. Cheat by using another program.
+ */
+void
+do_apropos (name)
+ register char *name;
+{
+ register int len;
+ register char *command;
+
+ len = strlen (APROPOS) + strlen (name) + 4;
+
+ if ((command = (char *) malloc(len)) == NULL)
+ gripe_alloc (len, "command");
+
+ sprintf (command, "%s \"%s\"", APROPOS, name);
+
+ (void) do_system_command (command);
+
+ free (command);
+}
+
+/*
+ * Handle the whatis option. Cheat by using another program.
+ */
+void
+do_whatis (name)
+ register char *name;
+{
+ register int len;
+ register char *command;
+
+ len = strlen (WHATIS) + strlen (name) + 4;
+
+ if ((command = (char *) malloc(len)) == NULL)
+ gripe_alloc (len, "command");
+
+ sprintf (command, "%s \"%s\"", WHATIS, name);
+
+ (void) do_system_command (command);
+
+ free (command);
+}
+
+/*
+ * Change a name of the form ...man/man1/name.1 to ...man/cat1/name.1
+ * or a name of the form ...man/cat1/name.1 to ...man/man1/name.1
+ */
+char *
+convert_name (name, to_cat)
+ register char *name;
+ register int to_cat;
+{
+ register char *to_name;
+ register char *t1;
+ register char *t2 = NULL;
+
+#ifdef DO_COMPRESS
+ if (to_cat)
+ {
+ int olen = strlen(name);
+ int cextlen = strlen(COMPRESS_EXT);
+ int len = olen + cextlen;
+
+ to_name = malloc (len+1);
+ if (to_name == NULL)
+ gripe_alloc (len+1, "to_name");
+ strcpy (to_name, name);
+ olen -= cextlen;
+ /* Avoid tacking it on twice */
+ if (olen >= 1 && strcmp(name + olen, COMPRESS_EXT) != 0)
+ strcat (to_name, COMPRESS_EXT);
+ }
+ else
+ to_name = strdup (name);
+#else
+ to_name = strdup (name);
+#endif
+
+ t1 = strrchr (to_name, '/');
+ if (t1 != NULL)
+ {
+ *t1 = '\0';
+ t2 = strrchr (to_name, '/');
+ *t1 = '/';
+
+ /* Skip architecture part (if present). */
+ if (t2 != NULL && (t1 - t2 < 5 || *(t2 + 1) != 'm' || *(t2 + 3) != 'n'))
+ {
+ t1 = t2;
+ *t1 = '\0';
+ t2 = strrchr (to_name, '/');
+ *t1 = '/';
+ }
+ }
+
+ if (t2 == NULL)
+ gripe_converting_name (name, to_cat);
+
+ if (to_cat)
+ {
+ *(++t2) = 'c';
+ *(t2+2) = 't';
+ }
+ else
+ {
+ *(++t2) = 'm';
+ *(t2+2) = 'n';
+ }
+
+ if (debug)
+ fprintf (stderr, "to_name in convert_name () is: %s\n", to_name);
+
+ return to_name;
+}
+
+/*
+ * Try to find the man page corresponding to the given name. The
+ * reason we do this with globbing is because some systems have man
+ * page directories named man3 which contain files with names like
+ * XtPopup.3Xt. Rather than requiring that this program know about
+ * all those possible names, we simply try to match things like
+ * .../man[sect]/name[sect]*. This is *much* easier.
+ *
+ * Note that globbing is only done when the section is unspecified.
+ */
+char **
+glob_for_file (path, section, longsec, name, cat)
+ char *path;
+ char *section;
+ char *longsec;
+ char *name;
+ int cat;
+{
+ char pathname[FILENAME_MAX];
+ char **gf;
+
+ if (longsec == NULL)
+ longsec = section;
+
+ if (cat)
+ snprintf (pathname, sizeof(pathname), "%s/cat%s/%s.%s*", path, section,
+ name, longsec);
+ else
+ snprintf (pathname, sizeof(pathname), "%s/man%s/%s.%s*", path, section,
+ name, longsec);
+
+ if (debug)
+ fprintf (stderr, "globbing %s\n", pathname);
+
+ gf = glob_filename (pathname);
+
+ if ((gf == (char **) -1 || *gf == NULL) && isdigit ((unsigned char)*section)
+ && strlen (longsec) == 1)
+ {
+ if (cat)
+ snprintf (pathname, sizeof(pathname), "%s/cat%s/%s.%c*", path, section, name, *section);
+ else
+ snprintf (pathname, sizeof(pathname), "%s/man%s/%s.%c*", path, section, name, *section);
+
+ gf = glob_filename (pathname);
+ }
+ if ((gf == (char **) -1 || *gf == NULL) && isdigit ((unsigned char)*section)
+ && strlen (longsec) == 1)
+ {
+ if (cat)
+ snprintf (pathname, sizeof(pathname), "%s/cat%s/%s.0*", path, section, name);
+ else
+ snprintf (pathname, sizeof(pathname), "%s/man%s/%s.0*", path, section, name);
+ if (debug)
+ fprintf (stderr, "globbing %s\n", pathname);
+ gf = glob_filename (pathname);
+ }
+ return gf;
+}
+
+/*
+ * Return an un-globbed name in the same form as if we were doing
+ * globbing.
+ */
+char **
+make_name (path, section, longsec, name, cat)
+ char *path;
+ char *section;
+ char *longsec;
+ char *name;
+ int cat;
+{
+ register int i = 0;
+ static char *names[3];
+ char buf[FILENAME_MAX];
+
+ if (cat)
+ snprintf (buf, sizeof(buf), "%s/cat%s/%s.%s", path, section, name, longsec);
+ else
+ snprintf (buf, sizeof(buf), "%s/man%s/%s.%s", path, section, name, longsec);
+
+ if (access (buf, R_OK) == 0)
+ names[i++] = strdup (buf);
+
+ /*
+ * If we're given a section that looks like `3f', we may want to try
+ * file names like .../man3/foo.3f as well. This seems a bit
+ * kludgey to me, but what the hey...
+ */
+ if (section[1] != '\0')
+ {
+ if (cat)
+ snprintf (buf, sizeof(buf), "%s/cat%c/%s.%s", path, section[0], name, section);
+ else
+ snprintf (buf, sizeof(buf), "%s/man%c/%s.%s", path, section[0], name, section);
+
+ if (access (buf, R_OK) == 0)
+ names[i++] = strdup (buf);
+ }
+
+ names[i] = NULL;
+
+ return &names[0];
+}
+
+char *
+get_expander (file)
+ char *file;
+{
+ char *end = file + (strlen (file) - 1);
+
+ while (end > file && end[-1] != '.')
+ --end;
+ if (end == file)
+ return NULL;
+#ifdef FCAT
+ if (*end == 'F')
+ return FCAT;
+#endif /* FCAT */
+#ifdef YCAT
+ if (*end == 'Y')
+ return YCAT;
+#endif /* YCAT */
+#ifdef ZCAT
+ if (*end == 'Z' || !strcmp(end, "gz"))
+ return ZCAT;
+#endif /* ZCAT */
+ return NULL;
+}
+
+/*
+ * Simply display the preformatted page.
+ */
+int
+display_cat_file (file)
+ register char *file;
+{
+ register int found;
+ char command[FILENAME_MAX];
+
+ found = 0;
+
+ if (access (file, R_OK) == 0)
+ {
+ char *expander = get_expander (file);
+
+ if (expander != NULL)
+ snprintf (command, sizeof(command), "%s %s | %s", expander, file, pager);
+ else
+ snprintf (command, sizeof(command), "%s %s", pager, file);
+
+ found = do_system_command (command);
+ }
+ return found;
+}
+
+/*
+ * Try to find the ultimate source file. If the first line of the
+ * current file is not of the form
+ *
+ * .so man3/printf.3s
+ *
+ * the input file name is returned.
+ */
+char *
+ultimate_source (name, path)
+ char *name;
+ char *path;
+{
+ static char buf[BUFSIZ];
+ static char ult[FILENAME_MAX];
+
+ FILE *fp;
+ char *beg;
+ char *end;
+
+ strncpy (ult, name, sizeof(ult)-1);
+ ult[sizeof(ult)-1] = '\0';
+ strncpy (buf, name, sizeof(buf)-1);
+ ult[sizeof(buf)-1] = '\0';
+
+ next:
+
+ if ((fp = fopen (ult, "r")) == NULL)
+ return ult;
+
+ end = fgets (buf, BUFSIZ, fp);
+ fclose(fp);
+
+ if (!end || strlen (buf) < 5)
+ return ult;
+
+ beg = buf;
+ if (*beg++ == '.' && *beg++ == 's' && *beg++ == 'o')
+ {
+ while ((*beg == ' ' || *beg == '\t') && *beg != '\0')
+ beg++;
+
+ end = beg;
+ while (*end != ' ' && *end != '\t' && *end != '\n' && *end != '\0')
+ end++;
+
+ *end = '\0';
+
+ snprintf(ult, sizeof(ult), "%s/%s", path, beg);
+ snprintf(buf, sizeof(buf), "%s", ult);
+
+ goto next;
+ }
+
+ if (debug)
+ fprintf (stderr, "found ultimate source file %s\n", ult);
+
+ return ult;
+}
+
+void
+add_directive (first, d, file, buf, bufsize)
+ int *first;
+ char *d;
+ char *file;
+ char *buf;
+ int bufsize;
+{
+ if (strcmp (d, "") != 0)
+ {
+ if (*first)
+ {
+ *first = 0;
+ snprintf(buf, bufsize, "%s %s", d, file);
+ }
+ else
+ {
+ strncat (buf, " | ", bufsize-strlen(buf)-1);
+ strncat (buf, d, bufsize-strlen(buf)-1);
+ }
+ }
+}
+
+int
+parse_roff_directive (cp, file, buf, bufsize)
+ char *cp;
+ char *file;
+ char *buf;
+ int bufsize;
+{
+ char c;
+ char *exp;
+ int first = 1;
+ int preproc_found = 0;
+ int use_col = 0;
+
+ if ((exp = get_expander(file)) != NULL)
+ add_directive (&first, exp, file, buf, bufsize);
+
+ while ((c = *cp++) != '\0')
+ {
+ switch (c)
+ {
+ case 'e':
+
+ if (debug)
+ fprintf (stderr, "found eqn(1) directive\n");
+
+ preproc_found++;
+ if (troff)
+ add_directive (&first, EQN, file, buf, bufsize);
+ else {
+#ifdef __FreeBSD__
+ char lbuf[FILENAME_MAX];
+
+ snprintf(lbuf, sizeof(lbuf), "%s -T%s", NEQN,
+ locale_opts == NULL ? "ascii" : locale_opts);
+ add_directive (&first, lbuf, file, buf, bufsize);
+#else
+ add_directive (&first, NEQN, file, buf, bufsize);
+#endif
+ }
+
+ break;
+
+ case 'g':
+
+ if (debug)
+ fprintf (stderr, "found grap(1) directive\n");
+
+ preproc_found++;
+ add_directive (&first, GRAP, file, buf, bufsize);
+
+ break;
+
+ case 'p':
+
+ if (debug)
+ fprintf (stderr, "found pic(1) directive\n");
+
+ preproc_found++;
+ add_directive (&first, PIC, file, buf, bufsize);
+
+ break;
+
+ case 't':
+
+ if (debug)
+ fprintf (stderr, "found tbl(1) directive\n");
+
+ preproc_found++;
+ use_col++;
+ add_directive (&first, TBL, file, buf, bufsize);
+ break;
+
+ case 'v':
+
+ if (debug)
+ fprintf (stderr, "found vgrind(1) directive\n");
+
+ add_directive (&first, VGRIND, file, buf, bufsize);
+ break;
+
+ case 'r':
+
+ if (debug)
+ fprintf (stderr, "found refer(1) directive\n");
+
+ add_directive (&first, REFER, file, buf, bufsize);
+ break;
+
+ case ' ':
+ case '\t':
+ case '\n':
+
+ goto done;
+
+ default:
+
+ return -1;
+ }
+ }
+
+ done:
+
+#ifdef HAS_TROFF
+ if (troff)
+ add_directive (&first, TROFF, file, buf, bufsize);
+ else
+#endif
+ {
+#ifdef __FreeBSD__
+ char lbuf[FILENAME_MAX];
+
+ snprintf(lbuf, sizeof(lbuf), "%s -T%s", NROFF,
+ locale_opts == NULL ? "ascii" : locale_opts);
+ add_directive (&first, lbuf, file, buf, bufsize);
+#else
+ add_directive (&first, NROFF " -Tascii", file, buf, bufsize);
+#endif
+ }
+ if (use_col && !troff)
+ add_directive (&first, COL, file, buf, bufsize);
+
+ if (preproc_found)
+ return 0;
+ else
+ return 1;
+}
+
+char *
+make_roff_command (file)
+ char *file;
+{
+#if HAVE_LIBZ > 0
+ gzFile fp;
+#else
+ FILE *fp;
+#endif
+ char line [BUFSIZ];
+ static char buf [BUFSIZ];
+ int status;
+ char *cp;
+
+ if (roff_directive != NULL)
+ {
+ if (debug)
+ fprintf (stderr, "parsing directive from command line\n");
+
+ status = parse_roff_directive (roff_directive, file, buf, sizeof(buf));
+
+ if (status == 0)
+ return buf;
+
+ if (status == -1)
+ gripe_roff_command_from_command_line (file);
+ }
+
+#if HAVE_LIBZ > 0
+ if ((fp = gzopen (file, "r")) != NULL)
+#else
+ if ((fp = fopen (file, "r")) != NULL)
+#endif
+ {
+ cp = line;
+#if HAVE_LIBZ > 0
+ gzgets (fp, line, BUFSIZ);
+ gzclose(fp);
+#else
+ fgets (line, BUFSIZ, fp);
+ fclose(fp);
+#endif
+ if (*cp++ == '\'' && *cp++ == '\\' && *cp++ == '"' && *cp++ == ' ')
+ {
+ if (debug)
+ fprintf (stderr, "parsing directive from file\n");
+
+ status = parse_roff_directive (cp, file, buf, sizeof(buf));
+
+ if (status == 0)
+ return buf;
+
+ if (status == -1)
+ gripe_roff_command_from_file (file);
+ }
+ }
+ else
+ {
+ /*
+ * Is there really any point in continuing to look for
+ * preprocessor options if we can't even read the man page source?
+ */
+ gripe_reading_man_file (file);
+ return NULL;
+ }
+
+ if ((cp = getenv ("MANROFFSEQ")) != NULL)
+ {
+ if (debug)
+ fprintf (stderr, "parsing directive from environment\n");
+
+ status = parse_roff_directive (cp, file, buf, sizeof(buf));
+
+ if (status == 0)
+ return buf;
+
+ if (status == -1)
+ gripe_roff_command_from_env ();
+ }
+
+ if (debug)
+ fprintf (stderr, "using default preprocessor sequence\n");
+
+ status = parse_roff_directive ("t", file, buf, sizeof(buf));
+ if (status >= 0)
+ return buf;
+ else /* can't happen */
+ return NULL;
+}
+
+sig_t ohup, oint, oquit, oterm;
+static char temp[FILENAME_MAX];
+
+void cleantmp()
+{
+ unlink(temp);
+ exit(1);
+}
+
+void
+set_sigs()
+{
+ ohup = signal(SIGHUP, cleantmp);
+ oint = signal(SIGINT, cleantmp);
+ oquit = signal(SIGQUIT, cleantmp);
+ oterm = signal(SIGTERM, cleantmp);
+}
+
+void
+restore_sigs()
+{
+ signal(SIGHUP, ohup);
+ signal(SIGINT, oint);
+ signal(SIGQUIT, oquit);
+ signal(SIGTERM, oterm);
+}
+
+/*
+ * Try to format the man page and create a new formatted file. Return
+ * 1 for success and 0 for failure.
+ */
+int
+make_cat_file (path, man_file, cat_file, manid)
+ register char *path;
+ register char *man_file;
+ register char *cat_file;
+{
+ int s, f;
+ FILE *fp, *pp;
+ char *roff_command;
+ char command[FILENAME_MAX];
+
+ roff_command = make_roff_command (man_file);
+ if (roff_command == NULL)
+ return 0;
+
+ snprintf(temp, sizeof(temp), "%s.tmpXXXXXX", cat_file);
+ if ((f = mkstemp(temp)) >= 0 && (fp = fdopen(f, "w")) != NULL)
+ {
+ set_sigs();
+
+ if (fchmod (f, CATMODE) < 0) {
+ perror("fchmod");
+ unlink(temp);
+ restore_sigs();
+ fclose(fp);
+ return 0;
+ } else if (debug)
+ fprintf (stderr, "mode of %s is now %o\n", temp, CATMODE);
+
+#ifdef DO_COMPRESS
+ snprintf (command, sizeof(command), "(cd %s ; %s | %s)", path,
+ roff_command, COMPRESSOR);
+#else
+ snprintf (command, sizeof(command), "(cd %s ; %s)", path,
+ roff_command);
+#endif
+ fprintf (stderr, "Formatting page, please wait...");
+ fflush(stderr);
+
+ if (debug)
+ fprintf (stderr, "\ntrying command: %s\n", command);
+ else {
+
+#ifdef SETUID
+ if (manid)
+ seteuid(ruid);
+#endif
+ if ((pp = popen(command, "r")) == NULL) {
+ s = errno;
+ fprintf(stderr, "Failed.\n");
+ errno = s;
+ perror("popen");
+#ifdef SETUID
+ if (manid)
+ seteuid(euid);
+#endif
+ unlink(temp);
+ restore_sigs();
+ fclose(fp);
+ return 0;
+ }
+#ifdef SETUID
+ if (manid)
+ seteuid(euid);
+#endif
+
+ f = 0;
+ while ((s = getc(pp)) != EOF) {
+ putc(s, fp); f++;
+ }
+
+ if (!f || ((s = pclose(pp)) == -1)) {
+ s = errno;
+ fprintf(stderr, "Failed.\n");
+ errno = s;
+ perror("pclose");
+ unlink(temp);
+ restore_sigs();
+ fclose(fp);
+ return 0;
+ }
+
+ if (s != 0) {
+ fprintf(stderr, "Failed.\n");
+ gripe_system_command(s);
+ unlink(temp);
+ restore_sigs();
+ fclose(fp);
+ return 0;
+ }
+ }
+
+ if (debug)
+ unlink(temp);
+ else if (rename(temp, cat_file) == -1) {
+ s = errno;
+ fprintf(stderr,
+ "\nHmm! Can't seem to rename %s to %s, check permissions on man dir!\n",
+ temp, cat_file);
+ errno = s;
+ perror("rename");
+ unlink(temp);
+ restore_sigs();
+ fclose(fp);
+ return 0;
+ }
+ restore_sigs();
+
+ if (fclose(fp)) {
+ s = errno;
+ if (!debug)
+ unlink(cat_file);
+ fprintf(stderr, "Failed.\n");
+ errno = s;
+ perror("fclose");
+ return 0;
+ }
+
+ if (debug) {
+ fprintf(stderr, "No output, debug mode.\n");
+ return 0;
+ }
+
+ fprintf(stderr, "Done.\n");
+
+ return 1;
+ }
+ else
+ {
+ if (f >= 0) {
+ s = errno;
+ unlink(temp);
+ errno = s;
+ }
+ if (debug) {
+ s = errno;
+ fprintf (stderr, "Couldn't open %s for writing.\n", temp);
+ errno = s;
+ }
+ if (f >= 0) {
+ perror("fdopen");
+ close(f);
+ }
+
+ return 0;
+ }
+}
+
+/*
+ * Try to format the man page source and save it, then display it. If
+ * that's not possible, try to format the man page source and display
+ * it directly.
+ *
+ * Note that we've already been handed the name of the ultimate source
+ * file at this point.
+ */
+int
+format_and_display (path, man_file, cat_file)
+ register char *path;
+ register char *man_file;
+ register char *cat_file;
+{
+ int status;
+ register int found;
+ char *roff_command;
+ char command[FILENAME_MAX];
+
+ found = 0;
+
+ if (access (man_file, R_OK) != 0)
+ return 0;
+
+ if (troff)
+ {
+ roff_command = make_roff_command (man_file);
+ if (roff_command == NULL)
+ return 0;
+ else
+ snprintf (command, sizeof(command), "(cd %s ; %s)", path, roff_command);
+
+ found = do_system_command (command);
+ }
+ else
+ {
+ status = is_newer (man_file, cat_file);
+ if (debug)
+ fprintf (stderr, "status from is_newer() = %d\n", status);
+
+ if (status == 1 || status == -2)
+ {
+ /*
+ * Cat file is out of date. Try to format and save it.
+ */
+ if (print_where)
+ {
+ printf ("%s\n", man_file);
+ found++;
+ }
+ else
+ {
+
+#ifdef SETUID
+ seteuid(euid);
+ found = make_cat_file (path, man_file, cat_file, 1);
+ seteuid(ruid);
+
+ if (!found)
+ {
+ /* Try again as real user - see note below.
+ By running with
+ effective group (user) ID == real group (user) ID
+ except for the call above, I believe the problems
+ of reading private man pages is avoided. */
+ found = make_cat_file (path, man_file, cat_file, 0);
+ }
+#else
+ found = make_cat_file (path, man_file, cat_file, 0);
+#endif
+ if (found)
+ {
+ /*
+ * Creating the cat file worked. Now just display it.
+ */
+ (void) display_cat_file (cat_file);
+ }
+ else
+ {
+ /*
+ * Couldn't create cat file. Just format it and
+ * display it through the pager.
+ */
+ roff_command = make_roff_command (man_file);
+ if (roff_command == NULL)
+ return 0;
+ else
+ snprintf (command, sizeof(command), "(cd %s ; %s | %s)", path,
+ roff_command, pager);
+
+ found = do_system_command (command);
+ }
+ }
+ }
+ else if (access (cat_file, R_OK) == 0)
+ {
+ /*
+ * Formatting not necessary. Cat file is newer than source
+ * file, or source file is not present but cat file is.
+ */
+ if (print_where)
+ {
+ printf ("%s (source: %s)\n", cat_file, man_file);
+ found++;
+ }
+ else
+ {
+ found = display_cat_file (cat_file);
+ }
+ }
+ }
+ return found;
+}
+
+/*
+ * See if the preformatted man page or the source exists in the given
+ * section.
+ */
+int
+try_section (path, section, longsec, name, glob)
+ char *path;
+ char *section;
+ char *longsec;
+ char *name;
+ int glob;
+{
+ register int found = 0;
+ register int to_cat;
+ register int cat;
+ register char **names;
+ register char **np;
+ static int arch_search;
+ char buf[FILENAME_MAX];
+
+ if (!arch_search)
+ {
+ snprintf(buf, sizeof(buf), "%s/man%s/%s", path, section, machine);
+ if (is_directory (buf) == 1)
+ {
+ snprintf(buf, sizeof(buf), "%s/%s", machine, name);
+ arch_search++;
+ found = try_section (path, section, longsec, buf, glob);
+ arch_search--;
+ if (found && !findall) /* only do this architecture... */
+ return found;
+ }
+ }
+
+ if (debug)
+ {
+ if (glob)
+ fprintf (stderr, "trying section %s with globbing\n", section);
+ else
+ fprintf (stderr, "trying section %s without globbing\n", section);
+ }
+
+#ifndef NROFF_MISSING
+ /*
+ * Look for man page source files.
+ */
+ cat = 0;
+ if (glob)
+ names = glob_for_file (path, section, longsec, name, cat);
+ else
+ names = make_name (path, section, longsec, name, cat);
+
+ if (names == (char **) -1 || *names == NULL)
+ /*
+ * No files match. See if there's a preformatted page around that
+ * we can display.
+ */
+#endif /* NROFF_MISSING */
+ {
+ if (!troff)
+ {
+ cat = 1;
+ if (glob)
+ names = glob_for_file (path, section, longsec, name, cat);
+ else
+ names = make_name (path, section, longsec, name, cat);
+
+ if (names != (char **) -1 && *names != NULL)
+ {
+ for (np = names; *np != NULL; np++)
+ {
+ if (print_where)
+ {
+ printf ("%s\n", *np);
+ found++;
+ }
+ else
+ {
+ found += display_cat_file (*np);
+ }
+ }
+ }
+ }
+ }
+#ifndef NROFF_MISSING
+ else
+ {
+ for (np = names; *np != NULL; np++)
+ {
+ register char *cat_file = NULL;
+ register char *man_file;
+
+ man_file = ultimate_source (*np, path);
+
+ if (!troff)
+ {
+ to_cat = 1;
+
+ cat_file = convert_name (man_file, to_cat);
+
+ if (debug)
+ fprintf (stderr, "will try to write %s if needed\n", cat_file);
+ }
+
+ found += format_and_display (path, man_file, cat_file);
+ }
+ }
+#endif /* NROFF_MISSING */
+ return found;
+}
+
+/*
+ * Search for manual pages.
+ *
+ * If preformatted manual pages are supported, look for the formatted
+ * file first, then the man page source file. If they both exist and
+ * the man page source file is newer, or only the source file exists,
+ * try to reformat it and write the results in the cat directory. If
+ * it is not possible to write the cat file, simply format and display
+ * the man file.
+ *
+ * If preformatted pages are not supported, or the troff option is
+ * being used, only look for the man page source file.
+ *
+ */
+int
+man (name)
+ char *name;
+{
+ register int found;
+ register int glob;
+ register char **mp;
+ register char **sp;
+#ifdef __FreeBSD__
+ int l_found;
+ char buf[FILENAME_MAX];
+#endif
+
+ found = 0;
+
+ fflush (stdout);
+ if (shortsec != NULL)
+ {
+ for (mp = manpathlist; *mp != NULL; mp++)
+ {
+ if (debug)
+ fprintf (stderr, "\nsearching in %s\n", *mp);
+
+ glob = 1;
+
+#ifdef __FreeBSD__
+ l_found = 0;
+ if (locale != NULL) {
+ locale_opts = locale_nroff;
+ if (*locale_lang != '\0' && *locale_terr != '\0') {
+ snprintf(buf, sizeof(buf), "%s/%s_%s.%s", *mp,
+ locale_lang, locale_terr, locale_codeset);
+ if (is_directory (buf) == 1)
+ l_found = try_section (buf, shortsec, longsec, name, glob);
+ }
+ if (!l_found) {
+ if (*locale_lang != '\0') {
+ snprintf(buf, sizeof(buf), "%s/%s.%s", *mp,
+ locale_lang, locale_codeset);
+ if (is_directory (buf) == 1)
+ l_found = try_section (buf, shortsec, longsec, name, glob);
+ }
+ if (!l_found && strcmp(locale_lang, "en") != 0) {
+ snprintf(buf, sizeof(buf), "%s/en.%s", *mp,
+ locale_codeset);
+ if (is_directory (buf) == 1)
+ l_found = try_section (buf, shortsec, longsec, name, glob);
+ }
+ }
+ locale_opts = NULL;
+ }
+ if (!l_found) {
+#endif
+ found += try_section (*mp, shortsec, longsec, name, glob);
+#ifdef __FreeBSD__
+ } else
+ found += l_found;
+#endif
+
+ if (found && !findall) /* i.e. only do this section... */
+ return found;
+ }
+ }
+ else
+ {
+ for (sp = section_list; *sp != NULL; sp++)
+ {
+ for (mp = manpathlist; *mp != NULL; mp++)
+ {
+ if (debug)
+ fprintf (stderr, "\nsearching in %s\n", *mp);
+
+ glob = 1;
+
+#ifdef __FreeBSD__
+ l_found = 0;
+ if (locale != NULL) {
+ locale_opts = locale_nroff;
+ if (*locale_lang != '\0' && *locale_terr != '\0') {
+ snprintf(buf, sizeof(buf), "%s/%s_%s.%s", *mp,
+ locale_lang, locale_terr, locale_codeset);
+ if (is_directory (buf) == 1)
+ l_found = try_section (buf, *sp, longsec, name, glob);
+ }
+ if (!l_found) {
+ if (*locale_lang != '\0') {
+ snprintf(buf, sizeof(buf), "%s/%s.%s", *mp,
+ locale_lang, locale_codeset);
+ if (is_directory (buf) == 1)
+ l_found = try_section (buf, *sp, longsec, name, glob);
+ }
+ if (!l_found && strcmp(locale_lang, "en") != 0) {
+ snprintf(buf, sizeof(buf), "%s/en.%s", *mp,
+ locale_codeset);
+ if (is_directory (buf) == 1)
+ l_found = try_section (buf, *sp, longsec, name, glob);
+ }
+ }
+ locale_opts = NULL;
+ }
+ if (!l_found) {
+#endif
+ found += try_section (*mp, *sp, longsec, name, glob);
+#ifdef __FreeBSD__
+ } else
+ found += l_found;
+#endif
+
+ if (found && !findall) /* i.e. only do this section... */
+ return found;
+ }
+ }
+ }
+ return found;
+}
+
+char **
+get_section_list ()
+{
+ int i;
+ char *p;
+ char *end;
+#define TMP_SECTION_LIST_SIZE 100
+ static char *tmp_section_list[TMP_SECTION_LIST_SIZE];
+
+ if (colon_sep_section_list == NULL)
+ {
+ if ((p = getenv ("MANSECT")) == NULL)
+ {
+ return std_sections;
+ }
+ else
+ {
+ colon_sep_section_list = strdup (p);
+ }
+ }
+
+ i = 0;
+ for (p = colon_sep_section_list; i < TMP_SECTION_LIST_SIZE ; p = end+1)
+ {
+ if ((end = strchr (p, ':')) != NULL)
+ *end = '\0';
+
+ tmp_section_list[i++] = strdup (p);
+
+ if (end == NULL)
+ break;
+ }
+
+ tmp_section_list [i] = NULL;
+ return tmp_section_list;
+}
diff --git a/gnu/usr.bin/man/man/man.man b/gnu/usr.bin/man/man/man.man
new file mode 100644
index 0000000..7d64b4c
--- /dev/null
+++ b/gnu/usr.bin/man/man/man.man
@@ -0,0 +1,251 @@
+.\" Man page for man
+.\"
+.\" Copyright (c) 1990, 1991, John W. Eaton.
+.\"
+.\" You may distribute under the terms of the GNU General Public
+.\" License as specified in the README file that comes with the man 1.0
+.\" distribution.
+.\"
+.\" John W. Eaton
+.\" jwe@che.utexas.edu
+.\" Department of Chemical Engineering
+.\" The University of Texas at Austin
+.\" Austin, Texas 78712
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 5, 1991
+.Dt MAN 1
+.Os
+.Sh NAME
+.Nm man
+.Nd format and display the on-line manual pages
+.Sh SYNOPSIS
+.Nm
+.Op Fl adfhkotw
+.Op Fl m Ar machine
+.Op Fl p Ar string
+.Op Fl M Ar path
+.Op Fl P Ar pager
+.Op Fl S Ar list
+.Op Ar section
+.Ar name ...
+.Sh DESCRIPTION
+.Nm Man
+formats and displays the on-line manual pages. This version knows
+about the
+.Ev MANPATH
+and
+.Ev PAGER
+environment variables, so you can have
+your own set(s) of personal man pages and choose whatever program you
+like to display the formatted pages. If section is specified,
+.Nm
+only looks in that section of the manual. You may also specify the
+order to search the sections for entries and which preprocessors to
+run on the source files via command line options or environment
+variables. If enabled by the system administrator, formatted man
+pages will also be compressed with the `%compress%' command to save
+space.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl M Ar path
+Specify an alternate manpath.
+By default,
+.Nm
+uses
+.Xr manpath 1
+(which is built into the
+.Nm
+binary)
+to determine the path to search. This option overrides the
+.Ev MANPATH
+environment variable.
+.It Fl P Ar pager
+Specify which pager to use.
+By default,
+.Nm
+uses
+.Nm %pager% .
+This option overrides the
+.Ev PAGER
+environment variable.
+.It Fl S Ar list
+List is a colon separated list of manual sections to search.
+This option overrides the
+.Ev MANSECT
+environment variable.
+.It Fl a
+By default,
+.Nm
+will exit after displaying the first manual page it
+finds. Using this option forces
+.Nm
+to display all the manual pages
+that match
+.Ar name ,
+not just the first.
+.It Fl d
+Don't actually display the man pages, but do print gobs of debugging
+information.
+.It Fl f
+Equivalent to
+.Nm whatis .
+.It Fl h
+Print a help message and exit.
+.It Fl k
+Equivalent to
+.Nm apropos .
+.It Fl m Ar machine
+As some manual pages are intended only for specific architectures,
+.Nm
+searches any subdirectories,
+with the same name as the current architecture,
+in every directory which it searches.
+Machine specific areas are checked before general areas.
+The current machine type may be overridden using this option
+or by setting the environment variable
+.Ev MACHINE
+to the name of a specific architecture.
+This option overrides the
+.Ev MACHINE
+environment variable.
+.It Fl o
+Look for original, non-localized manpages only.
+.Pp
+By default,
+.Nm
+searches for a localized manpage
+in a set of locale subdirectories of each
+.Xr manpath 1
+component.
+.Pp
+Locale name is taken from the first of three environment variables
+with a nonempty value:
+.Ev LC_ALL , LC_CTYPE ,
+or
+.Ev LANG ,
+in the specified order.
+.Pp
+If the value could not be determined, or is not a valid locale name,
+then only non-localized manpage will be looked up.
+.Pp
+Otherwise,
+.Nm
+will search in the following subdirectories, in the order of precedence:
+.Pp
+.Bl -item -offset indent -compact
+.Sm off
+.It
+.Pa <lang> _ <country> . <charset>
+.It
+.Pa <lang> . <charset>
+.It
+.Pa en . <charset>
+.Sm on
+.El
+.Pp
+For example, for
+.Dq de_DE.ISO8859-1
+locale,
+.Nm
+will search in the following subdirectories of the
+.Pa /usr/share/man
+manpath component:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Pa /usr/share/man/de_DE.ISO8859-1
+.It
+.Pa /usr/share/man/de.ISO8859-1
+.It
+.Pa /usr/share/man/en.ISO8859-1
+.El
+.Pp
+Finally,
+if the search of localized manpage fails,
+it will be looked up in the default
+.Pa /usr/share/man
+directory.
+.It Fl p Ar string
+Specify the sequence of preprocessors to run before nroff or troff.
+Not all installations will have a full set of preprocessors.
+Some of the preprocessors and the letters used to designate them are:
+eqn (e), grap (g), pic (p), tbl (t), vgrind (v), refer (r).
+This option overrides the
+.Ev MANROFFSEQ
+environment variable.
+.It Fl t
+Use
+.Nm %troff%
+to format the manual page, passing the output to stdout.
+The output from
+.Nm %troff%
+may need to be passed through some filter or another before being
+printed.
+.It Fl w
+Don't actually display the man pages, but do print the location(s) of
+the files that would be formatted or displayed.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width MANROFFSEQ
+.It Ev LC_ALL , LC_CTYPE , LANG
+These variables specify the preferred language for manual pages.
+(See the
+.Fl o
+option above.)
+.It Ev MACHINE
+If
+.Ev MACHINE
+is set, its value is used to override the current machine type
+when searching machine specific subdirectories.
+.It Ev MANPATH
+If
+.Ev MANPATH
+is set, its value is used as the path to search for manual pages.
+.It Ev MANROFFSEQ
+If
+.Ev MANROFFSEQ
+is set, its value is used to determine the set of preprocessors run
+before running nroff or troff. By default, pages are passed through
+the table preprocessor before nroff.
+.It Ev MANSECT
+If
+.Ev MANSECT
+is set, its value is used to determine which manual sections to search.
+.It Ev PAGER
+If
+.Ev PAGER
+is set, its value is used as the name of the program to use to display
+the man page. By default,
+.Nm %pager%
+is used.
+.El
+.Sh EXAMPLES
+.Pp
+Normally, to look at the relevant manpage information for getopt,
+one would use:
+.Pp
+.Dl man getopt
+.Pp
+However, when referring to a specific section of the manual,
+such as
+.Xr getopt 3 ,
+one would use:
+.Pp
+.Dl man 3 getopt
+.Sh SEE ALSO
+.Xr apropos 1 ,
+.Xr groff 1 ,
+.Xr manpath 1 ,
+.Xr more 1 ,
+.Xr whatis 1 ,
+.Xr man 7 ,
+.Xr mdoc 7
+.Sh BUGS
+The
+.Fl t
+option only works if the
+.Xr troff 1 Ns -like
+program is installed.
diff --git a/gnu/usr.bin/man/man/ndir.h b/gnu/usr.bin/man/man/ndir.h
new file mode 100644
index 0000000..438d5c2
--- /dev/null
+++ b/gnu/usr.bin/man/man/ndir.h
@@ -0,0 +1,51 @@
+/*
+ <dir.h> -- definitions for 4.2BSD-compatible directory access
+
+ last edit: 09-Jul-1983 D A Gwyn
+*/
+
+#ifdef VMS
+#ifndef FAB$C_BID
+#include <fab.h>
+#endif
+#ifndef NAM$C_BID
+#include <nam.h>
+#endif
+#ifndef RMS$_SUC
+#include <rmsdef.h>
+#endif
+#include "dir.h"
+#endif /* VMS */
+
+#define DIRBLKSIZ 512 /* size of directory block */
+#ifdef VMS
+#define MAXNAMLEN (DIR$S_NAME + 7) /* 80 plus room for version #. */
+#define MAXFULLSPEC NAM$C_MAXRSS /* Maximum full spec */
+#else
+#define MAXNAMLEN 15 /* maximum filename length */
+#endif /* VMS */
+ /* NOTE: MAXNAMLEN must be one less than a multiple of 4 */
+
+struct direct /* data from readdir() */
+ {
+ long d_ino; /* inode number of entry */
+ unsigned short d_reclen; /* length of this record */
+ unsigned short d_namlen; /* length of string in d_name */
+ char d_name[MAXNAMLEN+1]; /* name of file */
+ };
+
+typedef struct
+ {
+ int dd_fd; /* file descriptor */
+ int dd_loc; /* offset in block */
+ int dd_size; /* amount of valid data */
+ char dd_buf[DIRBLKSIZ]; /* directory block */
+ } DIR; /* stream data from opendir() */
+
+extern DIR *opendir();
+extern struct direct *readdir();
+extern long telldir();
+extern void seekdir();
+extern void closedir();
+
+#define rewinddir( dirp ) seekdir( dirp, 0L )
diff --git a/gnu/usr.bin/man/man/version.h b/gnu/usr.bin/man/man/version.h
new file mode 100644
index 0000000..2ec5c22
--- /dev/null
+++ b/gnu/usr.bin/man/man/version.h
@@ -0,0 +1,17 @@
+/*
+ * version.h
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ */
+
+static char version[] = "1.1";
diff --git a/gnu/usr.bin/man/manpath/Makefile b/gnu/usr.bin/man/manpath/Makefile
new file mode 100644
index 0000000..b4d04fa
--- /dev/null
+++ b/gnu/usr.bin/man/manpath/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+PROG= manpath
+
+DPADD= ${LIBMAN}
+LDADD= ${LIBMAN}
+
+CFLAGS+= -DMAIN -DSTDC_HEADERS -DPOSIX -DHAS_TROFF -DDO_UNCOMPRESS
+CFLAGS+= -I${.CURDIR}/../lib -I${.OBJDIR}/../lib
+CLEANFILES+= manpath.1
+
+manpath.1: ${.CURDIR}/manpath.man
+ @${ECHO} Making ${.TARGET:T} from ${.ALLSRC:T}; \
+ sed -e 's,%manpath_config_file%,/etc/manpath.config,' \
+ ${.ALLSRC} > ${.TARGET}
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/man/manpath/manpath.c b/gnu/usr.bin/man/manpath/manpath.c
new file mode 100644
index 0000000..c500a55
--- /dev/null
+++ b/gnu/usr.bin/man/manpath/manpath.c
@@ -0,0 +1,599 @@
+/*
+ * manpath.c
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ *
+ * $FreeBSD$
+ */
+
+#define MANPATH_MAIN
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "manpath.h"
+#include "gripes.h"
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern int fprintf ();
+extern int strcmp ();
+extern int strncmp ();
+extern char *memcpy ();
+extern char *getenv();
+extern char *malloc();
+extern void free ();
+extern int exit ();
+#endif
+
+extern char *strdup ();
+extern int is_directory ();
+
+#ifndef MAIN
+extern int debug;
+#endif
+
+#ifdef MAIN
+
+#ifndef STDC_HEADERS
+extern char *strcpy ();
+extern int fflush ();
+#endif
+
+char *prognam;
+int debug;
+int locale;
+char *man_locales;
+
+/*
+ * Examine user's PATH and print a reasonable MANPATH.
+ */
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int quiet;
+ char *mp;
+ extern int getopt ();
+ extern char *mkprogname ();
+ void usage ();
+ char *manpath ();
+
+ quiet = 1;
+
+ prognam = mkprogname (argv[0]);
+
+ while ((c = getopt (argc, argv, "dhLq?")) != EOF)
+ {
+ switch (c)
+ {
+ case 'd':
+ debug++;
+ break;
+ case 'L':
+ locale++;
+ break;
+ case 'q':
+ quiet = 0;
+ break;
+ case '?':
+ case 'h':
+ default:
+ usage();
+ break;
+ }
+ }
+
+ mp = manpath (quiet);
+
+ fprintf (stdout, "%s\n", mp);
+ fflush (stdout);
+
+ return 0;
+}
+
+void
+usage ()
+{
+ fprintf (stderr, "usage: %s [-dLq]\n", prognam);
+ exit (1);
+}
+#endif /* MAIN */
+
+/*
+ * If the environment variable MANPATH is set, return it.
+ * If the environment variable PATH is set and has a nonzero length,
+ * try to determine the corresponding manpath, otherwise, return the
+ * default manpath.
+ *
+ * The manpath.config file is used to map system wide /bin directories
+ * to top level man page directories.
+ *
+ * For directories which are in the user's path but not in the
+ * manpath.config file, see if there is a subdirectory `man' or `MAN'.
+ * If so, add that directory to the path. Example: user has
+ * $HOME/bin in his path and the directory $HOME/bin/man exists -- the
+ * directory $HOME/bin/man will be added to the manpath.
+ *
+ * Also search for a `man' directory next to the directory on the path.
+ * Example: $HOME/bin will look for $HOME/man
+ */
+char *
+manpath (perrs)
+ register int perrs;
+{
+ register int len;
+ register char *manpathlist;
+ register char *path;
+ int get_dirlist ();
+ char *def_path ();
+ char *get_manpath ();
+
+ if (get_dirlist ())
+ gripe_reading_mp_config (config_file);
+
+#ifdef MAIN
+ if (locale)
+ {
+ if ((manpathlist = getenv ("MANLOCALES")) != NULL)
+ /*
+ * This must be it.
+ */
+ {
+ if (perrs)
+ fprintf (stderr, "(Warning: MANLOCALES environment variable set)\n");
+ return strdup (manpathlist);
+ }
+ return (man_locales ? man_locales : "");
+ }
+#endif /* MAIN */
+
+ if ((manpathlist = getenv ("MANPATH")) != NULL)
+ /*
+ * This must be it.
+ */
+ {
+ if (perrs)
+ fprintf (stderr, "(Warning: MANPATH environment variable set)\n");
+ return strdup (manpathlist);
+ }
+ else if ((path = getenv ("PATH")) == NULL)
+ /*
+ * Things aren't going to work well, but hey...
+ */
+ {
+ if (perrs)
+ fprintf (stderr, "Warning: path not set\n");
+ return def_path (perrs);
+ }
+ else
+ {
+ if ((len = strlen (path)) == 0)
+ /*
+ * Things aren't going to work well here either...
+ */
+ {
+ if (perrs)
+ fprintf (stderr, "Warning: path set but has zero length\n");
+ return def_path (perrs);
+ }
+ return get_manpath (perrs, path);
+ }
+}
+
+/*
+ * Get the list of bin directories and the corresponding man
+ * directories from the manpath.config file.
+ *
+ * This is ugly.
+ */
+int
+get_dirlist ()
+{
+ int i;
+ char *bp;
+ char *p;
+ char buf[BUFSIZ];
+ DIRLIST *dlp = list;
+ FILE *config;
+
+ if ((config = fopen (config_file, "r")) == NULL)
+ gripe_getting_mp_config (config_file);
+
+ while ((bp = fgets (buf, BUFSIZ, config)) != NULL)
+ {
+ while (*bp && (*bp == ' ' || *bp == '\t'))
+ bp++;
+
+ if (*bp == '#' || *bp == '\n')
+ continue;
+
+ if (!strncmp ("MANDATORY_MANPATH", bp, 17) ||
+ !strncmp ("OPTIONAL_MANPATH", bp, 16))
+ {
+ if ((p = strchr (bp, ' ')) == NULL &&
+ (p = strchr (bp, '\t')) == NULL) {
+ fclose(config);
+ return -1;
+ }
+
+ dlp->type = *bp == 'M'? MANPATH_MANDATORY: MANPATH_OPTIONAL;
+
+ bp = p;
+
+ while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t'))
+ bp++;
+
+ i = 0;
+ while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t')
+ dlp->mandir[i++] = *bp++;
+ dlp->mandir[i] = '\0';
+
+ if (debug)
+ fprintf (stderr, "found %s man directory %s\n",
+ dlp->type == MANPATH_MANDATORY? "mandatory": "optional",
+ dlp->mandir);
+ }
+ else if (!strncmp ("MANPATH_MAP", bp, 11))
+ {
+ if ((p = strchr (bp, ' ')) == NULL &&
+ (p = strchr (bp, '\t')) == NULL) {
+ fclose(config);
+ return -1;
+ }
+
+ bp = p;
+
+ dlp->type = MANPATH_MAP;
+
+ while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t'))
+ bp++;
+
+ i = 0;
+ while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t')
+ dlp->bin[i++] = *bp++;
+ dlp->bin[i] = '\0';
+
+ while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t'))
+ bp++;
+
+ i = 0;
+ while (*bp && *bp != '\n' && *bp != ' ' && *bp != '\t')
+ dlp->mandir[i++] = *bp++;
+ dlp->mandir[i] = '\0';
+
+ if (debug)
+ fprintf (stderr, "found manpath map %s --> %s\n",
+ dlp->bin, dlp->mandir);
+ }
+ else if (!strncmp ("MANLOCALES", bp, 10))
+ {
+ if ((p = strchr (bp, ' ')) == NULL &&
+ (p = strchr (bp, '\t')) == NULL) {
+ fclose(config);
+ return -1;
+ }
+
+ bp = p;
+
+ while (*bp && *bp != '\n' && (*bp == ' ' || *bp == '\t'))
+ bp++;
+
+ for (p = bp; *p && *p != '\n'; p++)
+ ;
+ do {
+ *p-- = '\0';
+ } while (p >= bp && (*p == ' ' || *p == '\t'));
+
+#ifdef MAIN
+ if (man_locales != NULL)
+ free (man_locales);
+
+ if ((man_locales = strdup (bp)) == NULL) {
+ fclose(config);
+ return -1;
+ }
+#endif /* MAIN */
+
+ if (debug)
+ fprintf (stderr, "found man locales: %s\n", bp);
+ }
+ else
+ {
+ gripe_reading_mp_config (config_file);
+ }
+ dlp++;
+ }
+
+ fclose(config);
+ dlp->bin[0] = '\0';
+ dlp->mandir[0] = '\0';
+ dlp->type = MANPATH_NONE;
+
+ return 0;
+}
+
+/*
+ * Construct the default manpath. This picks up mandatory
+ * and optional (if they exist) manpaths only.
+ */
+char *
+def_path (perrs)
+ int perrs;
+{
+ register int len;
+ register char *manpathlist, *p;
+ register DIRLIST *dlp;
+
+ len = 0;
+ dlp = list;
+ while (dlp->type != MANPATH_NONE) {
+ if (dlp->type == MANPATH_MANDATORY || dlp->type == MANPATH_OPTIONAL)
+ len += strlen (dlp->mandir) + 1;
+ dlp++;
+ }
+
+ manpathlist = (char *) malloc (len);
+ if (manpathlist == NULL)
+ gripe_alloc (len, "manpathlist");
+
+ *manpathlist = '\0';
+
+ dlp = list;
+ p = manpathlist;
+ while (dlp->type != MANPATH_NONE) {
+ if (dlp->type == MANPATH_MANDATORY || dlp->type == MANPATH_OPTIONAL) {
+ int status;
+ char *path = dlp->mandir;
+
+ status = is_directory(path);
+
+ if (status < 0 && perrs && dlp->type == MANPATH_MANDATORY)
+ {
+ fprintf (stderr, "Warning: couldn't stat file %s!\n", path);
+ }
+ else if (status == 0 && perrs)
+ {
+ fprintf (stderr, "Warning: %s isn't a directory!\n", path);
+ }
+ else if (status == 1)
+ {
+ len = strlen (path);
+ memcpy (p, path, len);
+ p += len;
+ *p++ = ':';
+ }
+ }
+ dlp++;
+ }
+
+ p[-1] = '\0';
+
+ return manpathlist;
+}
+
+/*
+ * For each directory in the user's path, see if it is one of the
+ * directories listed in the manpath.config file. If so, and it is
+ * not already in the manpath, add it. If the directory is not listed
+ * in the manpath.config file, see if there is a subdirectory `man' or
+ * `MAN'. If so, and it is not already in the manpath, add it.
+ * Example: user has $HOME/bin in his path and the directory
+ * $HOME/bin/man exists -- the directory $HOME/bin/man will be added
+ * to the manpath.
+ */
+char *
+get_manpath (perrs, path)
+ register int perrs;
+ register char *path;
+{
+ register int len;
+ register char *tmppath;
+ register char *t;
+ register char *p;
+ register char **lp;
+ register char *end;
+ register char *manpathlist;
+ register DIRLIST *dlp;
+ void add_dir_to_list ();
+ char *has_subdirs ();
+
+ tmppath = strdup (path);
+
+ for (p = tmppath; ; p = end+1)
+ {
+ if ((end = strchr(p, ':')) != NULL)
+ *end = '\0';
+
+ if (debug)
+ fprintf (stderr, "\npath directory %s ", p);
+
+ if (*p != '/')
+ {
+ if (debug)
+ fprintf (stderr, "is not an absolute pathname\n");
+
+ goto found; /* skip. */
+ }
+
+ /*
+ * The directory we're working on is in the config file.
+ * If we haven't added it to the list yet, do.
+ */
+ for (dlp = list; dlp->mandir[0] != '\0'; dlp++)
+ if (dlp->bin[0] != '\0' && !strcmp (p, dlp->bin))
+ {
+ if (debug)
+ fprintf (stderr, "is in the config file\n");
+
+ add_dir_to_list (tmplist, dlp->mandir, perrs);
+ goto found;
+ }
+
+ /*
+ * The directory we're working on isn't in the config file. See
+ * if it has man or MAN subdirectories. If so, and it hasn't
+ * been added to the list, do.
+ */
+ if (debug)
+ fprintf (stderr, "is not in the config file\n");
+
+ t = has_subdirs (p);
+ if (t != NULL)
+ {
+ if (debug)
+ fprintf (stderr, "but it does have a man or MAN subdirectory\n");
+
+ add_dir_to_list (tmplist, t, perrs);
+ free (t);
+ }
+ else
+ {
+ if (debug)
+ fprintf (stderr, "and doesn't have man or MAN subdirectories\n");
+ }
+
+ found:
+
+ if (!end)
+ break;
+ }
+
+ if (debug)
+ fprintf (stderr, "\nadding mandatory man directories\n\n");
+
+ dlp = list;
+ while (dlp->type != MANPATH_NONE) {
+ if (dlp->type == MANPATH_MANDATORY || dlp->type == MANPATH_OPTIONAL)
+ add_dir_to_list (tmplist, dlp->mandir,
+ dlp->type == MANPATH_MANDATORY? perrs: 0);
+ dlp++;
+ }
+
+ len = 0;
+ lp = tmplist;
+ while (*lp != NULL)
+ {
+ len += strlen (*lp) + 1;
+ lp++;
+ }
+
+ manpathlist = (char *) malloc (len);
+ if (manpathlist == NULL)
+ gripe_alloc (len, "manpathlist");
+
+ *manpathlist = '\0';
+
+ lp = tmplist;
+ p = manpathlist;
+ while (*lp != NULL)
+ {
+ len = strlen (*lp);
+ memcpy (p, *lp, len);
+ p += len;
+ *p++ = ':';
+ lp++;
+ }
+
+ p[-1] = '\0';
+
+ return manpathlist;
+}
+
+/*
+ * Add a directory to the manpath list if it isn't already there.
+ */
+void
+add_dir_to_list (lp, dir, perrs)
+ char **lp;
+ char *dir;
+ int perrs;
+{
+ extern char *strdup ();
+ int status;
+
+ while (*lp != NULL)
+ {
+ if (!strcmp (*lp, dir))
+ {
+ if (debug)
+ fprintf (stderr, "%s is already in the manpath\n", dir);
+ return;
+ }
+ lp++;
+ }
+ /*
+ * Not found -- add it.
+ */
+ status = is_directory(dir);
+
+ if (status < 0 && perrs)
+ {
+ fprintf (stderr, "Warning: couldn't stat file %s!\n", dir);
+ }
+ else if (status == 0 && perrs)
+ {
+ fprintf (stderr, "Warning: %s isn't a directory!\n", dir);
+ }
+ else if (status == 1)
+ {
+ if (debug)
+ fprintf (stderr, "adding %s to manpath\n", dir);
+
+ *lp = strdup (dir);
+ }
+}
+
+/*
+ * Check to see if the current directory has man or MAN
+ * subdirectories.
+ */
+char *
+has_subdirs (p)
+ register char *p;
+{
+ int len;
+ register char *t;
+
+ len = strlen (p);
+
+ t = (char *) malloc ((unsigned) len + 5);
+ if (t == NULL)
+ gripe_alloc (len+5, "p\n");
+
+ memcpy (t, p, len);
+ strcpy (t + len, "/man");
+
+ if (is_directory (t) == 1)
+ return t;
+
+ strcpy (t + len, "/MAN");
+
+ if (is_directory (t) == 1)
+ return t;
+
+ /* If the path ends in `bin' then replace with `man' and see if that works. */
+ if (len > 3 && strncmp(t+len-4, "/bin", 4) == 0) {
+ strcpy(t+len-4, "/man");
+
+ if (is_directory(t) == 1)
+ return t;
+ }
+
+ return NULL;
+}
diff --git a/gnu/usr.bin/man/manpath/manpath.config b/gnu/usr.bin/man/manpath/manpath.config
new file mode 100644
index 0000000..eea98bf
--- /dev/null
+++ b/gnu/usr.bin/man/manpath/manpath.config
@@ -0,0 +1,29 @@
+# $FreeBSD$
+#
+# This file is read by manpath(1) to configure the mandatory manpath,
+# optional manpath and to map each path element to a manpath element.
+# The format is:
+#
+# MANDATORY_MANPATH manpath_element
+# OPTIONAL_MANPATH manpath_element
+# MANPATH_MAP path_element manpath_element
+# MANLOCALES locale1 locale2 ...
+#
+# every automatically generated MANPATH includes these fields
+#
+MANDATORY_MANPATH /usr/share/man
+#
+# check if the directory exists and if it does, add it to MANPATH
+#
+OPTIONAL_MANPATH /usr/local/lib/perl5/5.6.1/man
+#
+# set up PATH to MANPATH mapping
+#
+MANPATH_MAP /bin /usr/share/man
+MANPATH_MAP /usr/bin /usr/share/man
+MANPATH_MAP /usr/local/bin /usr/local/man
+MANPATH_MAP /usr/X11R6/bin /usr/X11R6/man
+#
+# set man locales, if needed
+#
+#MANLOCALES ru_RU.KOI8-R
diff --git a/gnu/usr.bin/man/manpath/manpath.h b/gnu/usr.bin/man/manpath/manpath.h
new file mode 100644
index 0000000..ab6eb0e
--- /dev/null
+++ b/gnu/usr.bin/man/manpath/manpath.h
@@ -0,0 +1,32 @@
+/*
+ * manpath.h
+ *
+ * Copyright (c) 1990, 1991, John W. Eaton.
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the file COPYING that comes with the man
+ * distribution.
+ *
+ * John W. Eaton
+ * jwe@che.utexas.edu
+ * Department of Chemical Engineering
+ * The University of Texas at Austin
+ * Austin, Texas 78712
+ */
+
+typedef struct
+{
+ char mandir[MAXPATHLEN];
+ char bin[MAXPATHLEN];
+ int type;
+} DIRLIST;
+
+/* manpath types */
+#define MANPATH_NONE 0
+#define MANPATH_MANDATORY 1 /* manpath is mandatory */
+#define MANPATH_OPTIONAL 2 /* manpath is optional */
+#define MANPATH_MAP 3 /* maps path to manpath */
+
+DIRLIST list[MAXDIRS];
+
+char *tmplist[MAXDIRS];
diff --git a/gnu/usr.bin/man/manpath/manpath.man b/gnu/usr.bin/man/manpath/manpath.man
new file mode 100644
index 0000000..8d5a8ab
--- /dev/null
+++ b/gnu/usr.bin/man/manpath/manpath.man
@@ -0,0 +1,97 @@
+.\" Man page for manpath
+.\"
+.\" Copyright (c) 1990, 1991, John W. Eaton.
+.\"
+.\" You may distribute under the terms of the GNU General Public
+.\" License as specified in the README file that comes with the man 1.0
+.\" distribution.
+.\"
+.\" John W. Eaton
+.\" jwe@che.utexas.edu
+.\" Department of Chemical Engineering
+.\" The University of Texas at Austin
+.\" Austin, Texas 78712
+.\"
+.\" $FreeBSD$
+.Dd August 16, 1999
+.Dt MANPATH 1
+.Os
+.Sh NAME
+.Nm manpath
+.Nd determine user's search path for man pages
+.Sh SYNOPSIS
+.Nm
+.Op Fl dLq
+.Sh DESCRIPTION
+.Nm Manpath
+tries to determine the user's manpath from a set of system
+defaults and the user's
+.Ev PATH ,
+echoing the result to the standard output.
+Warnings and errors are written to the standard error.
+If a directory in the user's path is not listed in the
+.Pa %manpath_config_file%
+file,
+.Nm
+looks for the subdirectories
+.Pa man
+or
+.Pa MAN .
+If they exist, they are added to the search path.
+If they do not exist, but the directory ends in
+.Pa /bin ,
+.Nm
+replaces
+.Pa /bin
+with
+.Pa /man
+and checks if that directory exists.
+If it exists, it is added to the search path.
+.Pp
+.Nm Manpath
+is used by
+.Xr man 1
+to determine the search path, so users normally don't need to set the
+.Ev MANPATH
+environment variable directly.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl d
+Output additional debug information.
+.It Fl L
+Output man locales list (if exist).
+.It Fl q
+Operate quietly.
+Only echo the final result.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width MANLOCALES -compact
+.It Ev MANPATH
+If
+.Ev MANPATH
+is set,
+.Nm
+echoes its value on the standard output and issues a warning on the
+standard error.
+.It Ev MANLOCALES
+If
+.Ev MANLOCALES
+is set and
+.Fl L
+option is set,
+.Nm
+echoes its value on the standard output and issues a warning on the
+standard error.
+.El
+.Sh FILES
+.Bl -tag -width %manpath_config_file% -compact
+.It Pa %manpath_config_file%
+System configuration file.
+.El
+.Sh SEE ALSO
+.Xr apropos 1 ,
+.Xr man 1 ,
+.Xr whatis 1
+.Sh BUGS
+None known.
diff --git a/gnu/usr.bin/patch/EXTERN.h b/gnu/usr.bin/patch/EXTERN.h
new file mode 100644
index 0000000..374c94f
--- /dev/null
+++ b/gnu/usr.bin/patch/EXTERN.h
@@ -0,0 +1,21 @@
+/* $FreeBSD$
+ *
+ * $Log: EXTERN.h,v $
+ * Revision 2.0 86/09/17 15:35:37 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+#ifdef EXT
+#undef EXT
+#endif
+#define EXT extern
+
+#ifdef INIT
+#undef INIT
+#endif
+#define INIT(x)
+
+#ifdef DOINIT
+#undef DOINIT
+#endif
diff --git a/gnu/usr.bin/patch/INTERN.h b/gnu/usr.bin/patch/INTERN.h
new file mode 100644
index 0000000..c04e722
--- /dev/null
+++ b/gnu/usr.bin/patch/INTERN.h
@@ -0,0 +1,19 @@
+/* $FreeBSD$
+ *
+ * $Log: INTERN.h,v $
+ * Revision 2.0 86/09/17 15:35:58 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+#ifdef EXT
+#undef EXT
+#endif
+#define EXT
+
+#ifdef INIT
+#undef INIT
+#endif
+#define INIT(x) = x
+
+#define DOINIT
diff --git a/gnu/usr.bin/patch/Makefile b/gnu/usr.bin/patch/Makefile
new file mode 100644
index 0000000..10eeab4
--- /dev/null
+++ b/gnu/usr.bin/patch/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+PROG= patch
+SRCS= backupfile.c getopt.c getopt1.c inp.c patch.c pch.c util.c \
+ version.c
+CFLAGS+=-DHAVE_CONFIG_H
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/patch/backupfile.c b/gnu/usr.bin/patch/backupfile.c
new file mode 100644
index 0000000..d4edebb4
--- /dev/null
+++ b/gnu/usr.bin/patch/backupfile.c
@@ -0,0 +1,390 @@
+/* backupfile.c -- make Emacs style backup file names
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
+ Some algorithms adapted from GNU Emacs.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "config.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include "backupfile.h"
+#ifdef STDC_HEADERS
+#include <string.h>
+#include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+
+#if defined(DIRENT) || defined(_POSIX_VERSION)
+#include <dirent.h>
+#define NLENGTH(direct) (strlen((direct)->d_name))
+#else /* not (DIRENT or _POSIX_VERSION) */
+#define dirent direct
+#define NLENGTH(direct) ((direct)->d_namlen)
+#ifdef SYSNDIR
+#include <sys/ndir.h>
+#endif /* SYSNDIR */
+#ifdef SYSDIR
+#include <sys/dir.h>
+#endif /* SYSDIR */
+#ifdef NDIR
+#include <ndir.h>
+#endif /* NDIR */
+#endif /* DIRENT or _POSIX_VERSION */
+
+#ifndef isascii
+#define ISDIGIT(c) (isdigit ((unsigned char) (c)))
+#else
+#define ISDIGIT(c) (isascii (c) && isdigit (c))
+#endif
+
+#if defined (_POSIX_VERSION)
+/* POSIX does not require that the d_ino field be present, and some
+ systems do not provide it. */
+#define REAL_DIR_ENTRY(dp) 1
+#else
+#define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0)
+#endif
+
+/* Which type of backup file names are generated. */
+enum backup_type backup_type = none;
+
+/* The extension added to file names to produce a simple (as opposed
+ to numbered) backup file name. */
+char *simple_backup_suffix = "~";
+
+int argmatch(char *_arg, char **_optlist);
+const char *basename(const char *_name);
+char *dirname(const char *_path);
+static char *concat(const char *_str1, const char *_str2);
+char *find_backup_file_name(char *_file);
+static char *make_version_name (char *_file, int _version);
+static int max_backup_version(char *_file, char *_dir);
+static int version_number(char *base, char *backup, int base_length);
+void invalid_arg(const char *_kind, char *_value, int _problem);
+
+/* Return NAME with any leading path stripped off. */
+
+const char *
+basename(const char *name)
+{
+ const char *r = name, *p = name;
+
+ while (*p)
+ if (*p++ == '/')
+ r = p;
+ return r;
+}
+
+#ifndef NODIR
+/* Return the name of the new backup file for file FILE,
+ allocated with malloc. Return 0 if out of memory.
+ FILE must not end with a '/' unless it is the root directory.
+ Do not call this function if backup_type == none. */
+
+char *
+find_backup_file_name(char *file)
+{
+ char *dir;
+ char *base_versions;
+ int highest_backup;
+
+ if (backup_type == simple)
+ {
+ char *s = malloc (strlen (file) + strlen (simple_backup_suffix) + 1);
+ strcpy (s, file);
+ addext (s, simple_backup_suffix, '~');
+ return s;
+ }
+ base_versions = concat (basename (file), ".~");
+ if (base_versions == 0)
+ return 0;
+ dir = dirname (file);
+ if (dir == 0)
+ {
+ free (base_versions);
+ return 0;
+ }
+ highest_backup = max_backup_version (base_versions, dir);
+ free (base_versions);
+ free (dir);
+ if (backup_type == numbered_existing && highest_backup == 0)
+ return concat (file, simple_backup_suffix);
+ return make_version_name (file, highest_backup + 1);
+}
+
+/* Return the number of the highest-numbered backup file for file
+ FILE in directory DIR. If there are no numbered backups
+ of FILE in DIR, or an error occurs reading DIR, return 0.
+ FILE should already have ".~" appended to it. */
+
+static int
+max_backup_version(char *file, char *dir)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ int highest_version;
+ int this_version;
+ int file_name_length;
+
+ dirp = opendir (dir);
+ if (!dirp)
+ return 0;
+
+ highest_version = 0;
+ file_name_length = strlen (file);
+
+ while ((dp = readdir (dirp)) != 0)
+ {
+ if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) <= file_name_length)
+ continue;
+
+ this_version = version_number (file, dp->d_name, file_name_length);
+ if (this_version > highest_version)
+ highest_version = this_version;
+ }
+ closedir (dirp);
+ return highest_version;
+}
+
+/* Return a string, allocated with malloc, containing
+ "FILE.~VERSION~". Return 0 if out of memory. */
+
+static char *
+make_version_name(char *file, int version)
+{
+ char *backup_name;
+
+ backup_name = malloc (strlen (file) + 16);
+ if (backup_name == 0)
+ return 0;
+ sprintf (backup_name, "%s.~%d~", file, version);
+ return backup_name;
+}
+
+/* If BACKUP is a numbered backup of BASE, return its version number;
+ otherwise return 0. BASE_LENGTH is the length of BASE.
+ BASE should already have ".~" appended to it. */
+
+static int
+version_number(char *base, char *backup, int base_length)
+{
+ int version;
+ char *p;
+
+ version = 0;
+ if (!strncmp (base, backup, base_length) && ISDIGIT (backup[base_length]))
+ {
+ for (p = &backup[base_length]; ISDIGIT (*p); ++p)
+ version = version * 10 + *p - '0';
+ if (p[0] != '~' || p[1])
+ version = 0;
+ }
+ return version;
+}
+
+/* Return the newly-allocated concatenation of STR1 and STR2.
+ If out of memory, return 0. */
+
+static char *
+concat(const char *str1, const char *str2)
+{
+ char *newstr;
+ char str1_length = strlen (str1);
+
+ newstr = malloc (str1_length + strlen (str2) + 1);
+ if (newstr == 0)
+ return 0;
+ strcpy (newstr, str1);
+ strcpy (newstr + str1_length, str2);
+ return newstr;
+}
+
+/* Return the leading directories part of PATH,
+ allocated with malloc. If out of memory, return 0.
+ Assumes that trailing slashes have already been
+ removed. */
+
+char *
+dirname(const char *path)
+{
+ char *newpath;
+ const char *slash;
+ int length; /* Length of result, not including NUL. */
+
+ slash = basename (path);
+ if (slash == path)
+ {
+ /* File is in the current directory. */
+ path = ".";
+ length = 1;
+ }
+ else
+ {
+ /* Remove any trailing slashes from result. */
+ while (*--slash == '/' && slash > path)
+ ;
+
+ length = slash - path + 1;
+ }
+ newpath = malloc (length + 1);
+ if (newpath == 0)
+ return 0;
+ strncpy (newpath, path, length);
+ newpath[length] = 0;
+ return newpath;
+}
+
+/* If ARG is an unambiguous match for an element of the
+ null-terminated array OPTLIST, return the index in OPTLIST
+ of the matched element, else -1 if it does not match any element
+ or -2 if it is ambiguous (is a prefix of more than one element). */
+
+int
+argmatch(char *arg, char **optlist)
+{
+ int i; /* Temporary index in OPTLIST. */
+ int arglen; /* Length of ARG. */
+ int matchind = -1; /* Index of first nonexact match. */
+ int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
+
+ arglen = strlen (arg);
+
+ /* Test all elements for either exact match or abbreviated matches. */
+ for (i = 0; optlist[i]; i++)
+ {
+ if (!strncmp (optlist[i], arg, arglen))
+ {
+ if (strlen (optlist[i]) == arglen)
+ /* Exact match found. */
+ return i;
+ else if (matchind == -1)
+ /* First nonexact match found. */
+ matchind = i;
+ else
+ /* Second nonexact match found. */
+ ambiguous = 1;
+ }
+ }
+ if (ambiguous)
+ return -2;
+ else
+ return matchind;
+}
+
+/* Error reporting for argmatch.
+ KIND is a description of the type of entity that was being matched.
+ VALUE is the invalid value that was given.
+ PROBLEM is the return value from argmatch. */
+
+void
+invalid_arg(const char *kind, char *value, int problem)
+{
+ fprintf (stderr, "patch: ");
+ if (problem == -1)
+ fprintf (stderr, "invalid");
+ else /* Assume -2. */
+ fprintf (stderr, "ambiguous");
+ fprintf (stderr, " %s `%s'\n", kind, value);
+}
+
+static const char *backup_args[] =
+{
+ "never", "simple", "nil", "existing", "t", "numbered", 0
+};
+
+static enum backup_type backup_types[] =
+{
+ simple, simple, numbered_existing, numbered_existing, numbered, numbered
+};
+
+/* Return the type of backup indicated by VERSION.
+ Unique abbreviations are accepted. */
+
+enum backup_type
+get_version(char *version)
+{
+ int i;
+
+ if (version == 0 || *version == 0)
+ return numbered_existing;
+ i = argmatch (version, backup_args);
+ if (i >= 0)
+ return backup_types[i];
+ invalid_arg ("version control type", version, i);
+ exit (1);
+}
+#endif /* NODIR */
+
+/* Append to FILENAME the extension EXT, unless the result would be too long,
+ in which case just append the character E. */
+
+void
+addext(char *filename, char *ext, int e)
+{
+ char *s = basename (filename);
+ int slen = strlen (s), extlen = strlen (ext);
+ long slen_max = -1;
+
+#if HAVE_PATHCONF && defined (_PC_NAME_MAX)
+#ifndef _POSIX_NAME_MAX
+#define _POSIX_NAME_MAX 14
+#endif
+ if (slen + extlen <= _POSIX_NAME_MAX)
+ /* The file name is so short there's no need to call pathconf. */
+ slen_max = _POSIX_NAME_MAX;
+ else if (s == filename)
+ slen_max = pathconf (".", _PC_NAME_MAX);
+ else
+ {
+ char c = *s;
+ *s = 0;
+ slen_max = pathconf (filename, _PC_NAME_MAX);
+ *s = c;
+ }
+#endif
+ if (slen_max == -1) {
+#ifdef HAVE_LONG_FILE_NAMES
+ slen_max = 255;
+#else
+ slen_max = 14;
+#endif
+ }
+ if (slen + extlen <= slen_max)
+ strcpy (s + slen, ext);
+ else
+ {
+ if (slen_max <= slen) {
+ /* Try to preserve difference between .h .c etc. */
+ if (slen == slen_max && s[slen - 2] == '.')
+ s[slen - 2] = s[slen - 1];
+
+ slen = slen_max - 1;
+ }
+ s[slen] = e;
+ s[slen + 1] = 0;
+ }
+}
diff --git a/gnu/usr.bin/patch/backupfile.h b/gnu/usr.bin/patch/backupfile.h
new file mode 100644
index 0000000..7600714
--- /dev/null
+++ b/gnu/usr.bin/patch/backupfile.h
@@ -0,0 +1,44 @@
+/* backupfile.h -- declarations for making Emacs style backup file names
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+/* When to make backup files. */
+enum backup_type
+{
+ /* Never make backups. */
+ none,
+
+ /* Make simple backups of every file. */
+ simple,
+
+ /* Make numbered backups of files that already have numbered backups,
+ and simple backups of the others. */
+ numbered_existing,
+
+ /* Make numbered backups of every file. */
+ numbered
+};
+
+extern enum backup_type backup_type;
+extern char *simple_backup_suffix;
+
+char *find_backup_file_name (char *_file);
+enum backup_type get_version(char *_version);
+void addext(char *_filename, char *_ext, int _e);
diff --git a/gnu/usr.bin/patch/common.h b/gnu/usr.bin/patch/common.h
new file mode 100644
index 0000000..5267e17
--- /dev/null
+++ b/gnu/usr.bin/patch/common.h
@@ -0,0 +1,190 @@
+/* $FreeBSD$
+ *
+ * $Log: common.h,v $
+ * Revision 2.0.1.2 88/06/22 20:44:53 lwall
+ * patch12: sprintf was declared wrong
+ *
+ * Revision 2.0.1.1 88/06/03 15:01:56 lwall
+ * patch10: support for shorter extensions.
+ *
+ * Revision 2.0 86/09/17 15:36:39 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+#define DEBUGGING
+
+#define VOIDUSED 7
+#include "config.h"
+
+/* shut lint up about the following when return value ignored */
+
+#define Signal (void)signal
+#define Unlink (void)unlink
+#define Lseek (void)lseek
+#define Fseek (void)fseek
+#define Fstat (void)fstat
+#define Pclose (void)pclose
+#define Close (void)close
+#define Fclose (void)fclose
+#define Fflush (void)fflush
+#define Sprintf (void)sprintf
+#define Mktemp (void)mktemp
+#define Strcpy (void)strcpy
+#define Strcat (void)strcat
+
+/* NeXT declares malloc and realloc incompatibly from us in some of
+ these files. Temporarily redefine them to prevent errors. */
+#define malloc system_malloc
+#define realloc system_realloc
+#include <stdio.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <signal.h>
+#undef malloc
+#undef realloc
+
+/* constants */
+
+/* AIX predefines these. */
+#ifdef TRUE
+#undef TRUE
+#endif
+#ifdef FALSE
+#undef FALSE
+#endif
+#define TRUE (1)
+#define FALSE (0)
+
+#define MAXHUNKSIZE 200000 /* is this enough lines? */
+#define INITHUNKMAX 125 /* initial dynamic allocation size */
+#define MAXLINELEN 4096
+#define BUFFERSIZE 4096
+
+#define SCCSPREFIX "s."
+#define GET "get %s"
+#define GET_LOCKED "get -e %s"
+#define SCCSDIFF "get -p %s | diff - %s >/dev/null"
+
+#define RCSSUFFIX ",v"
+#define CHECKOUT "co %s"
+#define CHECKOUT_LOCKED "co -l %s"
+#define RCSDIFF "rcsdiff %s > /dev/null"
+
+/* handy definitions */
+
+#define Null(t) ((t)0)
+#define Nullch Null(char *)
+#define Nullfp Null(FILE *)
+#define Nulline Null(LINENUM)
+
+#define Ctl(ch) ((ch) & 037)
+
+#define strNE(s1,s2) (strcmp(s1, s2))
+#define strEQ(s1,s2) (!strcmp(s1, s2))
+#define strnNE(s1,s2,l) (strncmp(s1, s2, l))
+#define strnEQ(s1,s2,l) (!strncmp(s1, s2, l))
+
+/* typedefs */
+
+typedef char bool;
+typedef long LINENUM; /* must be signed */
+typedef unsigned MEM; /* what to feed malloc */
+
+/* globals */
+
+EXT int Argc; /* guess */
+EXT char **Argv;
+EXT int optind_last; /* for restarting plan_b */
+
+EXT struct stat filestat; /* file statistics area */
+EXT int filemode INIT(0644);
+
+EXT char buf[MAXLINELEN]; /* general purpose buffer */
+EXT FILE *ofp INIT(Nullfp); /* output file pointer */
+EXT FILE *rejfp INIT(Nullfp); /* reject file pointer */
+
+EXT int myuid; /* cache getuid return value */
+
+EXT bool using_plan_a INIT(TRUE); /* try to keep everything in memory */
+EXT bool out_of_mem INIT(FALSE); /* ran out of memory in plan a */
+
+#define MAXFILEC 2
+EXT int filec INIT(0); /* how many file arguments? */
+EXT char *filearg[MAXFILEC];
+EXT bool ok_to_create_file INIT(FALSE);
+EXT char *bestguess INIT(Nullch); /* guess at correct filename */
+
+EXT char *outname INIT(Nullch);
+EXT char rejname[128];
+
+EXT char *origprae INIT(Nullch);
+
+EXT char *TMPOUTNAME;
+EXT char *TMPINNAME;
+EXT char *TMPREJNAME;
+EXT char *TMPPATNAME;
+EXT bool toutkeep INIT(FALSE);
+EXT bool trejkeep INIT(FALSE);
+
+EXT LINENUM last_offset INIT(0);
+#ifdef DEBUGGING
+EXT int debug INIT(0);
+#endif
+EXT LINENUM maxfuzz INIT(2);
+EXT bool force INIT(FALSE);
+EXT bool batch INIT(FALSE);
+EXT bool verbose INIT(TRUE);
+EXT bool reverse INIT(FALSE);
+EXT bool noreverse INIT(FALSE);
+EXT bool skip_rest_of_patch INIT(FALSE);
+EXT int strippath INIT(957);
+EXT bool canonicalize INIT(FALSE);
+
+#define CONTEXT_DIFF 1
+#define NORMAL_DIFF 2
+#define ED_DIFF 3
+#define NEW_CONTEXT_DIFF 4
+#define UNI_DIFF 5
+EXT int diff_type INIT(0);
+
+EXT bool do_defines INIT(FALSE); /* patch using ifdef, ifndef, etc. */
+EXT char if_defined[128]; /* #ifdef xyzzy */
+EXT char not_defined[128]; /* #ifndef xyzzy */
+EXT char else_defined[] INIT("#else\n");/* #else */
+EXT char end_defined[128]; /* #endif xyzzy */
+
+EXT char *revision INIT(Nullch); /* prerequisite revision, if any */
+
+#include <errno.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#else
+extern int errno;
+FILE *popen();
+char *malloc();
+char *realloc();
+long atol();
+char *getenv();
+char *strcpy();
+char *strcat();
+#endif
+char *mktemp(char *);
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#else
+long lseek();
+#endif
+#if defined(_POSIX_VERSION) || defined(HAVE_FCNTL_H)
+#include <fcntl.h>
+#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
diff --git a/gnu/usr.bin/patch/config.h b/gnu/usr.bin/patch/config.h
new file mode 100644
index 0000000..177a8c5
--- /dev/null
+++ b/gnu/usr.bin/patch/config.h
@@ -0,0 +1,81 @@
+/* config.h. Generated automatically by configure. */
+/* Portability variables. -*- C -*- */
+
+/* Define if the system does not support the `const' keyword. */
+/* #undef const */
+
+/* Define if the system supports file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES
+
+/* Define if the system has pathconf(). */
+/* #undef HAVE_PATHCONF */
+
+/* Define if the system has strerror(). */
+#define HAVE_STRERROR 1
+
+/* Define if the system has ANSI C header files and library functions. */
+#define STDC_HEADERS
+
+/* Define if the system uses strchr instead of index
+ and strrchr instead of rindex. */
+#define HAVE_STRING_H 1
+
+#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
+#define index strchr
+#define rindex strrchr
+#endif
+
+/* Define if the system has unistd.h. */
+#define HAVE_UNISTD_H 1
+
+/* Define if the system has fcntl.h. */
+#define HAVE_FCNTL_H 1
+
+/* Define as either int or void -- the type that signal handlers return. */
+#define RETSIGTYPE void
+
+#ifndef RETSIGTYPE
+#define RETSIGTYPE void
+#endif
+
+/* Which directory library header to use. */
+#define DIRENT 1 /* dirent.h */
+/* #undef SYSNDIR */ /* sys/ndir.h */
+/* #undef SYSDIR */ /* sys/dir.h */
+/* #undef NDIR */ /* ndir.h */
+/* #undef NODIR */ /* none -- don't make numbered backup files */
+
+/* Define if the system lets you pass fewer arguments to a function
+ than the function actually accepts (in the absence of a prototype).
+ Defining it makes I/O calls slightly more efficient.
+ You need not bother defining it unless your C preprocessor chokes on
+ multi-line arguments to macros. */
+/* #undef CANVARARG */
+
+/* Define Reg* as either `register' or nothing, depending on whether
+ the C compiler pays attention to this many register declarations.
+ The intent is that you don't have to order your register declarations
+ in the order of importance, so you can freely declare register variables
+ in sub-blocks of code and as function parameters.
+ Do not use Reg<n> more than once per routine.
+
+ These don't really matter a lot, since most modern C compilers ignore
+ register declarations and often do a better job of allocating
+ registers than people do. */
+
+#define Reg1 register
+#define Reg2 register
+#define Reg3 register
+#define Reg4 register
+#define Reg5 register
+#define Reg6 register
+#define Reg7
+#define Reg8
+#define Reg9
+#define Reg10
+#define Reg11
+#define Reg12
+#define Reg13
+#define Reg14
+#define Reg15
+#define Reg16
diff --git a/gnu/usr.bin/patch/getopt.c b/gnu/usr.bin/patch/getopt.c
new file mode 100644
index 0000000..d496ca0
--- /dev/null
+++ b/gnu/usr.bin/patch/getopt.c
@@ -0,0 +1,724 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+/* NOTE!!! AIX requires this to be the first thing in the file.
+ Do not put ANYTHING before it! */
+#if !defined (__GNUC__) && defined (_AIX)
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__))))
+#include <alloca.h>
+#else
+#ifndef _AIX
+char *alloca ();
+#endif
+#endif /* alloca.h */
+#endif /* not __GNUC__ */
+
+#if !__STDC__ && !defined(const) && IN_GCC
+#define const
+#endif
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#undef alloca
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#else /* Not GNU C library. */
+#define __alloca alloca
+#endif /* GNU C library. */
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+ long-named option. Because this is not POSIX.2 compliant, it is
+ being phased out. */
+/* #define GETOPT_COMPAT */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n))
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv(const char *_name);
+
+static char *
+my_index(const char *str, int chr)
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+static void
+my_bcopy (from, to, size)
+ const char *from;
+ char *to;
+ int size;
+{
+ int i;
+ for (i = 0; i < size; i++)
+ to[i] = from[i];
+}
+#endif /* GNU C library. */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange(char **argv)
+{
+ int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
+ char **temp = (char **) __alloca (nonopts_size);
+
+ /* Interchange the two blocks of data in ARGV. */
+
+ my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size);
+ my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt],
+ (optind - last_nonopt) * sizeof (char *));
+ my_bcopy ((char *) temp,
+ (char *) &argv[first_nonopt + optind - last_nonopt],
+ nonopts_size);
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal(int argc, char *const *argv, const char *optstring,
+ const struct option *longopts, int *longind, int long_only)
+{
+ int option_index;
+
+ optarg = 0;
+
+ /* Initialize the internal data when the first call is made.
+ Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ if (optind == 0)
+ {
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (getenv ("POSIXLY_CORRECT") != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+ }
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Now skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* Special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Start decoding its characters. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ if (longopts != NULL
+ && ((argv[optind][0] == '-'
+ && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ ))
+ {
+ const struct option *p;
+ char *s = nextchar;
+ int exact = 0;
+ int ambig = 0;
+ const struct option *pfound = NULL;
+ int indfound;
+
+ while (*s && *s != '=')
+ s++;
+
+ /* Test all options for either exact match or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name;
+ p++, option_index++)
+ if (!strncmp (p->name, nextchar, s - nextchar))
+ {
+ if (s - nextchar == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*s)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = s + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+#if 0
+ if (c < 040 || c >= 0177)
+ fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+ argv[0], c);
+ else
+ fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+#else
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+#endif
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = 0;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+#if 0
+ fprintf (stderr, "%s: option `-%c' requires an argument\n",
+ argv[0], c);
+#else
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+#endif
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt(int argc, char *const *argv, const char *optstring)
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/patch/getopt.h b/gnu/usr.bin/patch/getopt.h
new file mode 100644
index 0000000..e41e1a8
--- /dev/null
+++ b/gnu/usr.bin/patch/getopt.h
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * $FreeBSD$
+ */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt(int _argc, char *const *_argv, const char *_optstring);
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/gnu/usr.bin/patch/getopt1.c b/gnu/usr.bin/patch/getopt1.c
new file mode 100644
index 0000000..a32615c
--- /dev/null
+++ b/gnu/usr.bin/patch/getopt1.c
@@ -0,0 +1,176 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "getopt.h"
+
+#if !__STDC__ && !defined(const) && IN_GCC
+#define const
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/patch/inp.c b/gnu/usr.bin/patch/inp.c
new file mode 100644
index 0000000..d77ef65
--- /dev/null
+++ b/gnu/usr.bin/patch/inp.c
@@ -0,0 +1,397 @@
+/* $FreeBSD$
+ *
+ * $Log: inp.c,v $
+ * Revision 2.0.1.1 88/06/03 15:06:13 lwall
+ * patch10: made a little smarter about sccs files
+ *
+ * Revision 2.0 86/09/17 15:37:02 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "util.h"
+#include "pch.h"
+#include "INTERN.h"
+#include "inp.h"
+
+/* Input-file-with-indexable-lines abstract type. */
+
+static long i_size; /* Size of the input file */
+static char *i_womp; /* Plan a buffer for entire file */
+static char **i_ptr; /* Pointers to lines in i_womp */
+
+static int tifd = -1; /* Plan b virtual string array */
+static char *tibuf[2]; /* Plan b buffers */
+static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
+static LINENUM lines_per_buf; /* How many lines per buffer */
+static int tireclen; /* Length of records in tmp file */
+
+/*
+ * New patch--prepare to edit another file.
+ */
+void
+re_input(void)
+{
+ if (using_plan_a) {
+ i_size = 0;
+#ifndef lint
+ if (i_ptr != Null(char**))
+ free((char *)i_ptr);
+#endif
+ if (i_womp != Nullch)
+ free(i_womp);
+ i_womp = Nullch;
+ i_ptr = Null(char **);
+ } else {
+ using_plan_a = TRUE; /* maybe the next one is smaller */
+ Close(tifd);
+ tifd = -1;
+ free(tibuf[0]);
+ free(tibuf[1]);
+ tibuf[0] = tibuf[1] = Nullch;
+ tiline[0] = tiline[1] = -1;
+ tireclen = 0;
+ }
+}
+
+/*
+ * Constuct the line index, somehow or other.
+ */
+void
+scan_input(char *filename)
+{
+ if (!plan_a(filename))
+ plan_b(filename);
+ if (verbose) {
+ say3("Patching file %s using Plan %s...\n", filename,
+ (using_plan_a ? "A" : "B") );
+ }
+}
+
+/*
+ * Try keeping everything in memory.
+ */
+bool
+plan_a(char *filename)
+{
+ int ifd, statfailed;
+ Reg1 char *s;
+ Reg2 LINENUM iline;
+ char lbuf[MAXLINELEN];
+ int output_elsewhere = strcmp(filename, outname);
+ extern int check_patch;
+
+ statfailed = stat(filename, &filestat);
+ if (statfailed && ok_to_create_file) {
+ if (verbose)
+ say2("(Creating file %s...)\n",filename);
+ if (check_patch)
+ return TRUE;
+ makedirs(filename, TRUE);
+ close(creat(filename, 0666));
+ statfailed = stat(filename, &filestat);
+ }
+ if (statfailed && check_patch) {
+ fatal2("%s not found and in check_patch mode.", filename);
+ }
+ /*
+ * For nonexistent or read-only files, look for RCS or SCCS
+ * versions.
+ */
+ if (statfailed ||
+ (! output_elsewhere &&
+ (/* No one can write to it. */
+ (filestat.st_mode & 0222) == 0 ||
+ /* I can't write to it. */
+ ((filestat.st_mode & 0022) == 0 && filestat.st_uid != myuid)))) {
+ struct stat cstat;
+ char *cs = Nullch;
+ char *filebase;
+ int pathlen;
+
+ filebase = basename(filename);
+ pathlen = filebase - filename;
+
+ /*
+ * Put any leading path into `s'.
+ * Leave room in lbuf for the diff command.
+ */
+ s = lbuf + 20;
+ strncpy(s, filename, pathlen);
+
+#define try(f,a1,a2) (Sprintf(s + pathlen, f, a1, a2), stat(s, &cstat) == 0)
+ if ((try("RCS/%s%s", filebase, RCSSUFFIX) ||
+ try("RCS/%s%s", filebase, "") ||
+ try("%s%s", filebase, RCSSUFFIX)) &&
+ /*
+ * Check that RCS file is not working file.
+ * Some hosts don't report file name length errors.
+ */
+ (statfailed ||
+ ((filestat.st_dev ^ cstat.st_dev) |
+ (filestat.st_ino ^ cstat.st_ino)))) {
+ Sprintf(buf, output_elsewhere?CHECKOUT:CHECKOUT_LOCKED, filename);
+ Sprintf(lbuf, RCSDIFF, filename);
+ cs = "RCS";
+ } else if (try("SCCS/%s%s", SCCSPREFIX, filebase) ||
+ try("%s%s", SCCSPREFIX, filebase)) {
+ Sprintf(buf, output_elsewhere?GET:GET_LOCKED, s);
+ Sprintf(lbuf, SCCSDIFF, s, filename);
+ cs = "SCCS";
+ } else if (statfailed)
+ fatal2("can't find %s\n", filename);
+ /*
+ * else we can't write to it but it's not under a version
+ * control system, so just proceed.
+ */
+ if (cs) {
+ if (!statfailed) {
+ if ((filestat.st_mode & 0222) != 0)
+ /* The owner can write to it. */
+ fatal3(
+"file %s seems to be locked by somebody else under %s\n",
+ filename, cs);
+ /*
+ * It might be checked out unlocked. See if
+ * it's safe to check out the default version
+ * locked.
+ */
+ if (verbose)
+ say3(
+"Comparing file %s to default %s version...\n",
+ filename, cs);
+ if (system(lbuf))
+ fatal3(
+"can't check out file %s: differs from default %s version\n",
+ filename, cs);
+ }
+ if (verbose)
+ say3("Checking out file %s from %s...\n", filename, cs);
+ if (system(buf) || stat(filename, &filestat))
+ fatal3("can't check out file %s from %s\n",
+ filename, cs);
+ }
+ }
+ filemode = filestat.st_mode;
+ if (!S_ISREG(filemode))
+ fatal2("%s is not a normal file--can't patch\n", filename);
+ i_size = filestat.st_size;
+ if (out_of_mem) {
+ set_hunkmax(); /* make sure dynamic arrays are allocated */
+ out_of_mem = FALSE;
+ return FALSE; /* force plan b because plan a bombed */
+ }
+#ifdef lint
+ i_womp = Nullch;
+#else
+ /*
+ * Lint says this may alloc less than i_size,
+ * but that's okay, I think.
+ */
+ i_womp = malloc((MEM)(i_size + 2));
+#endif
+ if (i_womp == Nullch)
+ return FALSE;
+ if ((ifd = open(filename, 0)) < 0)
+ pfatal2("can't open file %s", filename);
+#ifndef lint
+ if (read(ifd, i_womp, (int)i_size) != i_size) {
+ /*
+ * This probably means i_size > 15 or 16 bits worth. At
+ * this point it doesn't matter if i_womp was undersized.
+ */
+ Close(ifd);
+ free(i_womp);
+ return FALSE;
+ }
+#endif
+ Close(ifd);
+ if (i_size && i_womp[i_size - 1] != '\n')
+ i_womp[i_size++] = '\n';
+ i_womp[i_size] = '\0';
+
+ /*
+ * Count the lines in the buffer so we know how many pointers we
+ * need.
+ */
+ iline = 0;
+ for (s = i_womp; *s; s++) {
+ if (*s == '\n')
+ iline++;
+ }
+#ifdef lint
+ i_ptr = Null(char**);
+#else
+ i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
+#endif
+ if (i_ptr == Null(char **)) { /* shucks, it was a near thing */
+ free((char *)i_womp);
+ return FALSE;
+ }
+
+ /* Now scan the buffer and build pointer array. */
+ iline = 1;
+ i_ptr[iline] = i_womp;
+ for (s = i_womp; *s; s++) {
+ if (*s == '\n') {
+ /* These are NOT null terminated. */
+ i_ptr[++iline] = s + 1;
+ }
+ }
+ input_lines = iline - 1;
+
+ /* Now check for revision, if any. */
+ if (revision != Nullch) {
+ if (!rev_in_string(i_womp)) {
+ if (force) {
+ if (verbose)
+ say2(
+"Warning: this file doesn't appear to be the %s version--patching anyway.\n",
+ revision);
+ } else if (batch) {
+ fatal2(
+"this file doesn't appear to be the %s version--aborting.\n", revision);
+ } else {
+ (void) ask2(
+"This file doesn't appear to be the %s version--patch anyway? [n] ",
+ revision);
+ if (*buf != 'y')
+ fatal1("aborted\n");
+ }
+ } else if (verbose)
+ say2("Good. This file appears to be the %s version.\n",
+ revision);
+ }
+
+ return TRUE; /* Plan a will work. */
+}
+
+/*
+ * Keep (virtually) nothing in memory.
+ */
+void
+plan_b(char *filename)
+{
+ Reg3 FILE *ifp;
+ Reg1 int i = 0;
+ Reg2 int maxlen = 1;
+ Reg4 bool found_revision = (revision == Nullch);
+
+ using_plan_a = FALSE;
+ if ((ifp = fopen(filename, "r")) == Nullfp)
+ pfatal2("can't open file %s", filename);
+ if ((tifd = creat(TMPINNAME, 0666)) < 0)
+ pfatal2("can't open file %s", TMPINNAME);
+ while (fgets(buf, sizeof buf, ifp) != Nullch) {
+ if (revision != Nullch && !found_revision && rev_in_string(buf))
+ found_revision = TRUE;
+ if ((i = strlen(buf)) > maxlen)
+ maxlen = i; /* Find longest line. */
+ }
+ if (revision != Nullch) {
+ if (!found_revision) {
+ if (force) {
+ if (verbose)
+ say2(
+"Warning: this file doesn't appear to be the %s version--patching anyway.\n",
+ revision);
+ } else if (batch) {
+ fatal2(
+"this file doesn't appear to be the %s version--aborting.\n", revision);
+ } else {
+ (void) ask2(
+"This file doesn't appear to be the %s version--patch anyway? [n] ",
+ revision);
+ if (*buf != 'y')
+ fatal1("aborted\n");
+ }
+ } else if (verbose)
+ say2("Good. This file appears to be the %s version.\n",
+ revision);
+ }
+ Fseek(ifp, 0L, 0); /* Rewind file. */
+ lines_per_buf = BUFFERSIZE / maxlen;
+ tireclen = maxlen;
+ tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
+ tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
+ if (tibuf[1] == Nullch)
+ fatal1("out of memory\n");
+ for (i = 1; ; i++) {
+ if (! (i % lines_per_buf)) /* New block. */
+ if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
+ pfatal1("can't write temp file");
+ if (fgets(tibuf[0] + maxlen * (i%lines_per_buf),
+ maxlen + 1, ifp) == Nullch) {
+ input_lines = i - 1;
+ if (i % lines_per_buf)
+ if (write(tifd, tibuf[0], BUFFERSIZE) <
+ BUFFERSIZE)
+ pfatal1("can't write temp file");
+ break;
+ }
+ }
+ Fclose(ifp);
+ Close(tifd);
+ if ((tifd = open(TMPINNAME, 0)) < 0) {
+ pfatal2("can't reopen file %s", TMPINNAME);
+ }
+}
+
+/*
+ * Fetch a line from the input file, \n terminated, not necessarily \0.
+ */
+char *
+ifetch(line,whichbuf)
+Reg1 LINENUM line;
+int whichbuf; /* ignored when file in memory */
+{
+ if (line < 1 || line > input_lines)
+ return "";
+ if (using_plan_a)
+ return i_ptr[line];
+ else {
+ LINENUM offline = line % lines_per_buf;
+ LINENUM baseline = line - offline;
+
+ if (tiline[0] == baseline)
+ whichbuf = 0;
+ else if (tiline[1] == baseline)
+ whichbuf = 1;
+ else {
+ tiline[whichbuf] = baseline;
+#ifndef lint /* complains of long accuracy */
+ Lseek(tifd, (long)baseline / lines_per_buf * BUFFERSIZE, 0);
+#endif
+ if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
+ pfatal2("error reading tmp file %s", TMPINNAME);
+ }
+ return tibuf[whichbuf] + (tireclen * offline);
+ }
+}
+
+/*
+ * True if the string argument contains the revision number we want.
+ */
+bool
+rev_in_string(char *string)
+{
+ Reg1 char *s;
+ Reg2 int patlen;
+
+ if (revision == Nullch)
+ return TRUE;
+ patlen = strlen(revision);
+ if (strnEQ(string,revision,patlen) &&
+ isspace((unsigned char)string[patlen]))
+ return TRUE;
+ for (s = string; *s; s++) {
+ if (isspace((unsigned char)*s) &&
+ strnEQ(s + 1, revision, patlen) &&
+ isspace((unsigned char)s[patlen + 1] )) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/gnu/usr.bin/patch/inp.h b/gnu/usr.bin/patch/inp.h
new file mode 100644
index 0000000..f1f0386
--- /dev/null
+++ b/gnu/usr.bin/patch/inp.h
@@ -0,0 +1,18 @@
+/* $FreeBSD$
+ *
+ * $Log: inp.h,v $
+ * Revision 2.0 86/09/17 15:37:25 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+EXT LINENUM input_lines INIT(0); /* how long is input file in lines */
+EXT LINENUM last_frozen_line INIT(0); /* how many input lines have been */
+ /* irretractibly output */
+void re_input(void);
+void scan_input(char *_filename);
+bool plan_a(char *_filename);
+void plan_b(char *_filename);
+bool rev_in_string(char *_string);
+char *ifetch(LINENUM _line, int _whichbuf);
+
diff --git a/gnu/usr.bin/patch/patch.1 b/gnu/usr.bin/patch/patch.1
new file mode 100644
index 0000000..4781369
--- /dev/null
+++ b/gnu/usr.bin/patch/patch.1
@@ -0,0 +1,594 @@
+.\" -*- nroff -*-
+.rn '' }`
+'\" $Header: patch.man,v 2.0.1.2 88/06/22 20:47:18 lwall Locked $
+'\" $FreeBSD$
+'\"
+'\" $Log: patch.man,v $
+'\" Revision 2.0.1.2 88/06/22 20:47:18 lwall
+'\" patch12: now avoids Bell System Logo
+'\"
+'\" Revision 2.0.1.1 88/06/03 15:12:51 lwall
+'\" patch10: -B switch was contributed.
+'\"
+'\" Revision 2.0 86/09/17 15:39:09 lwall
+'\" Baseline for netwide release.
+'\"
+'\" Revision 1.4 86/08/01 19:23:22 lwall
+'\" Documented -v, -p, -F.
+'\" Added notes to patch senders.
+'\"
+'\" Revision 1.3 85/03/26 15:11:06 lwall
+'\" Frozen.
+'\"
+'\" Revision 1.2.1.4 85/03/12 16:14:27 lwall
+'\" Documented -p.
+'\"
+'\" Revision 1.2.1.3 85/03/12 16:09:41 lwall
+'\" Documented -D.
+'\"
+'\" Revision 1.2.1.2 84/12/05 11:06:55 lwall
+'\" Added -l switch, and noted bistability bug.
+'\"
+'\" Revision 1.2.1.1 84/12/04 17:23:39 lwall
+'\" Branch for sdcrdcf changes.
+'\"
+'\" Revision 1.2 84/12/04 17:22:02 lwall
+'\" Baseline version.
+'\"
+.de Sh
+.br
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp
+.if t .sp .5v
+.if n .sp
+..
+'\"
+'\" Set up \*(-- to give an unbreakable dash;
+'\" string Tr holds user defined translation string.
+'\" Bell System Logo is used as a dummy character.
+'\"
+.if !d Tr .ds Tr
+.ie n \{\
+.tr \(*W-\*(Tr
+.ds -- \(*W-
+.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+.ds L" ""
+.ds R" ""
+.ds L' '
+.ds R' '
+'br \}
+.el \{\
+.ds -- \(em\|
+.tr \*(Tr
+.ds L" ``
+.ds R" ''
+.ds L' `
+.ds R' '
+'br\}
+.TH PATCH 1 LOCAL
+.SH NAME
+patch - apply a diff file to an original
+.SH SYNOPSIS
+.B patch
+[options] [origfile [patchfile]] [+ [options] [origfile]]...
+.sp
+but usually just
+.sp
+.B patch
+<patchfile
+.SH DESCRIPTION
+.I Patch
+will take a patch file containing any of the four forms of difference
+listing produced by the
+.I diff
+program and apply those differences to an original file, producing a patched
+version.
+By default, the patched version is put in place of the original, with
+the original file backed up to the same name with the
+extension \*(L".orig\*(R" (\*(L"~\*(R" on systems that do not
+support long file names), or as specified by the
+\fB\-b\fP (\fB\-\-suffix\fP),
+\fB\-B\fP (\fB\-\-prefix\fP),
+or
+\fB\-V\fP (\fB\-\-version\-control\fP)
+options.
+The extension used for making backup files may also be specified in the
+.B SIMPLE_BACKUP_SUFFIX
+environment variable, which is overridden by the above options.
+.PP
+If the backup file already exists,
+.B patch
+creates a new backup file name by changing the first lowercase letter
+in the last component of the file's name into uppercase. If there are
+no more lowercase letters in the name, it removes the first character
+from the name. It repeats this process until it comes up with a
+backup file that does not already exist.
+.PP
+You may also specify where you want the output to go with a
+\fB\-o\fP (\fB\-\-output\fP)
+option; if that file already exists, it is backed up first.
+.PP
+If
+.I patchfile
+is omitted, or is a hyphen, the patch will be read from standard input.
+If a
+\fB\-i\fP
+argument is specified, the filename following it will be used, instead of
+standard input. You may specify only one
+\fB\-i\fP
+directive.
+.PP
+Upon startup, patch will attempt to determine the type of the diff listing,
+unless over-ruled by a
+\fB\-c\fP (\fB\-\-context\fP),
+\fB\-e\fP (\fB\-\-ed\fP),
+\fB\-n\fP (\fB\-\-normal\fP),
+or
+\fB\-u\fP (\fB\-\-unified\fP)
+option.
+Context diffs (old-style, new-style, and unified) and
+normal diffs are applied by the
+.I patch
+program itself, while
+.I ed
+diffs are simply fed to the
+.I ed
+editor via a pipe.
+.PP
+.I Patch
+will try to skip any leading garbage, apply the diff,
+and then skip any trailing garbage.
+Thus you could feed an article or message containing a
+diff listing to
+.IR patch ,
+and it should work.
+If the entire diff is indented by a consistent amount,
+this will be taken into account.
+.PP
+With context diffs, and to a lesser extent with normal diffs,
+.I patch
+can detect when the line numbers mentioned in the patch are incorrect,
+and will attempt to find the correct place to apply each hunk of the patch.
+As a first guess, it takes the line number mentioned for the hunk, plus or
+minus any offset used in applying the previous hunk.
+If that is not the correct place,
+.I patch
+will scan both forwards and backwards for a set of lines matching the context
+given in the hunk.
+First
+.I patch
+looks for a place where all lines of the context match.
+If no such place is found, and it's a context diff, and the maximum fuzz factor
+is set to 1 or more, then another scan takes place ignoring the first and last
+line of context.
+If that fails, and the maximum fuzz factor is set to 2 or more,
+the first two and last two lines of context are ignored,
+and another scan is made.
+(The default maximum fuzz factor is 2.)
+If
+.I patch
+cannot find a place to install that hunk of the patch, it will put the
+hunk out to a reject file, which normally is the name of the output file
+plus \*(L".rej\*(R" (\*(L"#\*(R" on systems that do not support
+long file names).
+(Note that the rejected hunk will come out in context diff form whether the
+input patch was a context diff or a normal diff.
+If the input was a normal diff, many of the contexts will simply be null.)
+The line numbers on the hunks in the reject file may be different than
+in the patch file: they reflect the approximate location patch thinks the
+failed hunks belong in the new file rather than the old one.
+.PP
+As each hunk is completed, you will be told whether the hunk succeeded or
+failed, and which line (in the new file)
+.I patch
+thought the hunk should go on.
+If this is different from the line number specified in the diff you will
+be told the offset.
+A single large offset MAY be an indication that a hunk was installed in the
+wrong place.
+You will also be told if a fuzz factor was used to make the match, in which
+case you should also be slightly suspicious.
+.PP
+If no original file is specified on the command line,
+.I patch
+will try to figure out from the leading garbage what the name of the file
+to edit is.
+In the header of a context diff, the file name is found from lines beginning
+with \*(L"***\*(R" or \*(L"---\*(R", with the shortest name of an existing
+file winning.
+Only context diffs have lines like that, but if there is an \*(L"Index:\*(R"
+line in the leading garbage,
+.I patch
+will try to use the file name from that line.
+The context diff header takes precedence over an Index line.
+If no file name can be intuited from the leading garbage, you will be asked
+for the name of the file to patch.
+.PP
+If the original file cannot be found or is read-only, but a suitable
+SCCS or RCS file is handy,
+.I patch
+will attempt to get or check out the file.
+.PP
+Additionally, if the leading garbage contains a \*(L"Prereq: \*(R" line,
+.I patch
+will take the first word from the prerequisites line (normally a version
+number) and check the input file to see if that word can be found.
+If not,
+.I patch
+will ask for confirmation before proceeding.
+.PP
+The upshot of all this is that you should be able to say, while in a news
+interface, the following:
+.Sp
+ | patch -d /usr/src/local/blurfl
+.Sp
+and patch a file in the blurfl directory directly from the article containing
+the patch.
+.PP
+If the patch file contains more than one patch,
+.I patch
+will try to apply each of them as if they came from separate patch files.
+This means, among other things, that it is assumed that the name of the file
+to patch must be determined for each diff listing,
+and that the garbage before each diff listing will
+be examined for interesting things such as file names and revision level, as
+mentioned previously.
+You can give options (and another original file name) for the second and
+subsequent patches by separating the corresponding argument lists
+by a \*(L'+\*(R'.
+(The argument list for a second or subsequent patch may not specify a new
+patch file, however.)
+.PP
+.I Patch
+recognizes the following options:
+.TP 5
+.B "\-b suff, \-\-suffix=suff"
+causes
+.B suff
+to be interpreted as the backup extension, to be
+used in place of \*(L".orig\*(R" or \*(L"~\*(R".
+.TP 5
+.B "\-B pref, \-\-prefix=pref"
+causes
+.B pref
+to be interpreted as a prefix to the backup file
+name. If this argument is specified, any argument from
+.B \-b
+will be ignored.
+.TP 5
+.B "\-c, \-\-context"
+forces
+.I patch
+to interpret the patch file as a context diff.
+.TP 5
+.B "\-C, \-\-check"
+see what would happen, but don't do it.
+.TP 5
+.B "\-d dir, \-\-directory=dir"
+causes
+.I patch
+to interpret
+.B dir
+as a directory, and cd to it before doing
+anything else.
+.TP 5
+.B "\-D sym, \-\-ifdef=sym"
+causes
+.I patch
+to use the "#ifdef...#endif" construct to mark changes.
+.B sym
+will be used as the differentiating symbol.
+.TP 5
+.B "\-e, \-\-ed"
+forces
+.I patch
+to interpret the patch file as an
+.I ed
+script.
+.TP 5
+.B "\-E, \-\-remove\-empty\-files"
+causes
+.I patch
+to remove output files that are empty after the patches have been applied.
+.TP 5
+.B "\-f, \-\-force"
+forces
+.I patch
+to assume that the user knows exactly what he or she is doing, and to not
+ask any questions. It assumes the following: skip patches for which a
+file to patch can't be found; patch files even though they have the
+wrong version for the ``Prereq:'' line in the patch; and assume that
+patches are not reversed even if they look like they are.
+This option does not suppress commentary; use
+.B \-s
+for that.
+.TP 5
+.B "\-t, \-\-batch"
+similar to
+.BR \-f ,
+in that it suppresses questions, but makes some different assumptions:
+skip patches for which a file to patch can't be found (the same as \fB\-f\fP);
+skip patches for which the file has the wrong version for the ``Prereq:'' line
+in the patch; and assume that patches are reversed if they look like
+they are.
+.TP 5
+.B "\-F number, \-\-fuzz=number"
+sets the maximum fuzz factor.
+This option only applies to context diffs, and causes
+.I patch
+to ignore up to that many lines in looking for places to install a hunk.
+Note that a larger fuzz factor increases the odds of a faulty patch.
+The default fuzz factor is 2, and it may not be set to more than
+the number of lines of context in the context diff, ordinarily 3.
+.TP 5
+.B "\-i patchfile"
+tells
+.I patch
+to apply \fBpatchfile\fP instead of stdin.
+.TP 5
+.B "\-I, \-\-index-first"
+forces
+.I patch
+to take ``Index:'' line precedence over context diff header.
+The same effect have
+.B PATCH_INDEX_FIRST
+environment variable if present.
+.TP 5
+.B "\-l, \-\-ignore\-whitespace"
+causes the pattern matching to be done loosely, in case the tabs and
+spaces have been munged in your input file.
+Any sequence of whitespace in the pattern line will match any sequence
+in the input file.
+Normal characters must still match exactly.
+Each line of the context must still match a line in the input file.
+.TP 5
+.B "\-n, \-\-normal"
+forces
+.I patch
+to interpret the patch file as a normal diff.
+.TP 5
+.B "\-N, \-\-forward"
+causes
+.I patch
+to ignore patches that it thinks are reversed or already applied.
+See also
+.B \-R .
+.TP 5
+.B "\-o file, \-\-output=file"
+causes
+.B file
+to be interpreted as the output file name.
+.TP 5
+.B "\-p[number], \-\-strip[=number]"
+sets the pathname strip count,
+which controls how pathnames found in the patch file are treated, in case
+the you keep your files in a different directory than the person who sent
+out the patch.
+The strip count specifies how many slashes are to be stripped from
+the front of the pathname.
+(Any intervening directory names also go away.)
+For example, supposing the file name in the patch file was
+.sp
+ /u/howard/src/blurfl/blurfl.c
+.sp
+setting
+.B \-p
+or
+.B \-p0
+gives the entire pathname unmodified,
+.B \-p1
+gives
+.sp
+ u/howard/src/blurfl/blurfl.c
+.sp
+without the leading slash,
+.B \-p4
+gives
+.sp
+ blurfl/blurfl.c
+.sp
+and not specifying
+.B \-p
+at all just gives you "blurfl.c", unless all of the directories in the
+leading path (u/howard/src/blurfl) exist and that path is relative,
+in which case you get the entire pathname unmodified.
+Whatever you end up with is looked for either in the current directory,
+or the directory specified by the
+.B \-d
+option.
+.TP 5
+.B "\-r file, \-\-reject\-file=file"
+causes
+.B file
+to be interpreted as the reject file name.
+.TP 5
+.B "\-R, \-\-reverse"
+tells
+.I patch
+that this patch was created with the old and new files swapped.
+(Yes, I'm afraid that does happen occasionally, human nature being what it
+is.)
+.I Patch
+will attempt to swap each hunk around before applying it.
+Rejects will come out in the swapped format.
+The
+.B \-R
+option will not work with
+.I ed
+diff scripts because there is too little
+information to reconstruct the reverse operation.
+.Sp
+If the first hunk of a patch fails,
+.I patch
+will reverse the hunk to see if it can be applied that way.
+If it can, you will be asked if you want to have the
+.B \-R
+option set.
+If it can't, the patch will continue to be applied normally.
+(Note: this method cannot detect a reversed patch if it is a normal diff
+and if the first command is an append (i.e. it should have been a delete)
+since appends always succeed, due to the fact that a null context will match
+anywhere.
+Luckily, most patches add or change lines rather than delete them, so most
+reversed normal diffs will begin with a delete, which will fail, triggering
+the heuristic.)
+.TP 5
+.B "\-s, \-\-silent, \-\-quiet"
+makes
+.I patch
+do its work silently, unless an error occurs.
+.TP 5
+.B "\-S, \-\-skip"
+causes
+.I patch
+to ignore this patch from the patch file, but continue on looking
+for the next patch in the file.
+Thus
+.sp
+ patch -S + -S + <patchfile
+.sp
+will ignore the first and second of three patches.
+.TP 5
+.B "\-u, \-\-unified"
+forces
+.I patch
+to interpret the patch file as a unified context diff (a unidiff).
+.TP 5
+.B "\-v, \-\-version"
+causes
+.I patch
+to print out its revision header and patch level.
+.TP 5
+.B "\-V method, \-\-version\-control=method"
+causes
+.B method
+to be interpreted as a method for creating
+backup file names. The type of backups made can also be given in the
+.B VERSION_CONTROL
+environment variable, which is overridden by this option.
+The
+.B -B
+option overrides this option, causing the prefix to always be used for
+making backup file names.
+The value of the
+.B VERSION_CONTROL
+environment variable and the argument to the
+.B -V
+option are like the GNU
+Emacs `version-control' variable; they also recognize synonyms that
+are more descriptive. The valid values are (unique abbreviations are
+accepted):
+.RS
+.TP
+`t' or `numbered'
+Always make numbered backups.
+.TP
+`nil' or `existing'
+Make numbered backups of files that already
+have them, simple backups of the others.
+This is the default.
+.TP
+`never' or `simple'
+Always make simple backups.
+.RE
+.TP 5
+.B "\-x number, \-\-debug=number"
+sets internal debugging flags, and is of interest only to
+.I patch
+patchers.
+.SH AUTHOR
+Larry Wall <lwall@netlabs.com>
+.br
+with many other contributors.
+.SH ENVIRONMENT
+.TP
+.B TMPDIR
+Directory to put temporary files in; default is /tmp.
+.TP
+.B SIMPLE_BACKUP_SUFFIX
+Extension to use for backup file names instead of \*(L".orig\*(R" or
+\*(L"~\*(R".
+.TP
+.B VERSION_CONTROL
+Selects when numbered backup files are made.
+.SH FILES
+$TMPDIR/patch*
+.SH SEE ALSO
+diff(1)
+.SH NOTES FOR PATCH SENDERS
+There are several things you should bear in mind if you are going to
+be sending out patches.
+First, you can save people a lot of grief by keeping a patchlevel.h file
+which is patched to increment the patch level as the first diff in the
+patch file you send out.
+If you put a Prereq: line in with the patch, it won't let them apply
+patches out of order without some warning.
+Second, make sure you've specified the file names right, either in a
+context diff header, or with an Index: line.
+If you are patching something in a subdirectory, be sure to tell the patch
+user to specify a
+.B \-p
+option as needed.
+Third, you can create a file by sending out a diff that compares a
+null file to the file you want to create.
+This will only work if the file you want to create doesn't exist already in
+the target directory.
+Fourth, take care not to send out reversed patches, since it makes people wonder
+whether they already applied the patch.
+Fifth, while you may be able to get away with putting 582 diff listings into
+one file, it is probably wiser to group related patches into separate files in
+case something goes haywire.
+.SH DIAGNOSTICS
+Too many to list here, but generally indicative that
+.I patch
+couldn't parse your patch file.
+.PP
+The message \*(L"Hmm...\*(R" indicates that there is unprocessed text in
+the patch file and that
+.I patch
+is attempting to intuit whether there is a patch in that text and, if so,
+what kind of patch it is.
+.PP
+.I Patch
+will exit with a non-zero status if any reject files were created.
+When applying a set of patches in a loop it behooves you to check this
+exit status so you don't apply a later patch to a partially patched file.
+.SH CAVEATS
+.I Patch
+cannot tell if the line numbers are off in an
+.I ed
+script, and can only detect
+bad line numbers in a normal diff when it finds a \*(L"change\*(R" or
+a \*(L"delete\*(R" command.
+A context diff using fuzz factor 3 may have the same problem.
+Until a suitable interactive interface is added, you should probably do
+a context diff in these cases to see if the changes made sense.
+Of course, compiling without errors is a pretty good indication that the patch
+worked, but not always.
+.PP
+.I Patch
+usually produces the correct results, even when it has to do a lot of
+guessing.
+However, the results are guaranteed to be correct only when the patch is
+applied to exactly the same version of the file that the patch was
+generated from.
+.SH BUGS
+Could be smarter about partial matches, excessively \&deviant offsets and
+swapped code, but that would take an extra pass.
+.PP
+If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
+#endif),
+.I patch
+is incapable of patching both versions, and, if it works at all, will likely
+patch the wrong one, and tell you that it succeeded to boot.
+.PP
+If you apply a patch you've already applied,
+.I patch
+will think it is a reversed patch, and offer to un-apply the patch.
+This could be construed as a feature.
+.rn }` ''
diff --git a/gnu/usr.bin/patch/patch.c b/gnu/usr.bin/patch/patch.c
new file mode 100644
index 0000000..df64421
--- /dev/null
+++ b/gnu/usr.bin/patch/patch.c
@@ -0,0 +1,965 @@
+char rcsid[] =
+ "$FreeBSD$";
+
+/* patch - a program to apply diffs to original files
+ *
+ * Copyright 1986, Larry Wall
+ *
+ * This program may be copied as long as you don't try to make any
+ * money off of it, or pretend that you wrote it.
+ *
+ * $Log: patch.c,v $
+ * Revision 2.0.2.0 90/05/01 22:17:50 davison
+ * patch12u: unidiff support added
+ *
+ * Revision 2.0.1.6 88/06/22 20:46:39 lwall
+ * patch12: rindex() wasn't declared
+ *
+ * Revision 2.0.1.5 88/06/03 15:09:37 lwall
+ * patch10: exit code improved.
+ * patch10: better support for non-flexfilenames.
+ *
+ * Revision 2.0.1.4 87/02/16 14:00:04 lwall
+ * Short replacement caused spurious "Out of sync" message.
+ *
+ * Revision 2.0.1.3 87/01/30 22:45:50 lwall
+ * Improved diagnostic on sync error.
+ * Moved do_ed_script() to pch.c.
+ *
+ * Revision 2.0.1.2 86/11/21 09:39:15 lwall
+ * Fuzz factor caused offset of installed lines.
+ *
+ * Revision 2.0.1.1 86/10/29 13:10:22 lwall
+ * Backwards search could terminate prematurely.
+ *
+ * Revision 2.0 86/09/17 15:37:32 lwall
+ * Baseline for netwide release.
+ *
+ * Revision 1.5 86/08/01 20:53:24 lwall
+ * Changed some %d's to %ld's.
+ * Linted.
+ *
+ * Revision 1.4 86/08/01 19:17:29 lwall
+ * Fixes for machines that can't vararg.
+ * Added fuzz factor.
+ * Generalized -p.
+ * General cleanup.
+ *
+ * 85/08/15 van%ucbmonet@berkeley
+ * Changes for 4.3bsd diff -c.
+ *
+ * Revision 1.3 85/03/26 15:07:43 lwall
+ * Frozen.
+ *
+ * Revision 1.2.1.9 85/03/12 17:03:35 lwall
+ * Changed pfp->_file to fileno(pfp).
+ *
+ * Revision 1.2.1.8 85/03/12 16:30:43 lwall
+ * Check i_ptr and i_womp to make sure they aren't null before freeing.
+ * Also allow ed output to be suppressed.
+ *
+ * Revision 1.2.1.7 85/03/12 15:56:13 lwall
+ * Added -p option from jromine@uci-750a.
+ *
+ * Revision 1.2.1.6 85/03/12 12:12:51 lwall
+ * Now checks for normalness of file to patch.
+ *
+ * Revision 1.2.1.5 85/03/12 11:52:12 lwall
+ * Added -D (#ifdef) option from joe@fluke.
+ *
+ * Revision 1.2.1.4 84/12/06 11:14:15 lwall
+ * Made smarter about SCCS subdirectories.
+ *
+ * Revision 1.2.1.3 84/12/05 11:18:43 lwall
+ * Added -l switch to do loose string comparison.
+ *
+ * Revision 1.2.1.2 84/12/04 09:47:13 lwall
+ * Failed hunk count not reset on multiple patch file.
+ *
+ * Revision 1.2.1.1 84/12/04 09:42:37 lwall
+ * Branch for sdcrdcf changes.
+ *
+ * Revision 1.2 84/11/29 13:29:51 lwall
+ * Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed
+ * multiple calls to mktemp(). Will now work on machines that can only
+ * read 32767 chars. Added -R option for diffs with new and old swapped.
+ * Various cosmetic changes.
+ *
+ * Revision 1.1 84/11/09 17:03:58 lwall
+ * Initial revision
+ *
+ */
+
+#include "INTERN.h"
+#include "common.h"
+#include "EXTERN.h"
+#include "version.h"
+#include "util.h"
+#include "pch.h"
+#include "inp.h"
+#include "backupfile.h"
+#include "getopt.h"
+
+/* procedures */
+
+void reinitialize_almost_everything(void);
+void get_some_switches(void);
+LINENUM locate_hunk(LINENUM _fuzz);
+void abort_hunk(void);
+void apply_hunk(LINENUM _where);
+void init_output(char *_name);
+void init_reject(char *_name);
+void copy_till(LINENUM _lastline);
+void spew_output(void);
+void dump_line(LINENUM _line);
+bool patch_match(LINENUM _base, LINENUM _offset, LINENUM _fuzz);
+bool similar(char *_a, char *_b, int _len);
+void my_exit(int _status);
+
+
+/* TRUE if -E was specified on command line. */
+static int remove_empty_files = FALSE;
+
+/* TRUE if -R was specified on command line. */
+static int reverse_flag_specified = FALSE;
+
+/* TRUE if -C was specified on command line. */
+int check_patch = FALSE;
+
+/* TRUE if -I was specified on command line */
+/* or PATCH_INDEX_FIRST env. variable is set */
+int index_first;
+
+/* TRUE if -S was specified on command line. */
+int skip_flag_specified = FALSE;
+
+/* Apply a set of diffs as appropriate. */
+
+int
+main(argc,argv)
+int argc;
+char **argv;
+{
+ LINENUM where;
+ LINENUM newwhere;
+ LINENUM fuzz;
+ LINENUM mymaxfuzz;
+ int hunk = 0;
+ int failed = 0;
+ int failtotal = 0;
+ bool rev_okayed = 0;
+ int i;
+
+ setbuf(stderr, serrbuf);
+ for (i = 0; i<MAXFILEC; i++)
+ filearg[i] = Nullch;
+
+ myuid = getuid();
+
+ index_first = getenv ("PATCH_INDEX_FIRST") != 0;
+
+ /* Cons up the names of the temporary files. */
+ {
+ /* Directory for temporary files. */
+ char *tmpdir;
+ int tmpname_len;
+
+ tmpdir = getenv ("TMPDIR");
+ if (tmpdir == NULL) {
+ tmpdir = "/tmp";
+ }
+ tmpname_len = strlen (tmpdir) + 20;
+
+ TMPOUTNAME = (char *) malloc (tmpname_len);
+ strcpy (TMPOUTNAME, tmpdir);
+ strcat (TMPOUTNAME, "/patchoXXXXXX");
+ Mktemp(TMPOUTNAME);
+
+ TMPINNAME = (char *) malloc (tmpname_len);
+ strcpy (TMPINNAME, tmpdir);
+ strcat (TMPINNAME, "/patchiXXXXXX");
+ Mktemp(TMPINNAME);
+
+ TMPREJNAME = (char *) malloc (tmpname_len);
+ strcpy (TMPREJNAME, tmpdir);
+ strcat (TMPREJNAME, "/patchrXXXXXX");
+ Mktemp(TMPREJNAME);
+
+ TMPPATNAME = (char *) malloc (tmpname_len);
+ strcpy (TMPPATNAME, tmpdir);
+ strcat (TMPPATNAME, "/patchpXXXXXX");
+ Mktemp(TMPPATNAME);
+ }
+
+ {
+ char *v;
+
+ v = getenv ("SIMPLE_BACKUP_SUFFIX");
+ if (v)
+ simple_backup_suffix = v;
+ else
+ simple_backup_suffix = ".orig";
+#ifndef NODIR
+ v = getenv ("VERSION_CONTROL");
+ backup_type = get_version (v); /* OK to pass NULL. */
+#endif
+ }
+
+ /* parse switches */
+ Argc = argc;
+ Argv = argv;
+ get_some_switches();
+
+ /* make sure we clean up /tmp in case of disaster */
+ set_signals(0);
+
+ for (
+ open_patch_file(filearg[1]);
+ there_is_another_patch();
+ reinitialize_almost_everything()
+ ) { /* for each patch in patch file */
+
+ if (outname == Nullch)
+ outname = savestr(filearg[0]);
+
+ /* for ed script just up and do it and exit */
+ if (diff_type == ED_DIFF) {
+ do_ed_script();
+ continue;
+ }
+
+ /* initialize the patched file */
+ if (!skip_rest_of_patch)
+ init_output(TMPOUTNAME);
+
+ /* initialize reject file */
+ init_reject(TMPREJNAME);
+
+ /* find out where all the lines are */
+ if (!skip_rest_of_patch)
+ scan_input(filearg[0]);
+
+ /* from here on, open no standard i/o files, because malloc */
+ /* might misfire and we can't catch it easily */
+
+ /* apply each hunk of patch */
+ hunk = 0;
+ failed = 0;
+ rev_okayed = FALSE;
+ out_of_mem = FALSE;
+ while (another_hunk()) {
+ hunk++;
+ fuzz = Nulline;
+ mymaxfuzz = pch_context();
+ if (maxfuzz < mymaxfuzz)
+ mymaxfuzz = maxfuzz;
+ if (!skip_rest_of_patch) {
+ do {
+ where = locate_hunk(fuzz);
+ if (hunk == 1 && where == Nulline && !(force|rev_okayed)) {
+ /* dwim for reversed patch? */
+ if (!pch_swap()) {
+ if (fuzz == Nulline)
+ say1(
+"Not enough memory to try swapped hunk! Assuming unswapped.\n");
+ continue;
+ }
+ reverse = !reverse;
+ where = locate_hunk(fuzz); /* try again */
+ if (where == Nulline) { /* didn't find it swapped */
+ if (!pch_swap()) /* put it back to normal */
+ fatal1("lost hunk on alloc error!\n");
+ reverse = !reverse;
+ }
+ else if (noreverse) {
+ if (!pch_swap()) /* put it back to normal */
+ fatal1("lost hunk on alloc error!\n");
+ reverse = !reverse;
+ say1(
+"Ignoring previously applied (or reversed) patch.\n");
+ skip_rest_of_patch = TRUE;
+ }
+ else if (batch) {
+ if (verbose)
+ say3(
+"%seversed (or previously applied) patch detected! %s -R.",
+ reverse ? "R" : "Unr",
+ reverse ? "Assuming" : "Ignoring");
+ }
+ else {
+ (void) ask3(
+"%seversed (or previously applied) patch detected! %s -R? [y] ",
+ reverse ? "R" : "Unr",
+ reverse ? "Assume" : "Ignore");
+ if (*buf == 'n') {
+ (void) ask1("Apply anyway? [n] ");
+ if (*buf == 'y')
+ rev_okayed = TRUE;
+ else
+ skip_rest_of_patch = TRUE;
+ where = Nulline;
+ reverse = !reverse;
+ if (!pch_swap()) /* put it back to normal */
+ fatal1("lost hunk on alloc error!\n");
+ }
+ }
+ }
+ } while (!skip_rest_of_patch && where == Nulline &&
+ ++fuzz <= mymaxfuzz);
+
+ if (skip_rest_of_patch) { /* just got decided */
+ Fclose(ofp);
+ ofp = Nullfp;
+ }
+ }
+
+ newwhere = pch_newfirst() + last_offset;
+ if (skip_rest_of_patch) {
+ abort_hunk();
+ if (! skip_flag_specified)
+ failed++;
+ if (verbose)
+ say3("Hunk #%d ignored at %ld.\n", hunk, newwhere);
+ }
+ else if (where == Nulline) {
+ abort_hunk();
+ failed++;
+ if (verbose)
+ say3("Hunk #%d failed at %ld.\n", hunk, newwhere);
+ }
+ else {
+ apply_hunk(where);
+ if (verbose) {
+ say3("Hunk #%d succeeded at %ld", hunk, newwhere);
+ if (fuzz)
+ say2(" with fuzz %ld", fuzz);
+ if (last_offset)
+ say3(" (offset %ld line%s)",
+ last_offset, last_offset==1L?"":"s");
+ say1(".\n");
+ }
+ }
+ }
+
+ if (out_of_mem && using_plan_a) {
+ optind = optind_last;
+ say1("\n\nRan out of memory using Plan A--trying again...\n\n");
+ if (ofp)
+ Fclose(ofp);
+ ofp = Nullfp;
+ if (rejfp)
+ Fclose(rejfp);
+ rejfp = Nullfp;
+ continue;
+ }
+
+ assert(hunk);
+
+ /* finish spewing out the new file */
+ if (!skip_rest_of_patch)
+ spew_output();
+
+ /* and put the output where desired */
+ ignore_signals();
+ if (!skip_rest_of_patch) {
+ struct stat statbuf;
+ char *realout = outname;
+
+ if (check_patch) {
+ ;
+ } else if (move_file(TMPOUTNAME, outname) < 0) {
+ toutkeep = TRUE;
+ realout = TMPOUTNAME;
+ chmod(TMPOUTNAME, filemode);
+ }
+ else
+ chmod(outname, filemode);
+
+ if (remove_empty_files && stat(realout, &statbuf) == 0
+ && statbuf.st_size == 0) {
+ if (verbose)
+ say2("Removing %s (empty after patching).\n", realout);
+ while (unlink(realout) >= 0) ; /* while is for Eunice. */
+ }
+ }
+ Fclose(rejfp);
+ rejfp = Nullfp;
+ if (failed) {
+ failtotal += failed;
+ if (!*rejname) {
+ Strcpy(rejname, outname);
+ addext(rejname, ".rej", '#');
+ }
+ if (skip_rest_of_patch) {
+ say4("%d out of %d hunks ignored--saving rejects to %s\n",
+ failed, hunk, rejname);
+ }
+ else {
+ say4("%d out of %d hunks failed--saving rejects to %s\n",
+ failed, hunk, rejname);
+ }
+ if (check_patch) {
+ ;
+ } else if (move_file(TMPREJNAME, rejname) < 0)
+ trejkeep = TRUE;
+ }
+ set_signals(1);
+ }
+ my_exit(failtotal);
+ return (failtotal);
+}
+
+/* Prepare to find the next patch to do in the patch file. */
+
+void
+reinitialize_almost_everything(void)
+{
+ re_patch();
+ re_input();
+
+ input_lines = 0;
+ last_frozen_line = 0;
+
+ filec = 0;
+ if (filearg[0] != Nullch && !out_of_mem) {
+ free(filearg[0]);
+ filearg[0] = Nullch;
+ }
+
+ if (outname != Nullch) {
+ free(outname);
+ outname = Nullch;
+ }
+
+ last_offset = 0;
+
+ diff_type = 0;
+
+ if (revision != Nullch) {
+ free(revision);
+ revision = Nullch;
+ }
+
+ reverse = reverse_flag_specified;
+ skip_rest_of_patch = FALSE;
+ skip_flag_specified = FALSE;
+
+ get_some_switches();
+
+ if (filec >= 2)
+ fatal1("you may not change to a different patch file\n");
+}
+
+static char *shortopts = "-b:B:cCd:D:eEfF:i:IlnNo:p::r:RsStuvV:x:";
+static struct option longopts[] =
+{
+ {"suffix", 1, NULL, 'b'},
+ {"prefix", 1, NULL, 'B'},
+ {"check", 0, NULL, 'C'},
+ {"context", 0, NULL, 'c'},
+ {"directory", 1, NULL, 'd'},
+ {"ifdef", 1, NULL, 'D'},
+ {"ed", 0, NULL, 'e'},
+ {"remove-empty-files", 0, NULL, 'E'},
+ {"force", 0, NULL, 'f'},
+ {"fuzz", 1, NULL, 'F'},
+ {"index-first", 0, NULL, 'I'},
+ {"ignore-whitespace", 0, NULL, 'l'},
+ {"normal", 0, NULL, 'n'},
+ {"forward", 0, NULL, 'N'},
+ {"output", 1, NULL, 'o'},
+ {"strip", 2, NULL, 'p'},
+ {"reject-file", 1, NULL, 'r'},
+ {"reverse", 0, NULL, 'R'},
+ {"quiet", 0, NULL, 's'},
+ {"silent", 0, NULL, 's'},
+ {"skip", 0, NULL, 'S'},
+ {"batch", 0, NULL, 't'},
+ {"unified", 0, NULL, 'u'},
+ {"version", 0, NULL, 'v'},
+ {"version-control", 1, NULL, 'V'},
+ {"debug", 1, NULL, 'x'},
+ {0, 0, 0, 0}
+};
+
+/* Process switches and filenames up to next '+' or end of list. */
+
+void
+get_some_switches(void)
+{
+ Reg1 int optc;
+
+ rejname[0] = '\0';
+ optind_last = optind;
+ if (optind == Argc)
+ return;
+ while ((optc = getopt_long (Argc, Argv, shortopts, longopts, (int *) 0))
+ != -1) {
+ if (optc == 1) {
+ if (strEQ(optarg, "+"))
+ return;
+ if (filec == MAXFILEC)
+ fatal1("too many file arguments\n");
+ filearg[filec++] = savestr(optarg);
+ }
+ else {
+ switch (optc) {
+ case 'b':
+ simple_backup_suffix = savestr(optarg);
+ break;
+ case 'B':
+ origprae = savestr(optarg);
+ break;
+ case 'c':
+ diff_type = CONTEXT_DIFF;
+ break;
+ case 'C':
+ check_patch = TRUE;
+ break;
+ case 'd':
+ if (chdir(optarg) < 0)
+ pfatal2("can't cd to %s", optarg);
+ break;
+ case 'D':
+ do_defines = TRUE;
+ if (!isalpha((unsigned char)*optarg) && '_' != *optarg)
+ fatal1("argument to -D is not an identifier\n");
+ Sprintf(if_defined, "#ifdef %s\n", optarg);
+ Sprintf(not_defined, "#ifndef %s\n", optarg);
+ Sprintf(end_defined, "#endif /* %s */\n", optarg);
+ break;
+ case 'e':
+ diff_type = ED_DIFF;
+ break;
+ case 'E':
+ remove_empty_files = TRUE;
+ break;
+ case 'f':
+ force = TRUE;
+ break;
+ case 'F':
+ maxfuzz = atoi(optarg);
+ break;
+ case 'i':
+ filearg[1] = savestr(optarg);
+ break;
+ case 'I':
+ index_first = TRUE;
+ break;
+ case 'l':
+ canonicalize = TRUE;
+ break;
+ case 'n':
+ diff_type = NORMAL_DIFF;
+ break;
+ case 'N':
+ noreverse = TRUE;
+ break;
+ case 'o':
+ outname = savestr(optarg);
+ break;
+ case 'p':
+ if (optarg)
+ strippath = atoi(optarg);
+ else
+ strippath = 0;
+ break;
+ case 'r':
+ Strcpy(rejname, optarg);
+ break;
+ case 'R':
+ reverse = TRUE;
+ reverse_flag_specified = TRUE;
+ break;
+ case 's':
+ verbose = FALSE;
+ break;
+ case 'S':
+ skip_rest_of_patch = TRUE;
+ skip_flag_specified = TRUE;
+ break;
+ case 't':
+ batch = TRUE;
+ break;
+ case 'u':
+ diff_type = UNI_DIFF;
+ break;
+ case 'v':
+ version();
+ break;
+ case 'V':
+#ifndef NODIR
+ backup_type = get_version (optarg);
+#endif
+ break;
+#ifdef DEBUGGING
+ case 'x':
+ debug = atoi(optarg);
+ break;
+#endif
+ default:
+ fprintf(stderr, "\
+Usage: %s [options] [origfile [patchfile]] [+ [options] [origfile]]...\n",
+ Argv[0]);
+ fprintf(stderr, "\
+Options:\n\
+ [-cCeEflnNRsStuv] [-b backup-ext] [-B backup-prefix] [-d directory]\n\
+ [-D symbol] [-F max-fuzz] [-i patchfile] [-o out-file] [-p[strip-count]]\n\
+ [-r rej-name] [-V {numbered,existing,simple}] [--check] [--context]\n\
+ [--prefix=backup-prefix] [--suffix=backup-ext] [--ifdef=symbol]\n\
+ [--directory=directory] [--ed] [--fuzz=max-fuzz] [--force] [--batch]\n\
+ [--ignore-whitespace] [--forward] [--reverse] [--output=out-file]\n");
+ fprintf(stderr, "\
+ [--strip[=strip-count]] [--normal] [--reject-file=rej-name] [--skip]\n\
+ [--remove-empty-files] [--quiet] [--silent] [--unified] [--version]\n\
+ [--version-control={numbered,existing,simple}] [--index-first]\n");
+ my_exit(1);
+ }
+ }
+ }
+
+ /* Process any filename args given after "--". */
+ for (; optind < Argc; ++optind) {
+ if (filec == MAXFILEC)
+ fatal1("too many file arguments\n");
+ filearg[filec++] = savestr(Argv[optind]);
+ }
+}
+
+/*
+ * Attempt to find the right place to apply this hunk of patch.
+ */
+LINENUM
+locate_hunk(LINENUM fuzz)
+{
+ Reg1 LINENUM first_guess = pch_first() + last_offset;
+ Reg2 LINENUM offset;
+ LINENUM pat_lines = pch_ptrn_lines();
+ Reg3 LINENUM max_pos_offset = input_lines - first_guess
+ - pat_lines + 1;
+ Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1
+ + pch_context();
+
+ if (!pat_lines) /* null range matches always */
+ return first_guess;
+ if (max_neg_offset >= first_guess) /* do not try lines < 0 */
+ max_neg_offset = first_guess - 1;
+ if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz))
+ return first_guess;
+ for (offset = 1; ; offset++) {
+ Reg5 bool check_after = (offset <= max_pos_offset);
+ Reg6 bool check_before = (offset <= max_neg_offset);
+
+ if (check_after && patch_match(first_guess, offset, fuzz)) {
+#ifdef DEBUGGING
+ if (debug & 1)
+ say3("Offset changing from %ld to %ld\n", last_offset, offset);
+#endif
+ last_offset = offset;
+ return first_guess+offset;
+ }
+ else if (check_before && patch_match(first_guess, -offset, fuzz)) {
+#ifdef DEBUGGING
+ if (debug & 1)
+ say3("Offset changing from %ld to %ld\n", last_offset, -offset);
+#endif
+ last_offset = -offset;
+ return first_guess-offset;
+ }
+ else if (!check_before && !check_after)
+ return Nulline;
+ }
+}
+
+/* We did not find the pattern, dump out the hunk so they can handle it. */
+
+void
+abort_hunk(void)
+{
+ Reg1 LINENUM i;
+ Reg2 LINENUM pat_end = pch_end();
+ /* add in last_offset to guess the same as the previous successful hunk */
+ LINENUM oldfirst = pch_first() + last_offset;
+ LINENUM newfirst = pch_newfirst() + last_offset;
+ LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
+ LINENUM newlast = newfirst + pch_repl_lines() - 1;
+ char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : "");
+ char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----");
+
+ fprintf(rejfp, "***************\n");
+ for (i=0; i<=pat_end; i++) {
+ switch (pch_char(i)) {
+ case '*':
+ if (oldlast < oldfirst)
+ fprintf(rejfp, "*** 0%s\n", stars);
+ else if (oldlast == oldfirst)
+ fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
+ else
+ fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
+ break;
+ case '=':
+ if (newlast < newfirst)
+ fprintf(rejfp, "--- 0%s\n", minuses);
+ else if (newlast == newfirst)
+ fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
+ else
+ fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
+ break;
+ case '\n':
+ fprintf(rejfp, "%s", pfetch(i));
+ break;
+ case ' ': case '-': case '+': case '!':
+ fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
+ break;
+ default:
+ fatal1("fatal internal error in abort_hunk\n");
+ }
+ }
+}
+
+/*
+ * We found where to apply it (we hope), so do it.
+ */
+void
+apply_hunk(LINENUM where)
+{
+ Reg1 LINENUM old = 1;
+ Reg2 LINENUM lastline = pch_ptrn_lines();
+ Reg3 LINENUM new = lastline+1;
+#define OUTSIDE 0
+#define IN_IFNDEF 1
+#define IN_IFDEF 2
+#define IN_ELSE 3
+ Reg4 int def_state = OUTSIDE;
+ Reg5 bool R_do_defines = do_defines;
+ Reg6 LINENUM pat_end = pch_end();
+
+ where--;
+ while (pch_char(new) == '=' || pch_char(new) == '\n')
+ new++;
+
+ while (old <= lastline) {
+ if (pch_char(old) == '-') {
+ copy_till(where + old - 1);
+ if (R_do_defines) {
+ if (def_state == OUTSIDE) {
+ fputs(not_defined, ofp);
+ def_state = IN_IFNDEF;
+ }
+ else if (def_state == IN_IFDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ fputs(pfetch(old), ofp);
+ }
+ last_frozen_line++;
+ old++;
+ }
+ else if (new > pat_end) {
+ break;
+ }
+ else if (pch_char(new) == '+') {
+ copy_till(where + old - 1);
+ if (R_do_defines) {
+ if (def_state == IN_IFNDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ else if (def_state == OUTSIDE) {
+ fputs(if_defined, ofp);
+ def_state = IN_IFDEF;
+ }
+ }
+ fputs(pfetch(new), ofp);
+ new++;
+ }
+ else if (pch_char(new) != pch_char(old)) {
+ say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
+ pch_hunk_beg() + old,
+ pch_hunk_beg() + new);
+#ifdef DEBUGGING
+ say3("oldchar = '%c', newchar = '%c'\n",
+ pch_char(old), pch_char(new));
+#endif
+ my_exit(1);
+ }
+ else if (pch_char(new) == '!') {
+ copy_till(where + old - 1);
+ if (R_do_defines) {
+ fputs(not_defined, ofp);
+ def_state = IN_IFNDEF;
+ }
+ while (pch_char(old) == '!') {
+ if (R_do_defines) {
+ fputs(pfetch(old), ofp);
+ }
+ last_frozen_line++;
+ old++;
+ }
+ if (R_do_defines) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ while (pch_char(new) == '!') {
+ fputs(pfetch(new), ofp);
+ new++;
+ }
+ }
+ else {
+ assert(pch_char(new) == ' ');
+ old++;
+ new++;
+ if (R_do_defines && def_state != OUTSIDE) {
+ fputs(end_defined, ofp);
+ def_state = OUTSIDE;
+ }
+ }
+ }
+ if (new <= pat_end && pch_char(new) == '+') {
+ copy_till(where + old - 1);
+ if (R_do_defines) {
+ if (def_state == OUTSIDE) {
+ fputs(if_defined, ofp);
+ def_state = IN_IFDEF;
+ }
+ else if (def_state == IN_IFNDEF) {
+ fputs(else_defined, ofp);
+ def_state = IN_ELSE;
+ }
+ }
+ while (new <= pat_end && pch_char(new) == '+') {
+ fputs(pfetch(new), ofp);
+ new++;
+ }
+ }
+ if (R_do_defines && def_state != OUTSIDE) {
+ fputs(end_defined, ofp);
+ }
+}
+
+/* Open the new file. */
+
+void
+init_output(char *name)
+{
+ ofp = fopen(name, "w");
+ if (ofp == Nullfp)
+ pfatal2("can't create %s", name);
+}
+
+/* Open a file to put hunks we can't locate. */
+
+void
+init_reject(char *name)
+{
+ rejfp = fopen(name, "w");
+ if (rejfp == Nullfp)
+ pfatal2("can't create %s", name);
+}
+
+/* Copy input file to output, up to wherever hunk is to be applied. */
+
+void
+copy_till(LINENUM lastline)
+{
+ Reg2 LINENUM R_last_frozen_line = last_frozen_line;
+
+ if (R_last_frozen_line > lastline)
+ fatal1("misordered hunks! output would be garbled\n");
+ while (R_last_frozen_line < lastline) {
+ dump_line(++R_last_frozen_line);
+ }
+ last_frozen_line = R_last_frozen_line;
+}
+
+/* Finish copying the input file to the output file. */
+
+void
+spew_output(void)
+{
+#ifdef DEBUGGING
+ if (debug & 256)
+ say3("il=%ld lfl=%ld\n",input_lines,last_frozen_line);
+#endif
+ if (input_lines)
+ copy_till(input_lines); /* dump remainder of file */
+ Fclose(ofp);
+ ofp = Nullfp;
+}
+
+/* Copy one line from input to output. */
+
+void
+dump_line(LINENUM line)
+{
+ Reg1 char *s;
+ Reg2 char R_newline = '\n';
+
+ /* Note: string is not null terminated. */
+ for (s=ifetch(line, 0); putc(*s, ofp) != R_newline; s++) ;
+}
+
+/* Does the patch pattern match at line base+offset? */
+
+bool
+patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
+{
+ Reg1 LINENUM pline = 1 + fuzz;
+ Reg2 LINENUM iline;
+ Reg3 LINENUM pat_lines = pch_ptrn_lines() - fuzz;
+
+ for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) {
+ if (canonicalize) {
+ if (!similar(ifetch(iline, (offset >= 0)),
+ pfetch(pline),
+ pch_line_len(pline) ))
+ return FALSE;
+ }
+ else if (strnNE(ifetch(iline, (offset >= 0)),
+ pfetch(pline),
+ pch_line_len(pline) ))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Do two lines match with canonicalized white space? */
+
+bool
+similar(char *a, char *b, int len)
+{
+ while (len) {
+ if (isspace((unsigned char)*b)) { /* whitespace (or \n) to match? */
+ if (!isspace((unsigned char)*a)) /* no corresponding whitespace? */
+ return FALSE;
+ while (len && isspace((unsigned char)*b) && *b != '\n')
+ b++,len--; /* skip pattern whitespace */
+ while (isspace((unsigned char)*a) && *a != '\n')
+ a++; /* skip target whitespace */
+ if (*a == '\n' || *b == '\n')
+ return (*a == *b); /* should end in sync */
+ }
+ else if (*a++ != *b++) /* match non-whitespace chars */
+ return FALSE;
+ else
+ len--; /* probably not necessary */
+ }
+ return TRUE; /* actually, this is not reached */
+ /* since there is always a \n */
+}
+
+/* Exit with cleanup. */
+
+void
+my_exit(int status)
+{
+ Unlink(TMPINNAME);
+ if (!toutkeep) {
+ Unlink(TMPOUTNAME);
+ }
+ if (!trejkeep) {
+ Unlink(TMPREJNAME);
+ }
+ Unlink(TMPPATNAME);
+ exit(status);
+}
diff --git a/gnu/usr.bin/patch/patchlevel.h b/gnu/usr.bin/patch/patchlevel.h
new file mode 100644
index 0000000..d5de3a9
--- /dev/null
+++ b/gnu/usr.bin/patch/patchlevel.h
@@ -0,0 +1 @@
+#define PATCH_VERSION "2.1"
diff --git a/gnu/usr.bin/patch/pch.c b/gnu/usr.bin/patch/pch.c
new file mode 100644
index 0000000..7dee1a6
--- /dev/null
+++ b/gnu/usr.bin/patch/pch.c
@@ -0,0 +1,1404 @@
+/* $FreeBSD$
+ *
+ * $Log: pch.c,v $
+ * Revision 2.0.2.0 90/05/01 22:17:51 davison
+ * patch12u: unidiff support added
+ *
+ * Revision 2.0.1.7 88/06/03 15:13:28 lwall
+ * patch10: Can now find patches in shar scripts.
+ * patch10: Hunks that swapped and then swapped back could core dump.
+ *
+ * Revision 2.0.1.6 87/06/04 16:18:13 lwall
+ * pch_swap didn't swap p_bfake and p_efake.
+ *
+ * Revision 2.0.1.5 87/01/30 22:47:42 lwall
+ * Improved responses to mangled patches.
+ *
+ * Revision 2.0.1.4 87/01/05 16:59:53 lwall
+ * New-style context diffs caused double call to free().
+ *
+ * Revision 2.0.1.3 86/11/14 10:08:33 lwall
+ * Fixed problem where a long pattern wouldn't grow the hunk.
+ * Also restored p_input_line when backtracking so error messages are right.
+ *
+ * Revision 2.0.1.2 86/11/03 17:49:52 lwall
+ * New-style delete triggers spurious assertion error.
+ *
+ * Revision 2.0.1.1 86/10/29 15:52:08 lwall
+ * Could falsely report new-style context diff.
+ *
+ * Revision 2.0 86/09/17 15:39:37 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "util.h"
+#include "INTERN.h"
+#include "pch.h"
+
+/* Patch (diff listing) abstract type. */
+
+static long p_filesize; /* size of the patch file */
+static LINENUM p_first; /* 1st line number */
+static LINENUM p_newfirst; /* 1st line number of replacement */
+static LINENUM p_ptrn_lines; /* # lines in pattern */
+static LINENUM p_repl_lines; /* # lines in replacement text */
+static LINENUM p_end = -1; /* last line in hunk */
+static LINENUM p_max; /* max allowed value of p_end */
+static LINENUM p_context = 3; /* # of context lines */
+static LINENUM p_input_line = 0; /* current line # from patch file */
+static char **p_line = Null(char**); /* the text of the hunk */
+static short *p_len = Null(short*); /* length of each line */
+static char *p_Char = Nullch; /* +, -, and ! */
+static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */
+static int p_indent; /* indent to patch */
+static LINENUM p_base; /* where to intuit this time */
+static LINENUM p_bline; /* line # of p_base */
+static LINENUM p_start; /* where intuit found a patch */
+static LINENUM p_sline; /* and the line number for it */
+static LINENUM p_hunk_beg; /* line number of current hunk */
+static LINENUM p_efake = -1; /* end of faked up lines--don't free */
+static LINENUM p_bfake = -1; /* beg of faked up lines */
+
+/*
+ * Prepare to look for the next patch in the patch file.
+ */
+void
+re_patch(void)
+{
+ p_first = Nulline;
+ p_newfirst = Nulline;
+ p_ptrn_lines = Nulline;
+ p_repl_lines = Nulline;
+ p_end = (LINENUM)-1;
+ p_max = Nulline;
+ p_indent = 0;
+}
+
+/*
+ * Open the patch file at the beginning of time.
+ */
+void
+open_patch_file(char *filename)
+{
+ if (filename == Nullch || !*filename || strEQ(filename, "-")) {
+ pfp = fopen(TMPPATNAME, "w");
+ if (pfp == Nullfp)
+ pfatal2("can't create %s", TMPPATNAME);
+ while (fgets(buf, sizeof buf, stdin) != Nullch)
+ fputs(buf, pfp);
+ Fclose(pfp);
+ filename = TMPPATNAME;
+ }
+ pfp = fopen(filename, "r");
+ if (pfp == Nullfp)
+ pfatal2("patch file %s not found", filename);
+ Fstat(fileno(pfp), &filestat);
+ p_filesize = filestat.st_size;
+ next_intuit_at(0L,1L); /* start at the beginning */
+ set_hunkmax();
+}
+
+/*
+ * Make sure our dynamically realloced tables are malloced to begin with.
+ */
+void
+set_hunkmax(void)
+{
+#ifndef lint
+ if (p_line == Null(char**))
+ p_line = (char**) malloc((MEM)hunkmax * sizeof(char *));
+ if (p_len == Null(short*))
+ p_len = (short*) malloc((MEM)hunkmax * sizeof(short));
+#endif
+ if (p_Char == Nullch)
+ p_Char = (char*) malloc((MEM)hunkmax * sizeof(char));
+}
+
+/*
+ * Enlarge the arrays containing the current hunk of patch.
+ */
+void
+grow_hunkmax(void)
+{
+ hunkmax *= 2;
+ /*
+ * Note that on most systems, only the p_line array ever gets
+ * fresh memory since p_len can move into p_line's old space,
+ * and p_Char can move into p_len's old space. Not on PDP-11's
+ * however. But it doesn't matter.
+ */
+ assert(p_line != Null(char**) && p_len != Null(short*) &&
+ p_Char != Nullch);
+#ifndef lint
+ p_line = (char**) realloc((char*)p_line, (MEM)hunkmax * sizeof(char *));
+ p_len = (short*) realloc((char*)p_len, (MEM)hunkmax * sizeof(short));
+ p_Char = (char*) realloc((char*)p_Char, (MEM)hunkmax * sizeof(char));
+#endif
+ if (p_line != Null(char**) && p_len != Null(short*) && p_Char != Nullch)
+ return;
+ if (!using_plan_a)
+ fatal1("out of memory\n");
+ out_of_mem = TRUE; /* whatever is null will be allocated again */
+ /* from within plan_a(), of all places */
+}
+
+/*
+ * True if the remainder of the patch file contains a diff of some sort.
+ */
+bool
+there_is_another_patch(void)
+{
+ if (p_base != 0L && p_base >= p_filesize) {
+ if (verbose)
+ say1("done\n");
+ return FALSE;
+ }
+ if (verbose)
+ say1("Hmm...");
+ diff_type = intuit_diff_type();
+ if (!diff_type) {
+ if (p_base != 0L) {
+ if (verbose)
+ say1(" Ignoring the trailing garbage.\ndone\n");
+ }
+ else
+ say1(" I can't seem to find a patch in there anywhere.\n");
+ return FALSE;
+ }
+ if (verbose)
+ say3(" %sooks like %s to me...\n",
+ (p_base == 0L ? "L" : "The next patch l"),
+ diff_type == UNI_DIFF ? "a unified diff" :
+ diff_type == CONTEXT_DIFF ? "a context diff" :
+ diff_type == NEW_CONTEXT_DIFF ?
+ "a new-style context diff" :
+ diff_type == NORMAL_DIFF ? "a normal diff" :
+ "an ed script" );
+ if (p_indent && verbose)
+ say3("(Patch is indented %d space%s.)\n",
+ p_indent, p_indent==1?"":"s");
+ skip_to(p_start,p_sline);
+ while (filearg[0] == Nullch) {
+ if (force || batch || skip_rest_of_patch) {
+ say1("No file to patch. Skipping...\n");
+ filearg[0] = savestr(bestguess);
+ skip_rest_of_patch = TRUE;
+ return TRUE;
+ }
+ (void) ask1("File to patch: ");
+ if (*buf != '\n') {
+ if (bestguess)
+ free(bestguess);
+ bestguess = savestr(buf);
+ filearg[0] = fetchname(buf, 0, FALSE);
+ }
+ if (filearg[0] == Nullch) {
+ if (ask1("No file found--skip this patch? [n] ")) {
+ if (*buf != 'y') {
+ continue;
+ }
+ }
+ if (verbose)
+ say1("Skipping patch...\n");
+ filearg[0] = fetchname(bestguess, 0, TRUE);
+ skip_rest_of_patch = TRUE;
+ return TRUE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * Determine what kind of diff is in the remaining part of the patch file.
+ */
+int
+intuit_diff_type(void)
+{
+ Reg4 long this_line = 0;
+ Reg5 long previous_line;
+ Reg6 long first_command_line = -1;
+ long fcl_line;
+ Reg7 bool last_line_was_command = FALSE;
+ Reg8 bool this_is_a_command = FALSE;
+ Reg9 bool stars_last_line = FALSE;
+ Reg10 bool stars_this_line = FALSE;
+ Reg3 int indent;
+ Reg1 char *s;
+ Reg2 char *t;
+ char *indtmp = Nullch;
+ char *oldtmp = Nullch;
+ char *newtmp = Nullch;
+ char *indname = Nullch;
+ char *oldname = Nullch;
+ char *newname = Nullch;
+ Reg11 int retval;
+ bool no_filearg = (filearg[0] == Nullch);
+ extern int index_first;
+
+ ok_to_create_file = FALSE;
+ Fseek(pfp, p_base, 0);
+ p_input_line = p_bline - 1;
+ for (;;) {
+ previous_line = this_line;
+ last_line_was_command = this_is_a_command;
+ stars_last_line = stars_this_line;
+ this_line = ftell(pfp);
+ indent = 0;
+ p_input_line++;
+ if (fgets(buf, sizeof buf, pfp) == Nullch) {
+ if (first_command_line >= 0L) {
+ /* nothing but deletes!? */
+ p_start = first_command_line;
+ p_sline = fcl_line;
+ retval = ED_DIFF;
+ goto scan_exit;
+ }
+ else {
+ p_start = this_line;
+ p_sline = p_input_line;
+ retval = 0;
+ goto scan_exit;
+ }
+ }
+ for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
+ if (*s == '\t')
+ indent += 8 - (indent % 8);
+ else
+ indent++;
+ }
+ for (t=s; isdigit((unsigned char)*t) || *t == ','; t++)
+ ;
+ this_is_a_command = (isdigit((unsigned char)*s) &&
+ (*t == 'd' || *t == 'c' || *t == 'a') );
+ if (first_command_line < 0L && this_is_a_command) {
+ first_command_line = this_line;
+ fcl_line = p_input_line;
+ p_indent = indent; /* assume this for now */
+ }
+ if (!stars_last_line && strnEQ(s, "*** ", 4))
+ oldtmp = savestr(s+4);
+ else if (strnEQ(s, "--- ", 4))
+ newtmp = savestr(s+4);
+ else if (strnEQ(s, "+++ ", 4))
+ oldtmp = savestr(s+4); /* pretend it is the old name */
+ else if (strnEQ(s, "Index:", 6))
+ indtmp = savestr(s+6);
+ else if (strnEQ(s, "Prereq:", 7)) {
+ for (t = s + 7; isspace((unsigned char)*t); t++)
+ ;
+ revision = savestr(t);
+ for (t = revision; *t && !isspace((unsigned char)*t);
+ t++)
+ ;
+ *t = '\0';
+ if (!*revision) {
+ free(revision);
+ revision = Nullch;
+ }
+ }
+ if ((!diff_type || diff_type == ED_DIFF) &&
+ first_command_line >= 0L &&
+ strEQ(s, ".\n") ) {
+ p_indent = indent;
+ p_start = first_command_line;
+ p_sline = fcl_line;
+ retval = ED_DIFF;
+ goto scan_exit;
+ }
+ if ((!diff_type || diff_type == UNI_DIFF) &&
+ strnEQ(s, "@@ -", 4)) {
+ if (!atol(s+3))
+ ok_to_create_file = TRUE;
+ p_indent = indent;
+ p_start = this_line;
+ p_sline = p_input_line;
+ retval = UNI_DIFF;
+ goto scan_exit;
+ }
+ stars_this_line = strnEQ(s, "********", 8);
+ if ((!diff_type || diff_type == CONTEXT_DIFF) &&
+ stars_last_line &&
+ strnEQ(s, "*** ", 4)) {
+ if (!atol(s+4))
+ ok_to_create_file = TRUE;
+ /*
+ * If this is a new context diff the character just
+ * before the newline is a '*'.
+ */
+ while (*s != '\n')
+ s++;
+ p_indent = indent;
+ p_start = previous_line;
+ p_sline = p_input_line - 1;
+ retval = (*(s-1) == '*' ?
+ NEW_CONTEXT_DIFF : CONTEXT_DIFF);
+ goto scan_exit;
+ }
+ if ((!diff_type || diff_type == NORMAL_DIFF) &&
+ last_line_was_command &&
+ (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
+ p_start = previous_line;
+ p_sline = p_input_line - 1;
+ p_indent = indent;
+ retval = NORMAL_DIFF;
+ goto scan_exit;
+ }
+ }
+ scan_exit:
+ if (no_filearg) {
+ if (indtmp != Nullch)
+ indname = fetchname(indtmp, strippath,
+ ok_to_create_file);
+ if (oldtmp != Nullch)
+ oldname = fetchname(oldtmp, strippath,
+ ok_to_create_file);
+ if (newtmp != Nullch)
+ newname = fetchname(newtmp, strippath,
+ ok_to_create_file);
+ if (index_first && indname)
+ filearg[0] = savestr(indname);
+ else if (oldname && newname) {
+ if (strlen(oldname) < strlen(newname))
+ filearg[0] = savestr(oldname);
+ else
+ filearg[0] = savestr(newname);
+ } else if (indname)
+ filearg[0] = savestr(indname);
+ else if (oldname)
+ filearg[0] = savestr(oldname);
+ else if (newname)
+ filearg[0] = savestr(newname);
+ }
+ if (bestguess) {
+ free(bestguess);
+ bestguess = Nullch;
+ }
+ if (filearg[0] != Nullch)
+ bestguess = savestr(filearg[0]);
+ else if (indtmp != Nullch)
+ bestguess = fetchname(indtmp, strippath, TRUE);
+ else {
+ if (oldtmp != Nullch)
+ oldname = fetchname(oldtmp, strippath, TRUE);
+ if (newtmp != Nullch)
+ newname = fetchname(newtmp, strippath, TRUE);
+ if (oldname && newname) {
+ if (strlen(oldname) < strlen(newname))
+ bestguess = savestr(oldname);
+ else
+ bestguess = savestr(newname);
+ }
+ else if (oldname)
+ bestguess = savestr(oldname);
+ else if (newname)
+ bestguess = savestr(newname);
+ }
+ if (indtmp != Nullch)
+ free(indtmp);
+ if (oldtmp != Nullch)
+ free(oldtmp);
+ if (newtmp != Nullch)
+ free(newtmp);
+ if (indname != Nullch)
+ free(indname);
+ if (oldname != Nullch)
+ free(oldname);
+ if (newname != Nullch)
+ free(newname);
+ return retval;
+}
+
+/*
+ * Remember where this patch ends so we know where to start up again.
+ */
+void
+next_intuit_at(long file_pos, long file_line)
+{
+ p_base = file_pos;
+ p_bline = file_line;
+}
+
+/*
+ * Basically a verbose fseek() to the actual diff listing.
+ */
+void
+skip_to(long file_pos, long file_line)
+{
+ char *ret;
+
+ assert(p_base <= file_pos);
+ if (verbose && p_base < file_pos) {
+ Fseek(pfp, p_base, 0);
+ say1("The text leading up to this was:\n--------------------------\n");
+ while (ftell(pfp) < file_pos) {
+ ret = fgets(buf, sizeof buf, pfp);
+ assert(ret != Nullch);
+ say2("|%s", buf);
+ }
+ say1("--------------------------\n");
+ }
+ else
+ Fseek(pfp, file_pos, 0);
+ p_input_line = file_line - 1;
+}
+
+/*
+ * Make this a function for better debugging.
+ */
+static void
+malformed(void)
+{
+ fatal3("malformed patch at line %ld: %s", p_input_line, buf);
+ /* about as informative as "Syntax error" in C */
+}
+
+/*
+ * True if the line has been discarded (i.e. it is a line saying
+ * "\ No newline at end of file".)
+ */
+static bool
+remove_special_line(void)
+{
+ int c;
+
+ c = fgetc(pfp);
+ if (c == '\\') {
+ do {
+ c = fgetc(pfp);
+ } while (c != EOF && c != '\n');
+
+ return TRUE;
+ }
+
+ if (c != EOF)
+ fseek(pfp, -1, SEEK_CUR);
+
+ return FALSE;
+}
+
+/*
+ * True if there is more of the current diff listing to process.
+ */
+bool
+another_hunk(void)
+{
+ Reg1 char *s;
+ Reg8 char *ret;
+ Reg2 int context = 0;
+
+ while (p_end >= 0) {
+ if (p_end == p_efake)
+ p_end = p_bfake; /* don't free twice */
+ else
+ free(p_line[p_end]);
+ p_end--;
+ }
+ assert(p_end == -1);
+ p_efake = -1;
+
+ p_max = hunkmax; /* gets reduced when --- found */
+ if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
+ long line_beginning = ftell(pfp);
+ /* file pos of the current line */
+ LINENUM repl_beginning = 0; /* index of --- line */
+ Reg4 LINENUM fillcnt = 0; /* #lines of missing ptrn or repl */
+ Reg5 LINENUM fillsrc; /* index of first line to copy */
+ Reg6 LINENUM filldst; /* index of first missing line */
+ bool ptrn_spaces_eaten = FALSE; /* ptrn was slightly misformed */
+ Reg9 bool repl_could_be_missing = TRUE;
+ /* no + or ! lines in this hunk */
+ bool repl_missing = FALSE; /* we are now backtracking */
+ long repl_backtrack_position = 0;
+ /* file pos of first repl line */
+ LINENUM repl_patch_line; /* input line number for same */
+ Reg7 LINENUM ptrn_copiable = 0;
+ /* # of copiable lines in ptrn */
+
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch || strnNE(buf, "********", 8)) {
+ next_intuit_at(line_beginning,p_input_line);
+ return FALSE;
+ }
+ p_context = 100;
+ p_hunk_beg = p_input_line + 1;
+ while (p_end < p_max) {
+ line_beginning = ftell(pfp);
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch) {
+ if (p_max - p_end < 4)
+ Strcpy(buf, " \n"); /* assume blank lines got chopped */
+ else {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ fatal1("unexpected end of file in patch\n");
+ }
+ }
+ p_end++;
+ assert(p_end < hunkmax);
+ p_Char[p_end] = *buf;
+#ifdef zilog
+ p_line[(short)p_end] = Nullch;
+#else
+ p_line[p_end] = Nullch;
+#endif
+ switch (*buf) {
+ case '*':
+ if (strnEQ(buf, "********", 8)) {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ else
+ fatal2("unexpected end of hunk at line %ld\n",
+ p_input_line);
+ }
+ if (p_end != 0) {
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ fatal3("unexpected *** at line %ld: %s", p_input_line, buf);
+ }
+ context = 0;
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return FALSE;
+ }
+ for (s=buf; *s && !isdigit((unsigned char)*s); s++) ;
+ if (!*s)
+ malformed ();
+ if (strnEQ(s,"0,0",3))
+ strcpy(s,s+2);
+ p_first = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s)) s++;
+ if (*s == ',') {
+ for (; *s && !isdigit((unsigned char)*s); s++) ;
+ if (!*s)
+ malformed ();
+ p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
+ }
+ else if (p_first)
+ p_ptrn_lines = 1;
+ else {
+ p_ptrn_lines = 0;
+ p_first = 1;
+ }
+ p_max = p_ptrn_lines + 6; /* we need this much at least */
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ p_max = hunkmax;
+ break;
+ case '-':
+ if (buf[1] == '-') {
+ if (repl_beginning ||
+ (p_end != p_ptrn_lines + 1 + (p_Char[p_end-1] == '\n')))
+ {
+ if (p_end == 1) {
+ /* `old' lines were omitted - set up to fill */
+ /* them in from 'new' context lines. */
+ p_end = p_ptrn_lines + 1;
+ fillsrc = p_end + 1;
+ filldst = 1;
+ fillcnt = p_ptrn_lines;
+ }
+ else {
+ if (repl_beginning) {
+ if (repl_could_be_missing){
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ fatal3(
+"duplicate \"---\" at line %ld--check line numbers at line %ld\n",
+ p_input_line, p_hunk_beg + repl_beginning);
+ }
+ else {
+ fatal4(
+"%s \"---\" at line %ld--check line numbers at line %ld\n",
+ (p_end <= p_ptrn_lines
+ ? "Premature"
+ : "Overdue" ),
+ p_input_line, p_hunk_beg);
+ }
+ }
+ }
+ repl_beginning = p_end;
+ repl_backtrack_position = ftell(pfp);
+ repl_patch_line = p_input_line;
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return FALSE;
+ }
+ p_Char[p_end] = '=';
+ for (s=buf; *s && !isdigit((unsigned char)*s); s++) ;
+ if (!*s)
+ malformed ();
+ p_newfirst = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s)) s++;
+ if (*s == ',') {
+ for (; *s && !isdigit((unsigned char)*s); s++) ;
+ if (!*s)
+ malformed ();
+ p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1;
+ }
+ else if (p_newfirst)
+ p_repl_lines = 1;
+ else {
+ p_repl_lines = 0;
+ p_newfirst = 1;
+ }
+ p_max = p_repl_lines + p_end;
+ if (p_max > MAXHUNKSIZE)
+ fatal4("hunk too large (%ld lines) at line %ld: %s",
+ p_max, p_input_line, buf);
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ if (p_repl_lines != ptrn_copiable
+ && (p_context != 0 || p_repl_lines != 1))
+ repl_could_be_missing = FALSE;
+ break;
+ }
+ goto change_line;
+ case '+': case '!':
+ repl_could_be_missing = FALSE;
+ change_line:
+ if (buf[1] == '\n' && canonicalize)
+ strcpy(buf+1," \n");
+ if (!isspace((unsigned char)buf[1]) && buf[1] != '>' && buf[1] != '<' &&
+ repl_beginning && repl_could_be_missing) {
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ if (context >= 0) {
+ if (context < p_context)
+ p_context = context;
+ context = -1000;
+ }
+ p_line[p_end] = savestr(buf+2);
+ if (out_of_mem) {
+ p_end--;
+ return FALSE;
+ }
+ if (p_end == p_ptrn_lines)
+ {
+ if (remove_special_line()) {
+ int len;
+
+ len = strlen(p_line[p_end]) - 1;
+ (p_line[p_end])[len] = 0;
+ }
+ }
+ break;
+ case '\t': case '\n': /* assume the 2 spaces got eaten */
+ if (repl_beginning && repl_could_be_missing &&
+ (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF) ) {
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ p_line[p_end] = savestr(buf);
+ if (out_of_mem) {
+ p_end--;
+ return FALSE;
+ }
+ if (p_end != p_ptrn_lines + 1) {
+ ptrn_spaces_eaten |= (repl_beginning != 0);
+ context++;
+ if (!repl_beginning)
+ ptrn_copiable++;
+ p_Char[p_end] = ' ';
+ }
+ break;
+ case ' ':
+ if (!isspace((unsigned char)buf[1]) &&
+ repl_beginning && repl_could_be_missing) {
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ context++;
+ if (!repl_beginning)
+ ptrn_copiable++;
+ p_line[p_end] = savestr(buf+2);
+ if (out_of_mem) {
+ p_end--;
+ return FALSE;
+ }
+ break;
+ default:
+ if (repl_beginning && repl_could_be_missing) {
+ repl_missing = TRUE;
+ goto hunk_done;
+ }
+ malformed ();
+ }
+ /* set up p_len for strncmp() so we don't have to */
+ /* assume null termination */
+ if (p_line[p_end])
+ p_len[p_end] = strlen(p_line[p_end]);
+ else
+ p_len[p_end] = 0;
+ }
+
+ hunk_done:
+ if (p_end >=0 && !repl_beginning)
+ fatal2("no --- found in patch at line %ld\n", pch_hunk_beg());
+
+ if (repl_missing) {
+
+ /* reset state back to just after --- */
+ p_input_line = repl_patch_line;
+ for (p_end--; p_end > repl_beginning; p_end--)
+ free(p_line[p_end]);
+ Fseek(pfp, repl_backtrack_position, 0);
+
+ /* redundant 'new' context lines were omitted - set */
+ /* up to fill them in from the old file context */
+ if (!p_context && p_repl_lines == 1) {
+ p_repl_lines = 0;
+ p_max--;
+ }
+ fillsrc = 1;
+ filldst = repl_beginning+1;
+ fillcnt = p_repl_lines;
+ p_end = p_max;
+ }
+ else if (!p_context && fillcnt == 1) {
+ /* the first hunk was a null hunk with no context */
+ /* and we were expecting one line -- fix it up. */
+ while (filldst < p_end) {
+ p_line[filldst] = p_line[filldst+1];
+ p_Char[filldst] = p_Char[filldst+1];
+ p_len[filldst] = p_len[filldst+1];
+ filldst++;
+ }
+#if 0
+ repl_beginning--; /* this doesn't need to be fixed */
+#endif
+ p_end--;
+ p_first++; /* do append rather than insert */
+ fillcnt = 0;
+ p_ptrn_lines = 0;
+ }
+
+ if (diff_type == CONTEXT_DIFF &&
+ (fillcnt || (p_first > 1 && ptrn_copiable > 2*p_context)) ) {
+ if (verbose)
+ say4("%s\n%s\n%s\n",
+"(Fascinating--this is really a new-style context diff but without",
+"the telltale extra asterisks on the *** line that usually indicate",
+"the new style...)");
+ diff_type = NEW_CONTEXT_DIFF;
+ }
+
+ /* if there were omitted context lines, fill them in now */
+ if (fillcnt) {
+ p_bfake = filldst; /* remember where not to free() */
+ p_efake = filldst + fillcnt - 1;
+ while (fillcnt-- > 0) {
+ while (fillsrc <= p_end && p_Char[fillsrc] != ' ')
+ fillsrc++;
+ if (fillsrc > p_end)
+ fatal2("replacement text or line numbers mangled in hunk at line %ld\n",
+ p_hunk_beg);
+ p_line[filldst] = p_line[fillsrc];
+ p_Char[filldst] = p_Char[fillsrc];
+ p_len[filldst] = p_len[fillsrc];
+ fillsrc++; filldst++;
+ }
+ while (fillsrc <= p_end && fillsrc != repl_beginning &&
+ p_Char[fillsrc] != ' ')
+ fillsrc++;
+#ifdef DEBUGGING
+ if (debug & 64)
+ printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
+ fillsrc,filldst,repl_beginning,p_end+1);
+#endif
+ assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
+ assert(filldst==p_end+1 || filldst==repl_beginning);
+ }
+
+ if (p_line[p_end] != NULL)
+ {
+ if (remove_special_line()) {
+ p_len[p_end] -= 1;
+ (p_line[p_end])[p_len[p_end]] = 0;
+ }
+ }
+ }
+ else if (diff_type == UNI_DIFF) {
+ long line_beginning = ftell(pfp);
+ /* file pos of the current line */
+ Reg4 LINENUM fillsrc; /* index of old lines */
+ Reg5 LINENUM filldst; /* index of new lines */
+ char ch;
+
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch || strnNE(buf, "@@ -", 4)) {
+ next_intuit_at(line_beginning,p_input_line);
+ return FALSE;
+ }
+ s = buf+4;
+ if (!*s)
+ malformed ();
+ p_first = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s)) s++;
+ if (*s == ',') {
+ p_ptrn_lines = (LINENUM) atol(++s);
+ while (isdigit((unsigned char)*s)) s++;
+ } else
+ p_ptrn_lines = 1;
+ if (*s == ' ') s++;
+ if (*s != '+' || !*++s)
+ malformed ();
+ p_newfirst = (LINENUM) atol(s);
+ while (isdigit((unsigned char)*s)) s++;
+ if (*s == ',') {
+ p_repl_lines = (LINENUM) atol(++s);
+ while (isdigit((unsigned char)*s)) s++;
+ } else
+ p_repl_lines = 1;
+ if (*s == ' ') s++;
+ if (*s != '@')
+ malformed ();
+ if (!p_ptrn_lines)
+ p_first++; /* do append rather than insert */
+ p_max = p_ptrn_lines + p_repl_lines + 1;
+ while (p_max >= hunkmax)
+ grow_hunkmax();
+ fillsrc = 1;
+ filldst = fillsrc + p_ptrn_lines;
+ p_end = filldst + p_repl_lines;
+ Sprintf(buf,"*** %ld,%ld ****\n",p_first,p_first + p_ptrn_lines - 1);
+ p_line[0] = savestr(buf);
+ if (out_of_mem) {
+ p_end = -1;
+ return FALSE;
+ }
+ p_Char[0] = '*';
+ Sprintf(buf,"--- %ld,%ld ----\n",p_newfirst,p_newfirst+p_repl_lines-1);
+ p_line[filldst] = savestr(buf);
+ if (out_of_mem) {
+ p_end = 0;
+ return FALSE;
+ }
+ p_Char[filldst++] = '=';
+ p_context = 100;
+ context = 0;
+ p_hunk_beg = p_input_line + 1;
+ while (fillsrc <= p_ptrn_lines || filldst <= p_end) {
+ line_beginning = ftell(pfp);
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch) {
+ if (p_max - filldst < 3)
+ Strcpy(buf, " \n"); /* assume blank lines got chopped */
+ else {
+ fatal1("unexpected end of file in patch\n");
+ }
+ }
+ if (*buf == '\t' || *buf == '\n') {
+ ch = ' '; /* assume the space got eaten */
+ s = savestr(buf);
+ }
+ else {
+ ch = *buf;
+ s = savestr(buf+1);
+ }
+ if (out_of_mem) {
+ while (--filldst > p_ptrn_lines)
+ free(p_line[filldst]);
+ p_end = fillsrc-1;
+ return FALSE;
+ }
+ switch (ch) {
+ case '-':
+ if (fillsrc > p_ptrn_lines) {
+ free(s);
+ p_end = filldst-1;
+ malformed ();
+ }
+ p_Char[fillsrc] = ch;
+ p_line[fillsrc] = s;
+ p_len[fillsrc++] = strlen(s);
+ if (fillsrc > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[fillsrc - 1] -= 1;
+ s[p_len[fillsrc - 1]] = 0;
+ }
+ }
+ break;
+ case '=':
+ ch = ' ';
+ /* FALLTHROUGH */
+ case ' ':
+ if (fillsrc > p_ptrn_lines) {
+ free(s);
+ while (--filldst > p_ptrn_lines)
+ free(p_line[filldst]);
+ p_end = fillsrc-1;
+ malformed ();
+ }
+ context++;
+ p_Char[fillsrc] = ch;
+ p_line[fillsrc] = s;
+ p_len[fillsrc++] = strlen(s);
+ s = savestr(s);
+ if (out_of_mem) {
+ while (--filldst > p_ptrn_lines)
+ free(p_line[filldst]);
+ p_end = fillsrc-1;
+ return FALSE;
+ }
+ /* FALLTHROUGH */
+ case '+':
+ if (filldst > p_end) {
+ free(s);
+ while (--filldst > p_ptrn_lines)
+ free(p_line[filldst]);
+ p_end = fillsrc-1;
+ malformed ();
+ }
+ p_Char[filldst] = ch;
+ p_line[filldst] = s;
+ p_len[filldst++] = strlen(s);
+ if (fillsrc > p_ptrn_lines) {
+ if (remove_special_line()) {
+ p_len[filldst - 1] -= 1;
+ s[p_len[filldst - 1]] = 0;
+ }
+ }
+ break;
+ default:
+ p_end = filldst;
+ malformed ();
+ }
+ if (ch != ' ' && context > 0) {
+ if (context < p_context)
+ p_context = context;
+ context = -1000;
+ }
+ }/* while */
+ }
+ else { /* normal diff--fake it up */
+ char hunk_type;
+ Reg3 int i;
+ LINENUM min, max;
+ long line_beginning = ftell(pfp);
+
+ p_context = 0;
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch || !isdigit((unsigned char)*buf)) {
+ next_intuit_at(line_beginning,p_input_line);
+ return FALSE;
+ }
+ p_first = (LINENUM)atol(buf);
+ for (s=buf; isdigit((unsigned char)*s); s++) ;
+ if (*s == ',') {
+ p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
+ while (isdigit((unsigned char)*s)) s++;
+ }
+ else
+ p_ptrn_lines = (*s != 'a');
+ hunk_type = *s;
+ if (hunk_type == 'a')
+ p_first++; /* do append rather than insert */
+ min = (LINENUM)atol(++s);
+ for (; isdigit((unsigned char)*s); s++) ;
+ if (*s == ',')
+ max = (LINENUM)atol(++s);
+ else
+ max = min;
+ if (hunk_type == 'd')
+ min++;
+ p_end = p_ptrn_lines + 1 + max - min + 1;
+ if (p_end > MAXHUNKSIZE)
+ fatal4("hunk too large (%ld lines) at line %ld: %s",
+ p_end, p_input_line, buf);
+ while (p_end >= hunkmax)
+ grow_hunkmax();
+ p_newfirst = min;
+ p_repl_lines = max - min + 1;
+ Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
+ p_line[0] = savestr(buf);
+ if (out_of_mem) {
+ p_end = -1;
+ return FALSE;
+ }
+ p_Char[0] = '*';
+ for (i=1; i<=p_ptrn_lines; i++) {
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch)
+ fatal2("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '<')
+ fatal2("< expected at line %ld of patch\n", p_input_line);
+ p_line[i] = savestr(buf+2);
+ if (out_of_mem) {
+ p_end = i-1;
+ return FALSE;
+ }
+ p_len[i] = strlen(p_line[i]);
+ p_Char[i] = '-';
+ }
+
+ if (remove_special_line()) {
+ p_len[i-1] -= 1;
+ (p_line[i-1])[p_len[i-1]] = 0;
+ }
+
+ if (hunk_type == 'c') {
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch)
+ fatal2("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '-')
+ fatal2("--- expected at line %ld of patch\n", p_input_line);
+ }
+ Sprintf(buf, "--- %ld,%ld\n", min, max);
+ p_line[i] = savestr(buf);
+ if (out_of_mem) {
+ p_end = i-1;
+ return FALSE;
+ }
+ p_Char[i] = '=';
+ for (i++; i<=p_end; i++) {
+ ret = pgets(buf, sizeof buf, pfp);
+ p_input_line++;
+ if (ret == Nullch)
+ fatal2("unexpected end of file in patch at line %ld\n",
+ p_input_line);
+ if (*buf != '>')
+ fatal2("> expected at line %ld of patch\n", p_input_line);
+ p_line[i] = savestr(buf+2);
+ if (out_of_mem) {
+ p_end = i-1;
+ return FALSE;
+ }
+ p_len[i] = strlen(p_line[i]);
+ p_Char[i] = '+';
+ }
+
+ if (remove_special_line()) {
+ p_len[i-1] -= 1;
+ (p_line[i-1])[p_len[i-1]] = 0;
+ }
+ }
+ if (reverse) /* backwards patch? */
+ if (!pch_swap())
+ say1("Not enough memory to swap next hunk!\n");
+#ifdef DEBUGGING
+ if (debug & 2) {
+ int i;
+ char special;
+
+ for (i=0; i <= p_end; i++) {
+ if (i == p_ptrn_lines)
+ special = '^';
+ else
+ special = ' ';
+ fprintf(stderr, "%3d %c %c %s", i, p_Char[i], special, p_line[i]);
+ Fflush(stderr);
+ }
+ }
+#endif
+ if (p_end+1 < hunkmax) /* paranoia reigns supreme... */
+ p_Char[p_end+1] = '^'; /* add a stopper for apply_hunk */
+ return TRUE;
+}
+
+/*
+ * Input a line from the patch file, worrying about indentation.
+ */
+char *
+pgets(char *bf, int sz, FILE *fp)
+{
+ char *ret = fgets(bf, sz, fp);
+ Reg1 char *s;
+ Reg2 int indent = 0;
+
+ if (p_indent && ret != Nullch) {
+ for (s=buf;
+ indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X');
+ s++) {
+ if (*s == '\t')
+ indent += 8 - (indent % 7);
+ else
+ indent++;
+ }
+ if (buf != s)
+ Strcpy(buf, s);
+ }
+ return ret;
+}
+
+/*
+ * Reverse the old and new portions of the current hunk.
+ */
+bool
+pch_swap(void)
+{
+ char **tp_line; /* the text of the hunk */
+ short *tp_len; /* length of each line */
+ char *tp_char; /* +, -, and ! */
+ Reg1 LINENUM i;
+ Reg2 LINENUM n;
+ bool blankline = FALSE;
+ Reg3 char *s;
+
+ i = p_first;
+ p_first = p_newfirst;
+ p_newfirst = i;
+
+ /* make a scratch copy */
+
+ tp_line = p_line;
+ tp_len = p_len;
+ tp_char = p_Char;
+ p_line = Null(char**); /* force set_hunkmax to allocate again */
+ p_len = Null(short*);
+ p_Char = Nullch;
+ set_hunkmax();
+ if (p_line == Null(char**) || p_len == Null(short*) || p_Char == Nullch) {
+#ifndef lint
+ if (p_line == Null(char**))
+ free((char*)p_line);
+ p_line = tp_line;
+ if (p_len == Null(short*))
+ free((char*)p_len);
+ p_len = tp_len;
+#endif
+ if (p_Char == Nullch)
+ free((char*)p_Char);
+ p_Char = tp_char;
+ return FALSE; /* not enough memory to swap hunk! */
+ }
+
+ /* now turn the new into the old */
+
+ i = p_ptrn_lines + 1;
+ if (tp_char[i] == '\n') { /* account for possible blank line */
+ blankline = TRUE;
+ i++;
+ }
+ if (p_efake >= 0) { /* fix non-freeable ptr range */
+ if (p_efake <= i)
+ n = p_end - i + 1;
+ else
+ n = -i;
+ p_efake += n;
+ p_bfake += n;
+ }
+ for (n=0; i <= p_end; i++,n++) {
+ p_line[n] = tp_line[i];
+ p_Char[n] = tp_char[i];
+ if (p_Char[n] == '+')
+ p_Char[n] = '-';
+ p_len[n] = tp_len[i];
+ }
+ if (blankline) {
+ i = p_ptrn_lines + 1;
+ p_line[n] = tp_line[i];
+ p_Char[n] = tp_char[i];
+ p_len[n] = tp_len[i];
+ n++;
+ }
+ assert(p_Char[0] == '=');
+ p_Char[0] = '*';
+ for (s=p_line[0]; *s; s++)
+ if (*s == '-')
+ *s = '*';
+
+ /* now turn the old into the new */
+
+ assert(tp_char[0] == '*');
+ tp_char[0] = '=';
+ for (s=tp_line[0]; *s; s++)
+ if (*s == '*')
+ *s = '-';
+ for (i=0; n <= p_end; i++,n++) {
+ p_line[n] = tp_line[i];
+ p_Char[n] = tp_char[i];
+ if (p_Char[n] == '-')
+ p_Char[n] = '+';
+ p_len[n] = tp_len[i];
+ }
+ assert(i == p_ptrn_lines + 1);
+ i = p_ptrn_lines;
+ p_ptrn_lines = p_repl_lines;
+ p_repl_lines = i;
+#ifndef lint
+ if (tp_line == Null(char**))
+ free((char*)tp_line);
+ if (tp_len == Null(short*))
+ free((char*)tp_len);
+#endif
+ if (tp_char == Nullch)
+ free((char*)tp_char);
+ return TRUE;
+}
+
+/*
+ * Return the specified line position in the old file of the old context.
+ */
+LINENUM
+pch_first(void)
+{
+ return p_first;
+}
+
+/*
+ * Return the number of lines of old context.
+ */
+LINENUM
+pch_ptrn_lines(void)
+{
+ return p_ptrn_lines;
+}
+
+/*
+ * Return the probable line position in the new file of the first line.
+ */
+LINENUM
+pch_newfirst(void)
+{
+ return p_newfirst;
+}
+
+/*
+ * Return the number of lines in the replacement text including context.
+ */
+LINENUM
+pch_repl_lines(void)
+{
+ return p_repl_lines;
+}
+
+/*
+ * Return the number of lines in the whole hunk.
+ */
+LINENUM
+pch_end(void)
+{
+ return p_end;
+}
+
+/*
+ * Return the number of context lines before the first changed line.
+ */
+LINENUM
+pch_context(void)
+{
+ return p_context;
+}
+
+/*
+ * Return the length of a particular patch line.
+ */
+short
+pch_line_len(LINENUM line)
+{
+ return p_len[line];
+}
+
+/*
+ * Return the control character (+, -, *, !, etc) for a patch line.
+ */
+char
+pch_char(LINENUM line)
+{
+ return p_Char[line];
+}
+
+/*
+ * Return a pointer to a particular patch line.
+ */
+char *
+pfetch(LINENUM line)
+{
+ return p_line[line];
+}
+
+/*
+ * Return where in the patch file this hunk began, for error messages.
+ */
+LINENUM
+pch_hunk_beg(void)
+{
+ return p_hunk_beg;
+}
+
+/*
+ * Apply an ed script by feeding ed itself.
+ */
+void
+do_ed_script(void)
+{
+ Reg1 char *t;
+ Reg2 long beginning_of_this_line;
+ Reg3 bool this_line_is_command = FALSE;
+ Reg4 FILE *pipefp;
+
+ if (!skip_rest_of_patch) {
+ Unlink(TMPOUTNAME);
+ copy_file(filearg[0], TMPOUTNAME);
+ if (verbose)
+ Sprintf(buf, "/bin/ed %s", TMPOUTNAME);
+ else
+ Sprintf(buf, "/bin/ed - %s", TMPOUTNAME);
+ pipefp = popen(buf, "w");
+ }
+ for (;;) {
+ beginning_of_this_line = ftell(pfp);
+ if (pgets(buf, sizeof buf, pfp) == Nullch) {
+ next_intuit_at(beginning_of_this_line, p_input_line);
+ break;
+ }
+ p_input_line++;
+ for (t=buf; isdigit((unsigned char)*t) || *t == ','; t++)
+ ;
+ this_line_is_command = (isdigit((unsigned char)*buf) &&
+ (*t == 'd' || *t == 'c' || *t == 'a') );
+ if (this_line_is_command) {
+ if (!skip_rest_of_patch)
+ fputs(buf, pipefp);
+ if (*t != 'd') {
+ while (pgets(buf, sizeof buf, pfp) != Nullch) {
+ p_input_line++;
+ if (!skip_rest_of_patch)
+ fputs(buf, pipefp);
+ if (strEQ(buf, ".\n"))
+ break;
+ }
+ }
+ }
+ else {
+ next_intuit_at(beginning_of_this_line,p_input_line);
+ break;
+ }
+ }
+ if (skip_rest_of_patch)
+ return;
+ fprintf(pipefp, "w\n");
+ fprintf(pipefp, "q\n");
+ Fflush(pipefp);
+ Pclose(pipefp);
+ ignore_signals();
+ if (move_file(TMPOUTNAME, outname) < 0) {
+ toutkeep = TRUE;
+ chmod(TMPOUTNAME, filemode);
+ }
+ else
+ chmod(outname, filemode);
+ set_signals(1);
+}
diff --git a/gnu/usr.bin/patch/pch.h b/gnu/usr.bin/patch/pch.h
new file mode 100644
index 0000000..d815fe8
--- /dev/null
+++ b/gnu/usr.bin/patch/pch.h
@@ -0,0 +1,36 @@
+/* $FreeBSD$
+ *
+ * $Log: pch.h,v $
+ * Revision 2.0.1.1 87/01/30 22:47:16 lwall
+ * Added do_ed_script().
+ *
+ * Revision 2.0 86/09/17 15:39:57 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+EXT FILE *pfp INIT(Nullfp); /* patch file pointer */
+
+void re_patch(void);
+void open_patch_file(char *_filename);
+void set_hunkmax(void);
+void grow_hunkmax(void);
+bool there_is_another_patch(void);
+int intuit_diff_type(void);
+void next_intuit_at(long _file_pos, long _file_line);
+void skip_to(long _file_pos, long _file_line);
+bool another_hunk(void);
+bool pch_swap(void);
+char *pfetch(LINENUM _line);
+short pch_line_len(LINENUM _line);
+LINENUM pch_first(void);
+LINENUM pch_ptrn_lines(void);
+LINENUM pch_newfirst(void);
+LINENUM pch_repl_lines(void);
+LINENUM pch_end(void);
+LINENUM pch_context(void);
+LINENUM pch_hunk_beg(void);
+char pch_char(LINENUM _line);
+char *pfetch(LINENUM _line);
+char *pgets(char *_bf, int _sz, FILE *_fp);
+void do_ed_script(void);
diff --git a/gnu/usr.bin/patch/util.c b/gnu/usr.bin/patch/util.c
new file mode 100644
index 0000000..b6e6652
--- /dev/null
+++ b/gnu/usr.bin/patch/util.c
@@ -0,0 +1,458 @@
+/* $FreeBSD$ */
+
+#include <paths.h>
+
+#include "EXTERN.h"
+#include "common.h"
+#include "INTERN.h"
+#include "util.h"
+#include "backupfile.h"
+
+void my_exit(int _status); /* in patch.c */
+
+#ifndef HAVE_STRERROR
+static char *
+private_strerror (errnum)
+ int errnum;
+{
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+
+ if (errnum > 0 && errnum <= sys_nerr)
+ return sys_errlist[errnum];
+ return "Unknown system error";
+}
+#define strerror private_strerror
+#endif /* !HAVE_STRERROR */
+
+/*
+ * Rename a file, copying it if necessary.
+ */
+int
+move_file(char *from, char *to)
+{
+ char bakname[512];
+ Reg1 char *s;
+ Reg2 int i;
+ Reg3 int fromfd;
+
+ /* to stdout? */
+
+ if (strEQ(to, "-")) {
+#ifdef DEBUGGING
+ if (debug & 4)
+ say2("Moving %s to stdout.\n", from);
+#endif
+ fromfd = open(from, 0);
+ if (fromfd < 0)
+ pfatal2("internal error, can't reopen %s", from);
+ while ((i = read(fromfd, buf, sizeof buf)) > 0)
+ if (write(1, buf, i) != 1)
+ pfatal1("write failed");
+ Close(fromfd);
+ return 0;
+ }
+
+ if (origprae) {
+ Strcpy(bakname, origprae);
+ Strcat(bakname, to);
+ } else {
+#ifndef NODIR
+ char *backupname = find_backup_file_name(to);
+ if (backupname == (char *) 0)
+ fatal1("out of memory\n");
+ Strcpy(bakname, backupname);
+ free(backupname);
+#else /* NODIR */
+ Strcpy(bakname, to);
+ Strcat(bakname, simple_backup_suffix);
+#endif /* NODIR */
+ }
+
+ if (stat(to, &filestat) == 0) { /* output file exists */
+ dev_t to_device = filestat.st_dev;
+ ino_t to_inode = filestat.st_ino;
+ char *simplename = bakname;
+
+ for (s = bakname; *s; s++) {
+ if (*s == '/')
+ simplename = s + 1;
+ }
+ /*
+ * Find a backup name that is not the same file.
+ * Change the first lowercase char into uppercase;
+ * if that isn't sufficient, chop off the first char
+ * and try again.
+ */
+ while (stat(bakname, &filestat) == 0 &&
+ to_device == filestat.st_dev &&
+ to_inode == filestat.st_ino) {
+ /* Skip initial non-lowercase chars. */
+ for (s=simplename; *s && !islower((unsigned char)*s);
+ s++)
+ ;
+ if (*s)
+ *s = toupper((unsigned char)*s);
+ else
+ Strcpy(simplename, simplename + 1);
+ }
+ while (unlink(bakname) >= 0)
+ ; /* while() is for benefit of Eunice */
+#ifdef DEBUGGING
+ if (debug & 4)
+ say3("Moving %s to %s.\n", to, bakname);
+#endif
+ if (rename(to, bakname) < 0) {
+ say4("Can't backup %s, output is in %s: %s\n", to, from,
+ strerror(errno));
+ return -1;
+ }
+ while (unlink(to) >= 0)
+ ;
+ }
+#ifdef DEBUGGING
+ if (debug & 4)
+ say3("Moving %s to %s.\n", from, to);
+#endif
+ if (rename(from, to) < 0) { /* different file system? */
+ Reg4 int tofd;
+
+ tofd = creat(to, 0666);
+ if (tofd < 0) {
+ say4("Can't create %s, output is in %s: %s\n",
+ to, from, strerror(errno));
+ return -1;
+ }
+ fromfd = open(from, 0);
+ if (fromfd < 0)
+ pfatal2("internal error, can't reopen %s", from);
+ while ((i = read(fromfd, buf, sizeof buf)) > 0)
+ if (write(tofd, buf, i) != i)
+ pfatal1("write failed");
+ Close(fromfd);
+ Close(tofd);
+ }
+ Unlink(from);
+ return 0;
+}
+
+/*
+ * Copy a file.
+ */
+void
+copy_file(char *from, char *to)
+{
+ Reg3 int tofd;
+ Reg2 int fromfd;
+ Reg1 int i;
+
+ tofd = creat(to, 0666);
+ if (tofd < 0)
+ pfatal2("can't create %s", to);
+ fromfd = open(from, 0);
+ if (fromfd < 0)
+ pfatal2("internal error, can't reopen %s", from);
+ while ((i = read(fromfd, buf, sizeof buf)) > 0)
+ if (write(tofd, buf, i) != i)
+ pfatal2("write to %s failed", to);
+ Close(fromfd);
+ Close(tofd);
+}
+
+/*
+ * Allocate a unique area for a string.
+ */
+char *
+savestr(char *s)
+{
+ Reg3 char *rv;
+ Reg2 char *t;
+
+ if (!s)
+ s = "Oops";
+ t = s;
+ while (*t++)
+ ;
+ rv = malloc((MEM) (t - s));
+ if (rv == Nullch) {
+ if (using_plan_a)
+ out_of_mem = TRUE;
+ else
+ fatal1("out of memory\n");
+ } else {
+ t = rv;
+ while ((*t++ = *s++));
+ }
+ return rv;
+}
+
+#if defined(lint) && defined(CANVARARG)
+
+/*VARARGS ARGSUSED*/
+say(pat) char *pat; { ; }
+/*VARARGS ARGSUSED*/
+fatal(pat) char *pat; { ; }
+/*VARARGS ARGSUSED*/
+pfatal(pat) char *pat; { ; }
+/*VARARGS ARGSUSED*/
+ask(pat) char *pat; { ; }
+
+#else
+
+/*
+ * Vanilla terminal output (buffered).
+ */
+void
+say(pat,arg1,arg2,arg3)
+char *pat;
+long arg1,arg2,arg3;
+{
+ fprintf(stderr, pat, arg1, arg2, arg3);
+ Fflush(stderr);
+}
+
+/*
+ * Terminal output, pun intended.
+ */
+void /* very void */
+fatal(pat,arg1,arg2,arg3)
+char *pat;
+long arg1,arg2,arg3;
+{
+ fprintf(stderr, "patch: **** ");
+ fprintf(stderr, pat, arg1, arg2, arg3);
+ my_exit(1);
+}
+
+/*
+ * Say something from patch, something from the system, then silence...
+ */
+void /* very void */
+pfatal(pat,arg1,arg2,arg3)
+char *pat;
+long arg1,arg2,arg3;
+{
+ int errnum = errno;
+
+ fprintf(stderr, "patch: **** ");
+ fprintf(stderr, pat, arg1, arg2, arg3);
+ fprintf(stderr, ": %s\n", strerror(errnum));
+ my_exit(1);
+}
+
+/*
+ * Get a response from the user, somehow or other.
+ */
+int
+ask(pat,arg1,arg2,arg3)
+char *pat;
+long arg1,arg2,arg3;
+{
+ int ttyfd;
+ int r;
+ bool tty2 = isatty(2);
+
+ Sprintf(buf, pat, arg1, arg2, arg3);
+ Fflush(stderr);
+ write(2, buf, strlen(buf));
+ if (tty2) { /* might be redirected to a file */
+ r = read(2, buf, sizeof buf);
+ } else if (isatty(1)) { /* this may be new file output */
+ Fflush(stdout);
+ write(1, buf, strlen(buf));
+ r = read(1, buf, sizeof buf);
+ } else if ((ttyfd = open(_PATH_TTY, 2)) >= 0 && isatty(ttyfd)) {
+ /* might be deleted or unwriteable */
+ write(ttyfd, buf, strlen(buf));
+ r = read(ttyfd, buf, sizeof buf);
+ Close(ttyfd);
+ } else if (isatty(0)) { /* this is probably patch input */
+ Fflush(stdin);
+ write(0, buf, strlen(buf));
+ r = read(0, buf, sizeof buf);
+ } else { /* no terminal at all--default it */
+ buf[0] = '\n';
+ buf[1] = 0;
+ say1(buf);
+ return 0; /* signal possible error */
+ }
+ if (r <= 0)
+ buf[0] = 0;
+ else
+ buf[r] = '\0';
+ if (!tty2)
+ say1(buf);
+
+ if (r <= 0)
+ return 0; /* if there was an error, return it */
+ else
+ return 1;
+}
+#endif /* lint */
+
+/*
+ * How to handle certain events when not in a critical region.
+ */
+void
+set_signals(int reset)
+{
+#ifndef lint
+ static RETSIGTYPE (*hupval)(),(*intval)();
+
+ if (!reset) {
+ hupval = signal(SIGHUP, SIG_IGN);
+ if (hupval != SIG_IGN)
+ hupval = (RETSIGTYPE(*)())my_exit;
+ intval = signal(SIGINT, SIG_IGN);
+ if (intval != SIG_IGN)
+ intval = (RETSIGTYPE(*)())my_exit;
+ }
+ Signal(SIGHUP, hupval);
+ Signal(SIGINT, intval);
+#endif
+}
+
+/*
+ * How to handle certain events when in a critical region.
+ */
+void
+ignore_signals(void)
+{
+#ifndef lint
+ Signal(SIGHUP, SIG_IGN);
+ Signal(SIGINT, SIG_IGN);
+#endif
+}
+
+/*
+ * Make sure we'll have the directories to create a file.
+ * If `striplast' is TRUE, ignore the last element of `filename'.
+ */
+void
+makedirs(filename,striplast)
+Reg1 char *filename;
+bool striplast;
+{
+ char tmpbuf[256];
+ Reg2 char *s = tmpbuf;
+ char *dirv[20]; /* Point to the NULs between elements. */
+ Reg3 int i;
+ Reg4 int dirvp = 0; /* Number of finished entries in dirv. */
+
+ /*
+ * Copy `filename' into `tmpbuf' with a NUL instead of a slash
+ * between the directories.
+ */
+ while (*filename) {
+ if (*filename == '/') {
+ filename++;
+ dirv[dirvp++] = s;
+ *s++ = '\0';
+ } else {
+ *s++ = *filename++;
+ }
+ }
+ *s = '\0';
+ dirv[dirvp] = s;
+ if (striplast)
+ dirvp--;
+ if (dirvp < 0)
+ return;
+
+ strcpy(buf, "mkdir");
+ s = buf;
+ for (i = 0; i <= dirvp; i++) {
+ struct stat sbuf;
+
+ if (stat(tmpbuf, &sbuf) && errno == ENOENT) {
+ while (*s)
+ s++;
+ *s++ = ' ';
+ strcpy(s, tmpbuf);
+ }
+ *dirv[i] = '/';
+ }
+ if (s != buf)
+ system(buf);
+}
+
+/*
+ * Make filenames more reasonable.
+ */
+char *
+fetchname(char *at, int strip_leading, int assume_exists)
+{
+ char *fullname;
+ char *name;
+ Reg1 char *t;
+ char tmpbuf[200];
+ int sleading = strip_leading;
+
+ if (!at)
+ return Nullch;
+ while (isspace((unsigned char)*at))
+ at++;
+#ifdef DEBUGGING
+ if (debug & 128)
+ say4("fetchname %s %d %d\n",at,strip_leading,assume_exists);
+#endif
+ if (strnEQ(at, _PATH_DEVNULL, sizeof _PATH_DEVNULL - 1))
+ /* So files can be created by diffing against /dev/null. */
+ return Nullch;
+ name = fullname = t = savestr(at);
+
+ /* Strip off up to `sleading' leading slashes and null terminate. */
+ for (; *t && !isspace((unsigned char)*t); t++)
+ if (*t == '/')
+ if (--sleading >= 0)
+ name = t + 1;
+ *t = '\0';
+
+ /*
+ * If no -p option was given (957 is the default value!),
+ * we were given a relative pathname,
+ * and the leading directories that we just stripped off all exist,
+ * put them back on.
+ */
+ if (strip_leading == 957 && name != fullname && *fullname != '/') {
+ name[-1] = '\0';
+ if (stat(fullname, &filestat) == 0 &&
+ S_ISDIR(filestat.st_mode)) {
+ name[-1] = '/';
+ name = fullname;
+ }
+ }
+
+ name = savestr(name);
+ free(fullname);
+
+ if (stat(name, &filestat) && !assume_exists) {
+ char *filebase = basename(name);
+ int pathlen = filebase - name;
+
+ /* Put any leading path into `tmpbuf'. */
+ strncpy(tmpbuf, name, pathlen);
+
+#define try(f, a1, a2) \
+ (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0)
+ if (try("RCS/%s%s", filebase, RCSSUFFIX) ||
+ try("RCS/%s%s", filebase, "") ||
+ try( "%s%s", filebase, RCSSUFFIX) ||
+ try("SCCS/%s%s", SCCSPREFIX, filebase) ||
+ try( "%s%s", SCCSPREFIX, filebase))
+ return name;
+ free(name);
+ name = Nullch;
+ }
+
+ return name;
+}
+
+char *
+xmalloc(unsigned int size)
+{
+ register char *p = (char *) malloc (size);
+ if (!p)
+ fatal("out of memory");
+ return p;
+}
diff --git a/gnu/usr.bin/patch/util.h b/gnu/usr.bin/patch/util.h
new file mode 100644
index 0000000..f31f2e2
--- /dev/null
+++ b/gnu/usr.bin/patch/util.h
@@ -0,0 +1,88 @@
+/* $FreeBSD$
+ *
+ * $Log: util.h,v $
+ * Revision 2.0 86/09/17 15:40:06 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+/* and for those machine that can't handle a variable argument list */
+
+#ifdef CANVARARG
+
+#define say1 say
+#define say2 say
+#define say3 say
+#define say4 say
+#define ask1 ask
+#define ask2 ask
+#define ask3 ask
+#define ask4 ask
+#define fatal1 fatal
+#define fatal2 fatal
+#define fatal3 fatal
+#define fatal4 fatal
+#define pfatal1 pfatal
+#define pfatal2 pfatal
+#define pfatal3 pfatal
+#define pfatal4 pfatal
+
+#else /* hope they allow multi-line macro actual arguments */
+
+#ifdef lint
+
+#define say1(a) say(a, 0, 0, 0)
+#define say2(a,b) say(a, (b)==(b), 0, 0)
+#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0)
+#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d))
+#define ask1(a) ask(a, 0, 0, 0)
+#define ask2(a,b) ask(a, (b)==(b), 0, 0)
+#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0)
+#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d))
+#define fatal1(a) fatal(a, 0, 0, 0)
+#define fatal2(a,b) fatal(a, (b)==(b), 0, 0)
+#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0)
+#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d))
+#define pfatal1(a) pfatal(a, 0, 0, 0)
+#define pfatal2(a,b) pfatal(a, (b)==(b), 0, 0)
+#define pfatal3(a,b,c) pfatal(a, (b)==(b), (c)==(c), 0)
+#define pfatal4(a,b,c,d) pfatal(a, (b)==(b), (c)==(c), (d)==(d))
+
+#else /* lint */
+ /* if this doesn't work, try defining CANVARARG above */
+#define say1(a) say(a, Nullch, Nullch, Nullch)
+#define say2(a,b) say(a, b, Nullch, Nullch)
+#define say3(a,b,c) say(a, b, c, Nullch)
+#define say4 say
+#define ask1(a) ask(a, Nullch, Nullch, Nullch)
+#define ask2(a,b) ask(a, b, Nullch, Nullch)
+#define ask3(a,b,c) ask(a, b, c, Nullch)
+#define ask4 ask
+#define fatal1(a) fatal(a, Nullch, Nullch, Nullch)
+#define fatal2(a,b) fatal(a, b, Nullch, Nullch)
+#define fatal3(a,b,c) fatal(a, b, c, Nullch)
+#define fatal4 fatal
+#define pfatal1(a) pfatal(a, Nullch, Nullch, Nullch)
+#define pfatal2(a,b) pfatal(a, b, Nullch, Nullch)
+#define pfatal3(a,b,c) pfatal(a, b, c, Nullch)
+#define pfatal4 pfatal
+
+#endif /* lint */
+
+/* if neither of the above work, join all multi-line macro calls. */
+#endif
+
+EXT char serrbuf[BUFSIZ]; /* buffer for stderr */
+
+char *fetchname(char *_at, int _strip_leading, int _assume_exists);
+int move_file(char *_from, char *_to);
+void copy_file(char *_from, char *_to);
+void say(/*const char *pat, long _arg1, long _arg2, long _arg3*/);
+void fatal();
+void pfatal();
+int ask(/*const char *pat, long _arg1, long _arg2, long _arg3*/);
+char *savestr(char *_s);
+void set_signals(int _reset);
+void ignore_signals(void);
+void makedirs(/*char *_filename, bool _striplast*/);
+char *basename();
diff --git a/gnu/usr.bin/patch/version.c b/gnu/usr.bin/patch/version.c
new file mode 100644
index 0000000..753dbfb
--- /dev/null
+++ b/gnu/usr.bin/patch/version.c
@@ -0,0 +1,25 @@
+/* $FreeBSD$
+ *
+ * $Log: version.c,v $
+ * Revision 2.0 86/09/17 15:40:11 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+#include "EXTERN.h"
+#include "common.h"
+#include "util.h"
+#include "INTERN.h"
+#include "patchlevel.h"
+#include "version.h"
+
+void my_exit(int _status); /* in patch.c */
+
+/* Print out the version number and die. */
+
+void
+version(void)
+{
+ fprintf(stderr, "Patch version %s\n", PATCH_VERSION);
+ my_exit(0);
+}
diff --git a/gnu/usr.bin/patch/version.h b/gnu/usr.bin/patch/version.h
new file mode 100644
index 0000000..faddf7c
--- /dev/null
+++ b/gnu/usr.bin/patch/version.h
@@ -0,0 +1,9 @@
+/* $FreeBSD$
+ *
+ * $Log: version.h,v $
+ * Revision 2.0 86/09/17 15:40:14 lwall
+ * Baseline for netwide release.
+ *
+ */
+
+void version(void);
diff --git a/gnu/usr.bin/rcs/CREDITS b/gnu/usr.bin/rcs/CREDITS
new file mode 100644
index 0000000..589e8b6
--- /dev/null
+++ b/gnu/usr.bin/rcs/CREDITS
@@ -0,0 +1,24 @@
+RCS was designed and built by Walter F. Tichy of Purdue University.
+RCS version 3 was released in 1983.
+
+Adam Hammer, Thomas Narten, and Daniel Trinkle of Purdue supported RCS through
+version 4.3, released in 1990. Guy Harris of Sun contributed many porting
+fixes. Paul Eggert of System Development Corporation contributed bug fixes
+and tuneups. Jay Lepreau contributed 4.3BSD support.
+
+Paul Eggert of Twin Sun wrote the changes for RCS versions 5.5 and 5.6 (1991).
+Rich Braun of Kronos and Andy Glew of Intel contributed ideas for new options.
+Bill Hahn of Stratus contributed ideas for setuid support.
+Ideas for piece tables came from Joe Berkovitz of Stratus and Walter F. Tichy.
+Matt Cross of Stratus contributed test case ideas.
+Adam Hammer of Purdue QAed.
+
+Paul Eggert wrote most of the changes for this version of RCS,
+currently in beta test. K. Richard Pixley of Cygnus Support
+contributed several bug fixes. Robert Lupton of Princeton
+and Daniel Trinkle contributed ideas for $Name expansion.
+Brendan Kehoe of Cygnus Support suggested rlog's -N option.
+Paul D. Smith of Data General suggested improvements in option
+and error processing. Adam Hammer of Purdue QAed.
+
+$FreeBSD$
diff --git a/gnu/usr.bin/rcs/Makefile b/gnu/usr.bin/rcs/Makefile
new file mode 100644
index 0000000..4a9fd08
--- /dev/null
+++ b/gnu/usr.bin/rcs/Makefile
@@ -0,0 +1,3 @@
+SUBDIR= lib ci co ident merge rcs rcsclean rcsdiff rcsmerge rlog rcsfreeze
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/rcs/Makefile.inc b/gnu/usr.bin/rcs/Makefile.inc
new file mode 100644
index 0000000..22d60d7
--- /dev/null
+++ b/gnu/usr.bin/rcs/Makefile.inc
@@ -0,0 +1,7 @@
+# Location of librcs
+
+.if exists(${.OBJDIR}/../lib)
+LIBRCS= ${.OBJDIR}/../lib/librcs.a
+.else
+LIBRCS= ${.CURDIR}/../lib/librcs.a
+.endif
diff --git a/gnu/usr.bin/rcs/NEWS b/gnu/usr.bin/rcs/NEWS
new file mode 100644
index 0000000..9920806
--- /dev/null
+++ b/gnu/usr.bin/rcs/NEWS
@@ -0,0 +1,548 @@
+Recent changes to RCS (and possible future changes)
+
+ $FreeBSD$
+
+ Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+ This file is part of RCS.
+
+ RCS is free software; you can redistribute 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.
+
+ RCS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with RCS; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+
+Here is a brief summary of user-visible changes since 5.6.
+
+ New options:
+ `-kb' supports binary files.
+ `-T' preserves the modification time of RCS files.
+ `-V' prints the version number.
+ `-zLT' causes RCS to use local time in working files and logs.
+ `rcsclean -n' outputs what rcsclean would do, without actually doing it.
+ `rlog -N' omits symbolic names.
+ There is a new keyword `Name'.
+ Inserted log lines now have the same prefix as the preceding `$Log' line.
+
+Most changes for RCS version 5.7 are to fix bugs and improve portability.
+RCS now conforms to GNU configuration standards and to Posix 1003.1b-1993.
+
+
+Features new to RCS version 5.7, and possibly incompatible
+in minor ways with previous practice, include:
+
+ Inserted log lines now have the same prefix as the preceding `$Log' line.
+ E.g. if a $Log line starts with `// $Log', log lines are prefixed with `// '.
+ RCS still records the (now obsolescent) comment leader inside RCS files,
+ but it ignores the comment leader unless it is emulating older RCS versions.
+ If you plan to access a file with both old and new versions of RCS,
+ make sure its comment leader matches its `$Log' line prefix.
+ For backwards compatibility with older versions of RCS,
+ if the log prefix is `/*' or `(*' surrounded by optional white space,
+ inserted log lines contain ` *' instead of `/*' or `(*';
+ however, this usage is obsolescent and should not be relied on.
+
+ $Log string `Revision' times now use the same format as other times.
+
+ Log lines are now inserted even if -kk is specified; this simplifies merging.
+
+ ci's -rR option (with a nonempty R) now just specifies a revision number R.
+ In some beta versions, it also reestablished the default behavior of
+ releasing a lock and removing the working file.
+ Now, only the bare -r option does this.
+
+ With an empty extension, any appearance of a directory named `RCS'
+ in a pathname identifies the pathname as being that of an RCS file.
+ For example, `a/RCS/b/c' is now an RCS file with an empty extension.
+ Formerly, `RCS' had to be the last directory in the pathname.
+
+ rlog's -d option by default now uses exclusive time ranges.
+ E.g. `rlog -d"<T"' now excludes revisions whose times equal T exactly.
+ Use `rlog -d"<=T"' to get the old behavior.
+
+ merge now takes up to three -L options, one for each input file.
+ Formerly, it took at most two -L options, for the 1st and 3rd input files.
+
+ `rcs' now requires at least one option; this is for future expansion.
+
+Other features new to RCS version 5.7 include:
+
+ merge and rcsmerge now pass -A, -E, and -e options to the subsidiary diff3.
+
+ rcs -kb acts like rcs -ko, except it uses binary I/O on working files.
+ This makes no difference under Posix or Unix, but it does matter elsewhere.
+ With -kb in effect, rcsmerge refuses to merge;
+ this avoids common problems with CVS merging.
+
+ The following is for future use by GNU Emacs 19's version control package:
+
+ rcs's new -M option causes it to not send mail when you break somebody
+ else's lock. This is not meant for casual use; see rcs(1).
+
+ ci's new -i option causes an error if the RCS file already exists.
+ Similarly, -j causes an error if the RCS file does not already exist.
+
+ The new keyword `Name' is supported; its value is the name, if any,
+ used to check out the revision. E.g. `co -rN foo' causes foo's
+ $Name...$ keyword strings to end in `: N $'.
+
+ The new -zZONE option causes RCS to output dates and times using ISO 8601
+ format with ZONE as the time zone, and to use ZONE as the default time
+ zone for input. Its most common use is the -zLT option, which causes RCS
+ to use local time externally. You can also specify foreign time zones;
+ e.g. -z+05:30 causes RCS to use India time (5 hours 30 minutes east of UTC).
+ This option does not affect RCS files themselves, which always use UTC;
+ it affects only output (e.g. rlog output, keyword expansion, diff -c times)
+ and interpretation of options (e.g. the -d option of ci, co, and rlog).
+ Bare -z restores the default behavior of UTC with no time zone indication,
+ and the traditional RCS date separator `/' instead of the ISO 8601 `-'.
+ RCSINIT may contain a -z option. ci -k parses UTC offsets.
+
+ The new -T option of ci, co, rcs, and rcsclean preserves the modification
+ time of the RCS file unless a revision is added or removed.
+ ci -T sets the RCS file's modification time to the new revision's time
+ if the former precedes the latter and there is a new revision;
+ otherwise, it preserves the RCS file's modification time.
+ Use this option with care, as it can confuse `make'; see ci(1).
+
+ The new -N option of rlog omits symbolic names from the output.
+
+ A revision number that starts with `.' is considered to be relative to
+ the default branch (normally the trunk). A branch number followed by `.'
+ stands for the last revision on that branch.
+
+ If someone else already holds the lock, rcs -l now asks whether you want
+ to break it, instead of immediately reporting an error.
+
+ ci now always unlocks a revision like 3.5 if you check in a revision
+ like 3.5.2.1 that is the first of a new branch of that revision.
+ Formerly it was inconsistent.
+
+ File names may now contain tab, newline, space, and '$'.
+ They are represented in keyword strings with \t, \n, \040, and \044.
+ \ in a file name is now represented by \\ in a keyword string.
+
+ Identifiers may now start with a digit and (unless they are symbolic names)
+ may contain `.'. This permits author names like `john.doe' and `4tran'.
+
+ A bare -V option now prints the current version number.
+
+ rcsdiff outputs more readable context diff headers if diff -L works.
+
+ rcsdiff -rN -rN now suppresses needless checkout and comparison
+ of identical revisions.
+
+ Error messages now contain the names of files to which they apply.
+
+ Mach style memory mapping is now supported.
+
+ The installation procedure now conforms to the GNU coding standards.
+
+ When properly configured, RCS now strictly conforms to Posix 1003.1b-1993.
+
+
+Features new to RCS version 5.6 include:
+
+ Security holes have been plugged; setgid use is no longer supported.
+
+ co can retrieve old revisions much more efficiently.
+ To generate the Nth youngest revision on the trunk,
+ the old method used up to N passes through copies of the working file;
+ the new method uses a piece table to generate the working file in one pass.
+
+ When ci finds no changes in the working file,
+ it automatically reverts to the previous revision unless -f is given.
+
+ RCS follows symbolic links to RCS files instead of breaking them,
+ and warns when it breaks hard links to RCS files.
+
+ `$' stands for the revision number taken from working file keyword strings.
+ E.g. if F contains an Id keyword string,
+ `rcsdiff -r$ F' compares F to its checked-in revision, and
+ `rcs -nL:$ F' gives the symbolic name L to F's revision.
+
+ co and ci's new -M option sets the modification time
+ of the working file to be that of the revision.
+ Without -M, ci now tries to avoid changing the working file's
+ modification time if its contents are unchanged.
+
+ rcs's new -m option changes the log message of an old revision.
+
+ RCS is portable to hosts that do not permit `,' in filenames.
+ (`,' is not part of the Posix portable filename character set.)
+ A new -x option specifies extensions other than `,v' for RCS files.
+ The Unix default is `-x,v/', so that the working file `w' corresponds
+ to the first file in the list `RCS/w,v', `w,v', `RCS/w' that works.
+ The non-Unix default is `-x', so that only `RCS/w' is tried.
+ Eventually, the Unix default should change to `-x/,v'
+ to encourage interoperability among all Posix hosts.
+
+ A new RCSINIT environment variable specifies defaults for options like -x.
+
+ The separator for revision ranges has been changed from `-' to `:', because
+ the range `A-B' is ambiguous if `A', `B' and `A-B' are all symbolic names.
+ E.g. the old `rlog -r1.5-1.7' is now `rlog -r1.5:1.7'; ditto for `rcs -o'.
+ For a while RCS will still support (but warn about) the old `-' separator.
+
+ RCS manipulates its lock files using a method that is more reliable under NFS.
+
+
+Features new to RCS version 5 include:
+
+ RCS can check in arbitrary files, not just text files, if diff -a works.
+ RCS can merge lines containing just a single `.' if diff3 -m works.
+ GNU diff supports the -a and -m options.
+
+ RCS can now be used as a setuid program.
+ See ci(1) for how users can employ setuid copies of ci, co, and rcsclean.
+ Setuid privileges yield extra security if the effective user owns RCS files
+ and directories, and if only the effective user can write RCS directories.
+ RCS uses the real user for all accesses other than writing RCS directories.
+ As described in ci(1), there are three levels of setuid support.
+
+ 1. Setuid works fully if the seteuid() system call lets any
+ process switch back and forth between real and effective users,
+ as specified in Posix 1003.1a Draft 5.
+
+ 2. On hosts with saved setuids (a Posix 1003.1-1990 option) and without
+ a modern seteuid(), setuid works unless the real or effective user is root.
+
+ 3. On hosts that lack both modern seteuid() and saved setuids,
+ setuid does not work, and RCS uses the effective user for all accesses;
+ formerly it was inconsistent.
+
+ New options to co, rcsdiff, and rcsmerge give more flexibility to keyword
+ substitution.
+
+ -kkv substitutes the default `$Keyword: value $' for keyword strings.
+ However, a locker's name is inserted only as a file is being locked,
+ i.e. by `ci -l' and `co -l'. This is normally the default.
+
+ -kkvl acts like -kkv, except that a locker's name is always inserted
+ if the given revision is currently locked. This was the default in
+ version 4. It is now the default only with when using rcsdiff to
+ compare a revision to a working file whose mode is that of a file
+ checked out for changes.
+
+ -kk substitutes just `$Keyword$', which helps to ignore keyword values
+ when comparing revisions.
+
+ -ko retrieves the old revision's keyword string, thus bypassing keyword
+ substitution.
+
+ -kv retrieves just `value'. This can ease the use of keyword values, but
+ it is dangerous because it causes RCS to lose track of where the keywords
+ are, so for safety the owner write permission of the working file is
+ turned off when -kv is used; to edit the file later, check it out again
+ without -kv.
+
+ rcs -ko sets the default keyword substitution to be in the style of co -ko,
+ and similarly for the other -k options. This can be useful with file
+ formats that cannot tolerate changing the lengths of keyword strings.
+ However it also renders a RCS file readable only by RCS version 5 or later.
+ Use rcs -kkv to restore the usual default substitution.
+
+ RCS can now be used by development groups that span time zone boundaries.
+ All times are now displayed in UTC, and UTC is the default time zone.
+ To use local time with co -d, append ` LT' to the time.
+ When interchanging RCS files with sites running older versions of RCS,
+ time stamp discrepancies may prevent checkins; to work around this,
+ use `ci -d' with a time slightly in the future.
+
+ Dates are now displayed using four-digit years, not two-digit years.
+ Years given in -d options must now have four digits.
+ This change is required for RCS to continue to work after 1999/12/31.
+ The form of dates in version 5 RCS files will not change until 2000/01/01,
+ so in the meantime RCS files can still be interchanged with sites
+ running older versions of RCS. To make room for the longer dates,
+ rlog now outputs `lines: +A -D' instead of `lines added/del: A/D'.
+
+ To help prevent diff programs that are broken or have run out of memory
+ from trashing an RCS file, ci now checks diff output more carefully.
+
+ ci -k now handles the Log keyword, so that checking in a file
+ with -k does not normally alter the file's contents.
+
+ RCS no longer outputs white space at the ends of lines
+ unless the original working file had it.
+ For consistency with other keywords,
+ a space, not a tab, is now output after `$Log:'.
+ Rlog now puts lockers and symbolic names on separate lines in the output
+ to avoid generating lines that are too long.
+ A similar fix has been made to lists in the RCS files themselves.
+
+ RCS no longer outputs the string `Locker: ' when expanding Header or Id
+ keywords. This saves space and reverts back to version 3 behavior.
+
+ The default branch is not put into the RCS file unless it is nonempty.
+ Therefore, files generated by RCS version 5 can be read by RCS version 3
+ unless they use the default branch feature introduced in version 4.
+ This fixes a compatibility problem introduced by version 4.
+
+ RCS can now emulate older versions of RCS; see `co -V'.
+ This may be useful to overcome compatibility problems
+ due to the above changes.
+
+ Programs like Emacs can now interact with RCS commands via a pipe:
+ the new -I option causes ci, co, and rcs to run interactively,
+ even if standard input is not a terminal.
+ These commands now accept multiple inputs from stdin separated by `.' lines.
+
+ ci now silently ignores the -t option if the RCS file already exists.
+ This simplifies some shell scripts and improves security in setuid sites.
+
+ Descriptive text may be given directly in an argument of the form -t-string.
+
+ The character set for symbolic names has been upgraded
+ from Ascii to ISO 8859.
+
+ rcsdiff now passes through all options used by GNU diff;
+ this is a longer list than 4.3BSD diff.
+
+ merge's new -L option gives tags for merge's overlap report lines.
+ This ability used to be present in a different, undocumented form;
+ the new form is chosen for compatibility with GNU diff3's -L option.
+
+ rcsmerge and merge now have a -q option, just like their siblings do.
+
+ rcsclean's new -n option outputs what rcsclean would do,
+ without actually doing it.
+
+ RCS now attempts to ignore parts of an RCS file that look like they come
+ from a future version of RCS.
+
+ When properly configured, RCS now strictly conforms with Posix 1003.1-1990.
+ RCS can still be compiled in non-Posix traditional Unix environments,
+ and can use common BSD and USG extensions to Posix.
+ RCS is a conforming Standard C program, and also compiles under traditional C.
+
+ Arbitrary limits on internal table sizes have been removed.
+ The only limit now is the amount of memory available via malloc().
+
+ File temporaries, lock files, signals, and system call return codes
+ are now handled more cleanly, portably, and quickly.
+ Some race conditions have been removed.
+
+ A new compile-time option RCSPREFIX lets administrators avoid absolute path
+ names for subsidiary programs, trading speed for flexibility.
+
+ The configuration procedure is now more automatic.
+
+ Snooping has been removed.
+
+
+Version 4 was the first version distributed by FSF.
+Beside bug fixes, features new to RCS version 4 include:
+
+ The notion of default branch has been added; see rcs -b.
+
+
+Version 3 was included in the 4.3BSD distribution.
+
+
+Here are some possible future changes for RCS:
+
+ Bring back sccstorcs.
+
+ Add an option to `rcsmerge' so that it can use an arbitrary program
+ to do the 3-way merge, instead of the default `merge'.
+ Likewise for `rcsdiff' and `diff'. It should be possible to pass
+ arbitrary options to these programs, and to the subsidiary `co's.
+
+ Add format options for finer control over the output of ident and rlog.
+ E.g. there should be an easy way for rlog to output lines like
+ `src/main.c 2.4 wft', one for each locked revision.
+ rlog options should have three orthogonal types: selecting files,
+ selecting revisions, and selecting rlog format.
+
+ Add format options for finer control over the output of keyword strings.
+ E.g. there should be some way to prepend @(#), and there should be some
+ way to change $ to some other character to disable further substitution.
+ These options should make the resulting files uneditable, like -kv.
+
+ Add long options, e.g. `--version'. Unfortunately RCS's option syntax
+ is incompatible with getopt. Perhaps the best way is to overload `rcs', e.g.
+ `rcs diff --keyword-substitution=old file' instead of `rcsdiff -ko file'.
+
+ Add a way to put only the interesting part of the path into the $Header
+ keyword expansion.
+
+ rlog -rM:N should work even if M and N have different numbers of fields,
+ so long as M is an ancestor of N or vice versa.
+
+ rcs should evaluate options in order; this allows rcs -oS -nS.
+
+ rcs should be able to fix minor mistakes in checkin dates and authors.
+
+ Be able to redo your most recent checkin with minor changes.
+
+ co -u shouldn't complain about a writable working file if it won't change
+ its contents.
+
+ Configure the Makefile automatically, as well as conf.h.
+
+ Add a new option to rcs that behaves like -o, but that doesn't lose the
+ nonempty log messages, but instead merges them with the next revision
+ if it exists, perhaps with a 1-line header containing author, date, etc.
+
+ Add a `-' option to take the list of pathnames from standard input.
+ Perhaps the pathnames should be null-terminated, not newline-terminated,
+ so that pathnames that contain newlines are handled properly.
+
+ Permit multiple option-pathname pairs, e.g. co -r1.4 a -r1.5 b.
+
+ Add options to allow arbitrary combinations of working file names
+ with RCS file names -- they shouldn't have to match.
+
+ Add an option to break a symbolic link to an RCS file,
+ instead of breaking the hard link that it points to.
+
+ Add ways to specify the earliest revision, the most recent revision,
+ the earliest or latest revision on a particular branch, and
+ the parent or child of some other revision.
+
+ If a user has multiple locks, perhaps ci should fall back on ci -k's
+ method to figure out which revision to use.
+
+ Symbolic names need not refer to existing branches and revisions.
+ rcs(1)'s BUGS section says this is a bug. Is it? If so, it should be fixed.
+
+ Add an option to rcs -o so that old log messages are not deleted if
+ the next undeleted revision exists, but are merely appended to the log
+ message of that revision.
+
+ ci -k should be able to get keyword values from the first `$Log' entry.
+
+ Add an option to rcsclean to clean directories recursively.
+
+ Write an rcsck program that repairs corrupted RCS files,
+ much as fsck repairs corrupted file systems.
+ For example, it should remove stale lock files.
+
+ Clean up the source code with a consistent indenting style.
+
+ Update the date parser to use the more modern getdate.y by Bellovin,
+ Salz, and Berets, or the even more modern getdate by Moraes. None of
+ these getdate implementations are as robust as RCS's old warhorse in
+ avoiding problems like arithmetic overflow, so they'll have to be
+ fixed first.
+
+ Break up the code into a library so that it's easier to write new programs
+ that manipulate RCS files, and so that useless code is removed from the
+ existing programs. For example, the rcs command contains unnecessary
+ keyword substitution baggage, and the merge command can be greatly pruned.
+
+ Make it easier to use your favorite text editor to edit log messages,
+ etc. instead of having to type them in irretrievably at the terminal.
+
+ Let the user specify a search path for default branches,
+ e.g. to use L as the default branch if it works, and M otherwise.
+ Let the user require that at least one entry in the default branch path works.
+ Let the user say that later entries in the default branch path are read only,
+ i.e. one cannot check in changes to them.
+ This should be an option settable by RCSINIT.
+
+ Add a way for a user to see which revisions affected which lines.
+
+ Have `rlog -nN F' print just the revision number that N translates to.
+ E.g. `rlog -nB. F' would print the highest revision on the branch B.
+ Use this to add an option -bB to rcsbranch, to freeze the named branch.
+ This should interact well with default branches.
+
+ Add a co option that prints the revision number before each line,
+ as SCCS's `get -m' does.
+
+The following projects require a change to RCS file format.
+
+ Allow keyword expansion to be changed on a per-revision basis,
+ not on a per-file basis as now. This would allow -ko to be used
+ on imported revisions, with the default -kkv otherwise.
+
+ When two or more branches are merged, record all the ancestors
+ of the new revision. The hard part of this is keeping track of all
+ the ancestors of a working file while it's checked out.
+
+ Add loose locking, which is like non-strict but applies to all users,
+ not just the owner of the RCS file.
+
+ Be able to store RCS files in compressed format.
+ Don't bother to use a .Z extension that would exceed file name length limits;
+ just look at the magic number.
+
+ Add locker commentary, e.g. `co -l -m"checkout to fix merge bug" foo'
+ to tell others why you checked out `foo'.
+ Also record the time when the revision was locked,
+ and perhaps the working pathname (if applicable).
+
+ Let the user mark an RCS revision as deleted; checking out such a revision
+ would result in no working file. Similarly, using `co -d' with a date either
+ before the initial revision or after the file was marked deleted should
+ remove the working file. For extra credit, extend the notion of `deleted' to
+ include `renamed'. RCS should support arbitrary combinations of renaming and
+ deletion, e.g. renaming A to B and B to A, checking in new revisions to both
+ files, and then renaming them back.
+
+ Be able to check in an entire directory structure into a single RCS file.
+
+ Use a better scheme for locking revisions; the current scheme requires
+ changing the RCS file just to lock or unlock a revision.
+ The new scheme should coexist as well as possible with older versions of RCS,
+ and should avoid the rare NFS bugs mentioned in rcsedit.c.
+ E.g. if there's a reliable lockd running, RCS should use it
+ instead of relying on NFS.
+
+ Add rcs options for changing keyword names, e.g. XConsortium instead of Id.
+
+ Add a `$Description' keyword; but this may be tricky, since descriptions can
+ contain newlines and $s.
+
+ Add a `$Copyright' keyword that expands to a copyright notice.
+
+ Add frozen branches a la SCCS. In general, be able to emulate all of
+ SCCS, so that an SCCS-to-RCS program can be practical. For example,
+ there should be an equivalent to the SCCS prt command.
+
+ Add support for distributed RCS, where widely separated
+ users cannot easily access each others' RCS files,
+ and must periodically distribute and reconcile new revisions.
+
+ Be able to create empty branches.
+
+ Be able to store just deltas from a read-only principal copy,
+ e.g. from source on CD-ROM.
+
+ Improve RCS's method for storing binary files.
+ Although it is more efficient than SCCS's,
+ the diff algorithm is still line oriented,
+ and often generates long output for minor changes to an executable file.
+
+ From the user's point of view, it would be best if
+ RCS detected and handled binary files without human intervention,
+ switching expansion methods as needed from revision to revision.
+
+ Allow RCS to determine automagically whether -ko or -kb should be the default
+ by inspecting the file's contents or name. The magic should be optional
+ and user-programmable.
+
+ Extend the grammar of RCS files so that keywords need not be in a fixed order.
+
+ Internationalize messages; unfortunately, there's no common standard yet.
+ This requires a change in RCS file format because of the
+ `empty log message' and `checked in with -k' hacks inside RCS files.
+
+ Add documentation in texinfo format.
diff --git a/gnu/usr.bin/rcs/REFS b/gnu/usr.bin/rcs/REFS
new file mode 100644
index 0000000..89fc823
--- /dev/null
+++ b/gnu/usr.bin/rcs/REFS
@@ -0,0 +1,90 @@
+Here are references to RCS and related free software and documentation.
+Some of this information changes often; see the Frequently Asked Questions
+for more up-to-date references.
+
+ $FreeBSD$
+
+
+Frequently Asked Questions (FAQs)
+
+<http://www.qucis.queensu.ca/Software-Engineering/>
+<ftp://rtfm.mit.edu//pub/usenet-by-hierarchy/comp/software-eng/>
+ for software engineering; e.g. see
+ <http://www.qucis.queensu.ca/Software-Engineering/blurb/rcs>.
+
+<http://www.iac.honeywell.com/Pub/Tech/CM/CMFAQ.html>
+<ftp://rtfm.mit.edu//pub/usenet-by-hierarchy/comp/software/config-mgmt/>
+ for configuration management
+
+<http://www.winternet.com/~zoo/cvs/FAQ.txt>
+<ftp://ftp.odi.com/pub/users/dgg/FAQ.gz>
+ for CVS (see below)
+
+
+RCS and related GNU project software
+
+<ftp://ftp.cs.purdue.edu/pub/RCS/>
+ The RCS project distribution directory also contains beta versions,
+ ports, and prebuilt documentation.
+
+<ftp://prep.ai.mit.edu/pub/gnu/>
+ The GNU project distribution directory contains:
+ diffutils-N-tar.gz
+ the latest diffutils release; recommended for RCS
+ emacs-N-tar.gz
+ The latest Emacs release contains VC, a version-control package
+ that makes RCS easier to use.
+ make-N-tar.gz
+ GNU Make, which can automatically build from RCS files.
+ rcs-N-tar.gz
+ the latest RCS release
+ cvs-N-tar.gz
+ the latest official CVS release (see below)
+
+<ftp://ftp.leo.org/pub/comp/os/os2/gnu/devtools/> DOS, OS/2 ports
+<ftp://ftp.cc.utexas.edu/microlib/nt/gnu/> NT port
+
+
+CVS
+
+CVS, the Concurrent Versions System, keeps tracks of source changes
+made by groups of developers working on the same files concurrently,
+allowing them to resync as needed.
+
+<http://www.winternet.com/~zoo/cvs/>
+<http://www.loria.fr/~molli/cvs-index.html>
+ These pages have useful information about CVS.
+
+<ftp://prep.ai.mit.edu/pub/gnu/cvs-1.3.tar.gz>
+ CVS 1.3 is the latest released version.
+
+<ftp://ftp.delos.com/pub/cvs/alpha/cvs-1.4A2.tar.gz>
+ CVS 1.4 is in alpha test, but it is recommended if you are installing CVS
+ for the first time, or on a recent operating system.
+
+<ftp://ftp-os2.cdrom.com/pub/os2/unix/> DOS, OS/2 ports
+<ftp://ftp.cc.utexas.edu/microlib/nt/gnu/> NT port
+
+<ftp://ftp.cyclic.com/pub/cvs/>
+ Cyclic CVS adds network transparency to CVS; it supports efficient,
+ reliable, and authenticated repository access via TCP/IP.
+
+
+Other software that uses RCS
+
+<ftp://ftp.nau.edu/pub/Aegis/>
+ Aegis manages revisions, baselines, mandatory reviews, and mandatory testing.
+
+<ftp://ftp.vix.com/pub/patches/csu/>
+ BCS, the Baseline Configuration System,
+ manages revisions, baselines, and staging areas.
+
+<ftp://riftp.osf.org/pub/ode/>
+ ODE, the Open Software Foundation Development Environment,
+ manages revisions, builds, and sandboxes.
+ OSF uses it for their own development.
+
+<ftp://bellcore.com/pub/Odin/>
+ Odin, a `make' replacement, can build directly from arbitrary revisions
+ without requiring checkouts of working copies. It also handles
+ parallel builds on multiple remote hosts and of multiple variants.
diff --git a/gnu/usr.bin/rcs/ci/Makefile b/gnu/usr.bin/rcs/ci/Makefile
new file mode 100644
index 0000000..2fbb74f
--- /dev/null
+++ b/gnu/usr.bin/rcs/ci/Makefile
@@ -0,0 +1,8 @@
+PROG= ci
+SRCS= ci.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/ci/ci.1 b/gnu/usr.bin/rcs/ci/ci.1
new file mode 100644
index 0000000..1378af2
--- /dev/null
+++ b/gnu/usr.bin/rcs/ci/ci.1
@@ -0,0 +1,898 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds i \&\s-1ISO\s0
+.ds r \&\s-1RCS\s0
+.ds u \&\s-1UTC\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH CI 1 \*(Dt GNU
+.SH NAME
+ci \- check in RCS revisions
+.SH SYNOPSIS
+.B ci
+.RI [ options ] " file " .\|.\|.
+.SH DESCRIPTION
+.B ci
+stores new revisions into \*r files.
+Each pathname matching an \*r suffix
+is taken to be an \*r file.
+All others
+are assumed to be working files containing new revisions.
+.B ci
+deposits the contents of each working file
+into the corresponding \*r file.
+If only a working file is given,
+.B ci
+tries to find the corresponding \*r file in an \*r subdirectory
+and then in the working file's directory.
+For more details, see
+.SM "FILE NAMING"
+below.
+.PP
+For
+.B ci
+to work, the caller's login must be on the access list,
+except if the access list is empty or the caller is the superuser or the
+owner of the file.
+To append a new revision to an existing branch, the tip revision on
+that branch must be locked by the caller. Otherwise, only a
+new branch can be created. This restriction is not enforced
+for the owner of the file if non-strict locking is used
+(see
+.BR rcs (1)).
+A lock held by someone else can be broken with the
+.B rcs
+command.
+.PP
+Unless the
+.B \-f
+option is given,
+.B ci
+checks whether the revision to be deposited differs from the preceding one.
+If not, instead of creating a new revision
+.B ci
+reverts to the preceding one.
+To revert, ordinary
+.B ci
+removes the working file and any lock;
+.B "ci\ \-l"
+keeps and
+.B "ci\ \-u"
+removes any lock, and then they both generate a new working file much as if
+.B "co\ \-l"
+or
+.B "co\ \-u"
+had been applied to the preceding revision.
+When reverting, any
+.B \-n
+and
+.B \-s
+options apply to the preceding revision.
+.PP
+For each revision deposited,
+.B ci
+prompts for a log message.
+The log message should summarize the change and must be terminated by
+end-of-file or by a line containing
+.BR \&. "\ by"
+itself.
+If several files are checked in
+.B ci
+asks whether to reuse the
+previous log message.
+If the standard input is not a terminal,
+.B ci
+suppresses the prompt
+and uses the same log message for all files.
+See also
+.BR \-m .
+.PP
+If the \*r file does not exist,
+.B ci
+creates it and
+deposits the contents of the working file as the initial revision
+(default number:
+.BR 1.1 ).
+The access list is initialized to empty.
+Instead of the log message,
+.B ci
+requests descriptive text (see
+.B \-t
+below).
+.PP
+The number
+.I rev
+of the deposited revision can be given by any of the options
+.BR \-f ,
+.BR \-i ,
+.BR \-I ,
+.BR \-j ,
+.BR \-k ,
+.BR \-l ,
+.BR \-M ,
+.BR \-q ,
+.BR \-r ,
+or
+.BR \-u .
+.I rev
+can be symbolic, numeric, or mixed.
+Symbolic names in
+.I rev
+must already be defined;
+see the
+.B \-n
+and
+.B \-N
+options for assigning names during checkin.
+If
+.I rev
+is
+.BR $ ,
+.B ci
+determines the revision number from keyword values in the working file.
+.PP
+If
+.I rev
+begins with a period,
+then the default branch (normally the trunk) is prepended to it.
+If
+.I rev
+is a branch number followed by a period,
+then the latest revision on that branch is used.
+.PP
+If
+.I rev
+is a revision number, it must be higher than the latest
+one on the branch to which
+.I rev
+belongs, or must start a new branch.
+.PP
+If
+.I rev
+is a branch rather than a revision number,
+the new revision is appended to that branch. The level number is obtained
+by incrementing the tip revision number of that branch.
+If
+.I rev
+indicates a non-existing branch,
+that branch is created with the initial revision numbered
+.IB rev .1\f1.\fP
+.br
+.ne 8
+.PP
+If
+.I rev
+is omitted,
+.B ci
+tries to derive the new revision number from
+the caller's last lock. If the caller has locked the tip revision of a branch,
+the new revision is appended to that branch.
+The new revision number is obtained
+by incrementing the tip revision number.
+If the caller locked a non-tip revision, a new branch is started at
+that revision by incrementing the highest branch number at that revision.
+The default initial branch and level numbers are
+.BR 1 .
+.PP
+If
+.I rev
+is omitted and the caller has no lock, but owns
+the file and locking
+is not set to
+.IR strict ,
+then the revision is appended to the
+default branch (normally the trunk; see the
+.B \-b
+option of
+.BR rcs (1)).
+.PP
+Exception: On the trunk, revisions can be appended to the end, but
+not inserted.
+.SH OPTIONS
+.TP
+.BI \-r rev
+Check in revision
+.IR rev .
+.TP
+.BR \-r
+The bare
+.B \-r
+option (without any revision) has an unusual meaning in
+.BR ci .
+With other \*r commands, a bare
+.B \-r
+option specifies the most recent revision on the default branch,
+but with
+.BR ci ,
+a bare
+.B \-r
+option reestablishes the default behavior of releasing a lock and
+removing the working file, and is used to override any default
+.B \-l
+or
+.B \-u
+options established by shell aliases or scripts.
+.TP
+.BR \-l [\f2rev\fP]
+works like
+.BR \-r ,
+except it performs an additional
+.B "co\ \-l"
+for the
+deposited revision. Thus, the deposited revision is immediately
+checked out again and locked.
+This is useful for saving a revision although one wants to continue
+editing it after the checkin.
+.TP
+.BR \-u [\f2rev\fP]
+works like
+.BR \-l ,
+except that the deposited revision is not locked.
+This lets one read the working file
+immediately after checkin.
+.RS
+.PP
+The
+.BR \-l ,
+bare
+.BR \-r ,
+and
+.B \-u
+options are mutually exclusive and silently override each other.
+For example,
+.B "ci\ \-u\ \-r"
+is equivalent to
+.B "ci\ \-r"
+because bare
+.B \-r
+overrides
+.BR \-u .
+.RE
+.TP
+.BR \-f [\f2rev\fP]
+forces a deposit; the new revision is deposited even it is not different
+from the preceding one.
+.TP
+.BR \-k [\f2rev\fP]
+searches the working file for keyword values to determine its revision number,
+creation date, state, and author (see
+.BR co (1)),
+and assigns these
+values to the deposited revision, rather than computing them locally.
+It also generates a default login message noting the login of the caller
+and the actual checkin date.
+This option is useful for software distribution. A revision that is sent to
+several sites should be checked in with the
+.B \-k
+option at these sites to
+preserve the original number, date, author, and state.
+The extracted keyword values and the default log message can be overridden
+with the options
+.BR \-d ,
+.BR \-m ,
+.BR \-s ,
+.BR \-w ,
+and any option that carries a revision number.
+.TP
+.BR \-q [\f2rev\fP]
+quiet mode; diagnostic output is not printed.
+A revision that is not different from the preceding one is not deposited,
+unless
+.B \-f
+is given.
+.TP
+.BR \-i [\f2rev\fP]
+initial checkin; report an error if the \*r file already exists.
+This avoids race conditions in certain applications.
+.TP
+.BR \-j [\f2rev\fP]
+just checkin and do not initialize;
+report an error if the \*r file does not already exist.
+.TP
+.BR \-I [\f2rev\fP]
+interactive mode;
+the user is prompted and questioned
+even if the standard input is not a terminal.
+.TP
+.BR \-d "[\f2date\fP]"
+uses
+.I date
+for the checkin date and time.
+The
+.I date
+is specified in free format as explained in
+.BR co (1).
+This is useful for lying about the checkin date, and for
+.B \-k
+if no date is available.
+If
+.I date
+is empty, the working file's time of last modification is used.
+.TP
+.BR \-M [\f2rev\fP]
+Set the modification time on any new working file
+to be the date of the retrieved revision.
+For example,
+.BI "ci\ \-d\ \-M\ \-u" "\ f"
+does not alter
+.IR f 's
+modification time, even if
+.IR f 's
+contents change due to keyword substitution.
+Use this option with care; it can confuse
+.BR make (1).
+.TP
+.BI \-m "msg"
+uses the string
+.I msg
+as the log message for all revisions checked in.
+By convention, log messages that start with
+.B #
+are comments and are ignored by programs like GNU Emacs's
+.B vc
+package.
+Also, log messages that start with
+.BI { clumpname }
+(followed by white space) are meant to be clumped together if possible,
+even if they are associated with different files; the
+.BI { clumpname }
+label is used only for clumping,
+and is not considered to be part of the log message itself.
+.TP
+.BI \-n "name"
+assigns the symbolic name
+.I name
+to the number of the checked-in revision.
+.B ci
+prints an error message if
+.I name
+is already assigned to another
+number.
+.TP
+.BI \-N "name"
+same as
+.BR \-n ,
+except that it overrides a previous assignment of
+.IR name .
+.TP
+.BI \-s "state"
+sets the state of the checked-in revision to the identifier
+.IR state .
+The default state is
+.BR Exp .
+.TP
+.BI \-t file
+writes descriptive text from the contents of the named
+.I file
+into the \*r file,
+deleting the existing text.
+The
+.I file
+cannot begin with
+.BR \- .
+.TP
+.BI \-t\- string
+Write descriptive text from the
+.I string
+into the \*r file, deleting the existing text.
+.RS
+.PP
+The
+.B \-t
+option, in both its forms, has effect only during an initial checkin;
+it is silently ignored otherwise.
+.PP
+During the initial checkin, if
+.B \-t
+is not given,
+.B ci
+obtains the text from standard input,
+terminated by end-of-file or by a line containing
+.BR \&. "\ by"
+itself.
+The user is prompted for the text if interaction is possible; see
+.BR \-I .
+.PP
+For backward compatibility with older versions of \*r, a bare
+.B \-t
+option is ignored.
+.RE
+.TP
+.B \-T
+Set the \*r file's modification time to the new revision's time
+if the former precedes the latter and there is a new revision;
+preserve the \*r file's modification time otherwise.
+If you have locked a revision,
+.B ci
+usually updates the \*r file's modification time to the current time,
+because the lock is stored in the \*r file
+and removing the lock requires changing the \*r file.
+This can create an \*r file newer than the working file in one of two ways:
+first,
+.B "ci\ \-M"
+can create a working file with a date before the current time;
+second, when reverting to the previous revision
+the \*r file can change while the working file remains unchanged.
+These two cases can cause excessive recompilation caused by a
+.BR make (1)
+dependency of the working file on the \*r file.
+The
+.B \-T
+option inhibits this recompilation by lying about the \*r file's date.
+Use this option with care; it can suppress recompilation even when
+a checkin of one working file should affect
+another working file associated with the same \*r file.
+For example, suppose the \*r file's time is 01:00,
+the (changed) working file's time is 02:00,
+some other copy of the working file has a time of 03:00,
+and the current time is 04:00.
+Then
+.B "ci\ \-d\ \-T"
+sets the \*r file's time to 02:00 instead of the usual 04:00;
+this causes
+.BR make (1)
+to think (incorrectly) that the other copy is newer than the \*r file.
+.TP
+.BI \-w "login"
+uses
+.I login
+for the author field of the deposited revision.
+Useful for lying about the author, and for
+.B \-k
+if no author is available.
+.TP
+.BI \-V
+Print \*r's version number.
+.TP
+.BI \-V n
+Emulate \*r version
+.IR n .
+See
+.BR co (1)
+for details.
+.TP
+.BI \-x "suffixes"
+specifies the suffixes for \*r files.
+A nonempty suffix matches any pathname ending in the suffix.
+An empty suffix matches any pathname of the form
+.BI RCS/ path
+or
+.IB path1 /RCS/ path2.
+The
+.B \-x
+option can specify a list of suffixes
+separated by
+.BR / .
+For example,
+.B \-x,v/
+specifies two suffixes:
+.B ,v
+and the empty suffix.
+If two or more suffixes are specified,
+they are tried in order when looking for an \*r file;
+the first one that works is used for that file.
+If no \*r file is found but an \*r file can be created,
+the suffixes are tried in order
+to determine the new \*r file's name.
+The default for
+.IR suffixes
+is installation-dependent; normally it is
+.B ,v/
+for hosts like Unix that permit commas in filenames,
+and is empty (i.e. just the empty suffix) for other hosts.
+.TP
+.BI \-z zone
+specifies the date output format in keyword substitution,
+and specifies the default time zone for
+.I date
+in the
+.BI \-d date
+option.
+The
+.I zone
+should be empty, a numeric \*u offset, or the special string
+.B LT
+for local time.
+The default is an empty
+.IR zone ,
+which uses the traditional \*r format of \*u without any time zone indication
+and with slashes separating the parts of the date;
+otherwise, times are output in \*i 8601 format with time zone indication.
+For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
+eight hours west of \*u,
+then the time is output as follows:
+.RS
+.LP
+.RS
+.nf
+.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
+.ne 4
+\f2option\fP \f2time output\fP
+\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
+\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
+\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
+.ta 4n +4n +4n +4n
+.fi
+.RE
+.LP
+The
+.B \-z
+option does not affect dates stored in \*r files,
+which are always \*u.
+.SH "FILE NAMING"
+Pairs of \*r files and working files can be specified in three ways
+(see also the
+example section).
+.PP
+1) Both the \*r file and the working file are given. The \*r pathname is of
+the form
+.IB path1 / workfileX
+and the working pathname is of the form
+.IB path2 / workfile
+where
+.IB path1 /
+and
+.IB path2 /
+are (possibly different or empty) paths,
+.I workfile
+is a filename, and
+.I X
+is an \*r suffix.
+If
+.I X
+is empty,
+.IB path1 /
+must start with
+.B RCS/
+or must contain
+.BR /RCS/ .
+.PP
+2) Only the \*r file is given. Then the working file is created in the current
+directory and its name is derived from the name of the \*r file
+by removing
+.IB path1 /
+and the suffix
+.IR X .
+.PP
+3) Only the working file is given.
+Then
+.B ci
+considers each \*r suffix
+.I X
+in turn, looking for an \*r file of the form
+.IB path2 /RCS/ workfileX
+or (if the former is not found and
+.I X
+is nonempty)
+.IB path2 / workfileX.
+.PP
+If the \*r file is specified without a path in 1) and 2),
+.B ci
+looks for the \*r file first in the directory
+.B ./RCS
+and then in the current
+directory.
+.PP
+.B ci
+reports an error if an attempt to open an \*r file fails for an unusual reason,
+even if the \*r file's pathname is just one of several possibilities.
+For example, to suppress use of \*r commands in a directory
+.IR d ,
+create a regular file named
+.IB d /RCS
+so that casual attempts to use \*r commands in
+.I d
+fail because
+.IB d /RCS
+is not a directory.
+.SH EXAMPLES
+Suppose
+.B ,v
+is an \*r suffix and the current directory contains a subdirectory
+.B RCS
+with an \*r file
+.BR io.c,v .
+Then each of the following commands check in a copy of
+.B io.c
+into
+.B RCS/io.c,v
+as the latest revision, removing
+.BR io.c .
+.LP
+.RS
+.nf
+.ft 3
+ci io.c; ci RCS/io.c,v; ci io.c,v;
+ci io.c RCS/io.c,v; ci io.c io.c,v;
+ci RCS/io.c,v io.c; ci io.c,v io.c;
+.ft
+.fi
+.RE
+.PP
+Suppose instead that the empty suffix
+is an \*r suffix and the current directory contains a subdirectory
+.B RCS
+with an \*r file
+.BR io.c .
+The each of the following commands checks in a new revision.
+.LP
+.RS
+.nf
+.ft 3
+ci io.c; ci RCS/io.c;
+ci io.c RCS/io.c;
+ci RCS/io.c io.c;
+.ft
+.fi
+.RE
+.SH "FILE MODES"
+An \*r file created by
+.B ci
+inherits the read and execute permissions
+from the working file. If the \*r file exists already,
+.B ci
+preserves its read and execute permissions.
+.B ci
+always turns off all write permissions of \*r files.
+.SH FILES
+Temporary files are created in the directory containing
+the working file, and also in the temporary directory (see
+.B \s-1TMPDIR\s0
+under
+.BR \s-1ENVIRONMENT\s0 ).
+A semaphore file or files are created in the directory containing the \*r file.
+With a nonempty suffix, the semaphore names begin with
+the first character of the suffix; therefore, do not specify an suffix
+whose first character could be that of a working filename.
+With an empty suffix, the semaphore names end with
+.B _
+so working filenames should not end in
+.BR _ .
+.PP
+.B ci
+never changes an \*r or working file.
+Normally,
+.B ci
+unlinks the file and creates a new one;
+but instead of breaking a chain of one or more symbolic links to an \*r file,
+it unlinks the destination file instead.
+Therefore,
+.B ci
+breaks any hard or symbolic links to any working file it changes;
+and hard links to \*r files are ineffective,
+but symbolic links to \*r files are preserved.
+.PP
+The effective user must be able to
+search and write the directory containing the \*r file.
+Normally, the real user must be able to
+read the \*r and working files
+and to search and write the directory containing the working file;
+however, some older hosts
+cannot easily switch between real and effective users,
+so on these hosts the effective user is used for all accesses.
+The effective user is the same as the real user
+unless your copies of
+.B ci
+and
+.B co
+have setuid privileges.
+As described in the next section,
+these privileges yield extra security if
+the effective user owns all \*r files and directories,
+and if only the effective user can write \*r directories.
+.PP
+Users can control access to \*r files by setting the permissions
+of the directory containing the files; only users with write access
+to the directory can use \*r commands to change its \*r files.
+For example, in hosts that allow a user to belong to several groups,
+one can make a group's \*r directories writable to that group only.
+This approach suffices for informal projects,
+but it means that any group member can arbitrarily change the group's \*r files,
+and can even remove them entirely.
+Hence more formal projects sometimes distinguish between an \*r administrator,
+who can change the \*r files at will, and other project members,
+who can check in new revisions but cannot otherwise change the \*r files.
+.SH "SETUID USE"
+To prevent anybody but their \*r administrator from deleting revisions,
+a set of users can employ setuid privileges as follows.
+.nr n \w'\(bu'+2n-1/1n
+.ds n \nn
+.if \n(.g .if r an-tag-sep .ds n \w'\(bu'u+\n[an-tag-sep]u
+.IP \(bu \*n
+Check that the host supports \*r setuid use.
+Consult a trustworthy expert if there are any doubts.
+It is best if the
+.B seteuid
+system call works as described in Posix 1003.1a Draft 5,
+because \*r can switch back and forth easily
+between real and effective users, even if the real user is
+.BR root .
+If not, the second best is if the
+.B setuid
+system call supports saved setuid
+(the {\s-1_POSIX_SAVED_IDS\s0} behavior of Posix 1003.1-1990);
+this fails only if the real or effective user is
+.BR root .
+If \*r detects any failure in setuid, it quits immediately.
+.IP \(bu \nn
+Choose a user
+.I A
+to serve as \*r administrator for the set of users.
+Only
+.I A
+can invoke the
+.B rcs
+command on the users' \*r files.
+.I A
+should not be
+.B root
+or any other user with special powers.
+Mutually suspicious sets of users should use different administrators.
+.IP \(bu \nn
+Choose a pathname
+.I B
+to be a directory of files to be executed by the users.
+.IP \(bu \nn
+Have
+.I A
+set up
+.I B
+to contain copies of
+.B ci
+and
+.B co
+that are setuid to
+.I A
+by copying the commands from their standard installation directory
+.I D
+as follows:
+.LP
+.RS
+.nf
+.ne 3
+\f3mkdir\fP \f2B\fP
+\f3cp\fP \f2D\fP\^\f3/c[io]\fP \f2B\fP
+\f3chmod go\-w,u+s\fP \f2B\fP\f3/c[io]\fP
+.fi
+.RE
+.IP \(bu \nn
+Have each user prepend
+.I B
+to their path as follows:
+.LP
+.RS
+.nf
+.ne 2
+\f3PATH=\fP\f2B\fP\f3:$PATH; export PATH\fP # ordinary shell
+\f3set path=(\fP\f2B\fP \f3$path)\fP # C shell
+.fi
+.RE
+.IP \(bu \nn
+Have
+.I A
+create each \*r directory
+.I R
+with write access only to
+.I A
+as follows:
+.LP
+.RS
+.nf
+.ne 2
+\f3mkdir\fP \f2R\fP
+\f3chmod go\-w\fP \f2R\fP
+.fi
+.RE
+.IP \(bu \nn
+If you want to let only certain users read the \*r files,
+put the users into a group
+.IR G ,
+and have
+.I A
+further protect the \*r directory as follows:
+.LP
+.RS
+.nf
+.ne 2
+\f3chgrp\fP \f2G R\fP
+\f3chmod g\-w,o\-rwx\fP \f2R\fP
+.fi
+.RE
+.IP \(bu \nn
+Have
+.I A
+copy old \*r files (if any) into
+.IR R ,
+to ensure that
+.I A
+owns them.
+.IP \(bu \nn
+An \*r file's access list limits who can check in and lock revisions.
+The default access list is empty,
+which grants checkin access to anyone who can read the \*r file.
+If you want limit checkin access,
+have
+.I A
+invoke
+.B "rcs\ \-a"
+on the file; see
+.BR rcs (1).
+In particular,
+.BI "rcs\ \-e\ \-a" A
+limits access to just
+.IR A .
+.IP \(bu \nn
+Have
+.I A
+initialize any new \*r files with
+.B "rcs\ \-i"
+before initial checkin, adding the
+.B \-a
+option if you want to limit checkin access.
+.IP \(bu \nn
+Give setuid privileges only to
+.BR ci ,
+.BR co ,
+and
+.BR rcsclean ;
+do not give them to
+.B rcs
+or to any other command.
+.IP \(bu \nn
+Do not use other setuid commands to invoke \*r commands;
+setuid is trickier than you think!
+.SH ENVIRONMENT
+.TP
+.B \s-1RCSINIT\s0
+options prepended to the argument list, separated by spaces.
+A backslash escapes spaces within an option.
+The
+.B \s-1RCSINIT\s0
+options are prepended to the argument lists of most \*r commands.
+Useful
+.B \s-1RCSINIT\s0
+options include
+.BR \-q ,
+.BR \-V ,
+.BR \-x ,
+and
+.BR \-z .
+.TP
+.B \s-1TMPDIR\s0
+Name of the temporary directory.
+If not set, the environment variables
+.B \s-1TMP\s0
+and
+.B \s-1TEMP\s0
+are inspected instead and the first value found is taken;
+if none of them are set,
+a host-dependent default is used, typically
+.BR /tmp .
+.SH DIAGNOSTICS
+For each revision,
+.B ci
+prints the \*r file, the working file, and the number
+of both the deposited and the preceding revision.
+The exit status is zero if and only if all operations were successful.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
+.SH "SEE ALSO"
+co(1),
+ident(1), make(1), rcs(1), rcsclean(1), rcsdiff(1),
+rcsintro(1), rcsmerge(1), rlog(1), setuid(2), rcsfile(5)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.br
diff --git a/gnu/usr.bin/rcs/ci/ci.c b/gnu/usr.bin/rcs/ci/ci.c
new file mode 100644
index 0000000..749a4cf
--- /dev/null
+++ b/gnu/usr.bin/rcs/ci/ci.c
@@ -0,0 +1,1318 @@
+/* Check in revisions of RCS files from working files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.30 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.29 1995/06/01 16:23:43 eggert
+ * (main): Add -kb.
+ * Use `cmpdate', not `cmpnum', to compare dates.
+ * This is for MKS RCS's incompatible 20th-century date format.
+ * Don't worry about errno after ftruncate fails.
+ * Fix input file rewinding bug when large_memory && !maps_memory
+ * and checking in a branch tip.
+ *
+ * (fixwork): Fall back on chmod if fchmod fails, since it might be ENOSYS.
+ *
+ * Revision 5.28 1994/03/20 04:52:58 eggert
+ * Do not generate a corrupted RCS file if the user modifies the working file
+ * while `ci' is running.
+ * Do not remove the lock when `ci -l' reverts.
+ * Move buffer-flushes out of critical sections, since they aren't critical.
+ * Use ORCSerror to clean up after a fatal error.
+ * Specify subprocess input via file descriptor, not file name.
+ *
+ * Revision 5.27 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.26 1993/11/03 17:42:27 eggert
+ * Add -z. Don't subtract from RCS file timestamp even if -T.
+ * Scan for and use Name keyword if -k.
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.25 1992/07/28 16:12:44 eggert
+ * Add -i, -j, -V. Check that working and RCS files are distinct.
+ *
+ * Revision 5.24 1992/02/17 23:02:06 eggert
+ * `-rREV' now just specifies a revision REV; only bare `-r' reverts to default.
+ * Add -T.
+ *
+ * Revision 5.23 1992/01/27 16:42:51 eggert
+ * Always unlock branchpoint if caller has a lock.
+ * Add support for bad_chmod_close, bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.22 1992/01/06 02:42:34 eggert
+ * Invoke utime() before chmod() to keep some buggy systems happy.
+ *
+ * Revision 5.21 1991/11/20 17:58:07 eggert
+ * Don't read the delta tree from a nonexistent RCS file.
+ *
+ * Revision 5.20 1991/10/07 17:32:46 eggert
+ * Fix log bugs. Remove lint.
+ *
+ * Revision 5.19 1991/09/26 23:10:30 eggert
+ * Plug file descriptor leak.
+ *
+ * Revision 5.18 1991/09/18 07:29:10 eggert
+ * Work around a common ftruncate() bug.
+ *
+ * Revision 5.17 1991/09/10 22:15:46 eggert
+ * Fix test for redirected stdin.
+ *
+ * Revision 5.16 1991/08/19 23:17:54 eggert
+ * When there are no changes, revert to previous revision instead of aborting.
+ * Add piece tables, -M, -r$. Tune.
+ *
+ * Revision 5.15 1991/04/21 11:58:14 eggert
+ * Ensure that working file is newer than RCS file after ci -[lu].
+ * Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.14 1991/02/28 19:18:47 eggert
+ * Don't let a setuid ci create a new RCS file; rcs -i -a must be run first.
+ * Fix ci -ko -l mode bug. Open work file at most once.
+ *
+ * Revision 5.13 1991/02/25 07:12:33 eggert
+ * getdate -> getcurdate (SVR4 name clash)
+ *
+ * Revision 5.12 1990/12/31 01:00:12 eggert
+ * Don't use uninitialized storage when handling -{N,n}.
+ *
+ * Revision 5.11 1990/12/04 05:18:36 eggert
+ * Use -I for prompts and -q for diagnostics.
+ *
+ * Revision 5.10 1990/11/05 20:30:10 eggert
+ * Don't remove working file when aborting due to no changes.
+ *
+ * Revision 5.9 1990/11/01 05:03:23 eggert
+ * Add -I and new -t behavior. Permit arbitrary data in logs.
+ *
+ * Revision 5.8 1990/10/04 06:30:09 eggert
+ * Accumulate exit status across files.
+ *
+ * Revision 5.7 1990/09/25 20:11:46 hammer
+ * fixed another small typo
+ *
+ * Revision 5.6 1990/09/24 21:48:50 hammer
+ * added cleanups from Paul Eggert.
+ *
+ * Revision 5.5 1990/09/21 06:16:38 hammer
+ * made it handle multiple -{N,n}'s. Also, made it treat re-directed stdin
+ * the same as the terminal
+ *
+ * Revision 5.4 1990/09/20 02:38:51 eggert
+ * ci -k now checks dates more thoroughly.
+ *
+ * Revision 5.3 1990/09/11 02:41:07 eggert
+ * Fix revision bug with `ci -k file1 file2'.
+ *
+ * Revision 5.2 1990/09/04 08:02:10 eggert
+ * Permit adjacent revisions with identical time stamps (possible on fast hosts).
+ * Improve incomplete line handling. Standardize yes-or-no procedure.
+ *
+ * Revision 5.1 1990/08/29 07:13:44 eggert
+ * Expand locker value like co. Clean old log messages too.
+ *
+ * Revision 5.0 1990/08/22 08:10:00 eggert
+ * Don't require a final newline.
+ * Make lock and temp files faster and safer.
+ * Remove compile-time limits; use malloc instead.
+ * Permit dates past 1999/12/31. Switch to GMT.
+ * Add setuid support. Don't pass +args to diff. Check diff's output.
+ * Ansify and Posixate. Add -k, -V. Remove snooping. Tune.
+ * Check diff's output.
+ *
+ * Revision 4.9 89/05/01 15:10:54 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.8 88/11/08 13:38:23 narten
+ * changes from root@seismo.CSS.GOV (Super User)
+ * -d with no arguments uses the mod time of the file it is checking in
+ *
+ * Revision 4.7 88/08/09 19:12:07 eggert
+ * Make sure workfile is a regular file; use its mode if RCSfile doesn't have one.
+ * Use execv(), not system(); allow cc -R; remove lint.
+ * isatty(fileno(stdin)) -> ttystdin()
+ *
+ * Revision 4.6 87/12/18 11:34:41 narten
+ * lint cleanups (from Guy Harris)
+ *
+ * Revision 4.5 87/10/18 10:18:48 narten
+ * Updating version numbers. Changes relative to revision 1.1 are actually
+ * relative to 4.3
+ *
+ * Revision 1.3 87/09/24 13:57:19 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:21:33 jenkins
+ * Port to suns
+ *
+ * Revision 4.3 83/12/15 12:28:54 wft
+ * ci -u and ci -l now set mode of working file properly.
+ *
+ * Revision 4.2 83/12/05 13:40:54 wft
+ * Merged with 3.9.1.1: added calls to clearerr(stdin).
+ * made rewriteflag external.
+ *
+ * Revision 4.1 83/05/10 17:03:06 wft
+ * Added option -d and -w, and updated assingment of date, etc. to new delta.
+ * Added handling of default branches.
+ * Option -k generates std. log message; fixed undef. pointer in reading of log.
+ * Replaced getlock() with findlock(), link--unlink with rename(),
+ * getpwuid() with getcaller().
+ * Moved all revision number generation to new routine addelta().
+ * Removed calls to stat(); now done by pairfilenames().
+ * Changed most calls to catchints() with restoreints().
+ * Directed all interactive messages to stderr.
+ *
+ * Revision 3.9.1.1 83/10/19 04:21:03 lepreau
+ * Added clearerr(stdin) to getlogmsg() for re-reading stdin.
+ *
+ * Revision 3.9 83/02/15 15:25:44 wft
+ * 4.2 prerelease
+ *
+ * Revision 3.9 83/02/15 15:25:44 wft
+ * Added call to fastcopy() to copy remainder of RCS file.
+ *
+ * Revision 3.8 83/01/14 15:34:05 wft
+ * Added ignoring of interrupts while new RCS file is renamed;
+ * Avoids deletion of RCS files by interrupts.
+ *
+ * Revision 3.7 82/12/10 16:09:20 wft
+ * Corrected checking of return code from diff.
+ *
+ * Revision 3.6 82/12/08 21:34:49 wft
+ * Using DATEFORM to prepare date of checked-in revision;
+ * Fixed return from addbranch().
+ *
+ * Revision 3.5 82/12/04 18:32:42 wft
+ * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE. Updated
+ * field lockedby in removelock(), moved getlogmsg() before calling diff.
+ *
+ * Revision 3.4 82/12/02 13:27:13 wft
+ * added option -k.
+ *
+ * Revision 3.3 82/11/28 20:53:31 wft
+ * Added mustcheckin() to check for redundant checkins.
+ * Added xpandfile() to do keyword expansion for -u and -l;
+ * -m appends linefeed to log message if necessary.
+ * getlogmsg() suppresses prompt if stdin is not a terminal.
+ * Replaced keeplock with lockflag, fclose() with ffclose(),
+ * %02d with %.2d, getlogin() with getpwuid().
+ *
+ * Revision 3.2 82/10/18 20:57:23 wft
+ * An RCS file inherits its mode during the first ci from the working file,
+ * otherwise it stays the same, except that write permission is removed.
+ * Fixed ci -l, added ci -u (both do an implicit co after the ci).
+ * Fixed call to getlogin(), added call to getfullRCSname(), added check
+ * for write error.
+ * Changed conflicting identifiers.
+ *
+ * Revision 3.1 82/10/13 16:04:59 wft
+ * fixed type of variables receiving from getc() (char -> int).
+ * added include file dbm.h for getting BYTESIZ. This is used
+ * to check the return code from diff portably.
+ */
+
+#include "rcsbase.h"
+
+struct Symrev {
+ char const *ssymbol;
+ int override;
+ struct Symrev * nextsym;
+};
+
+static char const *getcurdate P((void));
+static int addbranch P((struct hshentry*,struct buf*,int));
+static int addelta P((void));
+static int addsyms P((char const*));
+static int fixwork P((mode_t,time_t));
+static int removelock P((struct hshentry*));
+static int xpandfile P((RILE*,struct hshentry const*,char const**,int));
+static struct cbuf getlogmsg P((void));
+static void cleanup P((void));
+static void incnum P((char const*,struct buf*));
+static void addassoclst P((int,char const*));
+
+static FILE *exfile;
+static RILE *workptr; /* working file pointer */
+static struct buf newdelnum; /* new revision number */
+static struct cbuf msg;
+static int exitstatus;
+static int forceciflag; /* forces check in */
+static int keepflag, keepworkingfile, rcsinitflag;
+static struct hshentries *gendeltas; /* deltas to be generated */
+static struct hshentry *targetdelta; /* old delta to be generated */
+static struct hshentry newdelta; /* new delta to be inserted */
+static struct stat workstat;
+static struct Symrev *assoclst, **nextassoc;
+
+mainProg(ciId, "ci", "$FreeBSD$")
+{
+ static char const cmdusage[] =
+ "\nci usage: ci -{fIklMqru}[rev] -d[date] -mmsg -{nN}name -sstate -ttext -T -Vn -wwho -xsuff -zzone file ...";
+ static char const default_state[] = DEFAULTSTATE;
+
+ char altdate[datesize];
+ char olddate[datesize];
+ char newdatebuf[datesize + zonelenmax];
+ char targetdatebuf[datesize + zonelenmax];
+ char *a, **newargv, *textfile;
+ char const *author, *krev, *rev, *state;
+ char const *diffname, *expname;
+ char const *newworkname;
+ int initflag, mustread;
+ int lockflag, lockthis, mtimeflag, removedlock, Ttimeflag;
+ int r;
+ int changedRCS, changework, dolog, newhead;
+ int usestatdate; /* Use mod time of file for -d. */
+ mode_t newworkmode; /* mode for working file */
+ time_t mtime, wtime;
+ struct hshentry *workdelta;
+
+ setrid();
+
+ author = rev = state = textfile = 0;
+ initflag = lockflag = mustread = false;
+ mtimeflag = false;
+ Ttimeflag = false;
+ altdate[0]= '\0'; /* empty alternate date for -d */
+ usestatdate=false;
+ suffixes = X_DEFAULT;
+ nextassoc = &assoclst;
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ while (a = *++argv, 0<--argc && *a++=='-') {
+ switch (*a++) {
+
+ case 'r':
+ if (*a)
+ goto revno;
+ keepworkingfile = lockflag = false;
+ break;
+
+ case 'l':
+ keepworkingfile = lockflag = true;
+ revno:
+ if (*a) {
+ if (rev) warn("redefinition of revision number");
+ rev = a;
+ }
+ break;
+
+ case 'u':
+ keepworkingfile=true; lockflag=false;
+ goto revno;
+
+ case 'i':
+ initflag = true;
+ goto revno;
+
+ case 'j':
+ mustread = true;
+ goto revno;
+
+ case 'I':
+ interactiveflag = true;
+ goto revno;
+
+ case 'q':
+ quietflag=true;
+ goto revno;
+
+ case 'f':
+ forceciflag=true;
+ goto revno;
+
+ case 'k':
+ keepflag=true;
+ goto revno;
+
+ case 'm':
+ if (msg.size) redefined('m');
+ msg = cleanlogmsg(a, strlen(a));
+ if (!msg.size)
+ error("missing message for -m option");
+ break;
+
+ case 'n':
+ if (!*a) {
+ error("missing symbolic name after -n");
+ break;
+ }
+ checkssym(a);
+ addassoclst(false, a);
+ break;
+
+ case 'N':
+ if (!*a) {
+ error("missing symbolic name after -N");
+ break;
+ }
+ checkssym(a);
+ addassoclst(true, a);
+ break;
+
+ case 's':
+ if (*a) {
+ if (state) redefined('s');
+ checksid(a);
+ state = a;
+ } else
+ error("missing state for -s option");
+ break;
+
+ case 't':
+ if (*a) {
+ if (textfile) redefined('t');
+ textfile = a;
+ }
+ break;
+
+ case 'd':
+ if (altdate[0] || usestatdate)
+ redefined('d');
+ altdate[0] = '\0';
+ if (!(usestatdate = !*a))
+ str2date(a, altdate);
+ break;
+
+ case 'M':
+ mtimeflag = true;
+ goto revno;
+
+ case 'w':
+ if (*a) {
+ if (author) redefined('w');
+ checksid(a);
+ author = a;
+ } else
+ error("missing author for -w option");
+ break;
+
+ case 'x':
+ suffixes = a;
+ break;
+
+ case 'V':
+ setRCSversion(*argv);
+ break;
+
+ case 'z':
+ zone_set(a);
+ break;
+
+ case 'T':
+ if (!*a) {
+ Ttimeflag = true;
+ break;
+ }
+ /* fall into */
+ default:
+ error("unknown option: %s%s", *argv, cmdusage);
+ };
+ } /* end processing of options */
+
+ /* Handle all pathnames. */
+ if (nerror) cleanup();
+ else if (argc < 1) faterror("no input file%s", cmdusage);
+ else for (; 0 < argc; cleanup(), ++argv, --argc) {
+ targetdelta = 0;
+ ffree();
+
+ switch (pairnames(argc, argv, rcswriteopen, mustread, false)) {
+
+ case -1: /* New RCS file */
+# if has_setuid && has_getuid
+ if (euid() != ruid()) {
+ workerror("setuid initial checkin prohibited; use `rcs -i -a' first");
+ continue;
+ }
+# endif
+ rcsinitflag = true;
+ break;
+
+ case 0: /* Error */
+ continue;
+
+ case 1: /* Normal checkin with prev . RCS file */
+ if (initflag) {
+ rcserror("already exists");
+ continue;
+ }
+ rcsinitflag = !Head;
+ }
+
+ /*
+ * RCSname contains the name of the RCS file, and
+ * workname contains the name of the working file.
+ * If the RCS file exists, finptr contains the file descriptor for the
+ * RCS file, and RCSstat is set. The admin node is initialized.
+ */
+
+ diagnose("%s <-- %s\n", RCSname, workname);
+
+ if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
+ eerror(workname);
+ continue;
+ }
+
+ if (finptr) {
+ if (same_file(RCSstat, workstat, 0)) {
+ rcserror("RCS file is the same as working file %s.",
+ workname
+ );
+ continue;
+ }
+ if (!checkaccesslist())
+ continue;
+ }
+
+ krev = rev;
+ if (keepflag) {
+ /* get keyword values from working file */
+ if (!getoldkeys(workptr)) continue;
+ if (!rev && !*(krev = prevrev.string)) {
+ workerror("can't find a revision number");
+ continue;
+ }
+ if (!*prevdate.string && *altdate=='\0' && usestatdate==false)
+ workwarn("can't find a date");
+ if (!*prevauthor.string && !author)
+ workwarn("can't find an author");
+ if (!*prevstate.string && !state)
+ workwarn("can't find a state");
+ } /* end processing keepflag */
+
+ /* Read the delta tree. */
+ if (finptr)
+ gettree();
+
+ /* expand symbolic revision number */
+ if (!fexpandsym(krev, &newdelnum, workptr))
+ continue;
+
+ /* splice new delta into tree */
+ if ((removedlock = addelta()) < 0)
+ continue;
+
+ newdelta.num = newdelnum.string;
+ newdelta.branches = 0;
+ newdelta.lockedby = 0; /* This might be changed by addlock(). */
+ newdelta.selector = true;
+ newdelta.name = 0;
+ clear_buf(&newdelta.ig);
+ clear_buf(&newdelta.igtext);
+ /* set author */
+ if (author)
+ newdelta.author=author; /* set author given by -w */
+ else if (keepflag && *prevauthor.string)
+ newdelta.author=prevauthor.string; /* preserve old author if possible*/
+ else newdelta.author=getcaller();/* otherwise use caller's id */
+ newdelta.state = default_state;
+ if (state)
+ newdelta.state=state; /* set state given by -s */
+ else if (keepflag && *prevstate.string)
+ newdelta.state=prevstate.string; /* preserve old state if possible */
+ if (usestatdate) {
+ time2date(workstat.st_mtime, altdate);
+ }
+ if (*altdate!='\0')
+ newdelta.date=altdate; /* set date given by -d */
+ else if (keepflag && *prevdate.string) {
+ /* Preserve old date if possible. */
+ str2date(prevdate.string, olddate);
+ newdelta.date = olddate;
+ } else
+ newdelta.date = getcurdate(); /* use current date */
+ /* now check validity of date -- needed because of -d and -k */
+ if (targetdelta &&
+ cmpdate(newdelta.date,targetdelta->date) < 0) {
+ rcserror("Date %s precedes %s in revision %s.",
+ date2str(newdelta.date, newdatebuf),
+ date2str(targetdelta->date, targetdatebuf),
+ targetdelta->num
+ );
+ continue;
+ }
+
+
+ if (lockflag && addlock(&newdelta, true) < 0) continue;
+
+ if (keepflag && *prevname.string)
+ if (addsymbol(newdelta.num, prevname.string, false) < 0)
+ continue;
+ if (!addsyms(newdelta.num))
+ continue;
+
+
+ putadmin();
+ puttree(Head,frewrite);
+ putdesc(false,textfile);
+
+ changework = Expand < MIN_UNCHANGED_EXPAND;
+ dolog = true;
+ lockthis = lockflag;
+ workdelta = &newdelta;
+
+ /* build rest of file */
+ if (rcsinitflag) {
+ diagnose("initial revision: %s\n", newdelta.num);
+ /* get logmessage */
+ newdelta.log=getlogmsg();
+ putdftext(&newdelta, workptr, frewrite, false);
+ RCSstat.st_mode = workstat.st_mode;
+ RCSstat.st_nlink = 0;
+ changedRCS = true;
+ } else {
+ diffname = maketemp(0);
+ newhead = Head == &newdelta;
+ if (!newhead)
+ foutptr = frewrite;
+ expname = buildrevision(
+ gendeltas, targetdelta, (FILE*)0, false
+ );
+ if (
+ !forceciflag &&
+ strcmp(newdelta.state, targetdelta->state) == 0 &&
+ (changework = rcsfcmp(
+ workptr, &workstat, expname, targetdelta
+ )) <= 0
+ ) {
+ diagnose("file is unchanged; reverting to previous revision %s\n",
+ targetdelta->num
+ );
+ if (removedlock < lockflag) {
+ diagnose("previous revision was not locked; ignoring -l option\n");
+ lockthis = 0;
+ }
+ dolog = false;
+ if (! (changedRCS = lockflag<removedlock || assoclst))
+ workdelta = targetdelta;
+ else {
+ /*
+ * We have started to build the wrong new RCS file.
+ * Start over from the beginning.
+ */
+ long hwm = ftell(frewrite);
+ int bad_truncate;
+ Orewind(frewrite);
+
+ /*
+ * Work around a common ftruncate() bug:
+ * NFS won't let you truncate a file that you
+ * currently lack permissions for, even if you
+ * had permissions when you opened it.
+ * Also, Posix 1003.1b-1993 sec 5.6.7.2 p 128 l 1022
+ * says ftruncate might fail because it's not supported.
+ */
+# if !has_ftruncate
+# undef ftruncate
+# define ftruncate(fd,length) (-1)
+# endif
+ bad_truncate = ftruncate(fileno(frewrite), (off_t)0);
+
+ Irewind(finptr);
+ Lexinit();
+ getadmin();
+ gettree();
+ if (!(workdelta = genrevs(
+ targetdelta->num, (char*)0, (char*)0, (char*)0,
+ &gendeltas
+ )))
+ continue;
+ workdelta->log = targetdelta->log;
+ if (newdelta.state != default_state)
+ workdelta->state = newdelta.state;
+ if (lockthis<removedlock && removelock(workdelta)<0)
+ continue;
+ if (!addsyms(workdelta->num))
+ continue;
+ if (dorewrite(true, true) != 0)
+ continue;
+ fastcopy(finptr, frewrite);
+ if (bad_truncate)
+ while (ftell(frewrite) < hwm)
+ /* White out any earlier mistake with '\n's. */
+ /* This is unlikely. */
+ afputc('\n', frewrite);
+ }
+ } else {
+ int wfd = Ifileno(workptr);
+ struct stat checkworkstat;
+ char const *diffv[6 + !!OPEN_O_BINARY], **diffp;
+# if large_memory && !maps_memory
+ FILE *wfile = workptr->stream;
+ long wfile_off;
+# endif
+# if !has_fflush_input && !(large_memory && maps_memory)
+ off_t wfd_off;
+# endif
+
+ diagnose("new revision: %s; previous revision: %s\n",
+ newdelta.num, targetdelta->num
+ );
+ newdelta.log = getlogmsg();
+# if !large_memory
+ Irewind(workptr);
+# if has_fflush_input
+ if (fflush(workptr) != 0)
+ Ierror();
+# endif
+# else
+# if !maps_memory
+ if (
+ (wfile_off = ftell(wfile)) == -1
+ || fseek(wfile, 0L, SEEK_SET) != 0
+# if has_fflush_input
+ || fflush(wfile) != 0
+# endif
+ )
+ Ierror();
+# endif
+# endif
+# if !has_fflush_input && !(large_memory && maps_memory)
+ wfd_off = lseek(wfd, (off_t)0, SEEK_CUR);
+ if (wfd_off == -1
+ || (wfd_off != 0
+ && lseek(wfd, (off_t)0, SEEK_SET) != 0))
+ Ierror();
+# endif
+ diffp = diffv;
+ *++diffp = DIFF;
+ *++diffp = DIFFFLAGS;
+# if OPEN_O_BINARY
+ if (Expand == BINARY_EXPAND)
+ *++diffp = "--binary";
+# endif
+ *++diffp = newhead ? "-" : expname;
+ *++diffp = newhead ? expname : "-";
+ *++diffp = 0;
+ switch (runv(wfd, diffname, diffv)) {
+ case DIFF_FAILURE: case DIFF_SUCCESS: break;
+ default: rcsfaterror("diff failed");
+ }
+# if !has_fflush_input && !(large_memory && maps_memory)
+ if (lseek(wfd, wfd_off, SEEK_CUR) == -1)
+ Ierror();
+# endif
+# if large_memory && !maps_memory
+ if (fseek(wfile, wfile_off, SEEK_SET) != 0)
+ Ierror();
+# endif
+ if (newhead) {
+ Irewind(workptr);
+ putdftext(&newdelta, workptr, frewrite, false);
+ if (!putdtext(targetdelta,diffname,frewrite,true)) continue;
+ } else
+ if (!putdtext(&newdelta,diffname,frewrite,true)) continue;
+
+ /*
+ * Check whether the working file changed during checkin,
+ * to avoid producing an inconsistent RCS file.
+ */
+ if (
+ fstat(wfd, &checkworkstat) != 0
+ || workstat.st_mtime != checkworkstat.st_mtime
+ || workstat.st_size != checkworkstat.st_size
+ ) {
+ workerror("file changed during checkin");
+ continue;
+ }
+
+ changedRCS = true;
+ }
+ }
+
+ /* Deduce time_t of new revision if it is needed later. */
+ wtime = (time_t)-1;
+ if (mtimeflag | Ttimeflag)
+ wtime = date2time(workdelta->date);
+
+ if (donerewrite(changedRCS,
+ !Ttimeflag ? (time_t)-1
+ : finptr && wtime < RCSstat.st_mtime ? RCSstat.st_mtime
+ : wtime
+ ) != 0)
+ continue;
+
+ if (!keepworkingfile) {
+ Izclose(&workptr);
+ r = un_link(workname); /* Get rid of old file */
+ } else {
+ newworkmode = WORKMODE(RCSstat.st_mode,
+ ! (Expand==VAL_EXPAND || lockthis < StrictLocks)
+ );
+ mtime = mtimeflag ? wtime : (time_t)-1;
+
+ /* Expand if it might change or if we can't fix mode, time. */
+ if (changework || (r=fixwork(newworkmode,mtime)) != 0) {
+ Irewind(workptr);
+ /* Expand keywords in file. */
+ locker_expansion = lockthis;
+ workdelta->name =
+ namedrev(
+ assoclst ? assoclst->ssymbol
+ : keepflag && *prevname.string ? prevname.string
+ : rev,
+ workdelta
+ );
+ switch (xpandfile(
+ workptr, workdelta, &newworkname, dolog
+ )) {
+ default:
+ continue;
+
+ case 0:
+ /*
+ * No expansion occurred; try to reuse working file
+ * unless we already tried and failed.
+ */
+ if (changework)
+ if ((r=fixwork(newworkmode,mtime)) == 0)
+ break;
+ /* fall into */
+ case 1:
+ Izclose(&workptr);
+ aflush(exfile);
+ ignoreints();
+ r = chnamemod(&exfile, newworkname,
+ workname, 1, newworkmode, mtime
+ );
+ keepdirtemp(newworkname);
+ restoreints();
+ }
+ }
+ }
+ if (r != 0) {
+ eerror(workname);
+ continue;
+ }
+ diagnose("done\n");
+
+ }
+
+ tempunlink();
+ exitmain(exitstatus);
+} /* end of main (ci) */
+
+ static void
+cleanup()
+{
+ if (nerror) exitstatus = EXIT_FAILURE;
+ Izclose(&finptr);
+ Izclose(&workptr);
+ Ozclose(&exfile);
+ Ozclose(&fcopy);
+ ORCSclose();
+ dirtempunlink();
+}
+
+#if RCS_lint
+# define exiterr ciExit
+#endif
+ void
+exiterr()
+{
+ ORCSerror();
+ dirtempunlink();
+ tempunlink();
+ _exit(EXIT_FAILURE);
+}
+
+/*****************************************************************/
+/* the rest are auxiliary routines */
+
+
+ static int
+addelta()
+/* Function: Appends a delta to the delta tree, whose number is
+ * given by newdelnum. Updates Head, newdelnum, newdelnumlength,
+ * and the links in newdelta.
+ * Return -1 on error, 1 if a lock is removed, 0 otherwise.
+ */
+{
+ register char *tp;
+ register int i;
+ int removedlock;
+ int newdnumlength; /* actual length of new rev. num. */
+
+ newdnumlength = countnumflds(newdelnum.string);
+
+ if (rcsinitflag) {
+ /* this covers non-existing RCS file and a file initialized with rcs -i */
+ if (newdnumlength==0 && Dbranch) {
+ bufscpy(&newdelnum, Dbranch);
+ newdnumlength = countnumflds(Dbranch);
+ }
+ if (newdnumlength==0) bufscpy(&newdelnum, "1.1");
+ else if (newdnumlength==1) bufscat(&newdelnum, ".1");
+ else if (newdnumlength>2) {
+ rcserror("Branch point doesn't exist for revision %s.",
+ newdelnum.string
+ );
+ return -1;
+ } /* newdnumlength == 2 is OK; */
+ Head = &newdelta;
+ newdelta.next = 0;
+ return 0;
+ }
+ if (newdnumlength==0) {
+ /* derive new revision number from locks */
+ switch (findlock(true, &targetdelta)) {
+
+ default:
+ /* found two or more old locks */
+ return -1;
+
+ case 1:
+ /* found an old lock */
+ /* check whether locked revision exists */
+ if (!genrevs(targetdelta->num,(char*)0,(char*)0,(char*)0,&gendeltas))
+ return -1;
+ if (targetdelta==Head) {
+ /* make new head */
+ newdelta.next=Head;
+ Head= &newdelta;
+ } else if (!targetdelta->next && countnumflds(targetdelta->num)>2) {
+ /* new tip revision on side branch */
+ targetdelta->next= &newdelta;
+ newdelta.next = 0;
+ } else {
+ /* middle revision; start a new branch */
+ bufscpy(&newdelnum, "");
+ return addbranch(targetdelta, &newdelnum, 1);
+ }
+ incnum(targetdelta->num, &newdelnum);
+ return 1; /* successful use of existing lock */
+
+ case 0:
+ /* no existing lock; try Dbranch */
+ /* update newdelnum */
+ if (StrictLocks || !myself(RCSstat.st_uid)) {
+ rcserror("no lock set by %s", getcaller());
+ return -1;
+ }
+ if (Dbranch) {
+ bufscpy(&newdelnum, Dbranch);
+ } else {
+ incnum(Head->num, &newdelnum);
+ }
+ newdnumlength = countnumflds(newdelnum.string);
+ /* now fall into next statement */
+ }
+ }
+ if (newdnumlength<=2) {
+ /* add new head per given number */
+ if(newdnumlength==1) {
+ /* make a two-field number out of it*/
+ if (cmpnumfld(newdelnum.string,Head->num,1)==0)
+ incnum(Head->num, &newdelnum);
+ else
+ bufscat(&newdelnum, ".1");
+ }
+ if (cmpnum(newdelnum.string,Head->num) <= 0) {
+ rcserror("revision %s too low; must be higher than %s",
+ newdelnum.string, Head->num
+ );
+ return -1;
+ }
+ targetdelta = Head;
+ if (0 <= (removedlock = removelock(Head))) {
+ if (!genrevs(Head->num,(char*)0,(char*)0,(char*)0,&gendeltas))
+ return -1;
+ newdelta.next = Head;
+ Head = &newdelta;
+ }
+ return removedlock;
+ } else {
+ /* put new revision on side branch */
+ /*first, get branch point */
+ tp = newdelnum.string;
+ for (i = newdnumlength - ((newdnumlength&1) ^ 1); --i; )
+ while (*tp++ != '.')
+ continue;
+ *--tp = 0; /* Kill final dot to get old delta temporarily. */
+ if (!(targetdelta=genrevs(newdelnum.string,(char*)0,(char*)0,(char*)0,&gendeltas)))
+ return -1;
+ if (cmpnum(targetdelta->num, newdelnum.string) != 0) {
+ rcserror("can't find branch point %s", newdelnum.string);
+ return -1;
+ }
+ *tp = '.'; /* Restore final dot. */
+ return addbranch(targetdelta, &newdelnum, 0);
+ }
+}
+
+
+
+ static int
+addbranch(branchpoint, num, removedlock)
+ struct hshentry *branchpoint;
+ struct buf *num;
+ int removedlock;
+/* adds a new branch and branch delta at branchpoint.
+ * If num is the null string, appends the new branch, incrementing
+ * the highest branch number (initially 1), and setting the level number to 1.
+ * the new delta and branchhead are in globals newdelta and newbranch, resp.
+ * the new number is placed into num.
+ * Return -1 on error, 1 if a lock is removed, 0 otherwise.
+ * If REMOVEDLOCK is 1, a lock was already removed.
+ */
+{
+ struct branchhead *bhead, **btrail;
+ struct buf branchnum;
+ int result;
+ int field, numlength;
+ static struct branchhead newbranch; /* new branch to be inserted */
+
+ numlength = countnumflds(num->string);
+
+ if (!branchpoint->branches) {
+ /* start first branch */
+ branchpoint->branches = &newbranch;
+ if (numlength==0) {
+ bufscpy(num, branchpoint->num);
+ bufscat(num, ".1.1");
+ } else if (numlength&1)
+ bufscat(num, ".1");
+ newbranch.nextbranch = 0;
+
+ } else if (numlength==0) {
+ /* append new branch to the end */
+ bhead=branchpoint->branches;
+ while (bhead->nextbranch) bhead=bhead->nextbranch;
+ bhead->nextbranch = &newbranch;
+ bufautobegin(&branchnum);
+ getbranchno(bhead->hsh->num, &branchnum);
+ incnum(branchnum.string, num);
+ bufautoend(&branchnum);
+ bufscat(num, ".1");
+ newbranch.nextbranch = 0;
+ } else {
+ /* place the branch properly */
+ field = numlength - ((numlength&1) ^ 1);
+ /* field of branch number */
+ btrail = &branchpoint->branches;
+ while (0 < (result=cmpnumfld(num->string,(*btrail)->hsh->num,field))) {
+ btrail = &(*btrail)->nextbranch;
+ if (!*btrail) {
+ result = -1;
+ break;
+ }
+ }
+ if (result < 0) {
+ /* insert/append new branchhead */
+ newbranch.nextbranch = *btrail;
+ *btrail = &newbranch;
+ if (numlength&1) bufscat(num, ".1");
+ } else {
+ /* branch exists; append to end */
+ bufautobegin(&branchnum);
+ getbranchno(num->string, &branchnum);
+ targetdelta = genrevs(
+ branchnum.string, (char*)0, (char*)0, (char*)0,
+ &gendeltas
+ );
+ bufautoend(&branchnum);
+ if (!targetdelta)
+ return -1;
+ if (cmpnum(num->string,targetdelta->num) <= 0) {
+ rcserror("revision %s too low; must be higher than %s",
+ num->string, targetdelta->num
+ );
+ return -1;
+ }
+ if (!removedlock
+ && 0 <= (removedlock = removelock(targetdelta))
+ ) {
+ if (numlength&1)
+ incnum(targetdelta->num,num);
+ targetdelta->next = &newdelta;
+ newdelta.next = 0;
+ }
+ return removedlock;
+ /* Don't do anything to newbranch. */
+ }
+ }
+ newbranch.hsh = &newdelta;
+ newdelta.next = 0;
+ if (branchpoint->lockedby)
+ if (strcmp(branchpoint->lockedby, getcaller()) == 0)
+ return removelock(branchpoint); /* This returns 1. */
+ return removedlock;
+}
+
+ static int
+addsyms(num)
+ char const *num;
+{
+ register struct Symrev *p;
+
+ for (p = assoclst; p; p = p->nextsym)
+ if (addsymbol(num, p->ssymbol, p->override) < 0)
+ return false;
+ return true;
+}
+
+
+ static void
+incnum(onum,nnum)
+ char const *onum;
+ struct buf *nnum;
+/* Increment the last field of revision number onum by one and
+ * place the result into nnum.
+ */
+{
+ register char *tp, *np;
+ register size_t l;
+
+ l = strlen(onum);
+ bufalloc(nnum, l+2);
+ np = tp = nnum->string;
+ VOID strcpy(np, onum);
+ for (tp = np + l; np != tp; )
+ if (isdigit(*--tp)) {
+ if (*tp != '9') {
+ ++*tp;
+ return;
+ }
+ *tp = '0';
+ } else {
+ tp++;
+ break;
+ }
+ /* We changed 999 to 000; now change it to 1000. */
+ *tp = '1';
+ tp = np + l;
+ *tp++ = '0';
+ *tp = 0;
+}
+
+
+
+ static int
+removelock(delta)
+struct hshentry * delta;
+/* function: Finds the lock held by caller on delta,
+ * removes it, and returns nonzero if successful.
+ * Print an error message and return -1 if there is no such lock.
+ * An exception is if !StrictLocks, and caller is the owner of
+ * the RCS file. If caller does not have a lock in this case,
+ * return 0; return 1 if a lock is actually removed.
+ */
+{
+ register struct rcslock *next, **trail;
+ char const *num;
+
+ num=delta->num;
+ for (trail = &Locks; (next = *trail); trail = &next->nextlock)
+ if (next->delta == delta)
+ if (strcmp(getcaller(), next->login) == 0) {
+ /* We found a lock on delta by caller; delete it. */
+ *trail = next->nextlock;
+ delta->lockedby = 0;
+ return 1;
+ } else {
+ rcserror("revision %s locked by %s", num, next->login);
+ return -1;
+ }
+ if (!StrictLocks && myself(RCSstat.st_uid))
+ return 0;
+ rcserror("no lock set by %s for revision %s", getcaller(), num);
+ return -1;
+}
+
+
+
+ static char const *
+getcurdate()
+/* Return a pointer to the current date. */
+{
+ static char buffer[datesize]; /* date buffer */
+
+ if (!buffer[0])
+ time2date(now(), buffer);
+ return buffer;
+}
+
+ static int
+#if has_prototypes
+fixwork(mode_t newworkmode, time_t mtime)
+ /* The `#if has_prototypes' is needed because mode_t might promote to int. */
+#else
+ fixwork(newworkmode, mtime)
+ mode_t newworkmode;
+ time_t mtime;
+#endif
+{
+ return
+ 1 < workstat.st_nlink
+ || (newworkmode&S_IWUSR && !myself(workstat.st_uid))
+ || setmtime(workname, mtime) != 0
+ ? -1
+ : workstat.st_mode == newworkmode ? 0
+#if has_fchmod
+ : fchmod(Ifileno(workptr), newworkmode) == 0 ? 0
+#endif
+#if bad_chmod_close
+ : -1
+#else
+ : chmod(workname, newworkmode)
+#endif
+ ;
+}
+
+ static int
+xpandfile(unexfile, delta, exname, dolog)
+ RILE *unexfile;
+ struct hshentry const *delta;
+ char const **exname;
+ int dolog;
+/*
+ * Read unexfile and copy it to a
+ * file, performing keyword substitution with data from delta.
+ * Return -1 if unsuccessful, 1 if expansion occurred, 0 otherwise.
+ * If successful, stores the stream descriptor into *EXFILEP
+ * and its name into *EXNAME.
+ */
+{
+ char const *targetname;
+ int e, r;
+
+ targetname = makedirtemp(1);
+ if (!(exfile = fopenSafer(targetname, FOPEN_W_WORK))) {
+ eerror(targetname);
+ workerror("can't build working file");
+ return -1;
+ }
+ r = 0;
+ if (MIN_UNEXPAND <= Expand)
+ fastcopy(unexfile,exfile);
+ else {
+ for (;;) {
+ e = expandline(
+ unexfile, exfile, delta, false, (FILE*)0, dolog
+ );
+ if (e < 0)
+ break;
+ r |= e;
+ if (e <= 1)
+ break;
+ }
+ }
+ *exname = targetname;
+ return r & 1;
+}
+
+
+
+
+/* --------------------- G E T L O G M S G --------------------------------*/
+
+
+ static struct cbuf
+getlogmsg()
+/* Obtain and yield a log message.
+ * If a log message is given with -m, yield that message.
+ * If this is the initial revision, yield a standard log message.
+ * Otherwise, reads a character string from the terminal.
+ * Stops after reading EOF or a single '.' on a
+ * line. getlogmsg prompts the first time it is called for the
+ * log message; during all later calls it asks whether the previous
+ * log message can be reused.
+ */
+{
+ static char const
+ emptych[] = EMPTYLOG,
+ initialch[] = "Initial revision";
+ static struct cbuf const
+ emptylog = { emptych, sizeof(emptych)-sizeof(char) },
+ initiallog = { initialch, sizeof(initialch)-sizeof(char) };
+ static struct buf logbuf;
+ static struct cbuf logmsg;
+
+ register char *tp;
+ register size_t i;
+ char const *caller;
+
+ if (msg.size) return msg;
+
+ if (keepflag) {
+ /* generate std. log message */
+ caller = getcaller();
+ i = sizeof(ciklog)+strlen(caller)+3;
+ bufalloc(&logbuf, i + datesize + zonelenmax);
+ tp = logbuf.string;
+ VOID sprintf(tp, "%s%s at ", ciklog, caller);
+ VOID date2str(getcurdate(), tp+i);
+ logmsg.string = tp;
+ logmsg.size = strlen(tp);
+ return logmsg;
+ }
+
+ if (!targetdelta && (
+ cmpnum(newdelnum.string,"1.1")==0 ||
+ cmpnum(newdelnum.string,"1.0")==0
+ ))
+ return initiallog;
+
+ if (logmsg.size) {
+ /*previous log available*/
+ if (yesorno(true, "reuse log message of previous file? [yn](y): "))
+ return logmsg;
+ }
+
+ /* now read string from stdin */
+ logmsg = getsstdin("m", "log message", "", &logbuf);
+
+ /* now check whether the log message is not empty */
+ if (logmsg.size)
+ return logmsg;
+ return emptylog;
+}
+
+/* Make a linked list of Symbolic names */
+
+ static void
+addassoclst(flag, sp)
+ int flag;
+ char const *sp;
+{
+ struct Symrev *pt;
+
+ pt = talloc(struct Symrev);
+ pt->ssymbol = sp;
+ pt->override = flag;
+ pt->nextsym = 0;
+ *nextassoc = pt;
+ nextassoc = &pt->nextsym;
+}
diff --git a/gnu/usr.bin/rcs/co/Makefile b/gnu/usr.bin/rcs/co/Makefile
new file mode 100644
index 0000000..0c73865
--- /dev/null
+++ b/gnu/usr.bin/rcs/co/Makefile
@@ -0,0 +1,8 @@
+PROG= co
+SRCS= co.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/co/co.1 b/gnu/usr.bin/rcs/co/co.1
new file mode 100644
index 0000000..2aea3ad
--- /dev/null
+++ b/gnu/usr.bin/rcs/co/co.1
@@ -0,0 +1,736 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds i \&\s-1ISO\s0
+.ds r \&\s-1RCS\s0
+.ds u \&\s-1UTC\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH CO 1 \*(Dt GNU
+.SH NAME
+co \- check out RCS revisions
+.SH SYNOPSIS
+.B co
+.RI [ options ] " file " .\|.\|.
+.SH DESCRIPTION
+.B co
+retrieves a revision from each \*r file and stores it into
+the corresponding working file.
+.PP
+Pathnames matching an \*r suffix denote \*r files;
+all others denote working files.
+Names are paired as explained in
+.BR ci (1).
+.PP
+Revisions of an \*r file can be checked out locked or unlocked. Locking a
+revision prevents overlapping updates. A revision checked out for reading or
+processing (e.g., compiling) need not be locked. A revision checked out
+for editing and later checkin must normally be locked. Checkout with locking
+fails if the revision to be checked out is currently locked by another user.
+(A lock can be broken with
+.BR rcs "(1).)\ \&"
+Checkout with locking also requires the caller to be on the access list of
+the \*r file, unless he is the owner of the
+file or the superuser, or the access list is empty.
+Checkout without locking is not subject to accesslist restrictions, and is
+not affected by the presence of locks.
+.PP
+A revision is selected by options for revision or branch number,
+checkin date/time, author, or state.
+When the selection options
+are applied in combination,
+.B co
+retrieves the latest revision
+that satisfies all of them.
+If none of the selection options
+is specified,
+.B co
+retrieves the latest revision
+on the default branch (normally the trunk, see the
+.B \-b
+option of
+.BR rcs (1)).
+A revision or branch number can be attached
+to any of the options
+.BR \-f ,
+.BR \-I ,
+.BR \-l ,
+.BR \-M ,
+.BR \-p ,
+.BR \-q ,
+.BR \-r ,
+or
+.BR \-u .
+The options
+.B \-d
+(date),
+.B \-s
+(state), and
+.B \-w
+(author)
+retrieve from a single branch, the
+.I selected
+branch,
+which is either specified by one of
+.BR \-f ,
+\&.\|.\|.,
+.BR \-u ,
+or the default branch.
+.PP
+A
+.B co
+command applied to an \*r
+file with no revisions creates a zero-length working file.
+.B co
+always performs keyword substitution (see below).
+.SH OPTIONS
+.TP
+.BR \-r [\f2rev\fP]
+retrieves the latest revision whose number is less than or equal to
+.IR rev .
+If
+.I rev
+indicates a branch rather than a revision,
+the latest revision on that branch is retrieved.
+If
+.I rev
+is omitted, the latest revision on the default branch
+(see the
+.B \-b
+option of
+.BR rcs (1))
+is retrieved.
+If
+.I rev
+is
+.BR $ ,
+.B co
+determines the revision number from keyword values in the working file.
+Otherwise, a revision is composed of one or more numeric or symbolic fields
+separated by periods.
+If
+.I rev
+begins with a period,
+then the default branch (normally the trunk) is prepended to it.
+If
+.I rev
+is a branch number followed by a period,
+then the latest revision on that branch is used.
+The numeric equivalent of a symbolic field
+is specified with the
+.B \-n
+option of the commands
+.BR ci (1)
+and
+.BR rcs (1).
+.TP
+.BR \-l [\f2rev\fP]
+same as
+.BR \-r ,
+except that it also locks the retrieved revision for
+the caller.
+.TP
+.BR \-u [\f2rev\fP]
+same as
+.BR \-r ,
+except that it unlocks the retrieved revision if it was
+locked by the caller. If
+.I rev
+is omitted,
+.B \-u
+retrieves the revision locked by the caller, if there is one; otherwise,
+it retrieves the latest revision on the default branch.
+.TP
+.BR \-f [\f2rev\fP]
+forces the overwriting of the working file;
+useful in connection with
+.BR \-q .
+See also
+.SM "FILE MODES"
+below.
+.TP
+.B \-kkv
+Generate keyword strings using the default form, e.g.\&
+.B "$\&Revision: \*(Rv $"
+for the
+.B Revision
+keyword.
+A locker's name is inserted in the value of the
+.BR Header ,
+.BR Id ,
+and
+.B Locker
+keyword strings
+only as a file is being locked,
+i.e. by
+.B "ci\ \-l"
+and
+.BR "co\ \-l".
+This is the default.
+.TP
+.B \-kkvl
+Like
+.BR \-kkv ,
+except that a locker's name is always inserted
+if the given revision is currently locked.
+.TP
+.B \-kk
+Generate only keyword names in keyword strings; omit their values.
+See
+.SM "KEYWORD SUBSTITUTION"
+below.
+For example, for the
+.B Revision
+keyword, generate the string
+.B $\&Revision$
+instead of
+.BR "$\&Revision: \*(Rv $" .
+This option is useful to ignore differences due to keyword substitution
+when comparing different revisions of a file.
+Log messages are inserted after
+.B $\&Log$
+keywords even if
+.B \-kk
+is specified,
+since this tends to be more useful when merging changes.
+.TP
+.B \-ko
+Generate the old keyword string,
+present in the working file just before it was checked in.
+For example, for the
+.B Revision
+keyword, generate the string
+.B "$\&Revision: 1.1 $"
+instead of
+.B "$\&Revision: \*(Rv $"
+if that is how the string appeared when the file was checked in.
+This can be useful for file formats
+that cannot tolerate any changes to substrings
+that happen to take the form of keyword strings.
+.TP
+.B \-kb
+Generate a binary image of the old keyword string.
+This acts like
+.BR \-ko ,
+except it performs all working file input and output in binary mode.
+This makes little difference on Posix and Unix hosts,
+but on DOS-like hosts one should use
+.B "rcs\ \-i\ \-kb"
+to initialize an \*r file intended to be used for binary files.
+Also, on all hosts,
+.BR rcsmerge (1)
+normally refuses to merge files when
+.B \-kb
+is in effect.
+.TP
+.B \-kv
+Generate only keyword values for keyword strings.
+For example, for the
+.B Revision
+keyword, generate the string
+.B \*(Rv
+instead of
+.BR "$\&Revision: \*(Rv $" .
+This can help generate files in programming languages where it is hard to
+strip keyword delimiters like
+.B "$\&Revision:\ $"
+from a string.
+However, further keyword substitution cannot be performed once the
+keyword names are removed, so this option should be used with care.
+Because of this danger of losing keywords,
+this option cannot be combined with
+.BR \-l ,
+and the owner write permission of the working file is turned off;
+to edit the file later, check it out again without
+.BR \-kv .
+.TP
+.BR \-p [\f2rev\fP]
+prints the retrieved revision on the standard output rather than storing it
+in the working file.
+This option is useful when
+.B co
+is part of a pipe.
+.TP
+.BR \-q [\f2rev\fP]
+quiet mode; diagnostics are not printed.
+.TP
+.BR \-I [\f2rev\fP]
+interactive mode;
+the user is prompted and questioned
+even if the standard input is not a terminal.
+.TP
+.BI \-d date
+retrieves the latest revision on the selected branch whose checkin date/time is
+less than or equal to
+.IR date .
+The date and time can be given in free format.
+The time zone
+.B LT
+stands for local time;
+other common time zone names are understood.
+For example, the following
+.IR date s
+are equivalent
+if local time is January 11, 1990, 8pm Pacific Standard Time,
+eight hours west of Coordinated Universal Time (\*u):
+.RS
+.LP
+.RS
+.nf
+.ta \w'\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP 'u
+.ne 10
+\f38:00 pm lt\fP
+\f34:00 AM, Jan. 12, 1990\fP default is \*u
+\f31990-01-12 04:00:00+00\fP \*i 8601 (\*u)
+\f31990-01-11 20:00:00\-08\fP \*i 8601 (local time)
+\f31990/01/12 04:00:00\fP traditional \*r format
+\f3Thu Jan 11 20:00:00 1990 LT\fP output of \f3ctime\fP(3) + \f3LT\fP
+\f3Thu Jan 11 20:00:00 PST 1990\fP output of \f3date\fP(1)
+\f3Fri Jan 12 04:00:00 GMT 1990\fP
+\f3Thu, 11 Jan 1990 20:00:00 \-0800\fP Internet RFC 822
+\f312-January-1990, 04:00 WET\fP
+.ta 4n +4n +4n +4n
+.fi
+.RE
+.LP
+Most fields in the date and time can be defaulted.
+The default time zone is normally \*u, but this can be overridden by the
+.B \-z
+option.
+The other defaults are determined in the order year, month, day,
+hour, minute, and second (most to least significant). At least one of these
+fields must be provided. For omitted fields that are of higher significance
+than the highest provided field, the time zone's current values are assumed.
+For all other omitted fields,
+the lowest possible values are assumed.
+For example, without
+.BR \-z ,
+the date
+.B "20, 10:30"
+defaults to
+10:30:00 \*u of the 20th of the \*u time zone's current month and year.
+The date/time must be quoted if it contains spaces.
+.RE
+.TP
+.BR \-M [\f2rev\fP]
+Set the modification time on the new working file
+to be the date of the retrieved revision.
+Use this option with care; it can confuse
+.BR make (1).
+.TP
+.BI \-s state
+retrieves the latest revision on the selected branch whose state is set to
+.IR state .
+.TP
+.B \-T
+Preserve the modification time on the \*r file
+even if the \*r file changes because a lock is added or removed.
+This option can suppress extensive recompilation caused by a
+.BR make (1)
+dependency of some other copy of the working file on the \*r file.
+Use this option with care; it can suppress recompilation even when it is needed,
+i.e. when the change of lock
+would mean a change to keyword strings in the other working file.
+.TP
+.BR \-w [\f2login\fP]
+retrieves the latest revision on the selected branch which was checked in
+by the user with login name
+.IR login .
+If the argument
+.I login
+is
+omitted, the caller's login is assumed.
+.TP
+.BI \-j joinlist
+generates a new revision which is the join of the revisions on
+.IR joinlist .
+This option is largely obsoleted by
+.BR rcsmerge (1)
+but is retained for backwards compatibility.
+.RS
+.PP
+The
+.I joinlist
+is a comma-separated list of pairs of the form
+.IB rev2 : rev3,
+where
+.I rev2
+and
+.I rev3
+are (symbolic or numeric)
+revision numbers.
+For the initial such pair,
+.I rev1
+denotes the revision selected
+by the above options
+.BR \-f ,
+\&.\|.\|.,
+.BR \-w .
+For all other pairs,
+.I rev1
+denotes the revision generated by the previous pair.
+(Thus, the output
+of one join becomes the input to the next.)
+.PP
+For each pair,
+.B co
+joins revisions
+.I rev1
+and
+.I rev3
+with respect to
+.IR rev2 .
+This means that all changes that transform
+.I rev2
+into
+.I rev1
+are applied to a copy of
+.IR rev3 .
+This is particularly useful if
+.I rev1
+and
+.I rev3
+are the ends of two branches that have
+.I rev2
+as a common ancestor. If
+.IR rev1 < rev2 < rev3
+on the same branch,
+joining generates a new revision which is like
+.I rev3,
+but with all changes that lead from
+.I rev1
+to
+.I rev2
+undone.
+If changes from
+.I rev2
+to
+.I rev1
+overlap with changes from
+.I rev2
+to
+.I rev3,
+.B co
+reports overlaps as described in
+.BR merge (1).
+.PP
+For the initial pair,
+.I rev2
+can be omitted. The default is the common
+ancestor.
+If any of the arguments indicate branches, the latest revisions
+on those branches are assumed.
+The options
+.B \-l
+and
+.B \-u
+lock or unlock
+.IR rev1 .
+.RE
+.TP
+.BI \-V
+Print \*r's version number.
+.TP
+.BI \-V n
+Emulate \*r version
+.I n,
+where
+.I n
+can be
+.BR 3 ,
+.BR 4 ,
+or
+.BR 5 .
+This can be useful when interchanging \*r files with others who are
+running older versions of \*r.
+To see which version of \*r your correspondents are running, have them invoke
+.BR "rcs \-V" ;
+this works with newer versions of \*r.
+If it doesn't work, have them invoke
+.B rlog
+on an \*r file;
+if none of the first few lines of output contain the string
+.B branch:
+it is version 3;
+if the dates' years have just two digits, it is version 4;
+otherwise, it is version 5.
+An \*r file generated while emulating version 3 loses its default branch.
+An \*r revision generated while emulating version 4 or earlier has
+a time stamp that is off by up to 13 hours.
+A revision extracted while emulating version 4 or earlier contains
+abbreviated dates of the form
+.IB yy / mm / dd
+and can also contain different white space and line prefixes
+in the substitution for
+.BR $\&Log$ .
+.TP
+.BI \-x "suffixes"
+Use
+.I suffixes
+to characterize \*r files.
+See
+.BR ci (1)
+for details.
+.TP
+.BI \-z zone
+specifies the date output format in keyword substitution,
+and specifies the default time zone for
+.I date
+in the
+.BI \-d date
+option.
+The
+.I zone
+should be empty, a numeric \*u offset, or the special string
+.B LT
+for local time.
+The default is an empty
+.IR zone ,
+which uses the traditional \*r format of \*u without any time zone indication
+and with slashes separating the parts of the date;
+otherwise, times are output in \*i 8601 format with time zone indication.
+For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
+eight hours west of \*u,
+then the time is output as follows:
+.RS
+.LP
+.RS
+.nf
+.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
+.ne 4
+\f2option\fP \f2time output\fP
+\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
+\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
+\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
+.ta 4n +4n +4n +4n
+.fi
+.RE
+.LP
+The
+.B \-z
+option does not affect dates stored in \*r files,
+which are always \*u.
+.RE
+.SH "KEYWORD SUBSTITUTION"
+Strings of the form
+.BI $ keyword $
+and
+.BI $ keyword : .\|.\|. $
+embedded in
+the text are replaced
+with strings of the form
+.BI $ keyword : value $
+where
+.I keyword
+and
+.I value
+are pairs listed below.
+Keywords can be embedded in literal strings
+or comments to identify a revision.
+.PP
+Initially, the user enters strings of the form
+.BI $ keyword $ .
+On checkout,
+.B co
+replaces these strings with strings of the form
+.BI $ keyword : value $ .
+If a revision containing strings of the latter form
+is checked back in, the value fields will be replaced during the next
+checkout.
+Thus, the keyword values are automatically updated on checkout.
+This automatic substitution can be modified by the
+.B \-k
+options.
+.PP
+Keywords and their corresponding values:
+.TP
+.B $\&Author$
+The login name of the user who checked in the revision.
+.TP
+.B $\&Date$
+The date and time the revision was checked in.
+With
+.BI \-z zone
+a numeric time zone offset is appended; otherwise, the date is \*u.
+.TP
+.B $\&Header$
+A standard header containing the full pathname of the \*r file, the
+revision number, the date and time, the author, the state,
+and the locker (if locked).
+With
+.BI \-z zone
+a numeric time zone offset is appended to the date; otherwise, the date is \*u.
+.TP
+.B $\&Id$
+Same as
+.BR $\&Header$ ,
+except that the \*r filename is without a path.
+.TP
+.B $\&Locker$
+The login name of the user who locked the revision (empty if not locked).
+.TP
+.B $\&Log$
+The log message supplied during checkin, preceded by a header
+containing the \*r filename, the revision number, the author, and the date
+and time.
+With
+.BI \-z zone
+a numeric time zone offset is appended; otherwise, the date is \*u.
+Existing log messages are
+.I not
+replaced.
+Instead, the new log message is inserted after
+.BR $\&Log: .\|.\|. $ .
+This is useful for
+accumulating a complete change log in a source file.
+.RS
+.LP
+Each inserted line is prefixed by the string that prefixes the
+.B $\&Log$
+line. For example, if the
+.B $\&Log$
+line is
+.RB \*(lq "//\ $\&Log: tan.cc\ $" \*(rq,
+\*r prefixes each line of the log with
+.RB \*(lq "//\ " \*(rq.
+This is useful for languages with comments that go to the end of the line.
+The convention for other languages is to use a
+.RB \*(lq " \(** " \(rq
+prefix inside a multiline comment.
+For example, the initial log comment of a C program
+conventionally is of the following form:
+.RS
+.LP
+.nf
+.ft 3
+.ne 3
+/\(**
+.in +\w'/'u
+\(** $\&Log$
+\(**/
+.in
+.ft
+.fi
+.RE
+.LP
+For backwards compatibility with older versions of \*r, if the log prefix is
+.B /\(**
+or
+.B (\(**
+surrounded by optional white space, inserted log lines contain a space
+instead of
+.B /
+or
+.BR ( ;
+however, this usage is obsolescent and should not be relied on.
+.RE
+.TP
+.B $\&Name$
+The symbolic name used to check out the revision, if any.
+For example,
+.B "co\ \-rJoe"
+generates
+.BR "$\&Name:\ Joe\ $" .
+Plain
+.B co
+generates just
+.BR "$\&Name:\ \ $" .
+.TP
+.B $\&RCSfile$
+The name of the \*r file without a path.
+.TP
+.B $\&Revision$
+The revision number assigned to the revision.
+.TP
+.B $\&Source$
+The full pathname of the \*r file.
+.TP
+.B $\&State$
+The state assigned to the revision with the
+.B \-s
+option of
+.BR rcs (1)
+or
+.BR ci (1).
+.PP
+The following characters in keyword values are represented by escape sequences
+to keep keyword strings well-formed.
+.LP
+.RS
+.nf
+.ne 6
+.ta \w'newline 'u
+\f2char escape sequence\fP
+tab \f3\et\fP
+newline \f3\en\fP
+space \f3\e040
+$ \e044
+\e \e\e\fP
+.fi
+.RE
+.SH "FILE MODES"
+The working file inherits the read and execute permissions from the \*r
+file. In addition, the owner write permission is turned on, unless
+.B \-kv
+is set or the file
+is checked out unlocked and locking is set to strict (see
+.BR rcs (1)).
+.PP
+If a file with the name of the working file exists already and has write
+permission,
+.B co
+aborts the checkout,
+asking beforehand if possible.
+If the existing working file is
+not writable or
+.B \-f
+is given, the working file is deleted without asking.
+.SH FILES
+.B co
+accesses files much as
+.BR ci (1)
+does, except that it does not need to read the working file
+unless a revision number of
+.B $
+is specified.
+.SH ENVIRONMENT
+.TP
+.B \s-1RCSINIT\s0
+options prepended to the argument list, separated by spaces.
+See
+.BR ci (1)
+for details.
+.SH DIAGNOSTICS
+The \*r pathname, the working pathname,
+and the revision number retrieved are
+written to the diagnostic output.
+The exit status is zero if and only if all operations were successful.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
+.SH "SEE ALSO"
+rcsintro(1), ci(1), ctime(3), date(1), ident(1), make(1),
+rcs(1), rcsclean(1), rcsdiff(1), rcsmerge(1), rlog(1),
+rcsfile(5)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.SH LIMITS
+Links to the \*r and working files are not preserved.
+.PP
+There is no way to selectively suppress the expansion of keywords, except
+by writing them differently. In nroff and troff, this is done by embedding the
+null-character
+.B \e&
+into the keyword.
+.br
diff --git a/gnu/usr.bin/rcs/co/co.c b/gnu/usr.bin/rcs/co/co.c
new file mode 100644
index 0000000..51cb2b2
--- /dev/null
+++ b/gnu/usr.bin/rcs/co/co.c
@@ -0,0 +1,826 @@
+/* Check out working files from revisions of RCS files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.18 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.17 1995/06/01 16:23:43 eggert
+ * (main, preparejoin): Pass argument instead of using `join' static variable.
+ * (main): Add -kb.
+ *
+ * Revision 5.16 1994/03/17 14:05:48 eggert
+ * Move buffer-flushes out of critical sections, since they aren't critical.
+ * Use ORCSerror to clean up after a fatal error. Remove lint.
+ * Specify subprocess input via file descriptor, not file name.
+ *
+ * Revision 5.15 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.14 1993/11/03 17:42:27 eggert
+ * Add -z. Generate a value for the Name keyword.
+ * Don't arbitrarily limit the number of joins.
+ * Improve quality of diagnostics.
+ *
+ * Revision 5.13 1992/07/28 16:12:44 eggert
+ * Add -V. Check that working and RCS files are distinct.
+ *
+ * Revision 5.12 1992/02/17 23:02:08 eggert
+ * Add -T.
+ *
+ * Revision 5.11 1992/01/24 18:44:19 eggert
+ * Add support for bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.10 1992/01/06 02:42:34 eggert
+ * Update usage string.
+ *
+ * Revision 5.9 1991/10/07 17:32:46 eggert
+ * -k affects just working file, not RCS file.
+ *
+ * Revision 5.8 1991/08/19 03:13:55 eggert
+ * Warn before removing somebody else's file.
+ * Add -M. Fix co -j bugs. Tune.
+ *
+ * Revision 5.7 1991/04/21 11:58:15 eggert
+ * Ensure that working file is newer than RCS file after co -[lu].
+ * Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.6 1990/12/04 05:18:38 eggert
+ * Don't checkaccesslist() unless necessary.
+ * Use -I for prompts and -q for diagnostics.
+ *
+ * Revision 5.5 1990/11/01 05:03:26 eggert
+ * Fix -j. Add -I.
+ *
+ * Revision 5.4 1990/10/04 06:30:11 eggert
+ * Accumulate exit status across files.
+ *
+ * Revision 5.3 1990/09/11 02:41:09 eggert
+ * co -kv yields a readonly working file.
+ *
+ * Revision 5.2 1990/09/04 08:02:13 eggert
+ * Standardize yes-or-no procedure.
+ *
+ * Revision 5.0 1990/08/22 08:10:02 eggert
+ * Permit multiple locks by same user. Add setuid support.
+ * Remove compile-time limits; use malloc instead.
+ * Permit dates past 1999/12/31. Switch to GMT.
+ * Make lock and temp files faster and safer.
+ * Ansify and Posixate. Add -k, -V. Remove snooping. Tune.
+ *
+ * Revision 4.7 89/05/01 15:11:41 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.6 88/08/09 19:12:15 eggert
+ * Fix "co -d" core dump; rawdate wasn't always initialized.
+ * Use execv(), not system(); fix putchar('\0') and diagnose() botches; remove lint
+ *
+ * Revision 4.5 87/12/18 11:35:40 narten
+ * lint cleanups (from Guy Harris)
+ *
+ * Revision 4.4 87/10/18 10:20:53 narten
+ * Updating version numbers changes relative to 1.1, are actually
+ * relative to 4.2
+ *
+ * Revision 1.3 87/09/24 13:58:30 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:21:38 jenkins
+ * Port to suns
+ *
+ * Revision 4.2 83/12/05 13:39:48 wft
+ * made rewriteflag external.
+ *
+ * Revision 4.1 83/05/10 16:52:55 wft
+ * Added option -u and -f.
+ * Added handling of default branch.
+ * Replaced getpwuid() with getcaller().
+ * Removed calls to stat(); now done by pairfilenames().
+ * Changed and renamed rmoldfile() to rmworkfile().
+ * Replaced catchints() calls with restoreints(), unlink()--link() with rename();
+ *
+ * Revision 3.7 83/02/15 15:27:07 wft
+ * Added call to fastcopy() to copy remainder of RCS file.
+ *
+ * Revision 3.6 83/01/15 14:37:50 wft
+ * Added ignoring of interrupts while RCS file is renamed; this avoids
+ * deletion of RCS files during the unlink/link window.
+ *
+ * Revision 3.5 82/12/08 21:40:11 wft
+ * changed processing of -d to use DATEFORM; removed actual from
+ * call to preparejoin; re-fixed printing of done at the end.
+ *
+ * Revision 3.4 82/12/04 18:40:00 wft
+ * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE.
+ * Fixed printing of "done".
+ *
+ * Revision 3.3 82/11/28 22:23:11 wft
+ * Replaced getlogin() with getpwuid(), flcose() with ffclose(),
+ * %02d with %.2d, mode generation for working file with WORKMODE.
+ * Fixed nil printing. Fixed -j combined with -l and -p, and exit
+ * for non-existing revisions in preparejoin().
+ *
+ * Revision 3.2 82/10/18 20:47:21 wft
+ * Mode of working file is now maintained even for co -l, but write permission
+ * is removed.
+ * The working file inherits its mode from the RCS file, plus write permission
+ * for the owner. The write permission is not given if locking is strict and
+ * co does not lock.
+ * An existing working file without write permission is deleted automatically.
+ * Otherwise, co asks (empty answer: abort co).
+ * Call to getfullRCSname() added, check for write error added, call
+ * for getlogin() fixed.
+ *
+ * Revision 3.1 82/10/13 16:01:30 wft
+ * fixed type of variables receiving from getc() (char -> int).
+ * removed unused variables.
+ */
+
+
+
+
+#include "rcsbase.h"
+
+static char *addjoin P((char*));
+static char const *getancestor P((char const*,char const*));
+static int buildjoin P((char const*));
+static int preparejoin P((char*));
+static int rmlock P((struct hshentry const*));
+static int rmworkfile P((void));
+static void cleanup P((void));
+
+static char const quietarg[] = "-q";
+
+static char const *expandarg, *suffixarg, *versionarg, *zonearg;
+static char const **joinlist; /* revisions to be joined */
+static int joinlength;
+static FILE *neworkptr;
+static int exitstatus;
+static int forceflag;
+static int lastjoin; /* index of last element in joinlist */
+static int lockflag; /* -1 -> unlock, 0 -> do nothing, 1 -> lock */
+static int mtimeflag;
+static struct hshentries *gendeltas; /* deltas to be generated */
+static struct hshentry *targetdelta; /* final delta to be generated */
+static struct stat workstat;
+
+mainProg(coId, "co", "$FreeBSD$")
+{
+ static char const cmdusage[] =
+ "\nco usage: co -{fIlMpqru}[rev] -ddate -jjoins -ksubst -sstate -T -w[who] -Vn -xsuff -zzone file ...";
+
+ char *a, *joinflag, **newargv;
+ char const *author, *date, *rev, *state;
+ char const *joinname, *newdate, *neworkname;
+ int changelock; /* 1 if a lock has been changed, -1 if error */
+ int expmode, r, tostdout, workstatstat;
+ int Ttimeflag;
+ struct buf numericrev; /* expanded revision number */
+ char finaldate[datesize];
+# if OPEN_O_BINARY
+ int stdout_mode = 0;
+# endif
+
+ setrid();
+ author = date = rev = state = 0;
+ joinflag = 0;
+ bufautobegin(&numericrev);
+ expmode = -1;
+ suffixes = X_DEFAULT;
+ tostdout = false;
+ Ttimeflag = false;
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ while (a = *++argv, 0<--argc && *a++=='-') {
+ switch (*a++) {
+
+ case 'r':
+ revno:
+ if (*a) {
+ if (rev) warn("redefinition of revision number");
+ rev = a;
+ }
+ break;
+
+ case 'f':
+ forceflag=true;
+ goto revno;
+
+ case 'l':
+ if (lockflag < 0) {
+ warn("-u overridden by -l.");
+ }
+ lockflag = 1;
+ goto revno;
+
+ case 'u':
+ if (0 < lockflag) {
+ warn("-l overridden by -u.");
+ }
+ lockflag = -1;
+ goto revno;
+
+ case 'p':
+ tostdout = true;
+ goto revno;
+
+ case 'I':
+ interactiveflag = true;
+ goto revno;
+
+ case 'q':
+ quietflag=true;
+ goto revno;
+
+ case 'd':
+ if (date)
+ redefined('d');
+ str2date(a, finaldate);
+ date=finaldate;
+ break;
+
+ case 'j':
+ if (*a) {
+ if (joinflag) redefined('j');
+ joinflag = a;
+ }
+ break;
+
+ case 'M':
+ mtimeflag = true;
+ goto revno;
+
+ case 's':
+ if (*a) {
+ if (state) redefined('s');
+ state = a;
+ }
+ break;
+
+ case 'T':
+ if (*a)
+ goto unknown;
+ Ttimeflag = true;
+ break;
+
+ case 'w':
+ if (author) redefined('w');
+ if (*a)
+ author = a;
+ else
+ author = getcaller();
+ break;
+
+ case 'x':
+ suffixarg = *argv;
+ suffixes = a;
+ break;
+
+ case 'V':
+ versionarg = *argv;
+ setRCSversion(versionarg);
+ break;
+
+ case 'z':
+ zonearg = *argv;
+ zone_set(a);
+ break;
+
+ case 'k': /* set keyword expand mode */
+ expandarg = *argv;
+ if (0 <= expmode) redefined('k');
+ if (0 <= (expmode = str2expmode(a)))
+ break;
+ /* fall into */
+ default:
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
+
+ };
+ } /* end of option processing */
+
+ /* Now handle all pathnames. */
+ if (nerror) cleanup();
+ else if (argc < 1) faterror("no input file%s", cmdusage);
+ else for (; 0 < argc; cleanup(), ++argv, --argc) {
+ ffree();
+
+ if (pairnames(argc, argv, lockflag?rcswriteopen:rcsreadopen, true, false) <= 0)
+ continue;
+
+ /*
+ * RCSname contains the name of the RCS file, and finptr
+ * points at it. workname contains the name of the working file.
+ * Also, RCSstat has been set.
+ */
+ diagnose("%s --> %s\n", RCSname, tostdout?"standard output":workname);
+
+ workstatstat = -1;
+ if (tostdout) {
+# if OPEN_O_BINARY
+ int newmode = Expand==BINARY_EXPAND ? OPEN_O_BINARY : 0;
+ if (stdout_mode != newmode) {
+ stdout_mode = newmode;
+ oflush();
+ VOID setmode(STDOUT_FILENO, newmode);
+ }
+# endif
+ neworkname = 0;
+ neworkptr = workstdout = stdout;
+ } else {
+ workstatstat = stat(workname, &workstat);
+ if (workstatstat == 0 && same_file(RCSstat, workstat, 0)) {
+ rcserror("RCS file is the same as working file %s.",
+ workname
+ );
+ continue;
+ }
+ neworkname = makedirtemp(1);
+ if (!(neworkptr = fopenSafer(neworkname, FOPEN_W_WORK))) {
+ if (errno == EACCES)
+ workerror("permission denied on parent directory");
+ else
+ eerror(neworkname);
+ continue;
+ }
+ }
+
+ gettree(); /* reads in the delta tree */
+
+ if (!Head) {
+ /* no revisions; create empty file */
+ diagnose("no revisions present; generating empty revision 0.0\n");
+ if (lockflag)
+ warn(
+ "no revisions, so nothing can be %slocked",
+ lockflag < 0 ? "un" : ""
+ );
+ Ozclose(&fcopy);
+ if (workstatstat == 0)
+ if (!rmworkfile()) continue;
+ changelock = 0;
+ newdate = 0;
+ } else {
+ int locks = lockflag ? findlock(false, &targetdelta) : 0;
+ if (rev) {
+ /* expand symbolic revision number */
+ if (!expandsym(rev, &numericrev))
+ continue;
+ } else {
+ switch (locks) {
+ default:
+ continue;
+ case 0:
+ bufscpy(&numericrev, Dbranch?Dbranch:"");
+ break;
+ case 1:
+ bufscpy(&numericrev, targetdelta->num);
+ break;
+ }
+ }
+ /* get numbers of deltas to be generated */
+ if (!(targetdelta=genrevs(numericrev.string,date,author,state,&gendeltas)))
+ continue;
+ /* check reservations */
+ changelock =
+ lockflag < 0 ?
+ rmlock(targetdelta)
+ : lockflag == 0 ?
+ 0
+ :
+ addlock(targetdelta, true);
+
+ if (
+ changelock < 0
+ || (changelock && !checkaccesslist())
+ || dorewrite(lockflag, changelock) != 0
+ )
+ continue;
+
+ if (0 <= expmode)
+ Expand = expmode;
+ if (0 < lockflag && Expand == VAL_EXPAND) {
+ rcserror("cannot combine -kv and -l");
+ continue;
+ }
+
+ if (joinflag && !preparejoin(joinflag))
+ continue;
+
+ diagnose("revision %s%s\n",targetdelta->num,
+ 0<lockflag ? " (locked)" :
+ lockflag<0 ? " (unlocked)" : "");
+
+ /* Prepare to remove old working file if necessary. */
+ if (workstatstat == 0)
+ if (!rmworkfile()) continue;
+
+ /* skip description */
+ getdesc(false); /* don't echo*/
+
+ locker_expansion = 0 < lockflag;
+ targetdelta->name = namedrev(rev, targetdelta);
+ joinname = buildrevision(
+ gendeltas, targetdelta,
+ joinflag&&tostdout ? (FILE*)0 : neworkptr,
+ Expand < MIN_UNEXPAND
+ );
+# if !large_memory
+ if (fcopy == neworkptr)
+ fcopy = 0; /* Don't close it twice. */
+# endif
+ if_advise_access(changelock && gendeltas->first!=targetdelta,
+ finptr, MADV_SEQUENTIAL
+ );
+
+ if (donerewrite(changelock,
+ Ttimeflag ? RCSstat.st_mtime : (time_t)-1
+ ) != 0)
+ continue;
+
+ if (changelock) {
+ locks += lockflag;
+ if (1 < locks)
+ rcswarn("You now have %d locks.", locks);
+ }
+
+ newdate = targetdelta->date;
+ if (joinflag) {
+ newdate = 0;
+ if (!joinname) {
+ aflush(neworkptr);
+ joinname = neworkname;
+ }
+ if (Expand == BINARY_EXPAND)
+ workerror("merging binary files");
+ if (!buildjoin(joinname))
+ continue;
+ }
+ }
+ if (!tostdout) {
+ mode_t m = WORKMODE(RCSstat.st_mode,
+ ! (Expand==VAL_EXPAND || (lockflag<=0 && StrictLocks))
+ );
+ time_t t = mtimeflag&&newdate ? date2time(newdate) : (time_t)-1;
+ aflush(neworkptr);
+ ignoreints();
+ r = chnamemod(&neworkptr, neworkname, workname, 1, m, t);
+ keepdirtemp(neworkname);
+ restoreints();
+ if (r != 0) {
+ eerror(workname);
+ error("see %s", neworkname);
+ continue;
+ }
+ diagnose("done\n");
+ }
+ }
+
+ tempunlink();
+ Ofclose(workstdout);
+ exitmain(exitstatus);
+
+} /* end of main (co) */
+
+ static void
+cleanup()
+{
+ if (nerror) exitstatus = EXIT_FAILURE;
+ Izclose(&finptr);
+ ORCSclose();
+# if !large_memory
+ if (fcopy!=workstdout) Ozclose(&fcopy);
+# endif
+ if (neworkptr!=workstdout) Ozclose(&neworkptr);
+ dirtempunlink();
+}
+
+#if RCS_lint
+# define exiterr coExit
+#endif
+ void
+exiterr()
+{
+ ORCSerror();
+ dirtempunlink();
+ tempunlink();
+ _exit(EXIT_FAILURE);
+}
+
+
+/*****************************************************************
+ * The following routines are auxiliary routines
+ *****************************************************************/
+
+ static int
+rmworkfile()
+/*
+ * Prepare to remove workname, if it exists, and if
+ * it is read-only.
+ * Otherwise (file writable):
+ * if !quietmode asks the user whether to really delete it (default: fail);
+ * otherwise failure.
+ * Returns true if permission is gotten.
+ */
+{
+ if (workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH) && !forceflag) {
+ /* File is writable */
+ if (!yesorno(false, "writable %s exists%s; remove it? [ny](n): ",
+ workname,
+ myself(workstat.st_uid) ? "" : ", and you do not own it"
+ )) {
+ error(!quietflag && ttystdin()
+ ? "checkout aborted"
+ : "writable %s exists; checkout aborted", workname);
+ return false;
+ }
+ }
+ /* Actual unlink is done later by caller. */
+ return true;
+}
+
+
+ static int
+rmlock(delta)
+ struct hshentry const *delta;
+/* Function: removes the lock held by caller on delta.
+ * Returns -1 if someone else holds the lock,
+ * 0 if there is no lock on delta,
+ * and 1 if a lock was found and removed.
+ */
+{ register struct rcslock * next, * trail;
+ char const *num;
+ struct rcslock dummy;
+ int whomatch, nummatch;
+
+ num=delta->num;
+ dummy.nextlock=next=Locks;
+ trail = &dummy;
+ while (next) {
+ whomatch = strcmp(getcaller(), next->login);
+ nummatch=strcmp(num,next->delta->num);
+ if ((whomatch==0) && (nummatch==0)) break;
+ /*found a lock on delta by caller*/
+ if ((whomatch!=0)&&(nummatch==0)) {
+ rcserror("revision %s locked by %s; use co -r or rcs -u",
+ num, next->login
+ );
+ return -1;
+ }
+ trail=next;
+ next=next->nextlock;
+ }
+ if (next) {
+ /*found one; delete it */
+ trail->nextlock=next->nextlock;
+ Locks=dummy.nextlock;
+ next->delta->lockedby = 0;
+ return 1; /*success*/
+ } else return 0; /*no lock on delta*/
+}
+
+
+
+
+/*****************************************************************
+ * The rest of the routines are for handling joins
+ *****************************************************************/
+
+
+ static char *
+addjoin(joinrev)
+ char *joinrev;
+/* Add joinrev's number to joinlist, yielding address of char past joinrev,
+ * or 0 if no such revision exists.
+ */
+{
+ register char *j;
+ register struct hshentry *d;
+ char terminator;
+ struct buf numrev;
+ struct hshentries *joindeltas;
+
+ j = joinrev;
+ for (;;) {
+ switch (*j++) {
+ default:
+ continue;
+ case 0:
+ case ' ': case '\t': case '\n':
+ case ':': case ',': case ';':
+ break;
+ }
+ break;
+ }
+ terminator = *--j;
+ *j = 0;
+ bufautobegin(&numrev);
+ d = 0;
+ if (expandsym(joinrev, &numrev))
+ d = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&joindeltas);
+ bufautoend(&numrev);
+ *j = terminator;
+ if (d) {
+ joinlist[++lastjoin] = d->num;
+ return j;
+ }
+ return 0;
+}
+
+ static int
+preparejoin(j)
+ register char *j;
+/* Parse join list J and place pointers to the
+ * revision numbers into joinlist.
+ */
+{
+ lastjoin= -1;
+ for (;;) {
+ while ((*j==' ')||(*j=='\t')||(*j==',')) j++;
+ if (*j=='\0') break;
+ if (lastjoin>=joinlength-2) {
+ joinlist =
+ (joinlength *= 2) == 0
+ ? tnalloc(char const *, joinlength = 16)
+ : trealloc(char const *, joinlist, joinlength);
+ }
+ if (!(j = addjoin(j))) return false;
+ while ((*j==' ') || (*j=='\t')) j++;
+ if (*j == ':') {
+ j++;
+ while((*j==' ') || (*j=='\t')) j++;
+ if (*j!='\0') {
+ if (!(j = addjoin(j))) return false;
+ } else {
+ rcsfaterror("join pair incomplete");
+ }
+ } else {
+ if (lastjoin==0) { /* first pair */
+ /* common ancestor missing */
+ joinlist[1]=joinlist[0];
+ lastjoin=1;
+ /*derive common ancestor*/
+ if (!(joinlist[0] = getancestor(targetdelta->num,joinlist[1])))
+ return false;
+ } else {
+ rcsfaterror("join pair incomplete");
+ }
+ }
+ }
+ if (lastjoin < 1)
+ rcsfaterror("empty join");
+ return true;
+}
+
+
+
+ static char const *
+getancestor(r1, r2)
+ char const *r1, *r2;
+/* Yield the common ancestor of r1 and r2 if successful, 0 otherwise.
+ * Work reliably only if r1 and r2 are not branch numbers.
+ */
+{
+ static struct buf t1, t2;
+
+ int l1, l2, l3;
+ char const *r;
+
+ l1 = countnumflds(r1);
+ l2 = countnumflds(r2);
+ if ((2<l1 || 2<l2) && cmpnum(r1,r2)!=0) {
+ /* not on main trunk or identical */
+ l3 = 0;
+ while (cmpnumfld(r1, r2, l3+1)==0 && cmpnumfld(r1, r2, l3+2)==0)
+ l3 += 2;
+ /* This will terminate since r1 and r2 are not the same; see above. */
+ if (l3==0) {
+ /* no common prefix; common ancestor on main trunk */
+ VOID partialno(&t1, r1, l1>2 ? 2 : l1);
+ VOID partialno(&t2, r2, l2>2 ? 2 : l2);
+ r = cmpnum(t1.string,t2.string)<0 ? t1.string : t2.string;
+ if (cmpnum(r,r1)!=0 && cmpnum(r,r2)!=0)
+ return r;
+ } else if (cmpnumfld(r1, r2, l3+1)!=0)
+ return partialno(&t1,r1,l3);
+ }
+ rcserror("common ancestor of %s and %s undefined", r1, r2);
+ return 0;
+}
+
+
+
+ static int
+buildjoin(initialfile)
+ char const *initialfile;
+/* Function: merge pairs of elements in joinlist into initialfile
+ * If workstdout is set, copy result to stdout.
+ * All unlinking of initialfile, rev2, and rev3 should be done by tempunlink().
+ */
+{
+ struct buf commarg;
+ struct buf subs;
+ char const *rev2, *rev3;
+ int i;
+ char const *cov[10], *mergev[11];
+ char const **p;
+
+ bufautobegin(&commarg);
+ bufautobegin(&subs);
+ rev2 = maketemp(0);
+ rev3 = maketemp(3); /* buildrevision() may use 1 and 2 */
+
+ cov[1] = CO;
+ /* cov[2] setup below */
+ p = &cov[3];
+ if (expandarg) *p++ = expandarg;
+ if (suffixarg) *p++ = suffixarg;
+ if (versionarg) *p++ = versionarg;
+ if (zonearg) *p++ = zonearg;
+ *p++ = quietarg;
+ *p++ = RCSname;
+ *p = 0;
+
+ mergev[1] = MERGE;
+ mergev[2] = mergev[4] = "-L";
+ /* rest of mergev setup below */
+
+ i=0;
+ while (i<lastjoin) {
+ /*prepare marker for merge*/
+ if (i==0)
+ bufscpy(&subs, targetdelta->num);
+ else {
+ bufscat(&subs, ",");
+ bufscat(&subs, joinlist[i-2]);
+ bufscat(&subs, ":");
+ bufscat(&subs, joinlist[i-1]);
+ }
+ diagnose("revision %s\n",joinlist[i]);
+ bufscpy(&commarg, "-p");
+ bufscat(&commarg, joinlist[i]);
+ cov[2] = commarg.string;
+ if (runv(-1, rev2, cov))
+ goto badmerge;
+ diagnose("revision %s\n",joinlist[i+1]);
+ bufscpy(&commarg, "-p");
+ bufscat(&commarg, joinlist[i+1]);
+ cov[2] = commarg.string;
+ if (runv(-1, rev3, cov))
+ goto badmerge;
+ diagnose("merging...\n");
+ mergev[3] = subs.string;
+ mergev[5] = joinlist[i+1];
+ p = &mergev[6];
+ if (quietflag) *p++ = quietarg;
+ if (lastjoin<=i+2 && workstdout) *p++ = "-p";
+ *p++ = initialfile;
+ *p++ = rev2;
+ *p++ = rev3;
+ *p = 0;
+ switch (runv(-1, (char*)0, mergev)) {
+ case DIFF_FAILURE: case DIFF_SUCCESS:
+ break;
+ default:
+ goto badmerge;
+ }
+ i=i+2;
+ }
+ bufautoend(&commarg);
+ bufautoend(&subs);
+ return true;
+
+ badmerge:
+ nerror++;
+ bufautoend(&commarg);
+ bufautoend(&subs);
+ return false;
+}
diff --git a/gnu/usr.bin/rcs/doc/rcs.ms b/gnu/usr.bin/rcs/doc/rcs.ms
new file mode 100644
index 0000000..f6b0db3
--- /dev/null
+++ b/gnu/usr.bin/rcs/doc/rcs.ms
@@ -0,0 +1,1518 @@
+.\" Format this file with:
+.\" pic file | tbl | troff -ms
+.\"
+.\" \*s stands for $, and avoids problems when this file is checked in.
+.ds s $
+.de D(
+.DS
+.nr VS 12p
+.vs 12p
+.I
+..
+.de D)
+.DE
+.nr VS 18p
+.vs 18p
+.R
+..
+.de Id
+.ND \\$4
+..
+.Id $FreeBSD$
+.RP
+.TL
+RCS\*-A System for Version Control
+.sp
+.AU
+Walter F. Tichy
+.AI
+Department of Computer Sciences
+Purdue University
+West Lafayette, Indiana 47907
+.sp
+.AB
+An important problem in program development and maintenance is version control,
+i.e., the task of keeping a software system consisting of many versions and
+configurations well organized.
+The Revision Control System (RCS)
+is a software tool that assists with that task.
+RCS manages revisions of text documents, in particular source programs,
+documentation, and test data.
+It automates the storing, retrieval, logging and identification of revisions,
+and it provides selection mechanisms for composing configurations.
+This paper introduces basic version control concepts and
+discusses the practice of version control
+using RCS.
+For conserving space, RCS stores deltas, i.e., differences between
+successive revisions. Several delta storage methods are discussed.
+Usage statistics show that RCS's delta storage method is
+space and time efficient.
+The paper concludes with a detailed survey of version control tools.
+.sp
+\fBKeywords\fR: configuration management, history management,
+version control, revisions, deltas.
+.AE
+.FS
+An earlier version of this paper was published in
+.I "Software\*-Practice & Experience"
+.B 15 ,
+7 (July 1985), 637-654.
+.FE
+.nr VS 18p
+.LP
+.NH
+Introduction
+.PP
+Version control is the task of keeping software
+systems consisting of many versions and configurations well organized.
+The Revision Control System (RCS) is a set of UNIX
+commands that assist with that task.
+.PP
+RCS' primary function is to manage \fIrevision groups\fR.
+A revision group is a set of text documents, called \fIrevisions\fR,
+that evolved from each other. A new revision is
+created by manually editing an existing one.
+RCS organizes the revisions into an ancestral tree. The initial revision
+is the root of the tree, and the tree edges indicate
+from which revision a given one evolved.
+Besides managing individual revision groups, RCS provides
+flexible selection functions for composing configurations.
+RCS may be combined with MAKE\u1\d,
+resulting in a powerful package for version control.
+.PP
+RCS also offers facilities for
+merging updates with customer modifications,
+for distributed software development, and
+for automatic identification.
+Identification is the `stamping'
+of revisions and configurations with unique markers.
+These markers are akin to serial numbers,
+telling software maintainers unambiguously which configuration
+is before them.
+.PP
+RCS is designed for both production and experimental
+environments.
+In production environments,
+access controls detect update conflicts and prevent overlapping changes.
+In experimental environments, where strong controls are
+counterproductive, it is possible to loosen the controls.
+.PP
+Although RCS was originally intended for programs, it is useful for any
+text that is revised frequently and whose previous revisions must be
+preserved. RCS has been applied successfully to store the source
+text for drawings, VLSI layouts, documentation, specifications,
+test data, form letters and articles.
+.PP
+This paper discusses the practice of
+version control using RCS.
+It also introduces basic version control concepts,
+useful for clarifying current practice and designing similar systems.
+Revision groups of individual components are treated in the next three sections,
+and the extensions to configurations follow.
+Because of its size, a survey of version control tools
+appears at the end of the paper.
+.NH
+Getting started with RCS
+.PP
+Suppose a text file \fIf.c\fR is to be placed under control of RCS.
+Invoking the check-in command
+.D(
+ci f.c
+.D)
+creates a new revision group with the contents of
+\fIf.c\fR as the initial
+revision (numbered 1.1)
+and stores the group into the file \fIf.c,v\fR.
+Unless told otherwise, the command deletes \fIf.c\fR.
+It also asks for a description of the group.
+The description should state the common purpose of all revisions in the group,
+and becomes part of the group's documentation.
+All later check-in commands will ask for a log entry,
+which should summarize the changes made.
+(The first revision is assigned a default log message,
+which just records the fact that it is the initial revision.)
+.PP
+Files ending in \fI,v\fR
+are called \fIRCS files\fR (\fIv\fR stands for \fIv\fRersions);
+the others are called working files.
+To get back the working file \fIf.c\fR in the previous example,
+execute the check-out command:
+.D(
+co f.c
+.D)
+.R
+This command extracts the latest revision from
+the revision group \fIf.c,v\fR and writes
+it into \fIf.c\fR.
+The file \fIf.c\fR can now be edited and, when finished,
+checked back in with \fIci\fR:
+.D(
+ci f.c
+.D)
+\fICi\fR assigns number 1.2 to
+the new revision.
+If \fIci\fR complains with the message
+.D(
+ci error: no lock set by <login>
+.D)
+then the system administrator has decided to configure RCS for a
+production environment by enabling the `strict locking feature'.
+If this feature is enabled, all RCS files are initialized
+such that check-in operations require a lock on the previous revision
+(the one from which the current one evolved).
+Locking prevents overlapping modifications if several people work on the same file.
+If locking is required, the revision should
+have been locked during the check-out by using
+the option \fI\-l\fR:
+.D(
+co \-l f.c
+.D)
+Of course it is too late now for the check-out with locking, because
+\fIf.c\fR has already been changed; checking out the file again
+would overwrite the modifications.
+(To prevent accidental overwrites, \fIco\fR senses the presence
+of a working file and asks whether the user really intended to overwrite it.
+The overwriting check-out is sometimes useful for
+backing up to the previous revision.)
+To be able to proceed with the check-in in the present case, first execute
+.D(
+rcs \-l f.c
+.D)
+This command retroactively locks the latest revision, unless someone
+else locked it in the meantime. In this case, the two programmers
+involved have to negotiate whose
+modifications should take precedence.
+.PP
+If an RCS file is private, i.e., if only the owner of the file is expected
+to deposit revisions into it, the strict locking feature is unnecessary and
+may be disabled.
+If strict locking is disabled,
+the owner of the RCS file need not have a lock for check-in.
+For safety reasons, all others
+still do. Turning strict locking off and on is done with the commands:
+.D(
+rcs \-U f.c \fRand\fP rcs \-L f.c
+.D)
+These commands enable or disable the strict locking feature for each RCS file
+individually.
+The system administrator only decides whether strict locking is
+enabled initially.
+.PP
+To reduce the clutter in a working directory, all RCS files can be moved
+to a subdirectory with the name \fIRCS\fR.
+RCS commands look first into that directory for RCS files.
+All the commands presented above work
+with the \fIRCS\fR subdirectory without change.\(dg
+.FS \(dg
+Pairs of RCS and working files can actually be specified in 3 ways:
+a) both are given, b) only the working file is given, c) only the
+RCS file is given.
+If a pair is given, both files may have arbitrary path prefixes;
+RCS commands pair them up intelligently.
+.FE
+.PP
+It may be undesirable that \fIci\fR deletes the working file.
+For instance, sometimes one would like to save the current revision,
+but continue editing.
+Invoking
+.D(
+ci \-l f.c
+.D)
+checks in \fIf.c\fR as usual, but performs an additional
+check-out with locking afterwards. Thus, the working file does
+not disappear after the check-in.
+Similarly, the option
+\fI\-u\fR does a check-in followed by a check-out without
+locking. This option is useful if the file is needed for compilation after the check-in.
+Both options update the identification markers in the working file
+(see below).
+.PP
+Besides the operations \fIci\fR and \fIco\fR, RCS provides the following
+commands:
+.sp 0
+.nr VS 12p
+.vs 12p
+.TS
+tab(%);
+li l.
+ident%extract identification markers
+rcs%change RCS file attributes
+rcsclean%remove unchanged working files (optional)
+rcsdiff%compare revisions
+rcsfreeze%record a configuration (optional)
+rcsmerge%merge revisions
+rlog%read log messages and other information in RCS files
+.TE
+A synopsis of these commands appears in the Appendix.
+.NH 2
+Automatic Identification
+.PP
+RCS can stamp source and object code with special identification strings,
+similar to product and serial numbers.
+To obtain such identification, place the marker
+.D(
+\*sId\*s
+.D)
+into the text of a revision, for instance inside a comment.
+The check-out operation will replace this marker with a string of the form
+.D(
+\*sId: filename revisionnumber date time author state locker \*s
+.D)
+This string need never be touched, because \fIco\fR keeps it
+up to date automatically.
+To propagate the marker into object code, simply put
+it into a literal character string. In C, this is done as follows:
+.D(
+static char rcsid[] = \&"\*sId\*s\&";
+.D)
+The command \fIident\fR extracts such markers from any file, in particular from
+object code.
+\fIIdent\fR helps to find out
+which revisions of which modules were used in a given program.
+It returns a complete and unambiguous component list,
+from which a copy of the program can be reconstructed.
+This facility is invaluable for program maintenance.
+.PP
+There are several additional identification markers, one for each component
+of \*sId\*s.
+The marker
+.D(
+\*sLog\*s
+.D)
+has a similar function. It accumulates
+the log messages that are requested during check-in.
+Thus, one can maintain the complete history of a revision directly inside it,
+by enclosing it in a comment.
+Figure 1 is an edited version of a log contained in revision 4.1 of
+the file \fIci.c\fR. The log appears at the beginning of the file,
+and makes it easy to determine what the recent modifications were.
+.sp
+.nr VS 12p
+.vs 12p
+.ne 18
+.nf
+.in +0.5i
+/*
+.in +\w'/'u
+* \*sLog: ci.c,v \*s
+* Revision 4.1 1983/05/10 17:03:06 wft
+* Added option \-d and \-w, and updated assignment of date, etc. to new delta.
+* Added handling of default branches.
+*
+* Revision 3.9 1983/02/15 15:25:44 wft
+* Added call to fastcopy() to copy remainder of RCS file.
+*
+* Revision 3.8 1983/01/14 15:34:05 wft
+* Added ignoring of interrupts while new RCS file is renamed;
+* avoids deletion of RCS files by interrupts.
+*
+* Revision 3.7 1982/12/10 16:09:20 wft
+* Corrected checking of return code from diff.
+* An RCS file now inherits its mode during the first ci from the working file,
+* except that write permission is removed.
+*/
+.in 0
+.ce 1
+Figure 1. Log entries produced by the marker \*sLog\*s.
+.fi
+.nr VS 18p
+.vs 18p
+.sp 0
+.LP
+Since revisions are stored in the form of differences,
+each log message is
+physically stored once,
+independent of the number of revisions present.
+Thus, the \*sLog\*s marker incurs negligible space overhead.
+.NH
+The RCS Revision Tree
+.PP
+RCS arranges revisions in an ancestral tree.
+The \fIci\fR command builds this tree; the auxiliary command \fIrcs\fR
+prunes it.
+The tree has a root revision, normally numbered 1.1, and successive revisions
+are numbered 1.2, 1.3, etc. The first field of a revision number
+is called the \fIrelease number\fR and the second one
+the \fIlevel number\fR. Unless given explicitly,
+the \fIci\fR command assigns a new revision number
+by incrementing the level number of the previous revision.
+The release number must be incremented explicitly, using the
+\fI\-r\fR option of \fIci\fR.
+Assuming there are revisions 1.1, 1.2, and 1.3 in the RCS file f.c,v, the command
+.D(
+ci \-r2.1 f.c \fRor\fP ci \-r2 f.c
+.D)
+assigns the number 2.1 to the new revision.
+Later check-ins without the \fI\-r\fR option will assign the numbers 2.2, 2.3,
+and so on.
+The release number should be incremented only at major transition points
+in the development, for instance when a new release of a software product has
+been completed.
+.NH 2
+When are branches needed?
+.PP
+A young revision tree is slender:
+It consists of only one branch, called the trunk.
+As the tree ages, side branches may form.
+Branches are needed in the following 4 situations.
+.IP "\fITemporary fixes\fR"
+.sp 0
+Suppose a tree has 5 revisions grouped in 2 releases,
+as illustrated in Figure 2.
+Revision 1.3, the last one of release 1, is in operation at customer sites,
+while release 2 is in active development.
+.ne 4
+.PS 4i
+.ps -2
+box "1.1"
+arrow
+box "1.2"
+arrow
+box "1.3"
+arrow
+box "2.1"
+arrow
+box "2.2"
+arrow dashed
+.ps +2
+.PE
+.ce 1
+Figure 2. A slender revision tree.
+.sp 0
+Now imagine a customer requesting a fix of
+a problem in revision 1.3, although actual development has moved on
+to release 2. RCS does not permit an extra
+revision to be spliced in between 1.3 and 2.1, since that would not reflect
+the actual development history. Instead, create a branch
+at revision 1.3, and check in the fix on that branch.
+The first branch starting at 1.3 has number 1.3.1, and
+the revisions on that branch are numbered 1.3.1.1, 1.3.1.2, etc.
+The double numbering is needed to allow for another
+branch at 1.3, say 1.3.2.
+Revisions on the second branch would be numbered
+1.3.2.1, 1.3.2.2, and so on.
+The following steps create
+branch 1.3.1 and add revision 1.3.1.1:
+.sp 0
+.I
+.nr VS 12p
+.vs 12p
+.TS
+tab(%);
+l l l.
+ %co \-r1.3 f.c% \*- check out revision 1.3
+ %edit f.c% \*- change it
+ %ci \-r1.3.1 f.c% \*- check it in on branch 1.3.1
+.TE
+.nr VS 18p
+.vs 18p
+.R
+This sequence of commands transforms the tree of Figure 2 into
+the one in Figure 3.
+Note that it may be necessary to incorporate the differences
+between 1.3 and 1.3.1.1
+into a revision at level 2. The operation \fIrcsmerge\fR automates this
+process (see the Appendix).
+.ne 7
+.PS 4i
+.ps -2
+ box "1.1"
+ arrow
+ box "1.2"
+ arrow
+R13: box "1.3"
+ arrow
+R21: box "2.1"
+ arrow
+R22: box "2.2"
+ arrow dashed
+ line invis down from R21.s
+RB1: box "1.3.1.1"
+ arrow dashed right from RB1.e
+ arrow from R13.s to RB1.w
+.ps +2
+.PE
+.ce 1
+Figure 3. A revision tree with one side branch
+.sp
+.IP "\fIDistributed development and customer modifications\fR"
+.sp 0
+Assume a situation as in Figure 2, where revision 1.3 is in operation
+at several customer sites,
+while release 2 is in development.
+Customer sites should use RCS to store the distributed software.
+However, customer modifications should not be placed on the same branch
+as the distributed source; instead, they should be placed on a side branch.
+When the next software distribution arrives,
+it should be appended to the trunk of
+the customer's RCS file, and the customer
+can then merge the local modifications back into the new release.
+In the above example, a
+customer's RCS file would contain the following tree, assuming
+that the customer has received revision 1.3, added his local modifications
+as revision 1.3.1.1, then received revision 2.4, and merged
+2.4 and 1.3.1.1, resulting in 2.4.1.1.
+.ne 7
+.PS 4i
+.ps -2
+R13: box "1.3"
+ line invis
+R21: box invis
+ line invis
+R22: box invis
+ line invis
+R24: box "2.4"
+ line invis
+R25: box invis
+ line invis
+ arrow from R13.e to R24.w
+ line invis down from R21.s
+RB1: box "1.3.1.1"
+ arrow from R13.s to RB1.w
+ right
+ line invis down from R25.s
+RB2: box "2.4.1.1"
+ arrow from R24.s to RB2.w
+.ps +2
+.PE
+.ce 1
+Figure 4. A customer's revision tree with local modifications.
+.sp 1
+This approach is actually practiced in the CSNET project,
+where several universities and a company cooperate
+in developing a national computer network.
+.IP "\fIParallel development\fR"
+.sp 0
+Sometimes it is desirable to explore an alternate design or
+a different implementation technique in parallel with the
+main line development. Such development
+should be carried out on a side branch.
+The experimental changes may later be moved into the main line, or abandoned.
+.IP "\fIConflicting updates\fR"
+.sp 0
+A common occurrence is that one programmer
+has checked out a revision, but cannot complete the assignment
+for some reason. In the meantime, another person
+must perform another modification
+immediately. In that case, the second person should check-out the same revision,
+modify it, and check it in on a side branch, for later merging.
+.PP
+Every node in a revision tree consists of the following attributes:
+a revision number, a check-in date and time, the author's identification,
+a log entry, a state and the actual text. All these attributes
+are determined at the time the revision is checked in.
+The state attribute indicates the status of a revision.
+It is set automatically to `experimental' during check-in.
+A revision can later be promoted to a higher status, for example
+`stable' or `released'. The set of states is user-defined.
+.NH 2
+Revisions are represented as deltas
+.PP
+For conserving space, RCS stores revisions in the form
+of deltas, i.e., as differences between revisions.
+The user interface completely hides this fact.
+.PP
+A delta is a sequence of edit commands that transforms one string
+into another. The deltas employed by RCS are line-based, which means
+that the only edit commands allowed are insertion and deletion of lines.
+If a single character in a line is changed, the
+edit scripts consider the entire line changed.
+The program \fIdiff\fR\u2\d
+produces a small, line-based delta between pairs of text files.
+A character-based edit script would take much longer to compute,
+and would not be significantly shorter.
+.PP
+Using deltas is a classical space-time tradeoff: deltas reduce the
+space consumed, but increase access time.
+However, a version control tool should impose as little delay
+as possible on programmers.
+Excessive delays discourage the use of version controls,
+or induce programmers to take shortcuts that compromise system integrity.
+To gain reasonably fast access time for both editing and compiling,
+RCS arranges deltas in the following way.
+The most recent revision on the trunk is stored intact.
+All other revisions on the trunk are stored as reverse deltas.
+A reverse delta describes how to go backward in the development history:
+it produces the desired revision if applied to the successor of that revision.
+This implementation has the advantage
+that extraction of the latest revision is a simple and fast copy
+operation.
+Adding a new revision to the trunk is also fast: \fIci\fR simply
+adds the new revision intact, replaces the previous
+revision with a reverse delta, and keeps the rest of the old deltas.
+Thus, \fIci\fR requires the computation
+of only one new delta.
+.PP
+Branches need special treatment. The naive solution would be to
+store complete copies for the tips of all branches.
+Clearly, this approach would cost too much space. Instead,
+RCS uses \fIforward\fR deltas for branches. Regenerating a revision
+on a side branch proceeds as follows. First, extract the latest revision
+on the trunk; secondly, apply reverse deltas until the fork revision for
+the branch is obtained; thirdly, apply forward deltas until the desired
+branch revision is reached. Figure 5 illustrates a tree with
+one side branch. Triangles pointing to the left and right represent
+reverse and forward deltas, respectively.
+.ne 8
+.PS 4i
+.ps -2
+define BD X [line invis $1 right .5;
+line up .3 then left .5 down .3 then right .5 down .3 then up .3] X
+
+define FD X [line invis $1 right .5;
+line left .5 down .3 then up .6 then right .5 down .3;] X
+
+right
+D11: BD(" 1.1")
+ arrow right from D11.e
+D12: BD(" 1.2")
+ arrow right from D12.e
+D13: BD(" 1.3")
+ arrow right from D13.e
+D21: BD(" 2.1")
+ arrow right from D21.e
+D22: box "2.2"
+ line invis down from D21.s
+F1: FD("1.3.1.1 ")
+ arrow from D13.se to F1.w
+ arrow from F1.e right
+ right
+F2: FD("1.3.1.2 ")
+.ps +2
+.PE
+.ce 1
+Figure 5. A revision tree with reverse and forward deltas.
+.sp 0
+.PP
+Although implementing fast check-out for the latest trunk revision,
+this arrangement has the disadvantage that generation of other revisions
+takes time proportional to the number of deltas applied. For example,
+regenerating the branch tip in Figure 5 requires application of five
+deltas (including the initial one). Since usage statistics show that
+the latest trunk revision is the one that is retrieved in 95 per cent
+of all cases (see the section on usage statistics), biasing check-out time
+in favor of that revision results in significant savings.
+However, careful implementation of the delta application process is
+necessary to provide low retrieval overhead for other revisions, in
+particular for branch tips.
+.PP
+There are several techniques for delta application.
+The naive one is to pass each delta to a general-purpose text editor.
+A prototype of RCS invoked the UNIX editor \fIed\fR both
+for applying deltas and for expanding the identification markers.
+Although easy to implement, performance was poor, owing to the
+high start-up costs and excess generality of \fIed\fR. An intermediate
+version of RCS used a special-purpose, stream-oriented editor.
+This technique reduced the cost of applying a delta to the cost of
+checking out the latest trunk revision. The reason for this behavior
+is that each delta application involves a complete pass over
+the preceding revision.
+.PP
+However, there is a much better algorithm. Note that the deltas are
+line oriented and that most of the work of a stream editor involves
+copying unchanged lines from one revision to the next. A faster
+algorithm avoids unnecessary copying of character strings by using
+a \fIpiece table\fR.
+A piece table is a one-dimensional array, specifying how a given
+revision is `pieced together' from lines in the RCS file.
+Suppose piece table \fIPT\dr\u\fR represents revision \fIr\fR.
+Then \fIPT\dr\u[i]\fR contains the starting position of line \fIi\fR
+of revision \fIr\fR.
+Application of the next delta transforms piece table \fIPT\dr\u\fR
+into \fIPT\dr+1\u\fR. For instance, a delete command removes a
+series of entries from the piece table. An insertion command inserts
+new entries, moving the entries following the insertion point further down the
+array. The inserted entries point to the text lines in the delta.
+Thus, no I/O is involved except for reading the delta itself. When all
+deltas have been applied to the piece table, a sequential pass
+through the table looks up each line in the RCS file and copies it to
+the output file, updating identification markers at the same time.
+Of course, the RCS file must permit random access, since the copied
+lines are scattered throughout that file. Figure 6 illustrates an
+RCS file with two revisions and the corresponding piece tables.
+.ne 13
+.sp 6
+.ce 1
+\fIFigure 6 is not available.\fP
+.sp 5
+.ce 1
+Figure 6. An RCS file and its piece tables
+.sp 0
+.PP
+The piece table approach has the property that the time for applying a single
+delta is roughly determined by the size of the delta, and not by the
+size of the revision. For example, if a delta is
+10 per cent of the size of a revision, then applying it takes only
+10 per cent of the time to generate the latest trunk revision. (The stream
+editor would take 100 per cent.)
+.PP
+There is an important alternative for representing deltas that affects
+performance. SCCS\u3\d,
+a precursor of RCS, uses \fIinterleaved\fR deltas.
+A file containing interleaved deltas is partitioned into blocks of lines.
+Each block has a header that specifies to which revision(s) the block
+belongs. The blocks are sorted out in such a way that a single
+pass over the file can pick up all the lines belonging to a given
+revision. Thus, the regeneration time for all revisions is the same:
+all headers must be inspected, and the associated blocks either copied
+or skipped. As the number of revisions increases, the cost of retrieving
+any revision is much higher than the cost of checking out the
+latest trunk revision with reverse deltas. A detailed comparison
+of SCCS's interleaved deltas and RCS's reverse deltas can be found
+in Reference 4.
+This reference considers the version of RCS with the
+stream editor only. The piece table method improves performance
+further, so that RCS is always faster than SCCS, except if 10
+or more deltas are applied.
+.PP
+Additional speed-up for both delta methods can be obtained by caching
+the most recently generated revision, as has been implemented in DSEE.\u5\d
+With caching, access time to frequently used revisions can approach normal file
+access time, at the cost of some additional space.
+.NH
+Locking: A Controversial Issue
+.PP
+The locking mechanism for RCS was difficult to design.
+The problem and its solution are first presented in their `pure' form,
+followed by a discussion of the complications
+caused by `real-world' considerations.
+.PP
+RCS must prevent two or more persons from depositing competing changes of the
+same revision.
+Suppose two programmers check out revision 2.4 and
+modify it. Programmer A checks in a revision before programmer B\&.
+Unfortunately, programmer B has not seen A's
+changes, so the effect is that A's changes are covered up by B's deposit.
+A's changes are not lost since all revisions
+are saved, but they are confined to a single revision.\(dd
+.FS \(dd
+Note that this problem is entirely different from the atomicity problem.
+Atomicity means that
+concurrent update operations on the same RCS file cannot be permitted,
+because that may result in inconsistent data.
+Atomic updates are essential (and implemented in RCS),
+but do not solve the conflict discussed here.
+.FE
+.PP
+This conflict is prevented in RCS by locking.
+Whenever someone intends to edit a revision (as opposed
+to reading or compiling it), the revision should be checked out
+and locked,
+using the \fI\-l\fR option on \fIco\fR. On subsequent check-in,
+\fIci\fR tests the lock and then removes it.
+At most one programmer at a time may
+lock a particular revision, and only this programmer may check in
+the succeeding revision.
+Thus, while a revision is locked, it is the exclusive responsibility
+of the locker.
+.PP
+An important maxim for software tools like RCS is that they must
+not stand in the way of making progress with a project.
+This consideration leads to several weakenings of the locking mechanism.
+First of all, even if a revision is locked, it can
+still be checked out. This is necessary if other people
+wish to compile or inspect the locked revision
+while the next one is in preparation. The only operations they
+cannot do are to lock the revision or to check in the succeeding one. Secondly,
+check-in operations on other branches in the RCS file are still possible; the
+locking of one revision does not affect any other revision.
+Thirdly, revisions are occasionally locked for a long period of time
+because a programmer is absent or otherwise unable to complete
+the assignment. If another programmer has to make a pressing change,
+there are the following three alternatives for making progress:
+a) find out who is holding the lock and ask that person to release it;
+b) check out the locked revision, modify it, check it
+in on a branch, and merge the changes later;
+c) break the lock. Breaking a lock leaves a highly visible
+trace, namely an electronic mail message that is sent automatically to the
+holder of the lock, recording the breaker and a commentary requested from him.
+Thus, breaking locks is tolerated under certain circumstances,
+but will not go unnoticed.
+Experience has shown that the automatic mail message attaches a high enough
+stigma to lock breaking,
+such that programmers break locks only in real emergencies,
+or when a co-worker resigns and leaves locked revisions behind.
+.PP
+If an RCS file is private, i.e., when a programmer owns an RCS file
+and does not expect anyone else to perform check-in operations,
+locking is an unnecessary nuisance.
+In this case,
+the `strict locking feature' discussed earlier may be disabled,
+provided that file protection
+is set such that only the owner may write the RCS file.
+This has the effect that only the owner can check-in revisions,
+and that no lock is needed for doing so.
+.PP
+As added protection,
+each RCS file contains an access list that specifies the users
+who may execute update operations. If an access list is empty,
+only normal UNIX file protection applies. Thus, the access list is
+useful for restricting the set of people who would otherwise have update
+permission. Just as with locking, the access list
+has no effect on read-only operations such as \fIco\fR. This approach
+is consistent with the UNIX philosophy of openness, which contributes
+to a productive software development environment.
+.NH
+Configuration Management
+.PP
+The preceding sections described how RCS deals with revisions of individual
+components; this section discusses how to handle configurations.
+A configuration is a set of revisions, where each revision comes
+from a different revision group, and the revisions are selected
+according to a certain criterion.
+For example,
+in order to build a functioning compiler, the `right'
+revisions from the scanner, the parser, the optimizer
+and the code generator must be combined.
+RCS, in conjunction with MAKE,
+provides a number of facilities to effect a smooth selection.
+.NH 2
+RCS Selection Functions
+.PP
+.IP "\fIDefault selection\fR"
+.sp 0
+During development, the usual selection criterion is to choose
+the latest revision of all components. The \fIco\fR command
+makes this selection by default. For example, the command
+.D(
+co *,v
+.D)
+retrieves the latest revision on the default branch of each RCS file
+in the current directory.
+The default branch is usually the trunk, but may be
+set to be a side branch.
+Side branches as defaults are needed in distributed software development,
+as discussed in the section on the RCS revision tree.
+.sp
+.IP "\fIRelease based selection\fR"
+.sp 0
+Specifying a release or branch number selects the latest revision in
+that release or branch.
+For instance,
+.D(
+co \-r2 *,v
+.D)
+retrieves the latest revision with release number 2 from each RCS file.
+This selection is convenient if a release has been completed and
+development has moved on to the next release.
+.sp
+.IP "\fIState and author based selection\fR"
+.sp 0
+If the highest level number within a given release number
+is not the desired one,
+the state attribute can help. For example,
+.D(
+co \-r2 \-sReleased *,v
+.D)
+retrieves the latest revision with release number 2 whose state attribute
+is `Released'.
+Of course, the state attribute has to be set appropriately, using the
+\fIci\fR or \fIrcs\fR commands.
+Another alternative is to select a revision by its author,
+using the \fI\-w\fR option.
+.sp
+.IP "\fIDate based selection\fR"
+.sp 0
+Revisions may also be selected by date.
+Suppose a release of an entire system was
+completed and current on March 4, at 1:00 p.m. local time. Then the command
+.D(
+co \-d'March 4, 1:00 pm LT' *,v
+.D)
+checks out all the components of that release, independent of the numbering.
+The \fI\-d\fR option specifies a `cutoff date', i.e.,
+the revision selected has a check-in date that
+is closest to, but not after the date given.
+.IP "\fIName based selection\fR"
+.sp 0
+The most powerful selection function is based on assigning symbolic
+names to revisions and branches.
+In large systems, a single release number or date is not sufficient
+to collect the appropriate revisions from all groups.
+For example, suppose one wishes to combine release 2
+of one subsystem and release 15 of another.
+Most likely, the creation dates of those releases differ also.
+Thus, a single revision number or date passed to the \fIco\fR command
+will not suffice to select the right revisions.
+Symbolic revision numbers solve this problem.
+Each RCS file may contain a set of symbolic names that are mapped
+to numeric revision numbers. For example, assume
+the symbol \fIV3\fR is bound to release number 2 in file \fIs,v\fR, and to
+revision number 15.9 in \fIt,v\fR.
+Then the single command
+.D(
+co \-rV3 s,v t,v
+.D)
+retrieves the latest revision of release 2 from \fIs,v\fR,
+and revision 15.9 from \fIt,v\fR.
+In a large system with many modules, checking out all
+revisions with one command greatly simplifies configuration management.
+.PP
+Judicious use of symbolic revision numbers helps with organizing
+large configurations.
+A special command, \fIrcsfreeze\fR,
+assigns a symbolic revision number to a selected revision
+in every RCS file.
+\fIRcsfreeze\fR effectively freezes a configuration.
+The assigned symbolic revision number selects all components
+of the configuration.
+If necessary, symbolic numbers
+may even be intermixed with numeric ones. Thus, \fIV3.5\fR in the
+above example
+would select revision 2.5 in \fIs,v\fR and branch 15.9.5 in \fIt,v\fR.
+.PP
+The options \fI\-r\fR, \fI\-s\fR, \fI\-w\fR and \fI\-d\fR
+may be combined. If a branch is given, the latest revision
+on that branch satisfying all conditions is retrieved;
+otherwise, the default branch is used.
+.NH 2
+Combining MAKE and RCS
+.PP
+MAKE\u1\d
+is a program that processes configurations.
+It is driven by configuration specifications
+recorded in a special file, called a `Makefile'.
+MAKE avoids redundant processing steps
+by comparing creation dates of source and processed objects.
+For example, when instructed to compile all
+modules of a given system, it only recompiles
+those source modules that were changed
+since they were processed last.
+.PP
+MAKE has been extended with an auto-checkout feature for RCS.*
+.FS *
+This auto-checkout extension is available only in some versions of MAKE,
+e.g. GNU MAKE.
+.FE
+When a certain file to be processed is not present,
+MAKE attempts a check-out operation.
+If successful, MAKE performs the required processing, and then deletes
+the checked out file to conserve space.
+The selection parameters discussed above can be passed to MAKE
+either as parameters, or directly embedded in the Makefile.
+MAKE has also been extended to search the subdirectory named \fIRCS\fR
+for needed files, rather than just the current working directory.
+However, if a working file is present, MAKE totally ignores the corresponding
+RCS file and uses the working file.
+(In newer versions of MAKE distributed by AT&T and others,
+auto-checkout can be
+achieved with the rule DEFAULT, instead of a special extension of MAKE.
+However, a file checked out by the rule DEFAULT
+will not be deleted after processing. \fIRcsclean\fR can be
+used for that purpose.)
+.PP
+With auto-checkout, RCS/MAKE can effect a selection rule
+especially tuned for multi-person software development and maintenance.
+In these situations,
+programmers should obtain configurations that consist of
+the revisions they have personally checked out plus the latest
+checked in revision of all other revision groups.
+This schema can be set up as follows.
+.PP
+Each programmer chooses a working directory
+and places into it a symbolic link, named \fIRCS\fR,
+to the directory containing the relevant RCS files.
+The symbolic link makes sure that \fIco\fR and \fIci\fR
+operations need only specify the working files, and that
+the Makefile need not be changed.
+The programmer then checks out the needed files and modifies them.
+If MAKE is invoked,
+it composes configurations by selecting those
+revisions that are checked out, and the rest from the
+subdirectory \fIRCS\fR.
+The latter selection may be controlled by a symbolic
+revision number or any of the other selection criteria.
+If there are several programmers editing in separate working directories,
+they are insulated from each other's changes until checking in their
+modifications.
+.PP
+Similarly, a maintainer can recreate an older configuration
+by starting to work in an empty working directory.
+During the initial MAKE invocation, all revisions are selected from RCS files.
+As the maintainer checks out files and modifies them,
+a new configuration is gradually built up.
+Every time MAKE is invoked, it substitutes the modified revisions
+into the configuration being manipulated.
+.PP
+A final application of RCS is to use it for storing Makefiles.
+Revision groups of Makefiles represent
+multiple versions of configurations.
+Whenever a configuration is baselined or distributed,
+the best approach is to unambiguously fix
+the configuration with a symbolic revision number by calling
+\fIrcsfreeze\fR,
+to embed that symbol into the Makefile, and to
+check in the Makefile (using the same symbolic revision number).
+With this approach, old configurations
+can be regenerated easily and reliably.
+.NH
+Usage Statistics
+.PP
+The following usage statistics were collected on two DEC VAX-11/780
+computers of the Purdue Computer Science Department. Both machines
+are mainly used for research purposes. Thus, the data
+reflect an environment in which the majority of projects
+involve prototyping and advanced software development,
+but relatively little long-term maintenance.
+.PP
+For the first experiment,
+the \fIci\fR and \fIco\fR operations were instrumented
+to log the number of backward and forward deltas applied.
+The data were collected during a 13 month period
+from Dec. 1982 to Dec. 1983.
+Table I summarizes the results.
+.sp 0
+.nr VS 12p
+.vs 12p
+.TS
+center,box,tab(#);
+c|c|c|c|c s|c s
+c|c|c|c|c s|c s
+l|n|n|n|n n|n n.
+Operation#Total#Total deltas#Mean deltas#Operations#Branch
+ #operations #applied#applied#with >1 delta#operations
+_
+co # 7867# 9320#1.18#509#(6%)#203#(3%)
+ci # 3468# 2207#0.64# 85#(2%)# 75#(2%)
+ci & co#11335#11527#1.02#594#(5%)#278#(2%)
+.TE
+.ce 1
+Table I. Statistics for \fIco\fR and \fIci\fR operations.
+.nr VS 18p
+.vs 18p
+.PP
+The first two lines show statistics for check-out and check-in;
+the third line shows the combination.
+Recall that \fIci\fR performs an implicit check-out to obtain
+a revision for computing the delta.
+In all measures presented, the most recent revision (stored intact)
+counts as one delta. The number of deltas applied represents
+the number of passes necessary, where the first `pass' is a copying step.
+.PP
+Note that the check-out operation is executed more than
+twice as frequently as the check-in operation.
+The fourth column gives the mean number of deltas
+applied in all three cases.
+For \fIci\fR, the mean number of deltas applied is less
+than one.
+The reasons are that the initial check-in requires no delta at all, and that
+the only time \fIci\fR requires more than one delta is for branches.
+Column 5 shows the actual number of operations that applied more than one
+delta.
+The last column indicates that branches were not used often.
+.PP
+The last three columns demonstrate that the most recent trunk revision
+is by far the most frequently accessed.
+For RCS, check-out of
+this revision is a simple copy operation, which is the absolute minimum
+given the copy-semantics of \fIco\fR.
+Access to older revisions and branches
+is more common in non-academic environments,
+yet even if access to older deltas were an order
+of magnitude more frequent,
+the combined average number of deltas applied would still be below 1.2.
+Since RCS is faster than SCCS until up to 10 delta applications,
+reverse deltas are clearly the method of choice.
+.PP
+The second experiment, conducted in March of 1984,
+involved surveying the existing RCS files
+on our two machines. The goal was to determine the mean number of
+revisions per RCS file, as well as the space consumed by them.
+Table II shows the results. (Tables I and II were produced at different
+times and are unrelated.)
+.sp 0
+.nr VS 12p
+.vs 12p
+.TS
+center,box,tab(#);
+c | c | c | c | c | c | c
+c | c | c | c | c | c | c
+l | n | n | n | n | n | n.
+ #Total RCS#Total#Mean#Mean size of#Mean size of#Overhead
+ #files#revisions#revisions#RCS files#revisions
+_
+All files #8033#11133#1.39#6156#5585#1.10
+Files with#1477# 4578#3.10#8074#6041#1.34
+\(>= 2 deltas
+.TE
+.ce 1
+Table II. Statistics for RCS files.
+.nr VS 18p
+.vs 18p
+.PP
+The mean number of revisions per RCS file is 1.39.
+Columns 5 and 6 show the mean sizes (in bytes) of an RCS file
+and of the latest revision of each RCS file, respectively.
+The `overhead' column contains the ratio of the mean sizes.
+Assuming that all revisions in an RCS file are approximately the same size,
+this ratio gives a measure of the space consumed by the extra revisions.
+.PP
+In our sample, over 80 per cent of the RCS files contained only a single revision.
+The reason is that our
+systems programmers routinely check in all source files
+on the distribution tapes, even though they may never touch them again.
+To get a better indication of how much space savings are possible
+with deltas, all measures with those files
+that contained 2 or more revisions were recomputed. Only for those files
+is RCS necessary.
+As shown in the second line, the average number of revisions for those files is
+3.10, with an overhead of 1.34. This means that the extra 2.10 deltas
+require 34 per cent extra space, or
+16 per cent per extra revision.
+Rochkind\u3\d
+measured the space consumed by SCCS, and
+reported an average of 5 revisions per group
+and an overhead of 1.37 (or about 9 per cent per extra revision).
+In a later paper, Glasser\u6\d
+observed an average of 7 revisions per group in a single, large project,
+but provided no overhead figure.
+In his paper on DSEE\u5\d,
+Leblang reported that delta storage combined with blank compression
+results in an overhead of a mere 1\-2 per cent per revision.
+Since leading blanks accounted for about 20 per cent of the surveyed Pascal
+programs, a revision group with 5\-10 members was smaller
+than a single cleartext copy.
+.PP
+The above observations demonstrate clearly that the space needed
+for extra revisions is small. With delta storage, the luxury of
+keeping multiple revisions online is certainly affordable.
+In fact, introducing a system with delta storage may reduce
+storage requirements, because programmers often save back-up copies
+anyway. Since back-up copies are stored much more efficiently with deltas,
+introducing a system such as RCS may
+actually free a considerable amount of space.
+.NH
+Survey of Version Control Tools
+.PP
+The need to keep back-up copies of software arose when
+programs and data were no longer stored on paper media, but were entered
+from terminals and stored on disk.
+Back-up copies are desirable for reliability, and many modern editors
+automatically save a back-up copy for every file touched.
+This strategy
+is valuable for short-term back-ups, but not suitable for long-term
+version control, since an existing back-up copy is overwritten whenever the
+corresponding file is edited.
+.PP
+Tape archives are suitable for long-term, offline storage.
+If all changed files are dumped on a back-up tape once per day, old revisions
+remain accessible. However, tape archives are unsatisfactory
+for version control in several ways. First, backing up the file
+system every 24 hours does not capture intermediate revisions.
+Secondly, the old revisions are not online,
+and accessing them is tedious and time-consuming.
+In particular, it is impractical to
+compare several old revisions of a group,
+because that may require mounting and searching several tapes.
+Tape archives are important fail-safe tools in the
+event of catastrophic disk failures or accidental deletions,
+but they are ill-suited for version control.
+Conversely, version control tools do not obviate the
+need for tape archives.
+.PP
+A natural technique for keeping several old revisions online is
+to never delete a file.
+Editing a file
+simply creates a new file with the same
+name, but with a different sequence number.
+This technique, available as an option in DEC's VMS operating system,
+turns out to be inadequate for version control.
+First, it is prohibitively expensive in terms of storage costs,
+especially since no data compression techniques are employed.
+Secondly, indiscriminately storing every change produces too many
+revisions, and programmers have difficulties distinguishing them.
+The proliferation of revisions forces programmers to spend much time on
+finding and deleting useless files.
+Thirdly, most of the support functions like locking, logging,
+revision selection,
+and identification described in this paper are not available.
+.PP
+An alternative approach is to separate editing from revision control.
+The user may repeatedly edit a given revision,
+until freezing it with an explicit command.
+Once a revision is frozen, it is stored permanently and can no longer be modified.
+(In RCS, freezing a revisions is done with \fIci\fR.)
+Editing a frozen revision implicitly creates a new one, which
+can again be changed repeatedly until it is frozen itself.
+This approach saves exactly those revisions that the user
+considers important, and keeps the number of revisions manageable.
+IBM's CLEAR/CASTER\u7\d,
+AT&T's SCCS\u3\d,
+CMU's SDC\u8\d
+and DEC's CMS\u9\d,
+are examples of version control systems using this approach.
+CLEAR/CASTER maintains a data base of programs, specifications,
+documentation and messages, using deltas.
+Its goal is to provide control over the development process from a
+management viewpoint.
+SCCS stores multiple revisions of source text in an ancestral tree,
+records a log entry for each revision,
+provides access control, and has facilities
+for uniquely identifying each revision.
+An efficient delta technique
+reduces the space consumed by each revision group.
+SDC is much simpler than SCCS because it stores not more than
+two revisions. However, it maintains a complete log for all old
+revisions, some of which may be on back-up tape.
+CMS, like SCCS, manages tree-structured revision groups,
+but offers no identification mechanism.
+.PP
+Tools for dealing with configurations are still in a state of flux.
+SCCS, SDC and CMS can be combined with MAKE or MAKE-like programs.
+Since flexible selection rules are missing from all these tools,
+it is sometimes difficult
+to specify precisely which revision of each group
+should be passed to MAKE for building a desired configuration.
+The Xerox Cedar system\u10\d
+provides a `System Modeller' that can rebuild
+a configuration from an arbitrary set of module revisions.
+The revisions of a module are only distinguished by creation time,
+and there is no tool for managing groups.
+Since the selection rules are primitive,
+the System Modeller appears to be somewhat tedious to use.
+Apollo's DSEE\u5\d
+is a sophisticated software engineering environment.
+It manages revision groups in a way similar to SCCS and CMS. Configurations
+are built using `configuration threads'.
+A configuration thread states which revision of each group
+named in a configuration should be chosen.
+A configuration thread may contain dynamic specifiers
+(e.g., `choose the revisions I am currently working on,
+and the most recent revisions otherwise'), which are bound
+automatically at build time.
+It also provides a notification mechanism for alerting
+maintainers about the need to rebuild a system after a change.
+.PP
+RCS is based on a general model for describing
+multi-version/multi-configuration systems\u11\d.
+The model describes systems using AND/OR graphs, where AND nodes represent
+configurations, and OR nodes represent version groups.
+The model gives rise to a suit of selection rules for
+composing configurations, almost all of which are implemented in RCS.
+The revisions selected by RCS are passed to MAKE for configuration building.
+Revision group management is modelled after SCCS.
+RCS retains SCCS's best features,
+but offers a significantly simpler user interface,
+flexible selection rules, adequate integration with MAKE
+and improved identification.
+A detailed comparison of RCS and SCCS appears in Reference 4.
+.PP
+An important component of all revision control systems
+is a program for computing deltas.
+SCCS and RCS use the program \fIdiff\fR\u2\d,
+which first computes the longest common substring of two
+revisions, and then produces the delta from that substring.
+The delta is simply an edit script consisting of deletion and
+insertion commands that generate one revision from the other.
+.PP
+A delta based on a longest common substring is not necessarily minimal,
+because it does not take advantage of crossing block moves.
+Crossing block moves arise if two or more blocks of lines
+(e.g., procedures)
+appear in a different order in two revisions.
+An edit script derived from a longest common substring
+first deletes the shorter of the two blocks, and then reinserts it.
+Heckel\u12\d
+proposed an algorithm for detecting block moves, but
+since the algorithm is based on heuristics,
+there are conditions
+under which the generated delta is far from minimal.
+DSEE uses this algorithm combined with blank compression,
+apparently with satisfactory overall results.
+A new algorithm that is guaranteed to produce a minimal delta based on
+block moves appears in Reference 13.
+A future release of RCS will use this algorithm.
+.PP
+\fIAcknowledgements\fR:
+Many people have helped make RCS a success by contributed criticisms, suggestions,
+corrections, and even whole new commands (including manual pages).
+The list of people is too long to be
+reproduced here, but my sincere thanks for their help and
+goodwill goes to all of them.
+.sp
+.nr VS 12p
+.vs 12p
+.SH
+Appendix: Synopsis of RCS Operations
+.LP
+.IP "\fIci\fP \fB\- check in revisions\fP"
+.sp 0
+\fICi\fR stores the contents of a working file into the
+corresponding RCS file as a new revision.
+If the RCS file doesn't exist, \fIci\fR creates it.
+\fICi\fR removes the working file, unless one of the options
+\fI\-u\fR or \fI\-l\fR is present.
+For each check-in, \fIci\fR asks for a commentary
+describing the changes relative to the previous revision.
+.sp 1
+\fICi\fR assigns the revision number given by the \fI\-r\fR option;
+if that option is missing, it derives the number from the
+lock held by the user; if there is no lock and locking is not strict,
+\fIci\fR increments the number of the latest revision on the trunk.
+A side branch can only be started by explicitly specifying its
+number with the \fI\-r\fR option during check-in.
+.sp 1
+\fICi\fR also determines
+whether the revision to be checked in is different from the
+previous one, and asks whether to proceed if not.
+This facility simplifies check-in operations for large systems,
+because one need not remember which files were changed.
+.sp 1
+The option \fI\-k\fR searches the checked in file for identification
+markers containing
+the attributes
+revision number, check-in date, author and state, and assigns these
+to the new revision rather than computing them. This option is
+useful for software distribution: Recipients of distributed software
+using RCS should check in updates with the \fI\-k\fR option.
+This convention guarantees that revision numbers, check-in dates,
+etc., are the same at all sites.
+.IP "\fIco\fP \fB\- check out revisions\fP"
+.sp 0
+\fICo\fR retrieves revisions according to revision number,
+date, author and state attributes. It either places the revision
+into the working file, or prints it on the standard output.
+\fICo\fR always expands the identification markers.
+.IP "\fIident\fP \fB\- extract identification markers\fP"
+.sp 0
+\fIIdent\fR extracts the identification markers expanded by \fIco\fR
+from any file and prints them.
+.IP "\fIrcs\fP \fB\- change RCS file attributes\fP"
+.sp 0
+\fIRcs\fR is an administrative operation that changes access lists,
+locks, unlocks, breaks locks, toggles the strict-locking feature,
+sets state attributes and symbolic revision numbers, changes the
+description, and deletes revisions. A revision can
+only be deleted if it is not the fork of a side branch.
+.br
+.ne 10
+.IP "\fIrcsclean\fP \fB\- clean working directory\fP"
+.sp 0
+\fIRcsclean\fR removes working files that were checked out but never changed.*
+.FS *
+The \fIrcsclean\fP and \fIrcsfreeze\fP commands
+are optional and are not always installed.
+.FE
+.IP "\fIrcsdiff\fP \fB\- compare revisions\fP"
+.sp 0
+\fIRcsdiff\fR compares two revisions and prints their
+difference, using the UNIX tool \fIdiff\fR.
+One of the revisions compared may be checked out.
+This command is useful for finding out about changes.
+.IP "\fIrcsfreeze\fP \fB\- freeze a configuration\fP"
+.sp 0
+\fIRcsfreeze\fR assigns the same symbolic revision number
+to a given revision in all RCS files.
+This command is useful for accurately recording a configuration.*
+.IP "\fIrcsmerge\fP \fB\- merge revisions\fP"
+.sp 0
+\fIRcsmerge\fR merges two revisions, \fIrev1\fR and \fIrev2\fR,
+with respect to a common ancestor.
+A 3-way file comparison determines the segments of lines that
+are (a) the same in all three revisions, or (b) the same in 2 revisions,
+or (c) different in all three. For all segments of type (b) where
+\fIrev1\fR is the differing revision,
+the segment in \fIrev1\fR replaces the corresponding segment of \fIrev2\fR.
+Type (c) indicates an overlapping change, is flagged as an error, and requires user
+intervention to select the correct alternative.
+.IP "\fIrlog\fP \fB\- read log messages\fP"
+.sp 0
+\fIRlog\fR prints the log messages and other information in an RCS file.
+.bp
+.LP
+.nr VS 12p
+.vs 12p
+.]<
+.ds [F 1
+.]-
+.ds [K FELD02
+.ds [K MakeArticle
+.ds [A Feldman, Stuart I.
+.ds [D March 1979
+.ds [T Make\*-A Program for Maintaining Computer Programs
+.ds [J Software\*-Practice & Experience
+.ds [V 9
+.ds [N 3
+.ds [P 255-265
+.nr [P 1
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 1 journal-article
+.ds [F 2
+.]-
+.ds [K HUNT01
+.ds [T An Algorithm for Differential File Comparison
+.ds [A Hunt, James W.
+.as [A " and McIlroy, M. D.
+.ds [I Computing Science Technical Report, Bell Laboratories
+.ds [R 41
+.ds [D June 1976
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 4 tech-report
+.ds [F 3
+.]-
+.ds [K SCCS
+.ds [A Rochkind, Marc J.
+.ds [D Dec. 1975
+.ds [T The Source Code Control System
+.ds [J IEEE Transactions on Software Engineering
+.ds [V SE-1
+.ds [N 4
+.ds [P 364-370
+.nr [P 1
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 1 journal-article
+.ds [F 4
+.]-
+.ds [K TICH08
+.ds [T Design, Implementation, and Evaluation of a Revision Control System
+.ds [A Tichy, Walter F.
+.ds [B Proceedings of the 6th International Conference on Software Engineering
+.ds [I ACM, IEEE, IPS, NBS
+.ds [D September 1982
+.ds [P 58-67
+.nr [P 1
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 3 article-in-book
+.ds [F 5
+.]-
+.ds [K LEBL01
+.ds [A Leblang, David B.
+.as [A " and Chase, Robert P.
+.ds [T Computer-Aided Software Engineering in a Distributed Workstation Environment
+.ds [O Proceedings of the ACM SIGSOFT/SIGPLAN Software Engineering Symposium
+.as [O " on Practical Software Development Environments.
+.ds [J SIGPLAN Notices
+.ds [V 19
+.ds [N 5
+.ds [D May 1984
+.ds [P 104-112
+.nr [P 1
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 1 journal-article
+.ds [F 1
+.ds [F 3
+.ds [F 6
+.]-
+.ds [K SCCSEval
+.ds [A Glasser, Alan L.
+.ds [D Nov. 1978
+.ds [T The Evolution of a Source Code Control System
+.ds [J Software Engineering Notes
+.ds [V 3
+.ds [N 5
+.ds [P 122-125
+.nr [P 1
+.ds [O Proceedings of the Software Quality and Assurance Workshop.
+.nr [T 0
+.nr [A 1
+.nr [O 1
+.][ 1 journal-article
+.ds [F 5
+.ds [F 7
+.]-
+.ds [K IBMClearCaster
+.ds [A Brown, H.B.
+.ds [D 1970
+.ds [T The Clear/Caster System
+.ds [J Nato Conference on Software Engineering, Rome
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 1 journal-article
+.ds [F 3
+.ds [F 8
+.]-
+.ds [K HabermannSDC
+.ds [A Habermann, A. Nico
+.ds [D Jan. 1979
+.ds [T A Software Development Control System
+.ds [I Technical Report, Carnegie-Mellon University, Department of Computer Science
+.nr [T 0
+.nr [A 0
+.nr [O 0
+.][ 2 book
+.ds [F 9
+.]-
+.ds [K CMS
+.ds [A DEC
+.ds [T Code Management System
+.ds [I Digital Equipment Corporation
+.ds [O Document No.\ EA-23134-82
+.ds [D 1982
+.nr [T 0
+.nr [A 0
+.nr [O 0
+.][ 2 book
+.ds [F 10
+.]-
+.ds [K LAMP01
+.ds [A Lampson, Butler W.
+.as [A " and Schmidt, Eric E.
+.ds [T Practical Use of a Polymorphic Applicative Language
+.ds [B Proceedings of the 10th Symposium on Principles of Programming Languages
+.ds [I ACM
+.ds [P 237-255
+.nr [P 1
+.ds [D January 1983
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 3 article-in-book
+.ds [F 5
+.ds [F 11
+.]-
+.ds [K TICH07
+.ds [T A Data Model for Programming Support Environments and its Application
+.ds [A Tichy, Walter F.
+.ds [B Automated Tools for Information System Design and Development
+.ds [E Hans-Jochen Schneider and Anthony I. Wasserman
+.ds [C Amsterdam
+.ds [I North-Holland Publishing Company
+.ds [D 1982
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 3 article-in-book
+.ds [F 4
+.ds [F 2
+.ds [F 12
+.]-
+.ds [K HECK01
+.ds [T A Technique for Isolating Differences Between Files
+.ds [A Heckel, Paul
+.ds [J Communications of the ACM
+.ds [D April 1978
+.ds [V 21
+.ds [N 4
+.ds [P 264-268
+.nr [P 1
+.nr [T 0
+.nr [A 0
+.nr [O 0
+.][ 1 journal-article
+.ds [F 13
+.]-
+.ds [K TICH11
+.ds [T The String-to-String Correction Problem with Block Moves
+.ds [A Tichy, Walter F.
+.ds [D Nov. 1984
+.ds [J ACM Transactions on Computer Systems
+.ds [V 2
+.ds [N 4
+.ds [P 309-321
+.nr [P 1
+.nr [T 0
+.nr [A 1
+.nr [O 0
+.][ 1 journal-article
+.]>
diff --git a/gnu/usr.bin/rcs/doc/rcs_func.ms b/gnu/usr.bin/rcs/doc/rcs_func.ms
new file mode 100644
index 0000000..9818086
--- /dev/null
+++ b/gnu/usr.bin/rcs/doc/rcs_func.ms
@@ -0,0 +1,95 @@
+.SH
+Functions of RCS (Revision Control System)
+.PP
+RCS manages software libraries. It greatly increases programmer productivity
+by providing the following functions.
+.IP 1.
+RCS stores and retrieves multiple revisions of program and other text.
+Thus, one can maintain one or more releases while developing the next
+release, with a minimum of space overhead. Changes no longer destroy the
+original -- previous revisions remain accessible.
+.RS
+.IP a.
+Maintains each module as a tree of revisions.
+.IP b.
+Project libraries can
+be organized centrally, decentralized, or any way you like.
+.IP c.
+RCS works for any type of text: programs, documentation, memos, papers,
+graphics, VLSI layouts, form letters, etc.
+.RE
+.IP 2.
+RCS maintains a complete history of changes.
+Thus, one can find out what happened to a module easily
+and quickly, without having to compare source listings or
+having to track down colleagues.
+.RS
+.IP a.
+RCS performs automatic record keeping.
+.IP b.
+RCS logs all changes automatically.
+.IP c.
+RCS guarantees project continuity.
+.RE
+.IP 3.
+RCS manages multiple lines of development.
+.IP 4.
+RCS can merge multiple lines of development.
+Thus, when several parallel lines of development must be consolidated
+into one line, the merging of changes is automatic.
+.IP 5.
+RCS flags coding conflicts.
+If two or more lines of development modify the same section of code,
+RCS can alert programmers about overlapping changes.
+.IP 6.
+RCS resolves access conflicts.
+When two or more programmers wish to modify the same revision,
+RCS alerts the programmers and makes sure that one modification won't wipe
+out the other one.
+.IP 7.
+RCS provides high-level retrieval functions.
+Revisions can be retrieved according to ranges of revision numbers,
+symbolic names, dates, authors, and states.
+.IP 8.
+RCS provides release and configuration control.
+Revisions can be marked as released, stable, experimental, etc.
+Configurations of modules can be described simply and directly.
+.IP 9.
+RCS performs automatic identification of modules with name, revision
+number, creation time, author, etc.
+Thus, it is always possible to determine which revisions of which
+modules make up a given configuration.
+.IP 10.
+Provides high-level management visibility.
+Thus, it is easy to track the status of a software project.
+.RS
+.IP a.
+RCS provides a complete change history.
+.IP b.
+RCS records who did what when to which revision of which module.
+.RE
+.IP 11.
+RCS is fully compatible with existing software development tools.
+RCS is unobtrusive -- its interface to the file system is such that
+all your existing software tools can be used as before.
+.IP 12.
+RCS' basic user interface is extremely simple. The novice need to learn
+only two commands. Its more sophisticated features have been
+tuned towards advanced software development environments and the
+experienced software professional.
+.IP 13.
+RCS simplifies software distribution if customers
+maintain sources with RCS also. This technique assures proper
+identification of versions and configurations, and tracking of customer
+modifications. Customer modifications can be merged into distributed
+versions locally or by the development group.
+.IP 14.
+RCS needs little extra space for the revisions (only the differences).
+If intermediate revisions are deleted, the corresponding
+differences are compressed into the shortest possible form.
+.IP 15.
+RCS is implemented with reverse deltas. This means that
+the latest revision, which is the one that is accessed most often,
+is stored intact. All others are regenerated from the latest one
+by applying reverse deltas (backward differences). This
+results in fast access time for the revision needed most often.
diff --git a/gnu/usr.bin/rcs/ident/Makefile b/gnu/usr.bin/rcs/ident/Makefile
new file mode 100644
index 0000000..f28f8d3
--- /dev/null
+++ b/gnu/usr.bin/rcs/ident/Makefile
@@ -0,0 +1,8 @@
+PROG= ident
+SRCS= ident.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/ident/ident.1 b/gnu/usr.bin/rcs/ident/ident.1
new file mode 100644
index 0000000..253a2ce
--- /dev/null
+++ b/gnu/usr.bin/rcs/ident/ident.1
@@ -0,0 +1,182 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+.ds iD \\$3 \\$4 \\$5 \\$6 \\$7
+..
+.Id $FreeBSD$
+.ds r \&\s-1RCS\s0
+.ds u \&\s-1UTC\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH IDENT 1 \*(Dt GNU
+.SH NAME
+ident \- identify RCS keyword strings in files
+.SH SYNOPSIS
+.B ident
+[
+.B \-q
+] [
+.B \-V
+] [
+.I file
+\&.\|.\|. ]
+.SH DESCRIPTION
+.B ident
+searches for all instances of the pattern
+.BI $ keyword : "\ text\ " $
+in the named files or, if no files are named, the standard input.
+.PP
+These patterns are normally inserted automatically by the \*r command
+.BR co (1),
+but can also be inserted manually.
+The option
+.B \-q
+suppresses
+the warning given if there are no patterns in a file.
+The option
+.B \-V
+prints
+.BR ident 's
+version number.
+.PP
+.B ident
+works on text files as well as object files and dumps.
+For example, if the C program in
+.B f.c
+contains
+.IP
+.ft 3
+#include <stdio.h>
+.br
+static char const rcsid[] =
+.br
+ \&"$\&Id: f.c,v \*(iD $\&";
+.br
+int main() { return printf(\&"%s\en\&", rcsid) == EOF; }
+.ft P
+.LP
+and
+.B f.c
+is compiled into
+.BR f.o ,
+then the command
+.IP
+.B "ident f.c f.o"
+.LP
+will output
+.nf
+.IP
+.ft 3
+f.c:
+ $\&Id: f.c,v \*(iD $
+f.o:
+ $\&Id: f.c,v \*(iD $
+.ft
+.fi
+.PP
+If a C program defines a string like
+.B rcsid
+above but does not use it,
+.BR lint (1)
+may complain, and some C compilers will optimize away the string.
+The most reliable solution is to have the program use the
+.B rcsid
+string, as shown in the example above.
+.PP
+.B ident
+finds all instances of the
+.BI $ keyword : "\ text\ " $
+pattern, even if
+.I keyword
+is not actually an \*r-supported keyword.
+This gives you information about nonstandard keywords like
+.BR $\&XConsortium$ .
+.SH KEYWORDS
+Here is the list of keywords currently maintained by
+.BR co (1).
+All times are given in Coordinated Universal Time (\*u,
+sometimes called \&\s-1GMT\s0) by default, but if the files
+were checked out with
+.BR co 's
+.BI \-z zone
+option, times are given with a numeric time zone indication appended.
+.TP
+.B $\&Author$
+The login name of the user who checked in the revision.
+.TP
+.B $\&Date$
+The date and time the revision was checked in.
+.TP
+.B $\&Header$
+A standard header containing the full pathname of the \*r file, the
+revision number, the date and time, the author, the state,
+and the locker (if locked).
+.TP
+.B $\&Id$
+Same as
+.BR $\&Header$ ,
+except that the \*r filename is without a path.
+.TP
+.B $\&Locker$
+The login name of the user who locked the revision (empty if not locked).
+.TP
+.B $\&Log$
+The log message supplied during checkin.
+For
+.BR ident 's
+purposes, this is equivalent to
+.BR $\&RCSfile$ .
+.TP
+.B $\&Name$
+The symbolic name used to check out the revision, if any.
+.TP
+.B $\&RCSfile$
+The name of the \*r file without a path.
+.TP
+.B $\&Revision$
+The revision number assigned to the revision.
+.TP
+.B $\&Source$
+The full pathname of the \*r file.
+.TP
+.B $\&State$
+The state assigned to the revision with the
+.B \-s
+option of
+.BR rcs (1)
+or
+.BR ci (1).
+.PP
+.BR co (1)
+represents the following characters in keyword values by escape sequences
+to keep keyword strings well-formed.
+.LP
+.RS
+.nf
+.ne 6
+.ta \w'newline 'u
+\f2char escape sequence\fP
+tab \f3\et\fP
+newline \f3\en\fP
+space \f3\e040
+$ \e044
+\e \e\e\fP
+.fi
+.RE
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1992, 1993 Paul Eggert.
+.SH "SEE ALSO"
+ci(1), co(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
+rcsfile(5)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
diff --git a/gnu/usr.bin/rcs/ident/ident.c b/gnu/usr.bin/rcs/ident/ident.c
new file mode 100644
index 0000000..9b8bf57
--- /dev/null
+++ b/gnu/usr.bin/rcs/ident/ident.c
@@ -0,0 +1,270 @@
+/* Identify RCS keyword strings in files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.9 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.8 1995/06/01 16:23:43 eggert
+ * (exiterr, reportError): New functions, needed for DOS and OS/2 ports.
+ * (scanfile): Use them.
+ *
+ * Revision 5.7 1994/03/20 04:52:58 eggert
+ * Remove `exiting' from identExit.
+ *
+ * Revision 5.6 1993/11/09 17:40:15 eggert
+ * Add -V.
+ *
+ * Revision 5.5 1993/11/03 17:42:27 eggert
+ * Test for char == EOF, not char < 0.
+ *
+ * Revision 5.4 1992/01/24 18:44:19 eggert
+ * lint -> RCS_lint
+ *
+ * Revision 5.3 1991/09/10 22:15:46 eggert
+ * Open files with FOPEN_R, not FOPEN_R_WORK,
+ * because they might be executables, not working files.
+ *
+ * Revision 5.2 1991/08/19 03:13:55 eggert
+ * Report read errors immediately.
+ *
+ * Revision 5.1 1991/02/25 07:12:37 eggert
+ * Don't report empty keywords. Check for I/O errors.
+ *
+ * Revision 5.0 1990/08/22 08:12:37 eggert
+ * Don't limit output to known keywords.
+ * Remove arbitrary limits and lint. Ansify and Posixate.
+ *
+ * Revision 4.5 89/05/01 15:11:54 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.4 87/10/23 17:09:57 narten
+ * added exit(0) so exit return code would be non random
+ *
+ * Revision 4.3 87/10/18 10:23:55 narten
+ * Updating version numbers. Changes relative to 1.1 are actually relative
+ * to 4.1
+ *
+ * Revision 1.3 87/07/09 09:20:52 trinkle
+ * Added check to make sure there is at least one arg before comparing argv[1]
+ * with "-q". This necessary on machines that don't allow dereferncing null
+ * pointers (i.e. Suns).
+ *
+ * Revision 1.2 87/03/27 14:21:47 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/05/10 16:31:02 wft
+ * Added option -q and input from reading stdin.
+ * Marker matching is now done with trymatch() (independent of keywords).
+ *
+ * Revision 3.4 83/02/18 17:37:49 wft
+ * removed printing of new line after last file.
+ *
+ * Revision 3.3 82/12/04 12:48:55 wft
+ * Added LOCKER.
+ *
+ * Revision 3.2 82/11/28 18:24:17 wft
+ * removed Suffix; added ungetc to avoid skipping over trailing KDELIM.
+ *
+ * Revision 3.1 82/10/13 15:58:51 wft
+ * fixed type of variables receiving from getc() (char-->int).
+*/
+
+#include "rcsbase.h"
+
+static int match P((FILE*));
+static int scanfile P((FILE*,char const*,int));
+static void reportError P((char const*));
+
+mainProg(identId, "ident", "$FreeBSD$")
+/* Ident searches the named files for all occurrences
+ * of the pattern $@: text $ where @ is a keyword.
+ */
+
+{
+ FILE *fp;
+ int quiet = 0;
+ int status = EXIT_SUCCESS;
+ char const *a;
+
+ while ((a = *++argv) && *a=='-')
+ while (*++a)
+ switch (*a) {
+ case 'q':
+ quiet = 1;
+ break;
+
+ case 'V':
+ VOID printf("RCS version %s\n", RCS_version_string);
+ quiet = -1;
+ break;
+
+ default:
+ VOID fprintf(stderr,
+ "ident: usage: ident -{qV} [file...]\n"
+ );
+ exitmain(EXIT_FAILURE);
+ break;
+ }
+
+ if (0 <= quiet)
+ if (!a)
+ VOID scanfile(stdin, (char*)0, quiet);
+ else
+ do {
+ if (!(fp = fopen(a, FOPEN_RB))) {
+ reportError(a);
+ status = EXIT_FAILURE;
+ } else if (
+ scanfile(fp, a, quiet) != 0
+ || (argv[1] && putchar('\n') == EOF)
+ )
+ break;
+ } while ((a = *++argv));
+
+ if (ferror(stdout) || fclose(stdout)!=0) {
+ reportError("standard output");
+ status = EXIT_FAILURE;
+ }
+ exitmain(status);
+}
+
+#if RCS_lint
+# define exiterr identExit
+#endif
+ void
+exiterr()
+{
+ _exit(EXIT_FAILURE);
+}
+
+ static void
+reportError(s)
+ char const *s;
+{
+ int e = errno;
+ VOID fprintf(stderr, "%s error: ", cmdid);
+ errno = e;
+ perror(s);
+}
+
+
+ static int
+scanfile(file, name, quiet)
+ register FILE *file;
+ char const *name;
+ int quiet;
+/* Function: scan an open file with descriptor file for keywords.
+ * Return -1 if there's a write error; exit immediately on a read error.
+ */
+{
+ register int c;
+
+ if (name) {
+ VOID printf("%s:\n", name);
+ if (ferror(stdout))
+ return -1;
+ } else
+ name = "standard input";
+ c = 0;
+ while (c != EOF || ! (feof(file)|ferror(file))) {
+ if (c == KDELIM) {
+ if ((c = match(file)))
+ continue;
+ if (ferror(stdout))
+ return -1;
+ quiet = true;
+ }
+ c = getc(file);
+ }
+ if (ferror(file) || fclose(file) != 0) {
+ reportError(name);
+ /*
+ * The following is equivalent to exit(EXIT_FAILURE), but we invoke
+ * exiterr to keep lint happy. The DOS and OS/2 ports need exiterr.
+ */
+ VOID fflush(stderr);
+ VOID fflush(stdout);
+ exiterr();
+ }
+ if (!quiet)
+ VOID fprintf(stderr, "%s warning: no id keywords in %s\n", cmdid, name);
+ return 0;
+}
+
+
+
+ static int
+match(fp) /* group substring between two KDELIM's; then do pattern match */
+ register FILE *fp;
+{
+ char line[BUFSIZ];
+ register int c;
+ register char * tp;
+
+ tp = line;
+ while ((c = getc(fp)) != VDELIM) {
+ if (c == EOF && feof(fp) | ferror(fp))
+ return c;
+ switch (ctab[c]) {
+ case LETTER: case Letter: case DIGIT:
+ *tp++ = c;
+ if (tp < line+sizeof(line)-4)
+ break;
+ /* fall into */
+ default:
+ return c ? c : '\n'/* anything but 0 or KDELIM or EOF */;
+ }
+ }
+ if (tp == line)
+ return c;
+ *tp++ = c;
+ if ((c = getc(fp)) != ' ')
+ return c ? c : '\n';
+ *tp++ = c;
+ while( (c = getc(fp)) != KDELIM ) {
+ if (c == EOF && feof(fp) | ferror(fp))
+ return c;
+ switch (ctab[c]) {
+ default:
+ *tp++ = c;
+ if (tp < line+sizeof(line)-2)
+ break;
+ /* fall into */
+ case NEWLN: case UNKN:
+ return c ? c : '\n';
+ }
+ }
+ if (tp[-1] != ' ')
+ return c;
+ *tp++ = c; /*append trailing KDELIM*/
+ *tp = '\0';
+ VOID printf(" %c%s\n", KDELIM, line);
+ return 0;
+}
diff --git a/gnu/usr.bin/rcs/lib/Makefile b/gnu/usr.bin/rcs/lib/Makefile
new file mode 100644
index 0000000..ce08651
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+# Define FSYNC_ALL to get slower but safer writes in case of crashes in
+# the middle of CVS/RCS changes
+#CFLAGS += -DFSYNC_ALL
+
+LIB = rcs
+SRCS = maketime.c partime.c rcsedit.c rcsfcmp.c rcsfnms.c rcsgen.c \
+ rcskeep.c rcskeys.c rcslex.c rcsmap.c rcsrev.c rcssyn.c rcstime.c \
+ rcsutil.c merger.c version.c
+
+INTERNALLIB= true
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/rcs/lib/conf.h b/gnu/usr.bin/rcs/lib/conf.h
new file mode 100644
index 0000000..d4be917
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/conf.h
@@ -0,0 +1,400 @@
+/* RCS compile-time configuration */
+
+ /* $FreeBSD$ */
+
+/*
+ * This file is generated automatically.
+ * If you edit it by hand your changes may be lost.
+ * Instead, please try to fix conf.sh,
+ * and send your fixes to rcs-bugs@cs.purdue.edu.
+ */
+
+#define exitmain(n) return n /* how to exit from main() */
+/* #define _POSIX_C_SOURCE 2147483647L */ /* if strict C + Posix 1003.1b-1993 or later */
+/* #define _POSIX_SOURCE */ /* if strict C + Posix 1003.1-1990 */
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+
+/* Comment out #include lines below that do not work. */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <limits.h>
+/* #include <mach/mach.h> */
+/* #include <net/errno.h> */
+#include <pwd.h>
+/* #include <siginfo.h> */
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+/* #include <ucontext.h> */
+#include <unistd.h>
+#include <utime.h>
+/* #include <vfork.h> */
+
+/* Define boolean symbols to be 0 (false, the default), or 1 (true). */
+#define has_sys_param_h 1 /* Does #include <sys/param.h> work? */
+/* extern int errno; */ /* Uncomment if <errno.h> doesn't declare errno. */
+#define has_readlink 1 /* Does readlink() work? */
+#define readlink_isreg_errno EINVAL /* errno after readlink on regular file */
+
+#if has_readlink && !defined(MAXSYMLINKS)
+# if has_sys_param_h
+# include <sys/param.h>
+# endif
+# ifndef MAXSYMLINKS
+# define MAXSYMLINKS 20 /* BSD; not standard yet */
+# endif
+#endif
+
+/* Comment out the typedefs below if the types are already declared. */
+/* Fix any uncommented typedefs that are wrong. */
+/* typedef int mode_t; */
+/* typedef long off_t; */
+/* typedef int pid_t; */
+/* typedef int sig_atomic_t; */
+/* typedef unsigned size_t; */
+/* typedef int ssize_t; */
+/* typedef long time_t; */
+/* typedef int uid_t; */
+
+/* Comment out the keyword definitions below if the keywords work. */
+/* #define const */
+/* #define volatile */
+
+/* Define boolean symbols to be 0 (false, the default), or 1 (true). */
+#define has_prototypes 1 /* Do function prototypes work? */
+#define has_stdarg 1 /* Does <stdarg.h> work? */
+/* #define has_varargs ? */ /* Does <varargs.h> work? */
+#define va_start_args 2 /* How many args does va_start() take? */
+
+#if O_BINARY
+ /* Text and binary i/o behave differently. */
+ /* This is incompatible with Posix and Unix. */
+# define FOPEN_RB "rb"
+# define FOPEN_R_WORK (Expand==BINARY_EXPAND ? "r" : "rb")
+# define FOPEN_WB "wb"
+# define FOPEN_W_WORK (Expand==BINARY_EXPAND ? "w" : "wb")
+# define FOPEN_WPLUS_WORK (Expand==BINARY_EXPAND ? "w+" : "w+b")
+# define OPEN_O_BINARY O_BINARY
+#else
+ /*
+ * Text and binary i/o behave the same.
+ * Omit "b", since some nonstandard hosts reject it.
+ */
+# define FOPEN_RB "r"
+# define FOPEN_R_WORK "r"
+# define FOPEN_WB "w"
+# define FOPEN_W_WORK "w"
+# define FOPEN_WPLUS_WORK "w+"
+# define OPEN_O_BINARY 0
+#endif
+
+/* This may need changing on non-Unix systems (notably DOS). */
+#define OPEN_CREAT_READONLY (S_IRUSR|S_IRGRP|S_IROTH) /* lock file mode */
+#define OPEN_O_LOCK 0 /* extra open flags for creating lock file */
+#define OPEN_O_WRONLY O_WRONLY /* main open flag for creating a lock file */
+
+/* Define or comment out the following symbols as needed. */
+#if has_prototypes
+# define P(params) params
+#else
+# define P(params) ()
+#endif
+#if has_stdarg
+# include <stdarg.h>
+#else
+# if has_varargs
+# include <varargs.h>
+# else
+ typedef char *va_list;
+# define va_dcl int va_alist;
+# define va_start(ap) ((ap) = (va_list)&va_alist)
+# define va_arg(ap,t) (((t*) ((ap)+=sizeof(t))) [-1])
+# define va_end(ap)
+# endif
+#endif
+#if va_start_args == 2
+# define vararg_start va_start
+#else
+# define vararg_start(ap,p) va_start(ap)
+#endif
+#define bad_chmod_close 0 /* Can chmod() close file descriptors? */
+#define bad_creat0 0 /* Do writes fail after creat(f,0)? */
+#define bad_fopen_wplus 0 /* Does fopen(f,"w+") fail to truncate f? */
+#define getlogin_is_secure 0 /* Is getlogin() secure? Usually it's not. */
+#define has_attribute_noreturn 1 /* Does __attribute__((noreturn)) work? */
+#if has_attribute_noreturn
+# define exiting __attribute__((noreturn))
+#else
+# define exiting
+#endif
+#define has_dirent 1 /* Do opendir(), readdir(), closedir() work? */
+#define void_closedir 0 /* Does closedir() yield void? */
+#define has_fchmod 1 /* Does fchmod() work? */
+#define has_fflush_input 0 /* Does fflush() work on input files? */
+#define has_fputs 1 /* Does fputs() work? */
+#define has_ftruncate 1 /* Does ftruncate() work? */
+#define has_getuid 1 /* Does getuid() work? */
+#define has_getpwuid 1 /* Does getpwuid() work? */
+#define has_memcmp 1 /* Does memcmp() work? */
+#define has_memcpy 1 /* Does memcpy() work? */
+#define has_memmove 1 /* Does memmove() work? */
+#define has_map_fd 0 /* Does map_fd() work? */
+#define has_mmap 1 /* Does mmap() work on regular files? */
+#define has_madvise 0 /* Does madvise() work? */
+#define mmap_signal SIGBUS /* signal received if you reference nonexistent part of mmapped file */
+#define has_rename 1 /* Does rename() work? */
+#define bad_a_rename 0 /* Does rename(A,B) fail if A is unwritable? */
+#define bad_b_rename 0 /* Does rename(A,B) fail if B is unwritable? */
+#define bad_NFS_rename 0 /* Can rename(A,B) falsely report success? */
+/* typedef int void; */ /* Some ancient compilers need this. */
+#define VOID (void) /* 'VOID e;' discards the value of an expression 'e'. */
+#define has_seteuid 1 /* Does seteuid() work? See ../INSTALL.RCS. */
+#define has_setreuid 0 /* Does setreuid() work? See ../INSTALL.RCS. */
+#define has_setuid 1 /* Does setuid() exist? */
+#define has_sigaction 1 /* Does struct sigaction work? */
+#define has_sa_sigaction 0 /* Does struct sigaction have sa_sigaction? */
+#define has_signal 1 /* Does signal() work? */
+#define signal_type void /* type returned by signal handlers */
+#define sig_zaps_handler 0 /* Must a signal handler reinvoke signal()? */
+/* #define has_sigblock ? */ /* Does sigblock() work? */
+/* #define sigmask(s) (1 << ((s)-1)) */ /* Yield mask for signal number. */
+typedef size_t fread_type; /* type returned by fread() and fwrite() */
+typedef size_t freadarg_type; /* type of their size arguments */
+typedef void *malloc_type; /* type returned by malloc() */
+#define has_getcwd 1 /* Does getcwd() work? */
+/* #define has_getwd ? */ /* Does getwd() work? */
+#define needs_getabsname 0 /* Must we define getabsname? */
+#define has_mktemp 1 /* Does mktemp() work? */
+#define has_mkstemp 1 /* Does mkstemp() work? */
+#define has_NFS 1 /* Might NFS be used? */
+#define has_psiginfo 0 /* Does psiginfo() work? */
+#define has_psignal 1 /* Does psignal() work? */
+/* #define has_si_errno ? */ /* Does siginfo_t have si_errno? */
+/* #define has_sys_siglist ? */ /* Does sys_siglist[] work? */
+/* #define strchr index */ /* Use old-fashioned name for strchr()? */
+/* #define strrchr rindex */ /* Use old-fashioned name for strrchr()? */
+#define bad_unlink 0 /* Does unlink() fail on unwritable files? */
+#define has_vfork 1 /* Does vfork() work? */
+#define has_fork 1 /* Does fork() work? */
+#define has_spawn 0 /* Does spawn*() work? */
+#define has_waitpid 1 /* Does waitpid() work? */
+#define bad_wait_if_SIGCHLD_ignored 0 /* Does ignoring SIGCHLD break wait()? */
+#define RCS_SHELL "/bin/sh" /* shell to run RCS subprograms */
+#define has_printf_dot 1 /* Does "%.2d" print leading 0? */
+#define has_vfprintf 1 /* Does vfprintf() work? */
+#define has_attribute_format_printf 1 /* Does __attribute__((format(printf,N,N+1))) work? */
+#if has_attribute_format_printf
+# define printf_string(m, n) __attribute__((format(printf, m, n)))
+#else
+# define printf_string(m, n)
+#endif
+#if has_attribute_format_printf && has_attribute_noreturn
+ /* Work around a bug in GCC 2.5.x. */
+# define printf_string_exiting(m, n) __attribute__((format(printf, m, n), noreturn))
+#else
+# define printf_string_exiting(m, n) printf_string(m, n) exiting
+#endif
+/* #define has__doprintf ? */ /* Does _doprintf() work? */
+/* #define has__doprnt ? */ /* Does _doprnt() work? */
+/* #undef EXIT_FAILURE */ /* Uncomment this if EXIT_FAILURE is broken. */
+#define large_memory 1 /* Can main memory hold entire RCS files? */
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647L /* long maximum */
+#endif
+/* Do struct stat s and t describe the same file? Answer d if unknown. */
+#define same_file(s,t,d) ((s).st_ino==(t).st_ino && (s).st_dev==(t).st_dev)
+#define has_utimbuf 1 /* Does struct utimbuf work? */
+#define CO "/usr/bin/co" /* name of 'co' program */
+#define COMPAT2 0 /* Are version 2 files supported? */
+#define DIFF "/usr/bin/diff" /* name of 'diff' program */
+#define DIFF3 "/usr/bin/diff3" /* name of 'diff3' program */
+#define DIFF3_BIN 1 /* Is diff3 user-visible (not the /usr/lib auxiliary)? */
+#define DIFFFLAGS "-an" /* Make diff output suitable for RCS. */
+#define DIFF_L 1 /* Does diff -L work? */
+#define DIFF_SUCCESS 0 /* DIFF status if no differences are found */
+#define DIFF_FAILURE 1 /* DIFF status if differences are found */
+#define DIFF_TROUBLE 2 /* DIFF status if trouble */
+#define ED "/bin/ed" /* name of 'ed' program (used only if !DIFF3_BIN) */
+#define MERGE "/usr/bin/merge" /* name of 'merge' program */
+#define TMPDIR "/tmp" /* default directory for temporary files */
+#define SLASH '/' /* principal filename separator */
+#define SLASHes '/' /* `case SLASHes:' labels all filename separators */
+#define isSLASH(c) ((c) == SLASH) /* Is arg a filename separator? */
+#define ROOTPATH(p) isSLASH((p)[0]) /* Is p an absolute pathname? */
+#define X_DEFAULT ",v/" /* default value for -x option */
+#define SLASHSLASH_is_SLASH 1 /* Are // and / the same directory? */
+#define ALL_ABSOLUTE 1 /* Do all subprograms satisfy ROOTPATH? */
+#define DIFF_ABSOLUTE 1 /* Is ROOTPATH(DIFF) true? */
+#define SENDMAIL "/usr/sbin/sendmail" /* how to send mail */
+#define TZ_must_be_set 0 /* Must TZ be set for gmtime() to work? */
+
+
+
+/* Adjust the following declarations as needed. */
+
+
+/* The rest is for the benefit of non-standard, traditional hosts. */
+/* Don't bother to declare functions that in traditional hosts do not appear, */
+/* or are declared in .h files, or return int or void. */
+
+
+/* traditional BSD */
+
+#if has_sys_siglist && !defined(sys_siglist)
+ extern char const * const sys_siglist[];
+#endif
+
+
+/* Posix (ISO/IEC 9945-1: 1990 / IEEE Std 1003.1-1990) */
+
+/* <fcntl.h> */
+#ifdef O_CREAT
+# define open_can_creat 1
+#else
+# define open_can_creat 0
+# define O_RDONLY 0
+# define O_WRONLY 1
+# define O_RDWR 2
+# define O_CREAT 01000
+# define O_TRUNC 02000
+#endif
+#ifndef O_EXCL
+#define O_EXCL 0
+#endif
+
+/* <sys/stat.h> */
+#ifndef S_IRUSR
+# ifdef S_IREAD
+# define S_IRUSR S_IREAD
+# else
+# define S_IRUSR 0400
+# endif
+# ifdef S_IWRITE
+# define S_IWUSR S_IWRITE
+# else
+# define S_IWUSR (S_IRUSR/2)
+# endif
+#endif
+#ifndef S_IRGRP
+# if has_getuid
+# define S_IRGRP (S_IRUSR / 0010)
+# define S_IWGRP (S_IWUSR / 0010)
+# define S_IROTH (S_IRUSR / 0100)
+# define S_IWOTH (S_IWUSR / 0100)
+# else
+ /* single user OS -- not Posix or Unix */
+# define S_IRGRP 0
+# define S_IWGRP 0
+# define S_IROTH 0
+# define S_IWOTH 0
+# endif
+#endif
+#ifndef S_ISREG
+#define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
+#endif
+
+/* <sys/wait.h> */
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 0377) == 0)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(stat_val) ((stat_val) & 0177)
+#undef WIFSIGNALED /* Avoid 4.3BSD incompatibility with Posix. */
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(stat_val) ((unsigned)(stat_val) - 1 < 0377)
+#endif
+
+/* <unistd.h> */
+char *getlogin P((void));
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+# define STDOUT_FILENO 1
+# define STDERR_FILENO 2
+#endif
+#if has_fork && !has_vfork
+# undef vfork
+# define vfork fork
+#endif
+#if has_getcwd || !has_getwd
+ char *getcwd P((char*,size_t));
+#else
+ char *getwd P((char*));
+#endif
+#if has_setuid && !has_seteuid
+# undef seteuid
+# define seteuid setuid
+#endif
+#if has_spawn
+# if ALL_ABSOLUTE
+# define spawn_RCS spawnv
+# else
+# define spawn_RCS spawnvp
+# endif
+#else
+# if ALL_ABSOLUTE
+# define exec_RCS execv
+# else
+# define exec_RCS execvp
+# endif
+#endif
+
+/* utime.h */
+#if !has_utimbuf
+ struct utimbuf { time_t actime, modtime; };
+#endif
+
+
+/* Standard C library */
+
+/* <stdio.h> */
+#ifndef L_tmpnam
+#define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
+#endif
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+#if has_mktemp
+ char *mktemp P((char*)); /* traditional */
+#else
+ char *tmpnam P((char*));
+#endif
+
+/* <stdlib.h> */
+char *getenv P((char const*));
+void _exit P((int)) exiting;
+void exit P((int)) exiting;
+malloc_type malloc P((size_t));
+malloc_type realloc P((malloc_type,size_t));
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+
+/* <string.h> */
+char *strcpy P((char*,char const*));
+char *strchr P((char const*,int));
+char *strrchr P((char const*,int));
+void *memcpy P((void*,void const*,size_t));
+#if has_memmove
+ void *memmove P((void*,void const*,size_t));
+#endif
+
+/* <time.h> */
+time_t time P((time_t*));
diff --git a/gnu/usr.bin/rcs/lib/maketime.c b/gnu/usr.bin/rcs/lib/maketime.c
new file mode 100644
index 0000000..0f83bf5
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/maketime.c
@@ -0,0 +1,344 @@
+/* Convert struct partime into time_t. */
+
+/* Copyright 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#if has_conf_h
+# include "conf.h"
+#else
+# ifdef __STDC__
+# define P(x) x
+# else
+# define const
+# define P(x) ()
+# endif
+# include <stdlib.h>
+# include <time.h>
+#endif
+
+#include "partime.h"
+#include "maketime.h"
+
+char const maketId[]
+ = "$FreeBSD$";
+
+static int isleap P((int));
+static int month_days P((struct tm const*));
+static time_t maketime P((struct partime const*,time_t));
+
+/*
+* For maximum portability, use only localtime and gmtime.
+* Make no assumptions about the time_t epoch or the range of time_t values.
+* Avoid mktime because it's not universal and because there's no easy,
+* portable way for mktime to yield the inverse of gmtime.
+*/
+
+#define TM_YEAR_ORIGIN 1900
+
+ static int
+isleap(y)
+ int y;
+{
+ return (y&3) == 0 && (y%100 != 0 || y%400 == 0);
+}
+
+static int const month_yday[] = {
+ /* days in year before start of months 0-12 */
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+/* Yield the number of days in TM's month. */
+ static int
+month_days(tm)
+ struct tm const *tm;
+{
+ int m = tm->tm_mon;
+ return month_yday[m+1] - month_yday[m]
+ + (m==1 && isleap(tm->tm_year + TM_YEAR_ORIGIN));
+}
+
+/*
+* Convert UNIXTIME to struct tm form.
+* Use gmtime if available and if !LOCALZONE, localtime otherwise.
+*/
+ struct tm *
+time2tm(unixtime, localzone)
+ time_t unixtime;
+ int localzone;
+{
+ struct tm *tm;
+# if TZ_must_be_set
+ static char const *TZ;
+ if (!TZ && !(TZ = getenv("TZ")))
+ faterror("The TZ environment variable is not set; please set it to your timezone");
+# endif
+ if (localzone || !(tm = gmtime(&unixtime)))
+ tm = localtime(&unixtime);
+ return tm;
+}
+
+/* Yield A - B, measured in seconds. */
+ time_t
+difftm(a, b)
+ struct tm const *a, *b;
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int difference_in_day_of_year = a->tm_yday - b->tm_yday;
+ int intervening_leap_days = (
+ ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ );
+ time_t difference_in_years = ay - by;
+ time_t difference_in_days = (
+ difference_in_years*365
+ + (intervening_leap_days + difference_in_day_of_year)
+ );
+ return
+ (
+ (
+ 24*difference_in_days
+ + (a->tm_hour - b->tm_hour)
+ )*60 + (a->tm_min - b->tm_min)
+ )*60 + (a->tm_sec - b->tm_sec);
+}
+
+/*
+* Adjust time T by adding SECONDS. SECONDS must be at most 24 hours' worth.
+* Adjust only T's year, mon, mday, hour, min and sec members;
+* plus adjust wday if it is defined.
+*/
+ void
+adjzone(t, seconds)
+ register struct tm *t;
+ long seconds;
+{
+ /*
+ * This code can be off by a second if SECONDS is not a multiple of 60,
+ * if T is local time, and if a leap second happens during this minute.
+ * But this bug has never occurred, and most likely will not ever occur.
+ * Liberia, the last country for which SECONDS % 60 was nonzero,
+ * switched to UTC in May 1972; the first leap second was in June 1972.
+ */
+ int leap_second = t->tm_sec == 60;
+ long sec = seconds + (t->tm_sec - leap_second);
+ if (sec < 0) {
+ if ((t->tm_min -= (59-sec)/60) < 0) {
+ if ((t->tm_hour -= (59-t->tm_min)/60) < 0) {
+ t->tm_hour += 24;
+ if (TM_DEFINED(t->tm_wday) && --t->tm_wday < 0)
+ t->tm_wday = 6;
+ if (--t->tm_mday <= 0) {
+ if (--t->tm_mon < 0) {
+ --t->tm_year;
+ t->tm_mon = 11;
+ }
+ t->tm_mday = month_days(t);
+ }
+ }
+ t->tm_min += 24 * 60;
+ }
+ sec += 24L * 60 * 60;
+ } else
+ if (60 <= (t->tm_min += sec/60))
+ if (24 <= (t->tm_hour += t->tm_min/60)) {
+ t->tm_hour -= 24;
+ if (TM_DEFINED(t->tm_wday) && ++t->tm_wday == 7)
+ t->tm_wday = 0;
+ if (month_days(t) < ++t->tm_mday) {
+ if (11 < ++t->tm_mon) {
+ ++t->tm_year;
+ t->tm_mon = 0;
+ }
+ t->tm_mday = 1;
+ }
+ }
+ t->tm_min %= 60;
+ t->tm_sec = (int) (sec%60) + leap_second;
+}
+
+/*
+* Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise.
+* Use only TM's year, mon, mday, hour, min, and sec members.
+* Ignore TM's old tm_yday and tm_wday, but fill in their correct values.
+* Yield -1 on failure (e.g. a member out of range).
+* Posix 1003.1-1990 doesn't allow leap seconds, but some implementations
+* have them anyway, so allow them if localtime/gmtime does.
+*/
+ time_t
+tm2time(tm, localzone)
+ struct tm *tm;
+ int localzone;
+{
+ /* Cache the most recent t,tm pairs; 1 for gmtime, 1 for localtime. */
+ static time_t t_cache[2];
+ static struct tm tm_cache[2];
+
+ time_t d, gt;
+ struct tm const *gtm;
+ /*
+ * The maximum number of iterations should be enough to handle any
+ * combinations of leap seconds, time zone rule changes, and solar time.
+ * 4 is probably enough; we use a bigger number just to be safe.
+ */
+ int remaining_tries = 8;
+
+ /* Avoid subscript errors. */
+ if (12 <= (unsigned)tm->tm_mon)
+ return -1;
+
+ tm->tm_yday = month_yday[tm->tm_mon] + tm->tm_mday
+ - (tm->tm_mon<2 || ! isleap(tm->tm_year + TM_YEAR_ORIGIN));
+
+ /* Make a first guess. */
+ gt = t_cache[localzone];
+ gtm = gt ? &tm_cache[localzone] : time2tm(gt,localzone);
+
+ /* Repeatedly use the error from the guess to improve the guess. */
+ while ((d = difftm(tm, gtm)) != 0) {
+ if (--remaining_tries == 0)
+ return -1;
+ gt += d;
+ gtm = time2tm(gt,localzone);
+ }
+ t_cache[localzone] = gt;
+ tm_cache[localzone] = *gtm;
+
+ /*
+ * Check that the guess actually matches;
+ * overflow can cause difftm to yield 0 even on differing times,
+ * or tm may have members out of range (e.g. bad leap seconds).
+ */
+ if ( (tm->tm_year ^ gtm->tm_year)
+ | (tm->tm_mon ^ gtm->tm_mon)
+ | (tm->tm_mday ^ gtm->tm_mday)
+ | (tm->tm_hour ^ gtm->tm_hour)
+ | (tm->tm_min ^ gtm->tm_min)
+ | (tm->tm_sec ^ gtm->tm_sec))
+ return -1;
+
+ tm->tm_wday = gtm->tm_wday;
+ return gt;
+}
+
+/*
+* Check *PT and convert it to time_t.
+* If it is incompletely specified, use DEFAULT_TIME to fill it out.
+* Use localtime if PT->zone is the special value TM_LOCAL_ZONE.
+* Yield -1 on failure.
+* ISO 8601 day-of-year and week numbers are not yet supported.
+*/
+ static time_t
+maketime(pt, default_time)
+ struct partime const *pt;
+ time_t default_time;
+{
+ int localzone, wday;
+ struct tm tm;
+ struct tm *tm0 = 0;
+ time_t r;
+
+ tm0 = 0; /* Keep gcc -Wall happy. */
+ localzone = pt->zone==TM_LOCAL_ZONE;
+
+ tm = pt->tm;
+
+ if (TM_DEFINED(pt->ymodulus) || !TM_DEFINED(tm.tm_year)) {
+ /* Get tm corresponding to current time. */
+ tm0 = time2tm(default_time, localzone);
+ if (!localzone)
+ adjzone(tm0, pt->zone);
+ }
+
+ if (TM_DEFINED(pt->ymodulus))
+ tm.tm_year +=
+ (tm0->tm_year + TM_YEAR_ORIGIN)/pt->ymodulus * pt->ymodulus;
+ else if (!TM_DEFINED(tm.tm_year)) {
+ /* Set default year, month, day from current time. */
+ tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN;
+ if (!TM_DEFINED(tm.tm_mon)) {
+ tm.tm_mon = tm0->tm_mon;
+ if (!TM_DEFINED(tm.tm_mday))
+ tm.tm_mday = tm0->tm_mday;
+ }
+ }
+
+ /* Convert from partime year (Gregorian) to Posix year. */
+ tm.tm_year -= TM_YEAR_ORIGIN;
+
+ /* Set remaining default fields to be their minimum values. */
+ if (!TM_DEFINED(tm.tm_mon)) tm.tm_mon = 0;
+ if (!TM_DEFINED(tm.tm_mday)) tm.tm_mday = 1;
+ if (!TM_DEFINED(tm.tm_hour)) tm.tm_hour = 0;
+ if (!TM_DEFINED(tm.tm_min)) tm.tm_min = 0;
+ if (!TM_DEFINED(tm.tm_sec)) tm.tm_sec = 0;
+
+ if (!localzone)
+ adjzone(&tm, -pt->zone);
+ wday = tm.tm_wday;
+
+ /* Convert and fill in the rest of the tm. */
+ r = tm2time(&tm, localzone);
+
+ /* Check weekday. */
+ if (r != -1 && TM_DEFINED(wday) && wday != tm.tm_wday)
+ return -1;
+
+ return r;
+}
+
+/* Parse a free-format date in SOURCE, yielding a Unix format time. */
+ time_t
+str2time(source, default_time, default_zone)
+ char const *source;
+ time_t default_time;
+ long default_zone;
+{
+ struct partime pt;
+
+ if (*partime(source, &pt))
+ return -1;
+ if (pt.zone == TM_UNDEFINED_ZONE)
+ pt.zone = default_zone;
+ return maketime(&pt, default_time);
+}
+
+#if TEST
+#include <stdio.h>
+ int
+main(argc, argv) int argc; char **argv;
+{
+ time_t default_time = time((time_t *)0);
+ long default_zone = argv[1] ? atol(argv[1]) : 0;
+ char buf[1000];
+ while (fgets(buf, 1000, stdin)) {
+ time_t t = str2time(buf, default_time, default_zone);
+ printf("%s", asctime(gmtime(&t)));
+ }
+ return 0;
+}
+#endif
diff --git a/gnu/usr.bin/rcs/lib/maketime.h b/gnu/usr.bin/rcs/lib/maketime.h
new file mode 100644
index 0000000..fbe1256
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/maketime.h
@@ -0,0 +1,39 @@
+/* Yield time_t from struct partime yielded by partime. */
+
+/* Copyright 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#if defined(__STDC__) || has_prototypes
+# define __MAKETIME_P(x) x
+#else
+# define __MAKETIME_P(x) ()
+#endif
+
+struct tm *time2tm __MAKETIME_P((time_t,int));
+time_t difftm __MAKETIME_P((struct tm const *, struct tm const *));
+time_t str2time __MAKETIME_P((char const *, time_t, long));
+time_t tm2time __MAKETIME_P((struct tm *, int));
+void adjzone __MAKETIME_P((struct tm *, long));
diff --git a/gnu/usr.bin/rcs/lib/merger.c b/gnu/usr.bin/rcs/lib/merger.c
new file mode 100644
index 0000000..8f1d610
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/merger.c
@@ -0,0 +1,148 @@
+/* three-way file merge internals */
+
+/* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#include "rcsbase.h"
+
+libId(mergerId, "$FreeBSD$")
+
+ static char const *normalize_arg P((char const*,char**));
+ static char const *
+normalize_arg(s, b)
+ char const *s;
+ char **b;
+/*
+ * If S looks like an option, prepend ./ to it. Yield the result.
+ * Set *B to the address of any storage that was allocated.
+ */
+{
+ char *t;
+ if (*s == '-') {
+ *b = t = testalloc(strlen(s) + 3);
+ VOID sprintf(t, ".%c%s", SLASH, s);
+ return t;
+ } else {
+ *b = 0;
+ return s;
+ }
+}
+
+ int
+merge(tostdout, edarg, label, argv)
+ int tostdout;
+ char const *edarg;
+ char const *const label[3];
+ char const *const argv[3];
+/*
+ * Do `merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2',
+ * where TOSTDOUT specifies whether -p is present,
+ * EDARG gives the editing type (e.g. "-A", or null for the default),
+ * LABEL gives l0, l1 and l2, and ARGV gives a0, a1 and a2.
+ * Yield DIFF_SUCCESS or DIFF_FAILURE.
+ */
+{
+ register int i;
+ FILE *f;
+ RILE *rt;
+ char const *a[3], *t;
+ char *b[3];
+ int s;
+#if !DIFF3_BIN
+ char const *d[2];
+#endif
+
+ for (i=3; 0<=--i; )
+ a[i] = normalize_arg(argv[i], &b[i]);
+
+ if (!edarg)
+ edarg = "-E";
+
+#if DIFF3_BIN
+ t = 0;
+ if (!tostdout)
+ t = maketemp(0);
+ s = run(
+ -1, t,
+ DIFF3, edarg, "-am",
+ "-L", label[0],
+ "-L", label[1],
+ "-L", label[2],
+ a[0], a[1], a[2], (char*)0
+ );
+ switch (s) {
+ case DIFF_SUCCESS:
+ break;
+ case DIFF_FAILURE:
+ warn("conflicts during merge");
+ break;
+ default:
+ exiterr();
+ }
+ if (t) {
+ if (!(f = fopenSafer(argv[0], "w")))
+ efaterror(argv[0]);
+ if (!(rt = Iopen(t, "r", (struct stat*)0)))
+ efaterror(t);
+ fastcopy(rt, f);
+ Ifclose(rt);
+ Ofclose(f);
+ }
+#else
+ for (i=0; i<2; i++)
+ switch (run(
+ -1, d[i]=maketemp(i),
+ DIFF, a[i], a[2], (char*)0
+ )) {
+ case DIFF_FAILURE: case DIFF_SUCCESS: break;
+ default: faterror("diff failed");
+ }
+ t = maketemp(2);
+ s = run(
+ -1, t,
+ DIFF3, edarg, d[0], d[1], a[0], a[1], a[2],
+ label[0], label[2], (char*)0
+ );
+ if (s != DIFF_SUCCESS) {
+ s = DIFF_FAILURE;
+ warn("overlaps or other problems during merge");
+ }
+ if (!(f = fopenSafer(t, "a+")))
+ efaterror(t);
+ aputs(tostdout ? "1,$p\n" : "w\n", f);
+ Orewind(f);
+ aflush(f);
+ if (run(fileno(f), (char*)0, ED, "-", a[0], (char*)0))
+ exiterr();
+ Ofclose(f);
+#endif
+
+ tempunlink();
+ for (i=3; 0<=--i; )
+ if (b[i])
+ tfree(b[i]);
+ return s;
+}
diff --git a/gnu/usr.bin/rcs/lib/partime.c b/gnu/usr.bin/rcs/lib/partime.c
new file mode 100644
index 0000000..05b0108
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/partime.c
@@ -0,0 +1,701 @@
+/* Parse a string, yielding a struct partime that describes it. */
+
+/* Copyright 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#if has_conf_h
+# include "conf.h"
+#else
+# ifdef __STDC__
+# define P(x) x
+# else
+# define const
+# define P(x) ()
+# endif
+# include <limits.h>
+# include <time.h>
+#endif
+
+#include <ctype.h>
+#undef isdigit
+#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than stock */
+
+#include "partime.h"
+
+char const partimeId[]
+ = "$FreeBSD$";
+
+
+/* Lookup tables for names of months, weekdays, time zones. */
+
+#define NAME_LENGTH_MAXIMUM 4
+
+struct name_val {
+ char name[NAME_LENGTH_MAXIMUM];
+ int val;
+};
+
+
+static char const *parse_decimal P((char const*,int,int,int,int,int*,int*));
+static char const *parse_fixed P((char const*,int,int*));
+static char const *parse_pattern_letter P((char const*,int,struct partime*));
+static char const *parse_prefix P((char const*,struct partime*,int*));
+static char const *parse_ranged P((char const*,int,int,int,int*));
+static int lookup P((char const*,struct name_val const[]));
+static int merge_partime P((struct partime*, struct partime const*));
+static void undefine P((struct partime*));
+
+
+static struct name_val const month_names[] = {
+ {"jan",0}, {"feb",1}, {"mar",2}, {"apr",3}, {"may",4}, {"jun",5},
+ {"jul",6}, {"aug",7}, {"sep",8}, {"oct",9}, {"nov",10}, {"dec",11},
+ {"", TM_UNDEFINED}
+};
+
+static struct name_val const weekday_names[] = {
+ {"sun",0}, {"mon",1}, {"tue",2}, {"wed",3}, {"thu",4}, {"fri",5}, {"sat",6},
+ {"", TM_UNDEFINED}
+};
+
+#define hr60nonnegative(t) ((t)/100 * 60 + (t)%100)
+#define hr60(t) ((t)<0 ? -hr60nonnegative(-(t)) : hr60nonnegative(t))
+#define zs(t,s) {s, hr60(t)}
+#define zd(t,s,d) zs(t, s), zs((t)+100, d)
+
+static struct name_val const zone_names[] = {
+ zs(-1000, "hst"), /* Hawaii */
+ zd(-1000,"hast","hadt"),/* Hawaii-Aleutian */
+ zd(- 900,"akst","akdt"),/* Alaska */
+ zd(- 800, "pst", "pdt"),/* Pacific */
+ zd(- 700, "mst", "mdt"),/* Mountain */
+ zd(- 600, "cst", "cdt"),/* Central */
+ zd(- 500, "est", "edt"),/* Eastern */
+ zd(- 400, "ast", "adt"),/* Atlantic */
+ zd(- 330, "nst", "ndt"),/* Newfoundland */
+ zs( 000, "utc"), /* Coordinated Universal */
+ zs( 000, "cut"), /* " */
+ zs( 000, "ut"), /* Universal */
+ zs( 000, "z"), /* Zulu (required by ISO 8601) */
+ zd( 000, "gmt", "bst"),/* Greenwich Mean, British Summer */
+ zs( 000, "wet"), /* Western Europe */
+ zs( 100, "met"), /* Middle Europe */
+ zs( 100, "cet"), /* Central Europe */
+ zs( 200, "eet"), /* Eastern Europe */
+ zs( 530, "ist"), /* India */
+ zd( 900, "jst", "jdt"),/* Japan */
+ zd( 900, "kst", "kdt"),/* Korea */
+ zd( 1200,"nzst","nzdt"),/* New Zealand */
+ { "lt", 1 },
+#if 0
+ /* The following names are duplicates or are not well attested. */
+ zs(-1100, "sst"), /* Samoa */
+ zs(-1000, "tht"), /* Tahiti */
+ zs(- 930, "mqt"), /* Marquesas */
+ zs(- 900, "gbt"), /* Gambier */
+ zd(- 900, "yst", "ydt"),/* Yukon - name is no longer used */
+ zs(- 830, "pit"), /* Pitcairn */
+ zd(- 500, "cst", "cdt"),/* Cuba */
+ zd(- 500, "ast", "adt"),/* Acre */
+ zd(- 400, "wst", "wdt"),/* Western Brazil */
+ zd(- 400, "ast", "adt"),/* Andes */
+ zd(- 400, "cst", "cdt"),/* Chile */
+ zs(- 300, "wgt"), /* Western Greenland */
+ zd(- 300, "est", "edt"),/* Eastern South America */
+ zs(- 300, "mgt"), /* Middle Greenland */
+ zd(- 200, "fst", "fdt"),/* Fernando de Noronha */
+ zs(- 100, "egt"), /* Eastern Greenland */
+ zs(- 100, "aat"), /* Atlantic Africa */
+ zs(- 100, "act"), /* Azores and Canaries */
+ zs( 000, "wat"), /* West Africa */
+ zs( 100, "cat"), /* Central Africa */
+ zd( 100, "mez","mesz"),/* Mittel-Europaeische Zeit */
+ zs( 200, "sat"), /* South Africa */
+ zd( 200, "ist", "idt"),/* Israel */
+ zs( 300, "eat"), /* East Africa */
+ zd( 300, "ast", "adt"),/* Arabia */
+ zd( 300, "msk", "msd"),/* Moscow */
+ zd( 330, "ist", "idt"),/* Iran */
+ zs( 400, "gst"), /* Gulf */
+ zs( 400, "smt"), /* Seychelles & Mascarene */
+ zd( 400, "esk", "esd"),/* Yekaterinburg */
+ zd( 400, "bsk", "bsd"),/* Baku */
+ zs( 430, "aft"), /* Afghanistan */
+ zd( 500, "osk", "osd"),/* Omsk */
+ zs( 500, "pkt"), /* Pakistan */
+ zd( 500, "tsk", "tsd"),/* Tashkent */
+ zs( 545, "npt"), /* Nepal */
+ zs( 600, "bgt"), /* Bangladesh */
+ zd( 600, "nsk", "nsd"),/* Novosibirsk */
+ zs( 630, "bmt"), /* Burma */
+ zs( 630, "cct"), /* Cocos */
+ zs( 700, "ict"), /* Indochina */
+ zs( 700, "jvt"), /* Java */
+ zd( 700, "isk", "isd"),/* Irkutsk */
+ zs( 800, "hkt"), /* Hong Kong */
+ zs( 800, "pst"), /* Philippines */
+ zs( 800, "sgt"), /* Singapore */
+ zd( 800, "cst", "cdt"),/* China */
+ zd( 800, "ust", "udt"),/* Ulan Bator */
+ zd( 800, "wst", "wst"),/* Western Australia */
+ zd( 800, "ysk", "ysd"),/* Yakutsk */
+ zs( 900, "blt"), /* Belau */
+ zs( 900, "mlt"), /* Moluccas */
+ zd( 900, "vsk", "vsd"),/* Vladivostok */
+ zd( 930, "cst", "cst"),/* Central Australia */
+ zs( 1000, "gst"), /* Guam */
+ zd( 1000, "gsk", "gsd"),/* Magadan */
+ zd( 1000, "est", "est"),/* Eastern Australia */
+ zd( 1100,"lhst","lhst"),/* Lord Howe */
+ zd( 1100, "psk", "psd"),/* Petropavlovsk-Kamchatski */
+ zs( 1100,"ncst"), /* New Caledonia */
+ zs( 1130,"nrft"), /* Norfolk */
+ zd( 1200, "ask", "asd"),/* Anadyr */
+ zs( 1245,"nz-chat"), /* Chatham */
+ zs( 1300, "tgt"), /* Tongatapu */
+#endif
+ {"", -1}
+};
+
+ static int
+lookup (s, table)
+ char const *s;
+ struct name_val const table[];
+/* Look for a prefix of S in TABLE, returning val for first matching entry. */
+{
+ int j;
+ char buf[NAME_LENGTH_MAXIMUM];
+
+ for (j = 0; j < NAME_LENGTH_MAXIMUM; j++) {
+ unsigned char c = *s++;
+ buf[j] = isupper (c) ? tolower (c) : c;
+ if (!isalpha (c))
+ break;
+ }
+ for (; table[0].name[0]; table++)
+ for (j = 0; buf[j] == table[0].name[j]; )
+ if (++j == NAME_LENGTH_MAXIMUM || !table[0].name[j])
+ goto done;
+ done:
+ return table[0].val;
+}
+
+
+ static void
+undefine (t) struct partime *t;
+/* Set *T to ``undefined'' values. */
+{
+ t->tm.tm_sec = t->tm.tm_min = t->tm.tm_hour = t->tm.tm_mday = t->tm.tm_mon
+ = t->tm.tm_year = t->tm.tm_wday = t->tm.tm_yday
+ = t->ymodulus = t->yweek
+ = TM_UNDEFINED;
+ t->zone = TM_UNDEFINED_ZONE;
+}
+
+/*
+* Array of patterns to look for in a date string.
+* Order is important: we look for the first matching pattern
+* whose values do not contradict values that we already know about.
+* See `parse_pattern_letter' below for the meaning of the pattern codes.
+*/
+static char const * const patterns[] = {
+ /*
+ * These traditional patterns must come first,
+ * to prevent an ISO 8601 format from misinterpreting their prefixes.
+ */
+ "E_n_y", "x", /* RFC 822 */
+ "E_n", "n_E", "n", "t:m:s_A", "t:m_A", "t_A", /* traditional */
+ "y/N/D$", /* traditional RCS */
+
+ /* ISO 8601:1988 formats, generalized a bit. */
+ "y-N-D$", "4ND$", "Y-N$",
+ "RND$", "-R=N$", "-R$", "--N=D$", "N=DT",
+ "--N$", "---D$", "DT",
+ "Y-d$", "4d$", "R=d$", "-d$", "dT",
+ "y-W-X", "yWX", "y=W",
+ "-r-W-X", "r-W-XT", "-rWX", "rWXT", "-W=X", "W=XT", "-W",
+ "-w-X", "w-XT", "---X$", "XT", "4$",
+ "T",
+ "h:m:s$", "hms$", "h:m$", "hm$", "h$", "-m:s$", "-ms$", "-m$", "--s$",
+ "Y", "Z",
+
+ 0
+};
+
+ static char const *
+parse_prefix (str, t, pi) char const *str; struct partime *t; int *pi;
+/*
+* Parse an initial prefix of STR, setting *T accordingly.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+* Start with pattern *PI; if success, set *PI to the next pattern to try.
+* Set *PI to -1 if we know there are no more patterns to try;
+* if *PI is initially negative, give up immediately.
+*/
+{
+ int i = *pi;
+ char const *pat;
+ unsigned char c;
+
+ if (i < 0)
+ return 0;
+
+ /* Remove initial noise. */
+ while (!isalnum (c = *str) && c != '-' && c != '+') {
+ if (!c) {
+ undefine (t);
+ *pi = -1;
+ return str;
+ }
+ str++;
+ }
+
+ /* Try a pattern until one succeeds. */
+ while ((pat = patterns[i++]) != 0) {
+ char const *s = str;
+ undefine (t);
+ do {
+ if (!(c = *pat++)) {
+ *pi = i;
+ return s;
+ }
+ } while ((s = parse_pattern_letter (s, c, t)) != 0);
+ }
+
+ return 0;
+}
+
+ static char const *
+parse_fixed (s, digits, res) char const *s; int digits, *res;
+/*
+* Parse an initial prefix of S of length DIGITS; it must be a number.
+* Store the parsed number into *RES.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ int n = 0;
+ char const *lim = s + digits;
+ while (s < lim) {
+ unsigned d = *s++ - '0';
+ if (9 < d)
+ return 0;
+ n = 10*n + d;
+ }
+ *res = n;
+ return s;
+}
+
+ static char const *
+parse_ranged (s, digits, lo, hi, res) char const *s; int digits, lo, hi, *res;
+/*
+* Parse an initial prefix of S of length DIGITS;
+* it must be a number in the range LO through HI.
+* Store the parsed number into *RES.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ s = parse_fixed (s, digits, res);
+ return s && lo<=*res && *res<=hi ? s : 0;
+}
+
+ static char const *
+parse_decimal (s, digits, lo, hi, resolution, res, fres)
+ char const *s;
+ int digits, lo, hi, resolution, *res, *fres;
+/*
+* Parse an initial prefix of S of length DIGITS;
+* it must be a number in the range LO through HI
+* and it may be followed by a fraction that is to be computed using RESOLUTION.
+* Store the parsed number into *RES; store the fraction times RESOLUTION,
+* rounded to the nearest integer, into *FRES.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ s = parse_fixed (s, digits, res);
+ if (s && lo<=*res && *res<=hi) {
+ int f = 0;
+ if ((s[0]==',' || s[0]=='.') && isdigit ((unsigned char) s[1])) {
+ char const *s1 = ++s;
+ int num10 = 0, denom10 = 10, product;
+ while (isdigit ((unsigned char) *++s))
+ denom10 *= 10;
+ s = parse_fixed (s1, s - s1, &num10);
+ product = num10*resolution;
+ f = (product + (denom10>>1)) / denom10;
+ f -= f & (product%denom10 == denom10>>1); /* round to even */
+ if (f < 0 || product/resolution != num10)
+ return 0; /* overflow */
+ }
+ *fres = f;
+ return s;
+ }
+ return 0;
+}
+
+ char *
+parzone (s, zone) char const *s; long *zone;
+/*
+* Parse an initial prefix of S; it must denote a time zone.
+* Set *ZONE to the number of seconds east of GMT,
+* or to TM_LOCAL_ZONE if it is the local time zone.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ char sign;
+ int hh, mm, ss;
+ int minutesEastOfUTC;
+ long offset, z;
+
+ /*
+ * The formats are LT, n, n DST, nDST, no, o
+ * where n is a time zone name
+ * and o is a time zone offset of the form [-+]hh[:mm[:ss]].
+ */
+ switch (*s) {
+ case '-': case '+':
+ z = 0;
+ break;
+
+ default:
+ minutesEastOfUTC = lookup (s, zone_names);
+ if (minutesEastOfUTC == -1)
+ return 0;
+
+ /* Don't bother to check rest of spelling. */
+ while (isalpha ((unsigned char) *s))
+ s++;
+
+ /* Don't modify LT. */
+ if (minutesEastOfUTC == 1) {
+ *zone = TM_LOCAL_ZONE;
+ return (char *) s;
+ }
+
+ z = minutesEastOfUTC * 60L;
+
+ /* Look for trailing " DST". */
+ if (
+ (s[-1]=='T' || s[-1]=='t') &&
+ (s[-2]=='S' || s[-2]=='s') &&
+ (s[-3]=='D' || s[-3]=='t')
+ )
+ goto trailing_dst;
+ while (isspace ((unsigned char) *s))
+ s++;
+ if (
+ (s[0]=='D' || s[0]=='d') &&
+ (s[1]=='S' || s[1]=='s') &&
+ (s[2]=='T' || s[2]=='t')
+ ) {
+ s += 3;
+ trailing_dst:
+ *zone = z + 60*60;
+ return (char *) s;
+ }
+
+ switch (*s) {
+ case '-': case '+': break;
+ default: return (char *) s;
+ }
+ }
+ sign = *s++;
+
+ if (!(s = parse_ranged (s, 2, 0, 23, &hh)))
+ return 0;
+ mm = ss = 0;
+ if (*s == ':')
+ s++;
+ if (isdigit ((unsigned char) *s)) {
+ if (!(s = parse_ranged (s, 2, 0, 59, &mm)))
+ return 0;
+ if (*s==':' && s[-3]==':' && isdigit ((unsigned char) s[1])) {
+ if (!(s = parse_ranged (s + 1, 2, 0, 59, &ss)))
+ return 0;
+ }
+ }
+ if (isdigit ((unsigned char) *s))
+ return 0;
+ offset = (hh*60 + mm)*60L + ss;
+ *zone = z + (sign=='-' ? -offset : offset);
+ /*
+ * ?? Are fractions allowed here?
+ * If so, they're not implemented.
+ */
+ return (char *) s;
+}
+
+ static char const *
+parse_pattern_letter (s, c, t) char const *s; int c; struct partime *t;
+/*
+* Parse an initial prefix of S, matching the pattern whose code is C.
+* Set *T accordingly.
+* Return the first character after the prefix, or 0 if it couldn't be parsed.
+*/
+{
+ switch (c) {
+ case '$': /* The next character must be a non-digit. */
+ if (isdigit ((unsigned char) *s))
+ return 0;
+ break;
+
+ case '-': case '/': case ':':
+ /* These characters stand for themselves. */
+ if (*s++ != c)
+ return 0;
+ break;
+
+ case '4': /* 4-digit year */
+ s = parse_fixed (s, 4, &t->tm.tm_year);
+ break;
+
+ case '=': /* optional '-' */
+ s += *s == '-';
+ break;
+
+ case 'A': /* AM or PM */
+ /*
+ * This matches the regular expression [AaPp][Mm]?.
+ * It must not be followed by a letter or digit;
+ * otherwise it would match prefixes of strings like "PST".
+ */
+ switch (*s++) {
+ case 'A': case 'a':
+ if (t->tm.tm_hour == 12)
+ t->tm.tm_hour = 0;
+ break;
+
+ case 'P': case 'p':
+ if (t->tm.tm_hour != 12)
+ t->tm.tm_hour += 12;
+ break;
+
+ default: return 0;
+ }
+ switch (*s) {
+ case 'M': case 'm': s++; break;
+ }
+ if (isalnum (*s))
+ return 0;
+ break;
+
+ case 'D': /* day of month [01-31] */
+ s = parse_ranged (s, 2, 1, 31, &t->tm.tm_mday);
+ break;
+
+ case 'd': /* day of year [001-366] */
+ s = parse_ranged (s, 3, 1, 366, &t->tm.tm_yday);
+ t->tm.tm_yday--;
+ break;
+
+ case 'E': /* extended day of month [1-9, 01-31] */
+ s = parse_ranged (s, (
+ isdigit ((unsigned char) s[0]) &&
+ isdigit ((unsigned char) s[1])
+ ) + 1, 1, 31, &t->tm.tm_mday);
+ break;
+
+ case 'h': /* hour [00-23 followed by optional fraction] */
+ {
+ int frac;
+ s = parse_decimal (s, 2, 0, 23, 60*60, &t->tm.tm_hour, &frac);
+ t->tm.tm_min = frac / 60;
+ t->tm.tm_sec = frac % 60;
+ }
+ break;
+
+ case 'm': /* minute [00-59 followed by optional fraction] */
+ s = parse_decimal (s, 2, 0, 59, 60, &t->tm.tm_min, &t->tm.tm_sec);
+ break;
+
+ case 'n': /* month name [e.g. "Jan"] */
+ if (!TM_DEFINED (t->tm.tm_mon = lookup (s, month_names)))
+ return 0;
+ /* Don't bother to check rest of spelling. */
+ while (isalpha ((unsigned char) *s))
+ s++;
+ break;
+
+ case 'N': /* month [01-12] */
+ s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon);
+ t->tm.tm_mon--;
+ break;
+
+ case 'r': /* year % 10 (remainder in origin-0 decade) [0-9] */
+ s = parse_fixed (s, 1, &t->tm.tm_year);
+ t->ymodulus = 10;
+ break;
+
+ case_R:
+ case 'R': /* year % 100 (remainder in origin-0 century) [00-99] */
+ s = parse_fixed (s, 2, &t->tm.tm_year);
+ t->ymodulus = 100;
+ break;
+
+ case 's': /* second [00-60 followed by optional fraction] */
+ {
+ int frac;
+ s = parse_decimal (s, 2, 0, 60, 1, &t->tm.tm_sec, &frac);
+ t->tm.tm_sec += frac;
+ }
+ break;
+
+ case 'T': /* 'T' or 't' */
+ switch (*s++) {
+ case 'T': case 't': break;
+ default: return 0;
+ }
+ break;
+
+ case 't': /* traditional hour [1-9 or 01-12] */
+ s = parse_ranged (s, (
+ isdigit ((unsigned char) s[0]) && isdigit ((unsigned char) s[1])
+ ) + 1, 1, 12, &t->tm.tm_hour);
+ break;
+
+ case 'w': /* 'W' or 'w' only (stands for current week) */
+ switch (*s++) {
+ case 'W': case 'w': break;
+ default: return 0;
+ }
+ break;
+
+ case 'W': /* 'W' or 'w', followed by a week of year [00-53] */
+ switch (*s++) {
+ case 'W': case 'w': break;
+ default: return 0;
+ }
+ s = parse_ranged (s, 2, 0, 53, &t->yweek);
+ break;
+
+ case 'X': /* weekday (1=Mon ... 7=Sun) [1-7] */
+ s = parse_ranged (s, 1, 1, 7, &t->tm.tm_wday);
+ t->tm.tm_wday--;
+ break;
+
+ case 'x': /* weekday name [e.g. "Sun"] */
+ if (!TM_DEFINED (t->tm.tm_wday = lookup (s, weekday_names)))
+ return 0;
+ /* Don't bother to check rest of spelling. */
+ while (isalpha ((unsigned char) *s))
+ s++;
+ break;
+
+ case 'y': /* either R or Y */
+ if (
+ isdigit ((unsigned char) s[0]) &&
+ isdigit ((unsigned char) s[1]) &&
+ !isdigit ((unsigned char) s[2])
+ )
+ goto case_R;
+ /* fall into */
+ case 'Y': /* year in full [4 or more digits] */
+ {
+ int len = 0;
+ while (isdigit ((unsigned char) s[len]))
+ len++;
+ if (len < 4)
+ return 0;
+ s = parse_fixed (s, len, &t->tm.tm_year);
+ }
+ break;
+
+ case 'Z': /* time zone */
+ s = parzone (s, &t->zone);
+ break;
+
+ case '_': /* possibly empty sequence of non-alphanumerics */
+ while (!isalnum (*s) && *s)
+ s++;
+ break;
+
+ default: /* bad pattern */
+ return 0;
+ }
+ return s;
+}
+
+ static int
+merge_partime (t, u) struct partime *t; struct partime const *u;
+/*
+* If there is no conflict, merge into *T the additional information in *U
+* and return 0. Otherwise do nothing and return -1.
+*/
+{
+# define conflict(a,b) ((a) != (b) && TM_DEFINED (a) && TM_DEFINED (b))
+ if (
+ conflict (t->tm.tm_sec, u->tm.tm_sec) ||
+ conflict (t->tm.tm_min, u->tm.tm_min) ||
+ conflict (t->tm.tm_hour, u->tm.tm_hour) ||
+ conflict (t->tm.tm_mday, u->tm.tm_mday) ||
+ conflict (t->tm.tm_mon, u->tm.tm_mon) ||
+ conflict (t->tm.tm_year, u->tm.tm_year) ||
+ conflict (t->tm.tm_wday, u->tm.tm_yday) ||
+ conflict (t->ymodulus, u->ymodulus) ||
+ conflict (t->yweek, u->yweek) ||
+ (
+ t->zone != u->zone &&
+ t->zone != TM_UNDEFINED_ZONE &&
+ u->zone != TM_UNDEFINED_ZONE
+ )
+ )
+ return -1;
+# undef conflict
+# define merge_(a,b) if (TM_DEFINED (b)) (a) = (b);
+ merge_ (t->tm.tm_sec, u->tm.tm_sec)
+ merge_ (t->tm.tm_min, u->tm.tm_min)
+ merge_ (t->tm.tm_hour, u->tm.tm_hour)
+ merge_ (t->tm.tm_mday, u->tm.tm_mday)
+ merge_ (t->tm.tm_mon, u->tm.tm_mon)
+ merge_ (t->tm.tm_year, u->tm.tm_year)
+ merge_ (t->tm.tm_wday, u->tm.tm_yday)
+ merge_ (t->ymodulus, u->ymodulus)
+ merge_ (t->yweek, u->yweek)
+# undef merge_
+ if (u->zone != TM_UNDEFINED_ZONE) t->zone = u->zone;
+ return 0;
+}
+
+ char *
+partime (s, t) char const *s; struct partime *t;
+/*
+* Parse a date/time prefix of S, putting the parsed result into *T.
+* Return the first character after the prefix.
+* The prefix may contain no useful information;
+* in that case, *T will contain only undefined values.
+*/
+{
+ struct partime p;
+
+ undefine (t);
+ while (*s) {
+ int i = 0;
+ char const *s1;
+ do {
+ if (!(s1 = parse_prefix (s, &p, &i)))
+ return (char *) s;
+ } while (merge_partime (t, &p) != 0);
+ s = s1;
+ }
+ return (char *) s;
+}
diff --git a/gnu/usr.bin/rcs/lib/partime.h b/gnu/usr.bin/rcs/lib/partime.h
new file mode 100644
index 0000000..5d3983f
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/partime.h
@@ -0,0 +1,71 @@
+/* Parse a string, yielding a struct partime that describes it. */
+
+/* Copyright 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#define TM_UNDEFINED (-1)
+#define TM_DEFINED(x) (0 <= (x))
+
+#define TM_UNDEFINED_ZONE ((long) -24 * 60 * 60)
+#define TM_LOCAL_ZONE (TM_UNDEFINED_ZONE - 1)
+
+struct partime {
+ /*
+ * This structure describes the parsed time.
+ * Only the following tm_* values in it are used:
+ * sec, min, hour, mday, mon, year, wday, yday.
+ * If TM_UNDEFINED(value), the parser never found the value.
+ * The tm_year field is the actual year, not the year - 1900;
+ * but see ymodulus below.
+ */
+ struct tm tm;
+
+ /*
+ * If !TM_UNDEFINED(ymodulus),
+ * then tm.tm_year is actually modulo ymodulus.
+ */
+ int ymodulus;
+
+ /*
+ * Week of year, ISO 8601 style.
+ * If TM_UNDEFINED(yweek), the parser never found yweek.
+ * Weeks start on Mondays.
+ * Week 1 includes Jan 4.
+ */
+ int yweek;
+
+ /* Seconds east of UTC; or TM_LOCAL_ZONE or TM_UNDEFINED_ZONE. */
+ long zone;
+};
+
+#if defined(__STDC__) || has_prototypes
+# define __PARTIME_P(x) x
+#else
+# define __PARTIME_P(x) ()
+#endif
+
+char *partime __PARTIME_P((char const *, struct partime *));
+char *parzone __PARTIME_P((char const *, long *));
diff --git a/gnu/usr.bin/rcs/lib/rcsbase.h b/gnu/usr.bin/rcs/lib/rcsbase.h
new file mode 100644
index 0000000..9f2f68c
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsbase.h
@@ -0,0 +1,762 @@
+/* RCS common definitions and data structures */
+
+#define RCSBASE "$FreeBSD$"
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.20 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.19 1995/06/01 16:23:43 eggert
+ * (SIZEABLE_PATH): Don't depend on PATH_MAX: it's not worth configuring.
+ * (Ioffset_type,BINARY_EXPAND,MIN_UNEXPAND,MIN_UNCHANGED_EXPAND): New macros.
+ * (maps_memory): New macro; replaces many instances of `has_mmap'.
+ * (cacheptr): Renamed from cachetell.
+ * (struct RILE): New alternate name for RILE; the type is now recursive.
+ * (deallocate): New member for RILE, used for generic buffer deallocation.
+ * (cacheunget_): No longer take a failure arg; just call Ierror on failure.
+ * (struct rcslock): Renamed from struct lock, to avoid collisions with
+ * system headers on some hosts. All users changed.
+ * (basefilename): Renamed from basename, likewise.
+ * (dirtpname): Remove; no longer external.
+ * (dirlen, dateform): Remove; no longer used.
+ * (cmpdate, fopenSafer, fdSafer, readAccessFilenameBuffer): New functions.
+ * (zonelenmax): Increase to 9 for full ISO 8601 format.
+ * (catchmmapints): Depend on has_NFS.
+ *
+ * Revision 5.18 1994/03/17 14:05:48 eggert
+ * Add primitives for reading backwards from a RILE;
+ * this is needed to go back and find the $Log prefix.
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ *
+ * Revision 5.17 1993/11/09 17:40:15 eggert
+ * Move RCS-specific time handling into rcstime.c.
+ * printf_string now takes two arguments, alas.
+ *
+ * Revision 5.16 1993/11/03 17:42:27 eggert
+ * Don't arbitrarily limit the number of joins. Remove `nil'.
+ * Add Name keyword. Don't discard ignored phrases.
+ * Add support for merge -A vs -E, and allow up to three labels.
+ * Improve quality of diagnostics and prototypes.
+ *
+ * Revision 5.15 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
+ *
+ * Revision 5.14 1992/02/17 23:02:22 eggert
+ * Add -T support. Work around NFS mmap SIGBUS problem.
+ *
+ * Revision 5.13 1992/01/24 18:44:19 eggert
+ * Add support for bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.12 1992/01/06 02:42:34 eggert
+ * while (E) ; -> while (E) continue;
+ *
+ * Revision 5.11 1991/10/07 17:32:46 eggert
+ * Support piece tables even if !has_mmap.
+ *
+ * Revision 5.10 1991/09/24 00:28:39 eggert
+ * Remove unexported functions.
+ *
+ * Revision 5.9 1991/08/19 03:13:55 eggert
+ * Add piece tables and other tuneups, and NFS workarounds.
+ *
+ * Revision 5.8 1991/04/21 11:58:20 eggert
+ * Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.7 1991/02/28 19:18:50 eggert
+ * Try setuid() if seteuid() doesn't work.
+ *
+ * Revision 5.6 1991/02/26 17:48:37 eggert
+ * Support new link behavior. Move ANSI C / Posix declarations into conf.sh.
+ *
+ * Revision 5.5 1990/12/04 05:18:43 eggert
+ * Use -I for prompts and -q for diagnostics.
+ *
+ * Revision 5.4 1990/11/01 05:03:35 eggert
+ * Don't assume that builtins are functions; they may be macros.
+ * Permit arbitrary data in logs.
+ *
+ * Revision 5.3 1990/09/26 23:36:58 eggert
+ * Port wait() to non-Posix ANSI C hosts.
+ *
+ * Revision 5.2 1990/09/04 08:02:20 eggert
+ * Don't redefine NAME_MAX, PATH_MAX.
+ * Improve incomplete line handling. Standardize yes-or-no procedure.
+ *
+ * Revision 5.1 1990/08/29 07:13:53 eggert
+ * Add -kkvl. Fix type typos exposed by porting. Clean old log messages too.
+ *
+ * Revision 5.0 1990/08/22 08:12:44 eggert
+ * Adjust ANSI C / Posix support. Add -k, -V, setuid. Don't call access().
+ * Remove compile-time limits; use malloc instead.
+ * Ansify and Posixate. Add support for ISO 8859.
+ * Remove snoop and v2 support.
+ *
+ * Revision 4.9 89/05/01 15:17:14 narten
+ * botched previous USG fix
+ *
+ * Revision 4.8 89/05/01 14:53:05 narten
+ * changed #include <strings.h> -> string.h for USG systems.
+ *
+ * Revision 4.7 88/11/08 15:58:45 narten
+ * removed defs for functions loaded from libraries
+ *
+ * Revision 4.6 88/08/09 19:12:36 eggert
+ * Shrink stdio code size; remove lint; permit -Dhshsize=nn.
+ *
+ * Revision 4.5 87/12/18 17:06:41 narten
+ * made removed BSD ifdef, now uses V4_2BSD
+ *
+ * Revision 4.4 87/10/18 10:29:49 narten
+ * Updating version numbers
+ * Changes relative to 1.1 are actually relative to 4.2
+ *
+ * Revision 1.3 87/09/24 14:02:25 narten
+ * changes for lint
+ *
+ * Revision 1.2 87/03/27 14:22:02 jenkins
+ * Port to suns
+ *
+ * Revision 4.2 83/12/20 16:04:20 wft
+ * merged 3.6.1.1 and 4.1 (SMALLOG, logsize).
+ * moved setting of STRICT_LOCKING to Makefile.
+ * changed DOLLAR to UNKN (conflict with KDELIM).
+ *
+ * Revision 4.1 83/05/04 09:12:41 wft
+ * Added markers Id and RCSfile.
+ * Added Dbranch for default branches.
+ *
+ * Revision 3.6.1.1 83/12/02 21:56:22 wft
+ * Increased logsize, added macro SMALLOG.
+ *
+ * Revision 3.6 83/01/15 16:43:28 wft
+ * 4.2 prerelease
+ *
+ * Revision 3.6 83/01/15 16:43:28 wft
+ * Replaced dbm.h with BYTESIZ, fixed definition of rindex().
+ * Added variants of NCPFN and NCPPN for bsd 4.2, selected by defining V4_2BSD.
+ * Added macro DELNUMFORM to have uniform format for printing delta text nodes.
+ * Added macro DELETE to mark deleted deltas.
+ *
+ * Revision 3.5 82/12/10 12:16:56 wft
+ * Added two forms of DATEFORM, one using %02d, the other %.2d.
+ *
+ * Revision 3.4 82/12/04 20:01:25 wft
+ * added LOCKER, Locker, and USG (redefinition of rindex).
+ *
+ * Revision 3.3 82/12/03 12:22:04 wft
+ * Added dbm.h, stdio.h, RCSBASE, RCSSEP, RCSSUF, WORKMODE, TMPFILE3,
+ * PRINTDATE, PRINTTIME, map, and ctab; removed Suffix. Redefined keyvallength
+ * using NCPPN. Changed putc() to abort on write error.
+ *
+ * Revision 3.2 82/10/18 15:03:52 wft
+ * added macro STRICT_LOCKING, removed RCSUMASK.
+ * renamed JOINFILE[1,2] to JOINFIL[1,2].
+ *
+ * Revision 3.1 82/10/11 19:41:17 wft
+ * removed NBPW, NBPC, NCPW.
+ * added typdef int void to aid compiling
+ */
+
+
+#include "conf.h"
+
+
+#define EXIT_TROUBLE DIFF_TROUBLE
+
+#ifdef _POSIX_PATH_MAX
+# define SIZEABLE_PATH _POSIX_PATH_MAX
+#else
+# define SIZEABLE_PATH 255 /* size of a large path; not a hard limit */
+#endif
+
+/* for traditional C hosts with unusual size arguments */
+#define Fread(p,s,n,f) fread(p, (freadarg_type)(s), (freadarg_type)(n), f)
+#define Fwrite(p,s,n,f) fwrite(p, (freadarg_type)(s), (freadarg_type)(n), f)
+
+
+/*
+ * Parameters
+ */
+
+/* backwards compatibility with old versions of RCS */
+#define VERSION_min 3 /* old output RCS format supported */
+#define VERSION_max 5 /* newest output RCS format supported */
+#ifndef VERSION_DEFAULT /* default RCS output format */
+# define VERSION_DEFAULT VERSION_max
+#endif
+#define VERSION(n) ((n) - VERSION_DEFAULT) /* internally, 0 is the default */
+
+#ifndef STRICT_LOCKING
+#define STRICT_LOCKING 1
+#endif
+ /* 0 sets the default locking to non-strict; */
+ /* used in experimental environments. */
+ /* 1 sets the default locking to strict; */
+ /* used in production environments. */
+
+#define yearlength 16 /* (good through AD 9,999,999,999,999,999) */
+#define datesize (yearlength+16) /* size of output of time2date */
+#define RCSTMPPREFIX '_' /* prefix for temp files in working dir */
+#define KDELIM '$' /* delimiter for keywords */
+#define VDELIM ':' /* separates keywords from values */
+#define DEFAULTSTATE "Exp" /* default state of revisions */
+
+
+
+#define true 1
+#define false 0
+
+
+/*
+ * RILE - readonly file
+ * declarecache; - declares local cache for RILE variable(s)
+ * setupcache - sets up the local RILE cache, but does not initialize it
+ * cache, uncache - caches and uncaches the local RILE;
+ * (uncache,cache) is needed around functions that advance the RILE pointer
+ * Igeteof_(f,c,s) - get a char c from f, executing statement s at EOF
+ * cachegeteof_(c,s) - Igeteof_ applied to the local RILE
+ * Iget_(f,c) - like Igeteof_, except EOF is an error
+ * cacheget_(c) - Iget_ applied to the local RILE
+ * cacheunget_(f,c,s) - read c backwards from cached f, executing s at BOF
+ * Ifileno, Ioffset_type, Irewind, Itell - analogs to stdio routines
+ *
+ * By conventions, macros whose names end in _ are statements, not expressions.
+ * Following such macros with `; else' results in a syntax error.
+ */
+
+#define maps_memory (has_map_fd || has_mmap)
+
+#if large_memory
+ typedef unsigned char const *Iptr_type;
+ typedef struct RILE {
+ Iptr_type ptr, lim;
+ unsigned char *base; /* not Iptr_type for lint's sake */
+ unsigned char *readlim;
+ int fd;
+# if maps_memory
+ void (*deallocate) P((struct RILE *));
+# else
+ FILE *stream;
+# endif
+ } RILE;
+# if maps_memory
+# define declarecache register Iptr_type ptr, lim
+# define setupcache(f) (lim = (f)->lim)
+# define Igeteof_(f,c,s) if ((f)->ptr==(f)->lim) s else (c)= *(f)->ptr++;
+# define cachegeteof_(c,s) if (ptr==lim) s else (c)= *ptr++;
+# else
+ int Igetmore P((RILE*));
+# define declarecache register Iptr_type ptr; register RILE *rRILE
+# define setupcache(f) (rRILE = (f))
+# define Igeteof_(f,c,s) if ((f)->ptr==(f)->readlim && !Igetmore(f)) s else (c)= *(f)->ptr++;
+# define cachegeteof_(c,s) if (ptr==rRILE->readlim && !Igetmore(rRILE)) s else (c)= *ptr++;
+# endif
+# define uncache(f) ((f)->ptr = ptr)
+# define cache(f) (ptr = (f)->ptr)
+# define Iget_(f,c) Igeteof_(f,c,Ieof();)
+# define cacheget_(c) cachegeteof_(c,Ieof();)
+# define cacheunget_(f,c) (c)=(--ptr)[-1];
+# define Ioffset_type size_t
+# define Itell(f) ((f)->ptr - (f)->base)
+# define Irewind(f) ((f)->ptr = (f)->base)
+# define cacheptr() ptr
+# define Ifileno(f) ((f)->fd)
+#else
+# define RILE FILE
+# define declarecache register FILE *ptr
+# define setupcache(f) (ptr = (f))
+# define uncache(f)
+# define cache(f)
+# define Igeteof_(f,c,s) {if(((c)=getc(f))==EOF){testIerror(f);if(feof(f))s}}
+# define cachegeteof_(c,s) Igeteof_(ptr,c,s)
+# define Iget_(f,c) { if (((c)=getc(f))==EOF) testIeof(f); }
+# define cacheget_(c) Iget_(ptr,c)
+# define cacheunget_(f,c) if(fseek(ptr,-2L,SEEK_CUR))Ierror();else cacheget_(c)
+# define Ioffset_type long
+# define Itell(f) ftell(f)
+# define Ifileno(f) fileno(f)
+#endif
+
+/* Print a char, but abort on write error. */
+#define aputc_(c,o) { if (putc(c,o)==EOF) testOerror(o); }
+
+/* Get a character from an RCS file, perhaps copying to a new RCS file. */
+#define GETCeof_(o,c,s) { cachegeteof_(c,s) if (o) aputc_(c,o) }
+#define GETC_(o,c) { cacheget_(c) if (o) aputc_(c,o) }
+
+
+#define WORKMODE(RCSmode, writable) (((RCSmode)&(mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH)) | ((writable)?S_IWUSR:0))
+/* computes mode of working file: same as RCSmode, but write permission */
+/* determined by writable */
+
+
+/* character classes and token codes */
+enum tokens {
+/* classes */ DELIM, DIGIT, IDCHAR, NEWLN, LETTER, Letter,
+ PERIOD, SBEGIN, SPACE, UNKN,
+/* tokens */ COLON, ID, NUM, SEMI, STRING
+};
+
+#define SDELIM '@' /* the actual character is needed for string handling*/
+/* SDELIM must be consistent with ctab[], so that ctab[SDELIM]==SBEGIN.
+ * there should be no overlap among SDELIM, KDELIM, and VDELIM
+ */
+
+#define isdigit(c) (((unsigned)(c)-'0') <= 9) /* faster than ctab[c]==DIGIT */
+
+
+
+
+
+/***************************************
+ * Data structures for the symbol table
+ ***************************************/
+
+/* Buffer of arbitrary data */
+struct buf {
+ char *string;
+ size_t size;
+};
+struct cbuf {
+ char const *string;
+ size_t size;
+};
+
+/* Hash table entry */
+struct hshentry {
+ char const * num; /* pointer to revision number (ASCIZ) */
+ char const * date; /* pointer to date of checkin */
+ char const * author; /* login of person checking in */
+ char const * lockedby; /* who locks the revision */
+ char const * state; /* state of revision (Exp by default) */
+ char const * name; /* name (if any) by which retrieved */
+ struct cbuf log; /* log message requested at checkin */
+ struct branchhead * branches; /* list of first revisions on branches*/
+ struct cbuf ig; /* ignored phrases in admin part */
+ struct cbuf igtext; /* ignored phrases in deltatext part */
+ struct hshentry * next; /* next revision on same branch */
+ struct hshentry * nexthsh; /* next revision with same hash value */
+ long insertlns;/* lines inserted (computed by rlog) */
+ long deletelns;/* lines deleted (computed by rlog) */
+ char selector; /* true if selected, false if deleted */
+};
+
+/* list of hash entries */
+struct hshentries {
+ struct hshentries *rest;
+ struct hshentry *first;
+};
+
+/* list element for branch lists */
+struct branchhead {
+ struct hshentry * hsh;
+ struct branchhead * nextbranch;
+};
+
+/* accesslist element */
+struct access {
+ char const * login;
+ struct access * nextaccess;
+};
+
+/* list element for locks */
+struct rcslock {
+ char const * login;
+ struct hshentry * delta;
+ struct rcslock * nextlock;
+};
+
+/* list element for symbolic names */
+struct assoc {
+ char const * symbol;
+ char const * num;
+ struct assoc * nextassoc;
+};
+
+
+#define mainArgs (argc,argv) int argc; char **argv;
+
+#if RCS_lint
+# define libId(name,rcsid)
+# define mainProg(name,cmd,rcsid) int name mainArgs
+#else
+# define libId(name,rcsid) char const name[] = rcsid;
+# define mainProg(n,c,i) char const Copyright[] = "Copyright 1982,1988,1989 Walter F. Tichy, Purdue CS\nCopyright 1990,1991,1992,1993,1994,1995 Paul Eggert", baseid[] = RCSBASE, cmdid[] = c; libId(n,i) int main P((int,char**)); int main mainArgs
+#endif
+
+/*
+ * Markers for keyword expansion (used in co and ident)
+ * Every byte must have class LETTER or Letter.
+ */
+#define AUTHOR "Author"
+#define DATE "Date"
+#define HEADER "Header"
+#define IDH "Id"
+#define LOCKER "Locker"
+#define LOG "Log"
+#define NAME "Name"
+#define RCSFILE "RCSfile"
+#define REVISION "Revision"
+#define SOURCE "Source"
+#define STATE "State"
+#define CVSHEADER "CVSHeader"
+#define keylength 9 /* max length of any of the above keywords */
+
+enum markers { Nomatch, Author, Date, Header, Id,
+ Locker, Log, Name, RCSfile, Revision, Source, State, CVSHeader,
+ LocalId };
+ /* This must be in the same order as rcskeys.c's Keyword[] array. */
+
+#define DELNUMFORM "\n\n%s\n%s\n"
+/* used by putdtext and scanlogtext */
+
+#define EMPTYLOG "*** empty log message ***" /* used by ci and rlog */
+
+/* main program */
+extern char const cmdid[];
+void exiterr P((void)) exiting;
+
+/* merge */
+int merge P((int,char const*,char const*const[3],char const*const[3]));
+
+/* rcsedit */
+#define ciklogsize 23 /* sizeof("checked in with -k by ") */
+extern FILE *fcopy;
+extern char const *resultname;
+extern char const ciklog[ciklogsize];
+extern int locker_expansion;
+RILE *rcswriteopen P((struct buf*,struct stat*,int));
+char const *makedirtemp P((int));
+char const *getcaller P((void));
+int addlock P((struct hshentry*,int));
+int addsymbol P((char const*,char const*,int));
+int checkaccesslist P((void));
+int chnamemod P((FILE**,char const*,char const*,int,mode_t,time_t));
+int donerewrite P((int,time_t));
+int dorewrite P((int,int));
+int expandline P((RILE*,FILE*,struct hshentry const*,int,FILE*,int));
+int findlock P((int,struct hshentry**));
+int setmtime P((char const*,time_t));
+void ORCSclose P((void));
+void ORCSerror P((void));
+void copystring P((void));
+void dirtempunlink P((void));
+void enterstring P((void));
+void finishedit P((struct hshentry const*,FILE*,int));
+void keepdirtemp P((char const*));
+void openfcopy P((FILE*));
+void snapshotedit P((FILE*));
+void xpandstring P((struct hshentry const*));
+#if has_NFS || bad_unlink
+ int un_link P((char const*));
+#else
+# define un_link(s) unlink(s)
+#endif
+#if large_memory
+ void edit_string P((void));
+# define editstring(delta) edit_string()
+#else
+ void editstring P((struct hshentry const*));
+#endif
+
+/* rcsfcmp */
+int rcsfcmp P((RILE*,struct stat const*,char const*,struct hshentry const*));
+
+/* rcsfnms */
+#define bufautobegin(b) clear_buf(b)
+#define clear_buf(b) (VOID ((b)->string = 0, (b)->size = 0))
+extern FILE *workstdout;
+extern char *workname;
+extern char const *RCSname;
+extern char const *suffixes;
+extern int fdlock;
+extern struct stat RCSstat;
+RILE *rcsreadopen P((struct buf*,struct stat*,int));
+char *bufenlarge P((struct buf*,char const**));
+char const *basefilename P((char const*));
+char const *getfullRCSname P((void));
+char const *getfullCVSname P((void));
+char const *maketemp P((int));
+char const *rcssuffix P((char const*));
+int pairnames P((int,char**,RILE*(*)P((struct buf*,struct stat*,int)),int,int));
+struct cbuf bufremember P((struct buf*,size_t));
+void bufalloc P((struct buf*,size_t));
+void bufautoend P((struct buf*));
+void bufrealloc P((struct buf*,size_t));
+void bufscat P((struct buf*,char const*));
+void bufscpy P((struct buf*,char const*));
+void tempunlink P((void));
+
+/* rcsgen */
+extern int interactiveflag;
+extern struct buf curlogbuf;
+char const *buildrevision P((struct hshentries const*,struct hshentry*,FILE*,int));
+int getcstdin P((void));
+int putdtext P((struct hshentry const*,char const*,FILE*,int));
+int ttystdin P((void));
+int yesorno P((int,char const*,...)) printf_string(2,3);
+struct cbuf cleanlogmsg P((char*,size_t));
+struct cbuf getsstdin P((char const*,char const*,char const*,struct buf*));
+void putdesc P((int,char*));
+void putdftext P((struct hshentry const*,RILE*,FILE*,int));
+
+/* rcskeep */
+extern int prevkeys;
+extern struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
+int getoldkeys P((RILE*));
+
+/* rcskeys */
+extern char const *Keyword[];
+extern enum markers LocalIdMode;
+enum markers trymatch P((char const*));
+void setRCSLocalId(char const *);
+void setIncExc(char const *);
+
+/* rcslex */
+extern FILE *foutptr;
+extern FILE *frewrite;
+extern RILE *finptr;
+extern char const *NextString;
+extern enum tokens nexttok;
+extern int hshenter;
+extern int nerror;
+extern int nextc;
+extern int quietflag;
+extern long rcsline;
+char const *getid P((void));
+void efaterror P((char const*)) exiting;
+void enfaterror P((int,char const*)) exiting;
+void fatcleanup P((int)) exiting;
+void faterror P((char const*,...)) printf_string_exiting(1,2);
+void fatserror P((char const*,...)) printf_string_exiting(1,2);
+void rcsfaterror P((char const*,...)) printf_string_exiting(1,2);
+void Ieof P((void)) exiting;
+void Ierror P((void)) exiting;
+void Oerror P((void)) exiting;
+char *checkid P((char*,int));
+char *checksym P((char*,int));
+int eoflex P((void));
+int getkeyopt P((char const*));
+int getlex P((enum tokens));
+struct cbuf getphrases P((char const*));
+struct cbuf savestring P((struct buf*));
+struct hshentry *getnum P((void));
+void Ifclose P((RILE*));
+void Izclose P((RILE**));
+void Lexinit P((void));
+void Ofclose P((FILE*));
+void Orewind P((FILE*));
+void Ozclose P((FILE**));
+void aflush P((FILE*));
+void afputc P((int,FILE*));
+void aprintf P((FILE*,char const*,...)) printf_string(2,3);
+void aputs P((char const*,FILE*));
+void checksid P((char*));
+void checkssym P((char*));
+void diagnose P((char const*,...)) printf_string(1,2);
+void eerror P((char const*));
+void eflush P((void));
+void enerror P((int,char const*));
+void error P((char const*,...)) printf_string(1,2);
+void fvfprintf P((FILE*,char const*,va_list));
+void getkey P((char const*));
+void getkeystring P((char const*));
+void nextlex P((void));
+void oflush P((void));
+void printstring P((void));
+void readstring P((void));
+void redefined P((int));
+void rcserror P((char const*,...)) printf_string(1,2);
+void rcswarn P((char const*,...)) printf_string(1,2);
+void testIerror P((FILE*));
+void testOerror P((FILE*));
+void warn P((char const*,...)) printf_string(1,2);
+void warnignore P((void));
+void workerror P((char const*,...)) printf_string(1,2);
+void workwarn P((char const*,...)) printf_string(1,2);
+#if has_madvise && has_mmap && large_memory
+ void advise_access P((RILE*,int));
+# define if_advise_access(p,f,advice) if (p) advise_access(f,advice)
+#else
+# define advise_access(f,advice)
+# define if_advise_access(p,f,advice)
+#endif
+#if large_memory && maps_memory
+ RILE *I_open P((char const*,struct stat*));
+# define Iopen(f,m,s) I_open(f,s)
+#else
+ RILE *Iopen P((char const*,char const*,struct stat*));
+#endif
+#if !large_memory
+ void testIeof P((FILE*));
+ void Irewind P((RILE*));
+#endif
+
+/* rcsmap */
+extern enum tokens const ctab[];
+
+/* rcsrev */
+char *partialno P((struct buf*,char const*,int));
+char const *namedrev P((char const*,struct hshentry*));
+char const *tiprev P((void));
+int cmpdate P((char const*,char const*));
+int cmpnum P((char const*,char const*));
+int cmpnumfld P((char const*,char const*,int));
+int compartial P((char const*,char const*,int));
+int expandsym P((char const*,struct buf*));
+int fexpandsym P((char const*,struct buf*,RILE*));
+struct hshentry *genrevs P((char const*,char const*,char const*,char const*,struct hshentries**));
+int countnumflds P((char const*));
+void getbranchno P((char const*,struct buf*));
+
+/* rcssyn */
+/* These expand modes must agree with Expand_names[] in rcssyn.c. */
+#define KEYVAL_EXPAND 0 /* -kkv `$Keyword: value $' */
+#define KEYVALLOCK_EXPAND 1 /* -kkvl `$Keyword: value locker $' */
+#define KEY_EXPAND 2 /* -kk `$Keyword$' */
+#define VAL_EXPAND 3 /* -kv `value' */
+#define OLD_EXPAND 4 /* -ko use old string, omitting expansion */
+#define BINARY_EXPAND 5 /* -kb like -ko, but use binary mode I/O */
+#define MIN_UNEXPAND OLD_EXPAND /* min value for no logical expansion */
+#define MIN_UNCHANGED_EXPAND (OPEN_O_BINARY ? BINARY_EXPAND : OLD_EXPAND)
+ /* min value guaranteed to yield an identical file */
+struct diffcmd {
+ long
+ line1, /* number of first line */
+ nlines, /* number of lines affected */
+ adprev, /* previous 'a' line1+1 or 'd' line1 */
+ dafter; /* sum of previous 'd' line1 and previous 'd' nlines */
+};
+extern char const * Dbranch;
+extern struct access * AccessList;
+extern struct assoc * Symbols;
+extern struct cbuf Comment;
+extern struct cbuf Ignored;
+extern struct rcslock *Locks;
+extern struct hshentry * Head;
+extern int Expand;
+extern int StrictLocks;
+extern int TotalDeltas;
+extern char const *const expand_names[];
+extern char const
+ Kaccess[], Kauthor[], Kbranch[], Kcomment[],
+ Kdate[], Kdesc[], Kexpand[], Khead[], Klocks[], Klog[],
+ Knext[], Kstate[], Kstrict[], Ksymbols[], Ktext[];
+void unexpected_EOF P((void)) exiting;
+int getdiffcmd P((RILE*,int,FILE*,struct diffcmd*));
+int str2expmode P((char const*));
+void getadmin P((void));
+void getdesc P((int));
+void gettree P((void));
+void ignorephrases P((char const*));
+void initdiffcmd P((struct diffcmd*));
+void putadmin P((void));
+void putstring P((FILE*,int,struct cbuf,int));
+void puttree P((struct hshentry const*,FILE*));
+
+/* rcstime */
+#define zonelenmax 9 /* maxiumum length of time zone string, e.g. "+12:34:56" */
+char const *date2str P((char const[datesize],char[datesize + zonelenmax]));
+time_t date2time P((char const[datesize]));
+void str2date P((char const*,char[datesize]));
+void time2date P((time_t,char[datesize]));
+void zone_set P((char const*));
+
+/* rcsutil */
+extern int RCSversion;
+FILE *fopenSafer P((char const*,char const*));
+char *cgetenv P((char const*));
+char *fstr_save P((char const*));
+char *str_save P((char const*));
+char const *getusername P((int));
+int fdSafer P((int));
+int getRCSINIT P((int,char**,char***));
+int run P((int,char const*,...));
+int runv P((int,char const*,char const**));
+malloc_type fremember P((malloc_type));
+malloc_type ftestalloc P((size_t));
+malloc_type testalloc P((size_t));
+malloc_type testrealloc P((malloc_type,size_t));
+#define ftalloc(T) ftnalloc(T,1)
+#define talloc(T) tnalloc(T,1)
+#if RCS_lint
+ extern malloc_type lintalloc;
+# define ftnalloc(T,n) (lintalloc = ftestalloc(sizeof(T)*(n)), (T*)0)
+# define tnalloc(T,n) (lintalloc = testalloc(sizeof(T)*(n)), (T*)0)
+# define trealloc(T,p,n) (lintalloc = testrealloc((malloc_type)0, sizeof(T)*(n)), p)
+# define tfree(p)
+#else
+# define ftnalloc(T,n) ((T*) ftestalloc(sizeof(T)*(n)))
+# define tnalloc(T,n) ((T*) testalloc(sizeof(T)*(n)))
+# define trealloc(T,p,n) ((T*) testrealloc((malloc_type)(p), sizeof(T)*(n)))
+# define tfree(p) free((malloc_type)(p))
+#endif
+time_t now P((void));
+void awrite P((char const*,size_t,FILE*));
+void fastcopy P((RILE*,FILE*));
+void ffree P((void));
+void ffree1 P((char const*));
+void setRCSversion P((char const*));
+#if has_signal
+ void catchints P((void));
+ void ignoreints P((void));
+ void restoreints P((void));
+#else
+# define catchints()
+# define ignoreints()
+# define restoreints()
+#endif
+#if has_mmap && large_memory
+# if has_NFS && mmap_signal
+ void catchmmapints P((void));
+ void readAccessFilenameBuffer P((char const*,unsigned char const*));
+# else
+# define catchmmapints()
+# endif
+#endif
+#if has_getuid
+ uid_t ruid P((void));
+# define myself(u) ((u) == ruid())
+#else
+# define myself(u) true
+#endif
+#if has_setuid
+ uid_t euid P((void));
+ void nosetid P((void));
+ void seteid P((void));
+ void setrid P((void));
+#else
+# define nosetid()
+# define seteid()
+# define setrid()
+#endif
+
+/* version */
+extern char const RCS_version_string[];
diff --git a/gnu/usr.bin/rcs/lib/rcsedit.c b/gnu/usr.bin/rcs/lib/rcsedit.c
new file mode 100644
index 0000000..dc9dd30
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsedit.c
@@ -0,0 +1,1958 @@
+/* RCS stream editor */
+
+/******************************************************************************
+ * edits the input file according to a
+ * script from stdin, generated by diff -n
+ * performs keyword expansion
+ ******************************************************************************
+ */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.19 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (dirtpname): No longer external.
+ * (do_link): Simplify logic.
+ * (finisheditline, finishedit): Replace Iseek/Itell with what they stand for.
+ * (fopen_update_truncate): Replace `#if' with `if'.
+ * (keyreplace, makedirtemp): dirlen(x) -> basefilename(x)-x.
+ *
+ * (edit_string): Fix bug: if !large_memory, a bogus trailing `@' was output
+ * at the end of incomplete lines.
+ *
+ * (keyreplace): Do not assume that seeking backwards
+ * at the start of a file will fail; on some systems it succeeds.
+ * Convert C- and Pascal-style comment starts to ` *' in comment leader.
+ *
+ * (rcswriteopen): Use fdSafer to get safer file descriptor.
+ * Open RCS file with FOPEN_RB.
+ *
+ * (chnamemod): Work around bad_NFS_rename bug; don't ignore un_link result.
+ * Fall back on chmod if fchmod fails, since it might be ENOSYS.
+ *
+ * (aflush): Move to rcslex.c.
+ *
+ * Revision 5.17 1994/03/20 04:52:58 eggert
+ * Normally calculate the $Log prefix from context, not from RCS file.
+ * Move setmtime here from rcsutil.c. Add ORCSerror. Remove lint.
+ *
+ * Revision 5.16 1993/11/03 17:42:27 eggert
+ * Add -z. Add Name keyword. If bad_unlink, ignore errno when unlink fails.
+ * Escape white space, $, and \ in keyword string file names.
+ * Don't output 2 spaces between date and time after Log.
+ *
+ * Revision 5.15 1992/07/28 16:12:44 eggert
+ * Some hosts have readlink but not ELOOP. Avoid `unsigned'.
+ * Preserve dates more systematically. Statement macro names now end in _.
+ *
+ * Revision 5.14 1992/02/17 23:02:24 eggert
+ * Add -T support.
+ *
+ * Revision 5.13 1992/01/24 18:44:19 eggert
+ * Add support for bad_chmod_close, bad_creat0.
+ *
+ * Revision 5.12 1992/01/06 02:42:34 eggert
+ * Add setmode parameter to chnamemod. addsymbol now reports changes.
+ * while (E) ; -> while (E) continue;
+ *
+ * Revision 5.11 1991/11/03 01:11:44 eggert
+ * Move the warning about link breaking to where they're actually being broken.
+ *
+ * Revision 5.10 1991/10/07 17:32:46 eggert
+ * Support piece tables even if !has_mmap. Fix rare NFS bugs.
+ *
+ * Revision 5.9 1991/09/17 19:07:40 eggert
+ * SGI readlink() yields ENXIO, not EINVAL, for nonlinks.
+ *
+ * Revision 5.8 1991/08/19 03:13:55 eggert
+ * Add piece tables, NFS bug workarounds. Catch odd filenames. Tune.
+ *
+ * Revision 5.7 1991/04/21 11:58:21 eggert
+ * Fix errno bugs. Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.6 1991/02/25 07:12:40 eggert
+ * Fix setuid bug. Support new link behavior. Work around broken "w+" fopen.
+ *
+ * Revision 5.5 1990/12/30 05:07:35 eggert
+ * Fix report of busy RCS files when !defined(O_CREAT) | !defined(O_EXCL).
+ *
+ * Revision 5.4 1990/11/01 05:03:40 eggert
+ * Permit arbitrary data in comment leaders.
+ *
+ * Revision 5.3 1990/09/11 02:41:13 eggert
+ * Tune expandline().
+ *
+ * Revision 5.2 1990/09/04 08:02:21 eggert
+ * Count RCS lines better. Improve incomplete line handling.
+ *
+ * Revision 5.1 1990/08/29 07:13:56 eggert
+ * Add -kkvl.
+ * Fix bug when getting revisions to files ending in incomplete lines.
+ * Fix bug in comment leader expansion.
+ *
+ * Revision 5.0 1990/08/22 08:12:47 eggert
+ * Don't require final newline.
+ * Don't append "checked in with -k by " to logs,
+ * so that checking in a program with -k doesn't change it.
+ * Don't generate trailing white space for empty comment leader.
+ * Remove compile-time limits; use malloc instead. Add -k, -V.
+ * Permit dates past 1999/12/31. Make lock and temp files faster and safer.
+ * Ansify and Posixate. Check diff's output.
+ *
+ * Revision 4.8 89/05/01 15:12:35 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.7 88/11/08 13:54:14 narten
+ * misplaced semicolon caused infinite loop
+ *
+ * Revision 4.6 88/08/09 19:12:45 eggert
+ * Shrink stdio code size; allow cc -R.
+ *
+ * Revision 4.5 87/12/18 11:38:46 narten
+ * Changes from the 43. version. Don't know the significance of the
+ * first change involving "rewind". Also, additional "lint" cleanup.
+ * (Guy Harris)
+ *
+ * Revision 4.4 87/10/18 10:32:21 narten
+ * Updating version numbers. Changes relative to version 1.1 actually
+ * relative to 4.1
+ *
+ * Revision 1.4 87/09/24 13:59:29 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.3 87/09/15 16:39:39 shepler
+ * added an initializatin of the variables editline and linecorr
+ * this will be done each time a file is processed.
+ * (there was an obscure bug where if co was used to retrieve multiple files
+ * it would dump)
+ * fix attributed to Roy Morris @FileNet Corp ...!felix!roy
+ *
+ * Revision 1.2 87/03/27 14:22:17 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/05/12 13:10:30 wft
+ * Added new markers Id and RCSfile; added locker to Header and Id.
+ * Overhauled expandline completely() (problem with $01234567890123456789@).
+ * Moved trymatch() and marker table to rcskeys.c.
+ *
+ * Revision 3.7 83/05/12 13:04:39 wft
+ * Added retry to expandline to resume after failed match which ended in $.
+ * Fixed truncation problem for $19chars followed by@@.
+ * Log no longer expands full path of RCS file.
+ *
+ * Revision 3.6 83/05/11 16:06:30 wft
+ * added retry to expandline to resume after failed match which ended in $.
+ * Fixed truncation problem for $19chars followed by@@.
+ *
+ * Revision 3.5 82/12/04 13:20:56 wft
+ * Added expansion of keyword Locker.
+ *
+ * Revision 3.4 82/12/03 12:26:54 wft
+ * Added line number correction in case editing does not start at the
+ * beginning of the file.
+ * Changed keyword expansion to always print a space before closing KDELIM;
+ * Expansion for Header shortened.
+ *
+ * Revision 3.3 82/11/14 14:49:30 wft
+ * removed Suffix from keyword expansion. Replaced fclose with ffclose.
+ * keyreplace() gets log message from delta, not from curlogmsg.
+ * fixed expression overflow in while(c=putc(GETC....
+ * checked nil printing.
+ *
+ * Revision 3.2 82/10/18 21:13:39 wft
+ * I added checks for write errors during the co process, and renamed
+ * expandstring() to xpandstring().
+ *
+ * Revision 3.1 82/10/13 15:52:55 wft
+ * changed type of result of getc() from char to int.
+ * made keyword expansion loop in expandline() portable to machines
+ * without sign-extension.
+ */
+
+
+#include "rcsbase.h"
+
+libId(editId, "$FreeBSD$")
+
+static void editEndsPrematurely P((void)) exiting;
+static void editLineNumberOverflow P((void)) exiting;
+static void escape_string P((FILE*,char const*));
+static void keyreplace P((enum markers,struct hshentry const*,int,RILE*,FILE*,int));
+
+FILE *fcopy; /* result file descriptor */
+char const *resultname; /* result pathname */
+int locker_expansion; /* should the locker name be appended to Id val? */
+#if !large_memory
+ static RILE *fedit; /* edit file descriptor */
+ static char const *editname; /* edit pathname */
+#endif
+static long editline; /* edit line counter; #lines before cursor */
+static long linecorr; /* #adds - #deletes in each edit run. */
+ /*used to correct editline in case file is not rewound after */
+ /* applying one delta */
+
+/* indexes into dirtpname */
+#define lockdirtp_index 0
+#define newRCSdirtp_index bad_creat0
+#define newworkdirtp_index (newRCSdirtp_index+1)
+#define DIRTEMPNAMES (newworkdirtp_index + 1)
+
+enum maker {notmade, real, effective};
+static struct buf dirtpname[DIRTEMPNAMES]; /* unlink these when done */
+static enum maker volatile dirtpmaker[DIRTEMPNAMES]; /* if these are set */
+#define lockname (dirtpname[lockdirtp_index].string)
+#define newRCSname (dirtpname[newRCSdirtp_index].string)
+
+
+#if has_NFS || bad_unlink
+ int
+un_link(s)
+ char const *s;
+/*
+ * Remove S, even if it is unwritable.
+ * Ignore unlink() ENOENT failures; NFS generates bogus ones.
+ */
+{
+# if bad_unlink
+ if (unlink(s) == 0)
+ return 0;
+ else {
+ int e = errno;
+ /*
+ * Forge ahead even if errno == ENOENT; some completely
+ * brain-damaged hosts (e.g. PCTCP 2.2) yield ENOENT
+ * even for existing unwritable files.
+ */
+ if (chmod(s, S_IWUSR) != 0) {
+ errno = e;
+ return -1;
+ }
+ }
+# endif
+# if has_NFS
+ return unlink(s)==0 || errno==ENOENT ? 0 : -1;
+# else
+ return unlink(s);
+# endif
+}
+#endif
+
+#if !has_rename
+# if !has_NFS
+# define do_link(s,t) link(s,t)
+# else
+ static int do_link P((char const*,char const*));
+ static int
+do_link(s, t)
+ char const *s, *t;
+/* Link S to T, ignoring bogus EEXIST problems due to NFS failures. */
+{
+ int r = link(s, t);
+
+ if (r != 0 && errno == EEXIST) {
+ struct stat sb, tb;
+ if (
+ stat(s, &sb) == 0 &&
+ stat(t, &tb) == 0 &&
+ same_file(sb, tb, 0)
+ )
+ r = 0;
+ errno = EEXIST;
+ }
+ return r;
+}
+# endif
+#endif
+
+
+ static void
+editEndsPrematurely()
+{
+ fatserror("edit script ends prematurely");
+}
+
+ static void
+editLineNumberOverflow()
+{
+ fatserror("edit script refers to line past end of file");
+}
+
+
+#if large_memory
+
+#if has_memmove
+# define movelines(s1, s2, n) VOID memmove(s1, s2, (n)*sizeof(Iptr_type))
+#else
+ static void movelines P((Iptr_type*,Iptr_type const*,long));
+ static void
+movelines(s1, s2, n)
+ register Iptr_type *s1;
+ register Iptr_type const *s2;
+ register long n;
+{
+ if (s1 < s2)
+ do {
+ *s1++ = *s2++;
+ } while (--n);
+ else {
+ s1 += n;
+ s2 += n;
+ do {
+ *--s1 = *--s2;
+ } while (--n);
+ }
+}
+#endif
+
+static void deletelines P((long,long));
+static void finisheditline P((RILE*,FILE*,Iptr_type,struct hshentry const*));
+static void insertline P((long,Iptr_type));
+static void snapshotline P((FILE*,Iptr_type));
+
+/*
+ * `line' contains pointers to the lines in the currently `edited' file.
+ * It is a 0-origin array that represents linelim-gapsize lines.
+ * line[0 .. gap-1] and line[gap+gapsize .. linelim-1] hold pointers to lines.
+ * line[gap .. gap+gapsize-1] contains garbage.
+ *
+ * Any @s in lines are duplicated.
+ * Lines are terminated by \n, or (for a last partial line only) by single @.
+ */
+static Iptr_type *line;
+static size_t gap, gapsize, linelim;
+
+ static void
+insertline(n, l)
+ long n;
+ Iptr_type l;
+/* Before line N, insert line L. N is 0-origin. */
+{
+ if (linelim-gapsize < n)
+ editLineNumberOverflow();
+ if (!gapsize)
+ line =
+ !linelim ?
+ tnalloc(Iptr_type, linelim = gapsize = 1024)
+ : (
+ gap = gapsize = linelim,
+ trealloc(Iptr_type, line, linelim <<= 1)
+ );
+ if (n < gap)
+ movelines(line+n+gapsize, line+n, gap-n);
+ else if (gap < n)
+ movelines(line+gap, line+gap+gapsize, n-gap);
+
+ line[n] = l;
+ gap = n + 1;
+ gapsize--;
+}
+
+ static void
+deletelines(n, nlines)
+ long n, nlines;
+/* Delete lines N through N+NLINES-1. N is 0-origin. */
+{
+ long l = n + nlines;
+ if (linelim-gapsize < l || l < n)
+ editLineNumberOverflow();
+ if (l < gap)
+ movelines(line+l+gapsize, line+l, gap-l);
+ else if (gap < n)
+ movelines(line+gap, line+gap+gapsize, n-gap);
+
+ gap = n;
+ gapsize += nlines;
+}
+
+ static void
+snapshotline(f, l)
+ register FILE *f;
+ register Iptr_type l;
+{
+ register int c;
+ do {
+ if ((c = *l++) == SDELIM && *l++ != SDELIM)
+ return;
+ aputc_(c, f)
+ } while (c != '\n');
+}
+
+ void
+snapshotedit(f)
+ FILE *f;
+/* Copy the current state of the edits to F. */
+{
+ register Iptr_type *p, *lim, *l=line;
+ for (p=l, lim=l+gap; p<lim; )
+ snapshotline(f, *p++);
+ for (p+=gapsize, lim=l+linelim; p<lim; )
+ snapshotline(f, *p++);
+}
+
+ static void
+finisheditline(fin, fout, l, delta)
+ RILE *fin;
+ FILE *fout;
+ Iptr_type l;
+ struct hshentry const *delta;
+{
+ fin->ptr = l;
+ if (expandline(fin, fout, delta, true, (FILE*)0, true) < 0)
+ faterror("finisheditline internal error");
+}
+
+ void
+finishedit(delta, outfile, done)
+ struct hshentry const *delta;
+ FILE *outfile;
+ int done;
+/*
+ * Doing expansion if DELTA is set, output the state of the edits to OUTFILE.
+ * But do nothing unless DONE is set (which means we are on the last pass).
+ */
+{
+ if (done) {
+ openfcopy(outfile);
+ outfile = fcopy;
+ if (!delta)
+ snapshotedit(outfile);
+ else {
+ register Iptr_type *p, *lim, *l = line;
+ register RILE *fin = finptr;
+ Iptr_type here = fin->ptr;
+ for (p=l, lim=l+gap; p<lim; )
+ finisheditline(fin, outfile, *p++, delta);
+ for (p+=gapsize, lim=l+linelim; p<lim; )
+ finisheditline(fin, outfile, *p++, delta);
+ fin->ptr = here;
+ }
+ }
+}
+
+/* Open a temporary NAME for output, truncating any previous contents. */
+# define fopen_update_truncate(name) fopenSafer(name, FOPEN_W_WORK)
+#else /* !large_memory */
+ static FILE * fopen_update_truncate P((char const*));
+ static FILE *
+fopen_update_truncate(name)
+ char const *name;
+{
+ if (bad_fopen_wplus && un_link(name) != 0)
+ efaterror(name);
+ return fopenSafer(name, FOPEN_WPLUS_WORK);
+}
+#endif
+
+
+ void
+openfcopy(f)
+ FILE *f;
+{
+ if (!(fcopy = f)) {
+ if (!resultname)
+ resultname = maketemp(2);
+ if (!(fcopy = fopen_update_truncate(resultname)))
+ efaterror(resultname);
+ }
+}
+
+
+#if !large_memory
+
+ static void swapeditfiles P((FILE*));
+ static void
+swapeditfiles(outfile)
+ FILE *outfile;
+/* Function: swaps resultname and editname, assigns fedit=fcopy,
+ * and rewinds fedit for reading. Set fcopy to outfile if nonnull;
+ * otherwise, set fcopy to be resultname opened for reading and writing.
+ */
+{
+ char const *tmpptr;
+
+ editline = 0; linecorr = 0;
+ Orewind(fcopy);
+ fedit = fcopy;
+ tmpptr=editname; editname=resultname; resultname=tmpptr;
+ openfcopy(outfile);
+}
+
+ void
+snapshotedit(f)
+ FILE *f;
+/* Copy the current state of the edits to F. */
+{
+ finishedit((struct hshentry *)0, (FILE*)0, false);
+ fastcopy(fedit, f);
+ Irewind(fedit);
+}
+
+ void
+finishedit(delta, outfile, done)
+ struct hshentry const *delta;
+ FILE *outfile;
+ int done;
+/* copy the rest of the edit file and close it (if it exists).
+ * if delta, perform keyword substitution at the same time.
+ * If DONE is set, we are finishing the last pass.
+ */
+{
+ register RILE *fe;
+ register FILE *fc;
+
+ fe = fedit;
+ if (fe) {
+ fc = fcopy;
+ if (delta) {
+ while (1 < expandline(fe,fc,delta,false,(FILE*)0,true))
+ ;
+ } else {
+ fastcopy(fe,fc);
+ }
+ Ifclose(fe);
+ }
+ if (!done)
+ swapeditfiles(outfile);
+}
+#endif
+
+
+
+#if large_memory
+# define copylines(upto,delta) (editline = (upto))
+#else
+ static void copylines P((long,struct hshentry const*));
+ static void
+copylines(upto, delta)
+ register long upto;
+ struct hshentry const *delta;
+/*
+ * Copy input lines editline+1..upto from fedit to fcopy.
+ * If delta, keyword expansion is done simultaneously.
+ * editline is updated. Rewinds a file only if necessary.
+ */
+{
+ register int c;
+ declarecache;
+ register FILE *fc;
+ register RILE *fe;
+
+ if (upto < editline) {
+ /* swap files */
+ finishedit((struct hshentry *)0, (FILE*)0, false);
+ /* assumes edit only during last pass, from the beginning*/
+ }
+ fe = fedit;
+ fc = fcopy;
+ if (editline < upto)
+ if (delta)
+ do {
+ if (expandline(fe,fc,delta,false,(FILE*)0,true) <= 1)
+ editLineNumberOverflow();
+ } while (++editline < upto);
+ else {
+ setupcache(fe); cache(fe);
+ do {
+ do {
+ cachegeteof_(c, editLineNumberOverflow();)
+ aputc_(c, fc)
+ } while (c != '\n');
+ } while (++editline < upto);
+ uncache(fe);
+ }
+}
+#endif
+
+
+
+ void
+xpandstring(delta)
+ struct hshentry const *delta;
+/* Function: Reads a string terminated by SDELIM from finptr and writes it
+ * to fcopy. Double SDELIM is replaced with single SDELIM.
+ * Keyword expansion is performed with data from delta.
+ * If foutptr is nonnull, the string is also copied unchanged to foutptr.
+ */
+{
+ while (1 < expandline(finptr,fcopy,delta,true,foutptr,true))
+ continue;
+}
+
+
+ void
+copystring()
+/* Function: copies a string terminated with a single SDELIM from finptr to
+ * fcopy, replacing all double SDELIM with a single SDELIM.
+ * If foutptr is nonnull, the string also copied unchanged to foutptr.
+ * editline is incremented by the number of lines copied.
+ * Assumption: next character read is first string character.
+ */
+{ register c;
+ declarecache;
+ register FILE *frew, *fcop;
+ register int amidline;
+ register RILE *fin;
+
+ fin = finptr;
+ setupcache(fin); cache(fin);
+ frew = foutptr;
+ fcop = fcopy;
+ amidline = false;
+ for (;;) {
+ GETC_(frew,c)
+ switch (c) {
+ case '\n':
+ ++editline;
+ ++rcsline;
+ amidline = false;
+ break;
+ case SDELIM:
+ GETC_(frew,c)
+ if (c != SDELIM) {
+ /* end of string */
+ nextc = c;
+ editline += amidline;
+ uncache(fin);
+ return;
+ }
+ /* fall into */
+ default:
+ amidline = true;
+ break;
+ }
+ aputc_(c,fcop)
+ }
+}
+
+
+ void
+enterstring()
+/* Like copystring, except the string is put into the edit data structure. */
+{
+#if !large_memory
+ editname = 0;
+ fedit = 0;
+ editline = linecorr = 0;
+ resultname = maketemp(1);
+ if (!(fcopy = fopen_update_truncate(resultname)))
+ efaterror(resultname);
+ copystring();
+#else
+ register int c;
+ declarecache;
+ register FILE *frew;
+ register long e, oe;
+ register int amidline, oamidline;
+ register Iptr_type optr;
+ register RILE *fin;
+
+ e = 0;
+ gap = 0;
+ gapsize = linelim;
+ fin = finptr;
+ setupcache(fin); cache(fin);
+ advise_access(fin, MADV_NORMAL);
+ frew = foutptr;
+ amidline = false;
+ for (;;) {
+ optr = cacheptr();
+ GETC_(frew,c)
+ oamidline = amidline;
+ oe = e;
+ switch (c) {
+ case '\n':
+ ++e;
+ ++rcsline;
+ amidline = false;
+ break;
+ case SDELIM:
+ GETC_(frew,c)
+ if (c != SDELIM) {
+ /* end of string */
+ nextc = c;
+ editline = e + amidline;
+ linecorr = 0;
+ uncache(fin);
+ return;
+ }
+ /* fall into */
+ default:
+ amidline = true;
+ break;
+ }
+ if (!oamidline)
+ insertline(oe, optr);
+ }
+#endif
+}
+
+
+
+
+ void
+#if large_memory
+edit_string()
+#else
+ editstring(delta)
+ struct hshentry const *delta;
+#endif
+/*
+ * Read an edit script from finptr and applies it to the edit file.
+#if !large_memory
+ * The result is written to fcopy.
+ * If delta, keyword expansion is performed simultaneously.
+ * If running out of lines in fedit, fedit and fcopy are swapped.
+ * editname is the name of the file that goes with fedit.
+#endif
+ * If foutptr is set, the edit script is also copied verbatim to foutptr.
+ * Assumes that all these files are open.
+ * resultname is the name of the file that goes with fcopy.
+ * Assumes the next input character from finptr is the first character of
+ * the edit script. Resets nextc on exit.
+ */
+{
+ int ed; /* editor command */
+ register int c;
+ declarecache;
+ register FILE *frew;
+# if !large_memory
+ register FILE *f;
+ long line_lim = LONG_MAX;
+ register RILE *fe;
+# endif
+ register long i;
+ register RILE *fin;
+# if large_memory
+ register long j;
+# endif
+ struct diffcmd dc;
+
+ editline += linecorr; linecorr=0; /*correct line number*/
+ frew = foutptr;
+ fin = finptr;
+ setupcache(fin);
+ initdiffcmd(&dc);
+ while (0 <= (ed = getdiffcmd(fin,true,frew,&dc)))
+#if !large_memory
+ if (line_lim <= dc.line1)
+ editLineNumberOverflow();
+ else
+#endif
+ if (!ed) {
+ copylines(dc.line1-1, delta);
+ /* skip over unwanted lines */
+ i = dc.nlines;
+ linecorr -= i;
+ editline += i;
+# if large_memory
+ deletelines(editline+linecorr, i);
+# else
+ fe = fedit;
+ do {
+ /*skip next line*/
+ do {
+ Igeteof_(fe, c, { if (i!=1) editLineNumberOverflow(); line_lim = dc.dafter; break; } )
+ } while (c != '\n');
+ } while (--i);
+# endif
+ } else {
+ /* Copy lines without deleting any. */
+ copylines(dc.line1, delta);
+ i = dc.nlines;
+# if large_memory
+ j = editline+linecorr;
+# endif
+ linecorr += i;
+#if !large_memory
+ f = fcopy;
+ if (delta)
+ do {
+ switch (expandline(fin,f,delta,true,frew,true)){
+ case 0: case 1:
+ if (i==1)
+ return;
+ /* fall into */
+ case -1:
+ editEndsPrematurely();
+ }
+ } while (--i);
+ else
+#endif
+ {
+ cache(fin);
+ do {
+# if large_memory
+ insertline(j++, cacheptr());
+# endif
+ for (;;) {
+ GETC_(frew, c)
+ if (c==SDELIM) {
+ GETC_(frew, c)
+ if (c!=SDELIM) {
+ if (--i)
+ editEndsPrematurely();
+ nextc = c;
+ uncache(fin);
+ return;
+ }
+ }
+# if !large_memory
+ aputc_(c, f)
+# endif
+ if (c == '\n')
+ break;
+ }
+ ++rcsline;
+ } while (--i);
+ uncache(fin);
+ }
+ }
+}
+
+
+
+/* The rest is for keyword expansion */
+
+
+
+ int
+expandline(infile, outfile, delta, delimstuffed, frewfile, dolog)
+ RILE *infile;
+ FILE *outfile, *frewfile;
+ struct hshentry const *delta;
+ int delimstuffed, dolog;
+/*
+ * Read a line from INFILE and write it to OUTFILE.
+ * Do keyword expansion with data from DELTA.
+ * If DELIMSTUFFED is true, double SDELIM is replaced with single SDELIM.
+ * If FREWFILE is set, copy the line unchanged to FREWFILE.
+ * DELIMSTUFFED must be true if FREWFILE is set.
+ * Append revision history to log only if DOLOG is set.
+ * Yields -1 if no data is copied, 0 if an incomplete line is copied,
+ * 2 if a complete line is copied; adds 1 to yield if expansion occurred.
+ */
+{
+ register c;
+ declarecache;
+ register FILE *out, *frew;
+ register char * tp;
+ register int e, ds, r;
+ char const *tlim;
+ static struct buf keyval;
+ enum markers matchresult;
+
+ setupcache(infile); cache(infile);
+ out = outfile;
+ frew = frewfile;
+ ds = delimstuffed;
+ bufalloc(&keyval, keylength+3);
+ e = 0;
+ r = -1;
+
+ for (;;) {
+ if (ds)
+ GETC_(frew, c)
+ else
+ cachegeteof_(c, goto uncache_exit;)
+ for (;;) {
+ switch (c) {
+ case SDELIM:
+ if (ds) {
+ GETC_(frew, c)
+ if (c != SDELIM) {
+ /* end of string */
+ nextc=c;
+ goto uncache_exit;
+ }
+ }
+ /* fall into */
+ default:
+ aputc_(c,out)
+ r = 0;
+ break;
+
+ case '\n':
+ rcsline += ds;
+ aputc_(c,out)
+ r = 2;
+ goto uncache_exit;
+
+ case KDELIM:
+ r = 0;
+ /* check for keyword */
+ /* first, copy a long enough string into keystring */
+ tp = keyval.string;
+ *tp++ = KDELIM;
+ for (;;) {
+ if (ds)
+ GETC_(frew, c)
+ else
+ cachegeteof_(c, goto keystring_eof;)
+ if (tp <= &keyval.string[keylength])
+ switch (ctab[c]) {
+ case LETTER: case Letter:
+ *tp++ = c;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+ *tp++ = c; *tp = '\0';
+ matchresult = trymatch(keyval.string+1);
+ if (matchresult==Nomatch) {
+ tp[-1] = 0;
+ aputs(keyval.string, out);
+ continue; /* last c handled properly */
+ }
+
+ /* Now we have a keyword terminated with a K/VDELIM */
+ if (c==VDELIM) {
+ /* try to find closing KDELIM, and replace value */
+ tlim = keyval.string + keyval.size;
+ for (;;) {
+ if (ds)
+ GETC_(frew, c)
+ else
+ cachegeteof_(c, goto keystring_eof;)
+ if (c=='\n' || c==KDELIM)
+ break;
+ *tp++ =c;
+ if (tlim <= tp)
+ tp = bufenlarge(&keyval, &tlim);
+ if (c==SDELIM && ds) { /*skip next SDELIM */
+ GETC_(frew, c)
+ if (c != SDELIM) {
+ /* end of string before closing KDELIM or newline */
+ nextc = c;
+ goto keystring_eof;
+ }
+ }
+ }
+ if (c!=KDELIM) {
+ /* couldn't find closing KDELIM -- give up */
+ *tp = 0;
+ aputs(keyval.string, out);
+ continue; /* last c handled properly */
+ }
+ }
+ /* now put out the new keyword value */
+ uncache(infile);
+ keyreplace(matchresult, delta, ds, infile, out, dolog);
+ cache(infile);
+ e = 1;
+ break;
+ }
+ break;
+ }
+ }
+
+ keystring_eof:
+ *tp = 0;
+ aputs(keyval.string, out);
+ uncache_exit:
+ uncache(infile);
+ return r + e;
+}
+
+
+ static void
+escape_string(out, s)
+ register FILE *out;
+ register char const *s;
+/* Output to OUT the string S, escaping chars that would break `ci -k'. */
+{
+ register char c;
+ for (;;)
+ switch ((c = *s++)) {
+ case 0: return;
+ case '\t': aputs("\\t", out); break;
+ case '\n': aputs("\\n", out); break;
+ case ' ': aputs("\\040", out); break;
+ case KDELIM: aputs("\\044", out); break;
+ case '\\': if (VERSION(5)<=RCSversion) {aputs("\\\\", out); break;}
+ /* fall into */
+ default: aputc_(c, out) break;
+ }
+}
+
+char const ciklog[ciklogsize] = "checked in with -k by ";
+
+ static void
+keyreplace(marker, delta, delimstuffed, infile, out, dolog)
+ enum markers marker;
+ register struct hshentry const *delta;
+ int delimstuffed;
+ RILE *infile;
+ register FILE *out;
+ int dolog;
+/* function: outputs the keyword value(s) corresponding to marker.
+ * Attributes are derived from delta.
+ */
+{
+ register char const *sp, *cp, *date;
+ register int c;
+ register size_t cs, cw, ls;
+ char const *sp1;
+ char datebuf[datesize + zonelenmax];
+ int RCSv;
+ int exp;
+
+ sp = Keyword[(int)marker];
+ exp = Expand;
+ date = delta->date;
+ RCSv = RCSversion;
+
+ if (exp != VAL_EXPAND)
+ aprintf(out, "%c%s", KDELIM, sp);
+ if (exp != KEY_EXPAND) {
+
+ if (exp != VAL_EXPAND)
+ aprintf(out, "%c%c", VDELIM,
+ marker==Log && RCSv<VERSION(5) ? '\t' : ' '
+ );
+
+ switch (marker) {
+ case Author:
+ aputs(delta->author, out);
+ break;
+ case Date:
+ aputs(date2str(date,datebuf), out);
+ break;
+ case Id:
+ case LocalId:
+ case Header:
+ case CVSHeader:
+ if (marker == Id || RCSv < VERSION(4) ||
+ (marker == LocalId && LocalIdMode == Id))
+ escape_string(out, basefilename(RCSname));
+ else if (marker == CVSHeader ||
+ (marker == LocalId && LocalIdMode == CVSHeader))
+ escape_string(out, getfullCVSname());
+ else
+ escape_string(out, getfullRCSname());
+ aprintf(out, " %s %s %s %s",
+ delta->num,
+ date2str(date, datebuf),
+ delta->author,
+ RCSv==VERSION(3) && delta->lockedby ? "Locked"
+ : delta->state
+ );
+ if (delta->lockedby)
+ if (VERSION(5) <= RCSv) {
+ if (locker_expansion || exp==KEYVALLOCK_EXPAND)
+ aprintf(out, " %s", delta->lockedby);
+ } else if (RCSv == VERSION(4))
+ aprintf(out, " Locker: %s", delta->lockedby);
+ break;
+ case Locker:
+ if (delta->lockedby)
+ if (
+ locker_expansion
+ || exp == KEYVALLOCK_EXPAND
+ || RCSv <= VERSION(4)
+ )
+ aputs(delta->lockedby, out);
+ break;
+ case Log:
+ case RCSfile:
+ escape_string(out, basefilename(RCSname));
+ break;
+ case Name:
+ if (delta->name)
+ aputs(delta->name, out);
+ break;
+ case Revision:
+ aputs(delta->num, out);
+ break;
+ case Source:
+ escape_string(out, getfullRCSname());
+ break;
+ case State:
+ aputs(delta->state, out);
+ break;
+ default:
+ break;
+ }
+ if (exp != VAL_EXPAND)
+ afputc(' ', out);
+ }
+ if (exp != VAL_EXPAND)
+ afputc(KDELIM, out);
+
+ if (marker == Log && dolog) {
+ struct buf leader;
+
+ sp = delta->log.string;
+ ls = delta->log.size;
+ if (sizeof(ciklog)-1<=ls && !memcmp(sp,ciklog,sizeof(ciklog)-1))
+ return;
+ bufautobegin(&leader);
+ if (RCSversion < VERSION(5)) {
+ cp = Comment.string;
+ cs = Comment.size;
+ } else {
+ int kdelim_found = 0;
+ Ioffset_type chars_read = Itell(infile);
+ declarecache;
+ setupcache(infile); cache(infile);
+
+ c = 0; /* Pacify `gcc -Wall'. */
+
+ /*
+ * Back up to the start of the current input line,
+ * setting CS to the number of characters before `$Log'.
+ */
+ cs = 0;
+ for (;;) {
+ if (!--chars_read)
+ goto done_backing_up;
+ cacheunget_(infile, c)
+ if (c == '\n')
+ break;
+ if (c == SDELIM && delimstuffed) {
+ if (!--chars_read)
+ break;
+ cacheunget_(infile, c)
+ if (c != SDELIM) {
+ cacheget_(c)
+ break;
+ }
+ }
+ cs += kdelim_found;
+ kdelim_found |= c==KDELIM;
+ }
+ cacheget_(c)
+ done_backing_up:;
+
+ /* Copy characters before `$Log' into LEADER. */
+ bufalloc(&leader, cs);
+ cp = leader.string;
+ for (cw = 0; cw < cs; cw++) {
+ leader.string[cw] = c;
+ if (c == SDELIM && delimstuffed)
+ cacheget_(c)
+ cacheget_(c)
+ }
+
+ /* Convert traditional C or Pascal leader to ` *'. */
+ for (cw = 0; cw < cs; cw++)
+ if (ctab[(unsigned char) cp[cw]] != SPACE)
+ break;
+ if (
+ cw+1 < cs
+ && cp[cw+1] == '*'
+ && (cp[cw] == '/' || cp[cw] == '(')
+ ) {
+ size_t i = cw+1;
+ for (;;)
+ if (++i == cs) {
+ warn(
+ "`%c* $Log' is obsolescent; use ` * $Log'.",
+ cp[cw]
+ );
+ leader.string[cw] = ' ';
+ break;
+ } else if (ctab[(unsigned char) cp[i]] != SPACE)
+ break;
+ }
+
+ /* Skip `$Log ... $' string. */
+ do {
+ cacheget_(c)
+ } while (c != KDELIM);
+ uncache(infile);
+ }
+ afputc('\n', out);
+ awrite(cp, cs, out);
+ sp1 = date2str(date, datebuf);
+ if (VERSION(5) <= RCSv) {
+ aprintf(out, "Revision %s %s %s",
+ delta->num, sp1, delta->author
+ );
+ } else {
+ /* oddity: 2 spaces between date and time, not 1 as usual */
+ sp1 = strchr(sp1, ' ');
+ aprintf(out, "Revision %s %.*s %s %s",
+ delta->num, (int)(sp1-datebuf), datebuf, sp1,
+ delta->author
+ );
+ }
+ /* Do not include state: it may change and is not updated. */
+ cw = cs;
+ if (VERSION(5) <= RCSv)
+ for (; cw && (cp[cw-1]==' ' || cp[cw-1]=='\t'); --cw)
+ continue;
+ for (;;) {
+ afputc('\n', out);
+ awrite(cp, cw, out);
+ if (!ls)
+ break;
+ --ls;
+ c = *sp++;
+ if (c != '\n') {
+ awrite(cp+cw, cs-cw, out);
+ do {
+ afputc(c,out);
+ if (!ls)
+ break;
+ --ls;
+ c = *sp++;
+ } while (c != '\n');
+ }
+ }
+ bufautoend(&leader);
+ }
+}
+
+#if has_readlink
+ static int resolve_symlink P((struct buf*));
+ static int
+resolve_symlink(L)
+ struct buf *L;
+/*
+ * If L is a symbolic link, resolve it to the name that it points to.
+ * If unsuccessful, set errno and yield -1.
+ * If it points to an existing file, yield 1.
+ * Otherwise, set errno=ENOENT and yield 0.
+ */
+{
+ char *b, a[SIZEABLE_PATH];
+ int e;
+ size_t s;
+ ssize_t r;
+ struct buf bigbuf;
+ int linkcount = MAXSYMLINKS;
+
+ b = a;
+ s = sizeof(a);
+ bufautobegin(&bigbuf);
+ while ((r = readlink(L->string,b,s)) != -1)
+ if (r == s) {
+ bufalloc(&bigbuf, s<<1);
+ b = bigbuf.string;
+ s = bigbuf.size;
+ } else if (!linkcount--) {
+# ifndef ELOOP
+ /*
+ * Some pedantic Posix 1003.1-1990 hosts have readlink
+ * but not ELOOP. Approximate ELOOP with EMLINK.
+ */
+# define ELOOP EMLINK
+# endif
+ errno = ELOOP;
+ return -1;
+ } else {
+ /* Splice symbolic link into L. */
+ b[r] = '\0';
+ L->string[
+ ROOTPATH(b) ? 0 : basefilename(L->string) - L->string
+ ] = '\0';
+ bufscat(L, b);
+ }
+ e = errno;
+ bufautoend(&bigbuf);
+ errno = e;
+ switch (e) {
+ case readlink_isreg_errno: return 1;
+ case ENOENT: return 0;
+ default: return -1;
+ }
+}
+#endif
+
+ RILE *
+rcswriteopen(RCSbuf, status, mustread)
+ struct buf *RCSbuf;
+ struct stat *status;
+ int mustread;
+/*
+ * Create the lock file corresponding to RCSBUF.
+ * Then try to open RCSBUF for reading and yield its RILE* descriptor.
+ * Put its status into *STATUS too.
+ * MUSTREAD is true if the file must already exist, too.
+ * If all goes well, discard any previously acquired locks,
+ * and set fdlock to the file descriptor of the RCS lockfile.
+ */
+{
+ register char *tp;
+ register char const *sp, *RCSpath, *x;
+ RILE *f;
+ size_t l;
+ int e, exists, fdesc, fdescSafer, r, waslocked;
+ struct buf *dirt;
+ struct stat statbuf;
+
+ waslocked = 0 <= fdlock;
+ exists =
+# if has_readlink
+ resolve_symlink(RCSbuf);
+# else
+ stat(RCSbuf->string, &statbuf) == 0 ? 1
+ : errno==ENOENT ? 0 : -1;
+# endif
+ if (exists < (mustread|waslocked))
+ /*
+ * There's an unusual problem with the RCS file;
+ * or the RCS file doesn't exist,
+ * and we must read or we already have a lock elsewhere.
+ */
+ return 0;
+
+ RCSpath = RCSbuf->string;
+ sp = basefilename(RCSpath);
+ l = sp - RCSpath;
+ dirt = &dirtpname[waslocked];
+ bufscpy(dirt, RCSpath);
+ tp = dirt->string + l;
+ x = rcssuffix(RCSpath);
+# if has_readlink
+ if (!x) {
+ error("symbolic link to non RCS file `%s'", RCSpath);
+ errno = EINVAL;
+ return 0;
+ }
+# endif
+ if (*sp == *x) {
+ error("RCS pathname `%s' incompatible with suffix `%s'", sp, x);
+ errno = EINVAL;
+ return 0;
+ }
+ /* Create a lock filename that is a function of the RCS filename. */
+ if (*x) {
+ /*
+ * The suffix is nonempty.
+ * The lock filename is the first char of of the suffix,
+ * followed by the RCS filename with last char removed. E.g.:
+ * foo,v RCS filename with suffix ,v
+ * ,foo, lock filename
+ */
+ *tp++ = *x;
+ while (*sp)
+ *tp++ = *sp++;
+ *--tp = 0;
+ } else {
+ /*
+ * The suffix is empty.
+ * The lock filename is the RCS filename
+ * with last char replaced by '_'.
+ */
+ while ((*tp++ = *sp++))
+ continue;
+ tp -= 2;
+ if (*tp == '_') {
+ error("RCS pathname `%s' ends with `%c'", RCSpath, *tp);
+ errno = EINVAL;
+ return 0;
+ }
+ *tp = '_';
+ }
+
+ sp = dirt->string;
+
+ f = 0;
+
+ /*
+ * good news:
+ * open(f, O_CREAT|O_EXCL|O_TRUNC|..., OPEN_CREAT_READONLY)
+ * is atomic according to Posix 1003.1-1990.
+ * bad news:
+ * NFS ignores O_EXCL and doesn't comply with Posix 1003.1-1990.
+ * good news:
+ * (O_TRUNC,OPEN_CREAT_READONLY) normally guarantees atomicity
+ * even with NFS.
+ * bad news:
+ * If you're root, (O_TRUNC,OPEN_CREAT_READONLY) doesn't
+ * guarantee atomicity.
+ * good news:
+ * Root-over-the-wire NFS access is rare for security reasons.
+ * This bug has never been reported in practice with RCS.
+ * So we don't worry about this bug.
+ *
+ * An even rarer NFS bug can occur when clients retry requests.
+ * This can happen in the usual case of NFS over UDP.
+ * Suppose client A releases a lock by renaming ",f," to "f,v" at
+ * about the same time that client B obtains a lock by creating ",f,",
+ * and suppose A's first rename request is delayed, so A reissues it.
+ * The sequence of events might be:
+ * A sends rename(",f,", "f,v")
+ * B sends create(",f,")
+ * A sends retry of rename(",f,", "f,v")
+ * server receives, does, and acknowledges A's first rename()
+ * A receives acknowledgment, and its RCS program exits
+ * server receives, does, and acknowledges B's create()
+ * server receives, does, and acknowledges A's retry of rename()
+ * This not only wrongly deletes B's lock, it removes the RCS file!
+ * Most NFS implementations have idempotency caches that usually prevent
+ * this scenario, but such caches are finite and can be overrun.
+ * This problem afflicts not only RCS, which uses open() and rename()
+ * to get and release locks; it also afflicts the traditional
+ * Unix method of using link() and unlink() to get and release locks,
+ * and the less traditional method of using mkdir() and rmdir().
+ * There is no easy workaround.
+ * Any new method based on lockf() seemingly would be incompatible with
+ * the old methods; besides, lockf() is notoriously buggy under NFS.
+ * Since this problem afflicts scads of Unix programs, but is so rare
+ * that nobody seems to be worried about it, we won't worry either.
+ */
+# if !open_can_creat
+# define create(f) creat(f, OPEN_CREAT_READONLY)
+# else
+# define create(f) open(f, OPEN_O_BINARY|OPEN_O_LOCK|OPEN_O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, OPEN_CREAT_READONLY)
+# endif
+
+ catchints();
+ ignoreints();
+
+ /*
+ * Create a lock file for an RCS file. This should be atomic, i.e.
+ * if two processes try it simultaneously, at most one should succeed.
+ */
+ seteid();
+ fdesc = create(sp);
+ fdescSafer = fdSafer(fdesc); /* Do it now; setrid might use stderr. */
+ e = errno;
+ setrid();
+
+ if (0 <= fdesc)
+ dirtpmaker[0] = effective;
+
+ if (fdescSafer < 0) {
+ if (e == EACCES && stat(sp,&statbuf) == 0)
+ /* The RCS file is busy. */
+ e = EEXIST;
+ } else {
+ e = ENOENT;
+ if (exists) {
+ f = Iopen(RCSpath, FOPEN_RB, status);
+ e = errno;
+ if (f && waslocked) {
+ /* Discard the previous lock in favor of this one. */
+ ORCSclose();
+ seteid();
+ r = un_link(lockname);
+ e = errno;
+ setrid();
+ if (r != 0)
+ enfaterror(e, lockname);
+ bufscpy(&dirtpname[lockdirtp_index], sp);
+ }
+ }
+ fdlock = fdescSafer;
+ }
+
+ restoreints();
+
+ errno = e;
+ return f;
+}
+
+ void
+keepdirtemp(name)
+ char const *name;
+/* Do not unlink name, either because it's not there any more,
+ * or because it has already been unlinked.
+ */
+{
+ register int i;
+ for (i=DIRTEMPNAMES; 0<=--i; )
+ if (dirtpname[i].string == name) {
+ dirtpmaker[i] = notmade;
+ return;
+ }
+ faterror("keepdirtemp");
+}
+
+ char const *
+makedirtemp(isworkfile)
+ int isworkfile;
+/*
+ * Create a unique pathname and store it into dirtpname.
+ * Because of storage in tpnames, dirtempunlink() can unlink the file later.
+ * Return a pointer to the pathname created.
+ * If ISWORKFILE is 1, put it into the working file's directory;
+ * if 0, put the unique file in RCSfile's directory.
+ */
+{
+ register char *tp, *np;
+ register size_t dl;
+ register struct buf *bn;
+ register char const *name = isworkfile ? workname : RCSname;
+# if has_mktemp
+ int fd;
+# endif
+
+ dl = basefilename(name) - name;
+ bn = &dirtpname[newRCSdirtp_index + isworkfile];
+ bufalloc(bn,
+# if has_mktemp
+ dl + 9
+# else
+ strlen(name) + 3
+# endif
+ );
+ bufscpy(bn, name);
+ np = tp = bn->string;
+ tp += dl;
+ *tp++ = '_';
+ *tp++ = '0'+isworkfile;
+ catchints();
+# if has_mktemp
+ VOID strcpy(tp, "XXXXXX");
+ fd = mkstemp(np);
+ if (fd < 0 || !*np)
+ faterror("can't make temporary pathname `%.*s_%cXXXXXX'",
+ (int)dl, name, '0'+isworkfile
+ );
+ close(fd);
+# else
+ /*
+ * Posix 1003.1-1990 has no reliable way
+ * to create a unique file in a named directory.
+ * We fudge here. If the filename is abcde,
+ * the temp filename is _Ncde where N is a digit.
+ */
+ name += dl;
+ if (*name) name++;
+ if (*name) name++;
+ VOID strcpy(tp, name);
+# endif
+ dirtpmaker[newRCSdirtp_index + isworkfile] = real;
+ return np;
+}
+
+ void
+dirtempunlink()
+/* Clean up makedirtemp() files. May be invoked by signal handler. */
+{
+ register int i;
+ enum maker m;
+
+ for (i = DIRTEMPNAMES; 0 <= --i; )
+ if ((m = dirtpmaker[i]) != notmade) {
+ if (m == effective)
+ seteid();
+ VOID un_link(dirtpname[i].string);
+ if (m == effective)
+ setrid();
+ dirtpmaker[i] = notmade;
+ }
+}
+
+
+ int
+#if has_prototypes
+chnamemod(
+ FILE **fromp, char const *from, char const *to,
+ int set_mode, mode_t mode, time_t mtime
+)
+ /* The `#if has_prototypes' is needed because mode_t might promote to int. */
+#else
+ chnamemod(fromp, from, to, set_mode, mode, mtime)
+ FILE **fromp; char const *from,*to;
+ int set_mode; mode_t mode; time_t mtime;
+#endif
+/*
+ * Rename a file (with stream pointer *FROMP) from FROM to TO.
+ * FROM already exists.
+ * If 0 < SET_MODE, change the mode to MODE, before renaming if possible.
+ * If MTIME is not -1, change its mtime to MTIME before renaming.
+ * Close and clear *FROMP before renaming it.
+ * Unlink TO if it already exists.
+ * Return -1 on error (setting errno), 0 otherwise.
+ */
+{
+ mode_t mode_while_renaming = mode;
+ int fchmod_set_mode = 0;
+
+# if bad_a_rename || bad_NFS_rename
+ struct stat st;
+ if (bad_NFS_rename || (bad_a_rename && set_mode <= 0)) {
+ if (fstat(fileno(*fromp), &st) != 0)
+ return -1;
+ if (bad_a_rename && set_mode <= 0)
+ mode = st.st_mode;
+ }
+# endif
+
+# if bad_a_rename
+ /*
+ * There's a short window of inconsistency
+ * during which the lock file is writable.
+ */
+ mode_while_renaming = mode|S_IWUSR;
+ if (mode != mode_while_renaming)
+ set_mode = 1;
+# endif
+
+# if has_fchmod
+ if (0<set_mode && fchmod(fileno(*fromp),mode_while_renaming) == 0)
+ fchmod_set_mode = set_mode;
+# endif
+ /* If bad_chmod_close, we must close before chmod. */
+ Ozclose(fromp);
+ if (fchmod_set_mode<set_mode && chmod(from, mode_while_renaming) != 0)
+ return -1;
+
+ if (setmtime(from, mtime) != 0)
+ return -1;
+
+# if !has_rename || bad_b_rename
+ /*
+ * There's a short window of inconsistency
+ * during which TO does not exist.
+ */
+ if (un_link(to) != 0 && errno != ENOENT)
+ return -1;
+# endif
+
+# if has_rename
+ if (rename(from,to) != 0 && !(has_NFS && errno==ENOENT))
+ return -1;
+# else
+ if (do_link(from,to) != 0 || un_link(from) != 0)
+ return -1;
+# endif
+
+# if bad_NFS_rename
+ {
+ /*
+ * Check whether the rename falsely reported success.
+ * A race condition can occur between the rename and the stat.
+ */
+ struct stat tostat;
+ if (stat(to, &tostat) != 0)
+ return -1;
+ if (! same_file(st, tostat, 0)) {
+ errno = EIO;
+ return -1;
+ }
+ }
+# endif
+
+# if bad_a_rename
+ if (0 < set_mode && chmod(to, mode) != 0)
+ return -1;
+# endif
+
+ return 0;
+}
+
+ int
+setmtime(file, mtime)
+ char const *file;
+ time_t mtime;
+/* Set FILE's last modified time to MTIME, but do nothing if MTIME is -1. */
+{
+ static struct utimbuf amtime; /* static so unused fields are zero */
+ if (mtime == -1)
+ return 0;
+ amtime.actime = now();
+ amtime.modtime = mtime;
+ return utime(file, &amtime);
+}
+
+
+
+ int
+findlock(delete, target)
+ int delete;
+ struct hshentry **target;
+/*
+ * Find the first lock held by caller and return a pointer
+ * to the locked delta; also removes the lock if DELETE.
+ * If one lock, put it into *TARGET.
+ * Return 0 for no locks, 1 for one, 2 for two or more.
+ */
+{
+ register struct rcslock *next, **trail, **found;
+
+ found = 0;
+ for (trail = &Locks; (next = *trail); trail = &next->nextlock)
+ if (strcmp(getcaller(), next->login) == 0) {
+ if (found) {
+ rcserror("multiple revisions locked by %s; please specify one", getcaller());
+ return 2;
+ }
+ found = trail;
+ }
+ if (!found)
+ return 0;
+ next = *found;
+ *target = next->delta;
+ if (delete) {
+ next->delta->lockedby = 0;
+ *found = next->nextlock;
+ }
+ return 1;
+}
+
+ int
+addlock(delta, verbose)
+ struct hshentry * delta;
+ int verbose;
+/*
+ * Add a lock held by caller to DELTA and yield 1 if successful.
+ * Print an error message if verbose and yield -1 if no lock is added because
+ * DELTA is locked by somebody other than caller.
+ * Return 0 if the caller already holds the lock.
+ */
+{
+ register struct rcslock *next;
+
+ for (next = Locks; next; next = next->nextlock)
+ if (cmpnum(delta->num, next->delta->num) == 0)
+ if (strcmp(getcaller(), next->login) == 0)
+ return 0;
+ else {
+ if (verbose)
+ rcserror("Revision %s is already locked by %s.",
+ delta->num, next->login
+ );
+ return -1;
+ }
+ next = ftalloc(struct rcslock);
+ delta->lockedby = next->login = getcaller();
+ next->delta = delta;
+ next->nextlock = Locks;
+ Locks = next;
+ return 1;
+}
+
+
+ int
+addsymbol(num, name, rebind)
+ char const *num, *name;
+ int rebind;
+/*
+ * Associate with revision NUM the new symbolic NAME.
+ * If NAME already exists and REBIND is set, associate NAME with NUM;
+ * otherwise, print an error message and return false;
+ * Return -1 if unsuccessful, 0 if no change, 1 if change.
+ */
+{
+ register struct assoc *next;
+
+ for (next = Symbols; next; next = next->nextassoc)
+ if (strcmp(name, next->symbol) == 0)
+ if (strcmp(next->num,num) == 0)
+ return 0;
+ else if (rebind) {
+ next->num = num;
+ return 1;
+ } else {
+ rcserror("symbolic name %s already bound to %s",
+ name, next->num
+ );
+ return -1;
+ }
+ next = ftalloc(struct assoc);
+ next->symbol = name;
+ next->num = num;
+ next->nextassoc = Symbols;
+ Symbols = next;
+ return 1;
+}
+
+
+
+ char const *
+getcaller()
+/* Get the caller's login name. */
+{
+# if has_setuid
+ return getusername(euid()!=ruid());
+# else
+ return getusername(false);
+# endif
+}
+
+
+ int
+checkaccesslist()
+/*
+ * Return true if caller is the superuser, the owner of the
+ * file, the access list is empty, or caller is on the access list.
+ * Otherwise, print an error message and return false.
+ */
+{
+ register struct access const *next;
+
+ if (!AccessList || myself(RCSstat.st_uid) || strcmp(getcaller(),"root")==0)
+ return true;
+
+ next = AccessList;
+ do {
+ if (strcmp(getcaller(), next->login) == 0)
+ return true;
+ } while ((next = next->nextaccess));
+
+ rcserror("user %s not on the access list", getcaller());
+ return false;
+}
+
+
+ int
+dorewrite(lockflag, changed)
+ int lockflag, changed;
+/*
+ * Do nothing if LOCKFLAG is zero.
+ * Prepare to rewrite an RCS file if CHANGED is positive.
+ * Stop rewriting if CHANGED is zero, because there won't be any changes.
+ * Fail if CHANGED is negative.
+ * Return 0 on success, -1 on failure.
+ */
+{
+ int r = 0, e;
+
+ if (lockflag)
+ if (changed) {
+ if (changed < 0)
+ return -1;
+ putadmin();
+ puttree(Head, frewrite);
+ aprintf(frewrite, "\n\n%s%c", Kdesc, nextc);
+ foutptr = frewrite;
+ } else {
+# if bad_creat0
+ int nr = !!frewrite, ne = 0;
+# endif
+ ORCSclose();
+ seteid();
+ ignoreints();
+# if bad_creat0
+ if (nr) {
+ nr = un_link(newRCSname);
+ ne = errno;
+ keepdirtemp(newRCSname);
+ }
+# endif
+ r = un_link(lockname);
+ e = errno;
+ keepdirtemp(lockname);
+ restoreints();
+ setrid();
+ if (r != 0)
+ enerror(e, lockname);
+# if bad_creat0
+ if (nr != 0) {
+ enerror(ne, newRCSname);
+ r = -1;
+ }
+# endif
+ }
+ return r;
+}
+
+ int
+donerewrite(changed, newRCStime)
+ int changed;
+ time_t newRCStime;
+/*
+ * Finish rewriting an RCS file if CHANGED is nonzero.
+ * Set its mode if CHANGED is positive.
+ * Set its modification time to NEWRCSTIME unless it is -1.
+ * Return 0 on success, -1 on failure.
+ */
+{
+ int r = 0, e = 0;
+# if bad_creat0
+ int lr, le;
+# endif
+
+ if (changed && !nerror) {
+ if (finptr) {
+ fastcopy(finptr, frewrite);
+ Izclose(&finptr);
+ }
+ if (1 < RCSstat.st_nlink)
+ rcswarn("breaking hard link");
+ aflush(frewrite);
+ seteid();
+ ignoreints();
+ r = chnamemod(
+ &frewrite, newRCSname, RCSname, changed,
+ RCSstat.st_mode & (mode_t)~(S_IWUSR|S_IWGRP|S_IWOTH),
+ newRCStime
+ );
+ e = errno;
+ keepdirtemp(newRCSname);
+# if bad_creat0
+ lr = un_link(lockname);
+ le = errno;
+ keepdirtemp(lockname);
+# endif
+ restoreints();
+ setrid();
+ if (r != 0) {
+ enerror(e, RCSname);
+ error("saved in %s", newRCSname);
+ }
+# if bad_creat0
+ if (lr != 0) {
+ enerror(le, lockname);
+ r = -1;
+ }
+# endif
+ }
+ return r;
+}
+
+ void
+ORCSclose()
+{
+ if (0 <= fdlock) {
+ if (close(fdlock) != 0)
+ efaterror(lockname);
+ fdlock = -1;
+ }
+ Ozclose(&frewrite);
+}
+
+ void
+ORCSerror()
+/*
+* Like ORCSclose, except we are cleaning up after an interrupt or fatal error.
+* Do not report errors, since this may loop. This is needed only because
+* some brain-damaged hosts (e.g. OS/2) cannot unlink files that are open, and
+* some nearly-Posix hosts (e.g. NFS) work better if the files are closed first.
+* This isn't a completely reliable away to work around brain-damaged hosts,
+* because of the gap between actual file opening and setting frewrite etc.,
+* but it's better than nothing.
+*/
+{
+ if (0 <= fdlock)
+ VOID close(fdlock);
+ if (frewrite)
+ /* Avoid fclose, since stdio may not be reentrant. */
+ VOID close(fileno(frewrite));
+}
diff --git a/gnu/usr.bin/rcs/lib/rcsfcmp.c b/gnu/usr.bin/rcs/lib/rcsfcmp.c
new file mode 100644
index 0000000..ef05290
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsfcmp.c
@@ -0,0 +1,354 @@
+/* Compare working files, ignoring RCS keyword strings. */
+
+/*****************************************************************************
+ * rcsfcmp()
+ * Testprogram: define FCMPTEST
+ *****************************************************************************
+ */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+
+
+
+
+/*
+ * Revision 5.14 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.13 1995/06/01 16:23:43 eggert
+ * (rcsfcmp): Add -kb support.
+ *
+ * Revision 5.12 1994/03/17 14:05:48 eggert
+ * Normally calculate the $Log prefix from context, not from RCS file.
+ * Calculate line numbers correctly even if the $Log prefix contains newlines.
+ * Remove lint.
+ *
+ * Revision 5.11 1993/11/03 17:42:27 eggert
+ * Fix yet another off-by-one error when comparing Log string expansions.
+ *
+ * Revision 5.10 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
+ *
+ * Revision 5.9 1991/10/07 17:32:46 eggert
+ * Count log lines correctly.
+ *
+ * Revision 5.8 1991/08/19 03:13:55 eggert
+ * Tune.
+ *
+ * Revision 5.7 1991/04/21 11:58:22 eggert
+ * Fix errno bug. Add MS-DOS support.
+ *
+ * Revision 5.6 1991/02/28 19:18:47 eggert
+ * Open work file at most once.
+ *
+ * Revision 5.5 1990/11/27 09:26:05 eggert
+ * Fix comment leader bug.
+ *
+ * Revision 5.4 1990/11/01 05:03:42 eggert
+ * Permit arbitrary data in logs and comment leaders.
+ *
+ * Revision 5.3 1990/09/11 02:41:15 eggert
+ * Don't ignore differences inside keyword strings if -ko is set.
+ *
+ * Revision 5.1 1990/08/29 07:13:58 eggert
+ * Clean old log messages too.
+ *
+ * Revision 5.0 1990/08/22 08:12:49 eggert
+ * Don't append "checked in with -k by " log to logs,
+ * so that checking in a program with -k doesn't change it.
+ * Ansify and Posixate. Remove lint.
+ *
+ * Revision 4.5 89/05/01 15:12:42 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.4 88/08/09 19:12:50 eggert
+ * Shrink stdio code size.
+ *
+ * Revision 4.3 87/12/18 11:40:02 narten
+ * lint cleanups (Guy Harris)
+ *
+ * Revision 4.2 87/10/18 10:33:06 narten
+ * updting version number. Changes relative to 1.1 actually relative to
+ * 4.1
+ *
+ * Revision 1.2 87/03/27 14:22:19 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/05/10 16:24:04 wft
+ * Marker matching now uses trymatch(). Marker pattern is now
+ * checked precisely.
+ *
+ * Revision 3.1 82/12/04 13:21:40 wft
+ * Initial revision.
+ *
+ */
+
+/*
+#define FCMPTEST
+*/
+/* Testprogram; prints out whether two files are identical,
+ * except for keywords
+ */
+
+#include "rcsbase.h"
+
+libId(fcmpId, "$FreeBSD$")
+
+ static int discardkeyval P((int,RILE*));
+ static int
+discardkeyval(c, f)
+ register int c;
+ register RILE *f;
+{
+ for (;;)
+ switch (c) {
+ case KDELIM:
+ case '\n':
+ return c;
+ default:
+ Igeteof_(f, c, return EOF;)
+ break;
+ }
+}
+
+ int
+rcsfcmp(xfp, xstatp, uname, delta)
+ register RILE *xfp;
+ struct stat const *xstatp;
+ char const *uname;
+ struct hshentry const *delta;
+/* Compare the files xfp and uname. Return zero
+ * if xfp has the same contents as uname and neither has keywords,
+ * otherwise -1 if they are the same ignoring keyword values,
+ * and 1 if they differ even ignoring
+ * keyword values. For the LOG-keyword, rcsfcmp skips the log message
+ * given by the parameter delta in xfp. Thus, rcsfcmp returns nonpositive
+ * if xfp contains the same as uname, with the keywords expanded.
+ * Implementation: character-by-character comparison until $ is found.
+ * If a $ is found, read in the marker keywords; if they are real keywords
+ * and identical, read in keyword value. If value is terminated properly,
+ * disregard it and optionally skip log message; otherwise, compare value.
+ */
+{
+ register int xc, uc;
+ char xkeyword[keylength+2];
+ int eqkeyvals;
+ register RILE *ufp;
+ register int xeof, ueof;
+ register char * tp;
+ register char const *sp;
+ register size_t leaderlen;
+ int result;
+ enum markers match1;
+ struct stat ustat;
+
+ if (!(ufp = Iopen(uname, FOPEN_R_WORK, &ustat))) {
+ efaterror(uname);
+ }
+ xeof = ueof = false;
+ if (MIN_UNEXPAND <= Expand) {
+ if (!(result = xstatp->st_size!=ustat.st_size)) {
+# if large_memory && maps_memory
+ result = !!memcmp(xfp->base,ufp->base,(size_t)xstatp->st_size);
+# else
+ for (;;) {
+ /* get the next characters */
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
+ if (xeof | ueof)
+ goto eof;
+ if (xc != uc)
+ goto return1;
+ }
+# endif
+ }
+ } else {
+ xc = 0;
+ uc = 0; /* Keep lint happy. */
+ leaderlen = 0;
+ result = 0;
+
+ for (;;) {
+ if (xc != KDELIM) {
+ /* get the next characters */
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
+ if (xeof | ueof)
+ goto eof;
+ } else {
+ /* try to get both keywords */
+ tp = xkeyword;
+ for (;;) {
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
+ if (xeof | ueof)
+ goto eof;
+ if (xc != uc)
+ break;
+ switch (xc) {
+ default:
+ if (xkeyword+keylength <= tp)
+ break;
+ *tp++ = xc;
+ continue;
+ case '\n': case KDELIM: case VDELIM:
+ break;
+ }
+ break;
+ }
+ if (
+ (xc==KDELIM || xc==VDELIM) && (uc==KDELIM || uc==VDELIM) &&
+ (*tp = xc, (match1 = trymatch(xkeyword)) != Nomatch)
+ ) {
+#ifdef FCMPTEST
+ VOID printf("found common keyword %s\n",xkeyword);
+#endif
+ result = -1;
+ for (;;) {
+ if (xc != uc) {
+ xc = discardkeyval(xc, xfp);
+ uc = discardkeyval(uc, ufp);
+ if ((xeof = xc==EOF) | (ueof = uc==EOF))
+ goto eof;
+ eqkeyvals = false;
+ break;
+ }
+ switch (xc) {
+ default:
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
+ if (xeof | ueof)
+ goto eof;
+ continue;
+
+ case '\n': case KDELIM:
+ eqkeyvals = true;
+ break;
+ }
+ break;
+ }
+ if (xc != uc)
+ goto return1;
+ if (xc==KDELIM) {
+ /* Skip closing KDELIM. */
+ Igeteof_(xfp, xc, xeof=true;)
+ Igeteof_(ufp, uc, ueof=true;)
+ if (xeof | ueof)
+ goto eof;
+ /* if the keyword is LOG, also skip the log message in xfp*/
+ if (match1==Log) {
+ /* first, compute the number of line feeds in log msg */
+ int lncnt;
+ size_t ls, ccnt;
+ sp = delta->log.string;
+ ls = delta->log.size;
+ if (ls<sizeof(ciklog)-1 || memcmp(sp,ciklog,sizeof(ciklog)-1)) {
+ /*
+ * This log message was inserted. Skip its header.
+ * The number of newlines to skip is
+ * 1 + (C+1)*(1+L+1), where C is the number of newlines
+ * in the comment leader, and L is the number of
+ * newlines in the log string.
+ */
+ int c1 = 1;
+ for (ccnt=Comment.size; ccnt--; )
+ c1 += Comment.string[ccnt] == '\n';
+ lncnt = 2*c1 + 1;
+ while (ls--) if (*sp++=='\n') lncnt += c1;
+ for (;;) {
+ if (xc=='\n')
+ if(--lncnt==0) break;
+ Igeteof_(xfp, xc, goto returnresult;)
+ }
+ /* skip last comment leader */
+ /* Can't just skip another line here, because there may be */
+ /* additional characters on the line (after the Log....$) */
+ ccnt = RCSversion<VERSION(5) ? Comment.size : leaderlen;
+ do {
+ Igeteof_(xfp, xc, goto returnresult;)
+ /*
+ * Read to the end of the comment leader or '\n',
+ * whatever comes first, because the leader's
+ * trailing white space was probably stripped.
+ */
+ } while (ccnt-- && (xc!='\n' || --c1));
+ }
+ }
+ } else {
+ /* both end in the same character, but not a KDELIM */
+ /* must compare string values.*/
+#ifdef FCMPTEST
+ VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
+#endif
+ if (!eqkeyvals)
+ goto return1;
+ }
+ }
+ }
+ if (xc != uc)
+ goto return1;
+ if (xc == '\n')
+ leaderlen = 0;
+ else
+ leaderlen++;
+ }
+ }
+
+ eof:
+ if (xeof==ueof)
+ goto returnresult;
+ return1:
+ result = 1;
+ returnresult:
+ Ifclose(ufp);
+ return result;
+}
+
+
+
+#ifdef FCMPTEST
+
+char const cmdid[] = "rcsfcmp";
+
+main(argc, argv)
+int argc; char *argv[];
+/* first argument: comment leader; 2nd: log message, 3rd: expanded file,
+ * 4th: unexpanded file
+ */
+{ struct hshentry delta;
+
+ Comment.string = argv[1];
+ Comment.size = strlen(argv[1]);
+ delta.log.string = argv[2];
+ delta.log.size = strlen(argv[2]);
+ if (rcsfcmp(Iopen(argv[3], FOPEN_R_WORK, (struct stat*)0), argv[4], &delta))
+ VOID printf("files are the same\n");
+ else VOID printf("files are different\n");
+}
+#endif
diff --git a/gnu/usr.bin/rcs/lib/rcsfnms.c b/gnu/usr.bin/rcs/lib/rcsfnms.c
new file mode 100644
index 0000000..00caec5
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsfnms.c
@@ -0,0 +1,1132 @@
+/* RCS filename and pathname handling */
+
+/****************************************************************************
+ * creation and deletion of /tmp temporaries
+ * pairing of RCS pathnames and working pathnames.
+ * Testprogram: define PAIRTEST
+ ****************************************************************************
+ */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+
+
+
+/*
+ * Revision 5.16 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.15 1995/06/01 16:23:43 eggert
+ * (basefilename): Renamed from basename to avoid collisions.
+ * (dirlen): Remove (for similar reasons).
+ * (rcsreadopen): Open with FOPEN_RB.
+ * (SLASHSLASH_is_SLASH): Default is 0.
+ * (getcwd): Work around bad_wait_if_SIGCHLD_ignored bug.
+ *
+ * Revision 5.14 1994/03/17 14:05:48 eggert
+ * Strip trailing SLASHes from TMPDIR; some systems need this. Remove lint.
+ *
+ * Revision 5.13 1993/11/03 17:42:27 eggert
+ * Determine whether a file name is too long indirectly,
+ * by examining inode numbers, instead of trying to use operating system
+ * primitives like pathconf, which are not trustworthy in general.
+ * File names may now hold white space or $.
+ * Do not flatten ../X in pathnames; that may yield wrong answer for symlinks.
+ * Add getabsname hook. Improve quality of diagnostics.
+ *
+ * Revision 5.12 1992/07/28 16:12:44 eggert
+ * Add .sty. .pl now implies Perl, not Prolog. Fix fdlock initialization bug.
+ * Check that $PWD is really ".". Be consistent about pathnames vs filenames.
+ *
+ * Revision 5.11 1992/02/17 23:02:25 eggert
+ * `a/RCS/b/c' is now an RCS file with an empty extension, not just `a/b/RCS/c'.
+ *
+ * Revision 5.10 1992/01/24 18:44:19 eggert
+ * Fix bug: Expand and Ignored weren't reinitialized.
+ * Avoid `char const c=ch;' compiler bug.
+ * Add support for bad_creat0.
+ *
+ * Revision 5.9 1992/01/06 02:42:34 eggert
+ * Shorten long (>31 chars) name.
+ * while (E) ; -> while (E) continue;
+ *
+ * Revision 5.8 1991/09/24 00:28:40 eggert
+ * Don't export bindex().
+ *
+ * Revision 5.7 1991/08/19 03:13:55 eggert
+ * Fix messages when rcswriteopen fails.
+ * Look in $TMP and $TEMP if $TMPDIR isn't set. Tune.
+ *
+ * Revision 5.6 1991/04/21 11:58:23 eggert
+ * Fix errno bugs. Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.5 1991/02/26 17:48:38 eggert
+ * Fix setuid bug. Support new link behavior.
+ * Define more portable getcwd().
+ *
+ * Revision 5.4 1990/11/01 05:03:43 eggert
+ * Permit arbitrary data in comment leaders.
+ *
+ * Revision 5.3 1990/09/14 22:56:16 hammer
+ * added more filename extensions and their comment leaders
+ *
+ * Revision 5.2 1990/09/04 08:02:23 eggert
+ * Fix typo when !RCSSEP.
+ *
+ * Revision 5.1 1990/08/29 07:13:59 eggert
+ * Work around buggy compilers with defective argument promotion.
+ *
+ * Revision 5.0 1990/08/22 08:12:50 eggert
+ * Ignore signals when manipulating the semaphore file.
+ * Modernize list of filename extensions.
+ * Permit paths of arbitrary length. Beware filenames beginning with "-".
+ * Remove compile-time limits; use malloc instead.
+ * Permit dates past 1999/12/31. Make lock and temp files faster and safer.
+ * Ansify and Posixate.
+ * Don't use access(). Fix test for non-regular files. Tune.
+ *
+ * Revision 4.8 89/05/01 15:09:41 narten
+ * changed getwd to not stat empty directories.
+ *
+ * Revision 4.7 88/08/09 19:12:53 eggert
+ * Fix troff macro comment leader bug; add Prolog; allow cc -R; remove lint.
+ *
+ * Revision 4.6 87/12/18 11:40:23 narten
+ * additional file types added from 4.3 BSD version, and SPARC assembler
+ * comment character added. Also, more lint cleanups. (Guy Harris)
+ *
+ * Revision 4.5 87/10/18 10:34:16 narten
+ * Updating version numbers. Changes relative to 1.1 actually relative
+ * to verion 4.3
+ *
+ * Revision 1.3 87/03/27 14:22:21 jenkins
+ * Port to suns
+ *
+ * Revision 1.2 85/06/26 07:34:28 svb
+ * Comment leader '% ' for '*.tex' files added.
+ *
+ * Revision 4.3 83/12/15 12:26:48 wft
+ * Added check for KDELIM in filenames to pairfilenames().
+ *
+ * Revision 4.2 83/12/02 22:47:45 wft
+ * Added csh, red, and sl filename suffixes.
+ *
+ * Revision 4.1 83/05/11 16:23:39 wft
+ * Added initialization of Dbranch to InitAdmin(). Canged pairfilenames():
+ * 1. added copying of path from workfile to RCS file, if RCS file is omitted;
+ * 2. added getting the file status of RCS and working files;
+ * 3. added ignoring of directories.
+ *
+ * Revision 3.7 83/05/11 15:01:58 wft
+ * Added comtable[] which pairs filename suffixes with comment leaders;
+ * updated InitAdmin() accordingly.
+ *
+ * Revision 3.6 83/04/05 14:47:36 wft
+ * fixed Suffix in InitAdmin().
+ *
+ * Revision 3.5 83/01/17 18:01:04 wft
+ * Added getwd() and rename(); these can be removed by defining
+ * V4_2BSD, since they are not needed in 4.2 bsd.
+ * Changed sys/param.h to sys/types.h.
+ *
+ * Revision 3.4 82/12/08 21:55:20 wft
+ * removed unused variable.
+ *
+ * Revision 3.3 82/11/28 20:31:37 wft
+ * Changed mktempfile() to store the generated filenames.
+ * Changed getfullRCSname() to store the file and pathname, and to
+ * delete leading "../" and "./".
+ *
+ * Revision 3.2 82/11/12 14:29:40 wft
+ * changed pairfilenames() to handle file.sfx,v; also deleted checkpathnosfx(),
+ * checksuffix(), checkfullpath(). Semaphore name generation updated.
+ * mktempfile() now checks for nil path; freefilename initialized properly.
+ * Added Suffix .h to InitAdmin. Added testprogram PAIRTEST.
+ * Moved rmsema, trysema, trydiraccess, getfullRCSname from rcsutil.c to here.
+ *
+ * Revision 3.1 82/10/18 14:51:28 wft
+ * InitAdmin() now initializes StrictLocks=STRICT_LOCKING (def. in rcsbase.h).
+ * renamed checkpath() to checkfullpath().
+ */
+
+
+#include "rcsbase.h"
+
+libId(fnmsId, "$FreeBSD$")
+
+static char const *bindex P((char const*,int));
+static int fin2open P((char const*, size_t, char const*, size_t, char const*, size_t, RILE*(*)P((struct buf*,struct stat*,int)), int));
+static int finopen P((RILE*(*)P((struct buf*,struct stat*,int)), int));
+static int suffix_matches P((char const*,char const*));
+static size_t dir_useful_len P((char const*));
+static size_t suffixlen P((char const*));
+static void InitAdmin P((void));
+
+char const *RCSname;
+char *workname;
+int fdlock;
+FILE *workstdout;
+struct stat RCSstat;
+char const *suffixes;
+
+static char const rcsdir[] = "RCS";
+#define rcslen (sizeof(rcsdir)-1)
+
+static struct buf RCSbuf, RCSb;
+static int RCSerrno;
+
+
+/* Temp names to be unlinked when done, if they are not 0. */
+#define TEMPNAMES 5 /* must be at least DIRTEMPNAMES (see rcsedit.c) */
+static char *volatile tpnames[TEMPNAMES];
+
+
+struct compair {
+ char const *suffix, *comlead;
+};
+
+/*
+* This table is present only for backwards compatibility.
+* Normally we ignore this table, and use the prefix of the `$Log' line instead.
+*/
+static struct compair const comtable[] = {
+ { "a" , "-- " }, /* Ada */
+ { "ada" , "-- " },
+ { "adb" , "-- " },
+ { "ads" , "-- " },
+ { "asm" , ";; " }, /* assembler (MS-DOS) */
+ { "bat" , ":: " }, /* batch (MS-DOS) */
+ { "body", "-- " }, /* Ada */
+ { "c" , " * " }, /* C */
+ { "c++" , "// " }, /* C++ in all its infinite guises */
+ { "cc" , "// " },
+ { "cpp" , "// " },
+ { "cxx" , "// " },
+ { "cl" , ";;; "}, /* Common Lisp */
+ { "cmd" , ":: " }, /* command (OS/2) */
+ { "cmf" , "c " }, /* CM Fortran */
+ { "cs" , " * " }, /* C* */
+ { "el" , "; " }, /* Emacs Lisp */
+ { "f" , "c " }, /* Fortran */
+ { "for" , "c " },
+ { "h" , " * " }, /* C-header */
+ { "hpp" , "// " }, /* C++ header */
+ { "hxx" , "// " },
+ { "l" , " * " }, /* lex (NOTE: franzlisp disagrees) */
+ { "lisp", ";;; "}, /* Lucid Lisp */
+ { "lsp" , ";; " }, /* Microsoft Lisp */
+ { "m" , "// " }, /* Objective C */
+ { "mac" , ";; " }, /* macro (DEC-10, MS-DOS, PDP-11, VMS, etc) */
+ { "me" , ".\\\" "}, /* troff -me */
+ { "ml" , "; " }, /* mocklisp */
+ { "mm" , ".\\\" "}, /* troff -mm */
+ { "ms" , ".\\\" "}, /* troff -ms */
+ { "p" , " * " }, /* Pascal */
+ { "pas" , " * " },
+ { "ps" , "% " }, /* PostScript */
+ { "spec", "-- " }, /* Ada */
+ { "sty" , "% " }, /* LaTeX style */
+ { "tex" , "% " }, /* TeX */
+ { "y" , " * " }, /* yacc */
+ { 0 , "# " } /* default for unknown suffix; must be last */
+};
+
+#if has_mktemp
+ static char const *tmp P((void));
+ static char const *
+tmp()
+/* Yield the name of the tmp directory. */
+{
+ static char const *s;
+ if (!s
+ && !(s = cgetenv("TMPDIR")) /* Unix tradition */
+ && !(s = cgetenv("TMP")) /* DOS tradition */
+ && !(s = cgetenv("TEMP")) /* another DOS tradition */
+ )
+ s = TMPDIR;
+ return s;
+}
+#endif
+
+ char const *
+maketemp(n)
+ int n;
+/* Create a unique pathname using n and the process id and store it
+ * into the nth slot in tpnames.
+ * Because of storage in tpnames, tempunlink() can unlink the file later.
+ * Return a pointer to the pathname created.
+ */
+{
+ char *p;
+ char const *t = tpnames[n];
+# if has_mktemp
+ int fd;
+# endif
+
+ if (t)
+ return t;
+
+ catchints();
+ {
+# if has_mktemp
+ char const *tp = tmp();
+ size_t tplen = dir_useful_len(tp);
+ p = testalloc(tplen + 10);
+ VOID sprintf(p, "%.*s%cT%cXXXXXX", (int)tplen, tp, SLASH, '0'+n);
+ fd = mkstemp(p);
+ if (fd < 0 || !*p)
+ faterror("can't make temporary pathname `%.*s%cT%cXXXXXX'",
+ (int)tplen, tp, SLASH, '0'+n
+ );
+ close(fd);
+# else
+ static char tpnamebuf[TEMPNAMES][L_tmpnam];
+ p = tpnamebuf[n];
+ if (!tmpnam(p) || !*p)
+# ifdef P_tmpdir
+ faterror("can't make temporary pathname `%s...'",P_tmpdir);
+# else
+ faterror("can't make temporary pathname");
+# endif
+# endif
+ }
+
+ tpnames[n] = p;
+ return p;
+}
+
+ void
+tempunlink()
+/* Clean up maketemp() files. May be invoked by signal handler.
+ */
+{
+ register int i;
+ register char *p;
+
+ for (i = TEMPNAMES; 0 <= --i; )
+ if ((p = tpnames[i])) {
+ VOID unlink(p);
+ /*
+ * We would tfree(p) here,
+ * but this might dump core if we're handing a signal.
+ * We're about to exit anyway, so we won't bother.
+ */
+ tpnames[i] = 0;
+ }
+}
+
+
+ static char const *
+bindex(sp, c)
+ register char const *sp;
+ register int c;
+/* Function: Finds the last occurrence of character c in string sp
+ * and returns a pointer to the character just beyond it. If the
+ * character doesn't occur in the string, sp is returned.
+ */
+{
+ register char const *r;
+ r = sp;
+ while (*sp) {
+ if (*sp++ == c) r=sp;
+ }
+ return r;
+}
+
+
+
+ static int
+suffix_matches(suffix, pattern)
+ register char const *suffix, *pattern;
+{
+ register int c;
+ if (!pattern)
+ return true;
+ for (;;)
+ switch (*suffix++ - (c = *pattern++)) {
+ case 0:
+ if (!c)
+ return true;
+ break;
+
+ case 'A'-'a':
+ if (ctab[c] == Letter)
+ break;
+ /* fall into */
+ default:
+ return false;
+ }
+}
+
+
+ static void
+InitAdmin()
+/* function: initializes an admin node */
+{
+ register char const *Suffix;
+ register int i;
+
+ Head=0; Dbranch=0; AccessList=0; Symbols=0; Locks=0;
+ StrictLocks=STRICT_LOCKING;
+
+ /* guess the comment leader from the suffix*/
+ Suffix = bindex(workname, '.');
+ if (Suffix==workname) Suffix= ""; /* empty suffix; will get default*/
+ for (i=0; !suffix_matches(Suffix,comtable[i].suffix); i++)
+ continue;
+ Comment.string = comtable[i].comlead;
+ Comment.size = strlen(comtable[i].comlead);
+ Expand = KEYVAL_EXPAND;
+ clear_buf(&Ignored);
+ Lexinit(); /* note: if !finptr, reads nothing; only initializes */
+}
+
+
+
+ void
+bufalloc(b, size)
+ register struct buf *b;
+ size_t size;
+/* Ensure *B is a name buffer of at least SIZE bytes.
+ * *B's old contents can be freed; *B's new contents are undefined.
+ */
+{
+ if (b->size < size) {
+ if (b->size)
+ tfree(b->string);
+ else
+ b->size = sizeof(malloc_type);
+ while (b->size < size)
+ b->size <<= 1;
+ b->string = tnalloc(char, b->size);
+ }
+}
+
+ void
+bufrealloc(b, size)
+ register struct buf *b;
+ size_t size;
+/* like bufalloc, except *B's old contents, if any, are preserved */
+{
+ if (b->size < size) {
+ if (!b->size)
+ bufalloc(b, size);
+ else {
+ while ((b->size <<= 1) < size)
+ continue;
+ b->string = trealloc(char, b->string, b->size);
+ }
+ }
+}
+
+ void
+bufautoend(b)
+ struct buf *b;
+/* Free an auto buffer at block exit. */
+{
+ if (b->size)
+ tfree(b->string);
+}
+
+ struct cbuf
+bufremember(b, s)
+ struct buf *b;
+ size_t s;
+/*
+ * Free the buffer B with used size S.
+ * Yield a cbuf with identical contents.
+ * The cbuf will be reclaimed when this input file is finished.
+ */
+{
+ struct cbuf cb;
+
+ if ((cb.size = s))
+ cb.string = fremember(trealloc(char, b->string, s));
+ else {
+ bufautoend(b); /* not really auto */
+ cb.string = "";
+ }
+ return cb;
+}
+
+ char *
+bufenlarge(b, alim)
+ register struct buf *b;
+ char const **alim;
+/* Make *B larger. Set *ALIM to its new limit, and yield the relocated value
+ * of its old limit.
+ */
+{
+ size_t s = b->size;
+ bufrealloc(b, s + 1);
+ *alim = b->string + b->size;
+ return b->string + s;
+}
+
+ void
+bufscat(b, s)
+ struct buf *b;
+ char const *s;
+/* Concatenate S to B's end. */
+{
+ size_t blen = b->string ? strlen(b->string) : 0;
+ bufrealloc(b, blen+strlen(s)+1);
+ VOID strcpy(b->string+blen, s);
+}
+
+ void
+bufscpy(b, s)
+ struct buf *b;
+ char const *s;
+/* Copy S into B. */
+{
+ bufalloc(b, strlen(s)+1);
+ VOID strcpy(b->string, s);
+}
+
+
+ char const *
+basefilename(p)
+ char const *p;
+/* Yield the address of the base filename of the pathname P. */
+{
+ register char const *b = p, *q = p;
+ for (;;)
+ switch (*q++) {
+ case SLASHes: b = q; break;
+ case 0: return b;
+ }
+}
+
+
+ static size_t
+suffixlen(x)
+ char const *x;
+/* Yield the length of X, an RCS pathname suffix. */
+{
+ register char const *p;
+
+ p = x;
+ for (;;)
+ switch (*p) {
+ case 0: case SLASHes:
+ return p - x;
+
+ default:
+ ++p;
+ continue;
+ }
+}
+
+ char const *
+rcssuffix(name)
+ char const *name;
+/* Yield the suffix of NAME if it is an RCS pathname, 0 otherwise. */
+{
+ char const *x, *p, *nz;
+ size_t nl, xl;
+
+ nl = strlen(name);
+ nz = name + nl;
+ x = suffixes;
+ do {
+ if ((xl = suffixlen(x))) {
+ if (xl <= nl && memcmp(p = nz-xl, x, xl) == 0)
+ return p;
+ } else
+ for (p = name; p < nz - rcslen; p++)
+ if (
+ isSLASH(p[rcslen])
+ && (p==name || isSLASH(p[-1]))
+ && memcmp(p, rcsdir, rcslen) == 0
+ )
+ return nz;
+ x += xl;
+ } while (*x++);
+ return 0;
+}
+
+ /*ARGSUSED*/ RILE *
+rcsreadopen(RCSpath, status, mustread)
+ struct buf *RCSpath;
+ struct stat *status;
+ int mustread;
+/* Open RCSPATH for reading and yield its FILE* descriptor.
+ * If successful, set *STATUS to its status.
+ * Pass this routine to pairnames() for read-only access to the file. */
+{
+ return Iopen(RCSpath->string, FOPEN_RB, status);
+}
+
+ static int
+finopen(rcsopen, mustread)
+ RILE *(*rcsopen)P((struct buf*,struct stat*,int));
+ int mustread;
+/*
+ * Use RCSOPEN to open an RCS file; MUSTREAD is set if the file must be read.
+ * Set finptr to the result and yield true if successful.
+ * RCSb holds the file's name.
+ * Set RCSbuf to the best RCS name found so far, and RCSerrno to its errno.
+ * Yield true if successful or if an unusual failure.
+ */
+{
+ int interesting, preferold;
+
+ /*
+ * We prefer an old name to that of a nonexisting new RCS file,
+ * unless we tried locking the old name and failed.
+ */
+ preferold = RCSbuf.string[0] && (mustread||0<=fdlock);
+
+ finptr = (*rcsopen)(&RCSb, &RCSstat, mustread);
+ interesting = finptr || errno!=ENOENT;
+ if (interesting || !preferold) {
+ /* Use the new name. */
+ RCSerrno = errno;
+ bufscpy(&RCSbuf, RCSb.string);
+ }
+ return interesting;
+}
+
+ static int
+fin2open(d, dlen, base, baselen, x, xlen, rcsopen, mustread)
+ char const *d, *base, *x;
+ size_t dlen, baselen, xlen;
+ RILE *(*rcsopen)P((struct buf*,struct stat*,int));
+ int mustread;
+/*
+ * D is a directory name with length DLEN (including trailing slash).
+ * BASE is a filename with length BASELEN.
+ * X is an RCS pathname suffix with length XLEN.
+ * Use RCSOPEN to open an RCS file; MUSTREAD is set if the file must be read.
+ * Yield true if successful.
+ * Try dRCS/basex first; if that fails and x is nonempty, try dbasex.
+ * Put these potential names in RCSb.
+ * Set RCSbuf to the best RCS name found so far, and RCSerrno to its errno.
+ * Yield true if successful or if an unusual failure.
+ */
+{
+ register char *p;
+
+ bufalloc(&RCSb, dlen + rcslen + 1 + baselen + xlen + 1);
+
+ /* Try dRCS/basex. */
+ VOID memcpy(p = RCSb.string, d, dlen);
+ VOID memcpy(p += dlen, rcsdir, rcslen);
+ p += rcslen;
+ *p++ = SLASH;
+ VOID memcpy(p, base, baselen);
+ VOID memcpy(p += baselen, x, xlen);
+ p[xlen] = 0;
+ if (xlen) {
+ if (finopen(rcsopen, mustread))
+ return true;
+
+ /* Try dbasex. */
+ /* Start from scratch, because finopen() may have changed RCSb. */
+ VOID memcpy(p = RCSb.string, d, dlen);
+ VOID memcpy(p += dlen, base, baselen);
+ VOID memcpy(p += baselen, x, xlen);
+ p[xlen] = 0;
+ }
+ return finopen(rcsopen, mustread);
+}
+
+ int
+pairnames(argc, argv, rcsopen, mustread, quiet)
+ int argc;
+ char **argv;
+ RILE *(*rcsopen)P((struct buf*,struct stat*,int));
+ int mustread, quiet;
+/*
+ * Pair the pathnames pointed to by argv; argc indicates
+ * how many there are.
+ * Place a pointer to the RCS pathname into RCSname,
+ * and a pointer to the pathname of the working file into workname.
+ * If both are given, and workstdout
+ * is set, a warning is printed.
+ *
+ * If the RCS file exists, places its status into RCSstat.
+ *
+ * If the RCS file exists, it is RCSOPENed for reading, the file pointer
+ * is placed into finptr, and the admin-node is read in; returns 1.
+ * If the RCS file does not exist and MUSTREAD,
+ * print an error unless QUIET and return 0.
+ * Otherwise, initialize the admin node and return -1.
+ *
+ * 0 is returned on all errors, e.g. files that are not regular files.
+ */
+{
+ static struct buf tempbuf;
+
+ register char *p, *arg, *RCS1;
+ char const *base, *RCSbase, *x;
+ int paired;
+ size_t arglen, dlen, baselen, xlen;
+
+ fdlock = -1;
+
+ if (!(arg = *argv)) return 0; /* already paired pathname */
+ if (*arg == '-') {
+ error("%s option is ignored after pathnames", arg);
+ return 0;
+ }
+
+ base = basefilename(arg);
+ paired = false;
+
+ /* first check suffix to see whether it is an RCS file or not */
+ if ((x = rcssuffix(arg)))
+ {
+ /* RCS pathname given */
+ RCS1 = arg;
+ RCSbase = base;
+ baselen = x - base;
+ if (
+ 1 < argc &&
+ !rcssuffix(workname = p = argv[1]) &&
+ baselen <= (arglen = strlen(p)) &&
+ ((p+=arglen-baselen) == workname || isSLASH(p[-1])) &&
+ memcmp(base, p, baselen) == 0
+ ) {
+ argv[1] = 0;
+ paired = true;
+ } else {
+ bufscpy(&tempbuf, base);
+ workname = p = tempbuf.string;
+ p[baselen] = 0;
+ }
+ } else {
+ /* working file given; now try to find RCS file */
+ workname = arg;
+ baselen = strlen(base);
+ /* Derive RCS pathname. */
+ if (
+ 1 < argc &&
+ (x = rcssuffix(RCS1 = argv[1])) &&
+ baselen <= x - RCS1 &&
+ ((RCSbase=x-baselen)==RCS1 || isSLASH(RCSbase[-1])) &&
+ memcmp(base, RCSbase, baselen) == 0
+ ) {
+ argv[1] = 0;
+ paired = true;
+ } else
+ RCSbase = RCS1 = 0;
+ }
+ /* Now we have a (tentative) RCS pathname in RCS1 and workname. */
+ /* Second, try to find the right RCS file */
+ if (RCSbase!=RCS1) {
+ /* a path for RCSfile is given; single RCS file to look for */
+ bufscpy(&RCSbuf, RCS1);
+ finptr = (*rcsopen)(&RCSbuf, &RCSstat, mustread);
+ RCSerrno = errno;
+ } else {
+ bufscpy(&RCSbuf, "");
+ if (RCS1)
+ /* RCS filename was given without path. */
+ VOID fin2open(arg, (size_t)0, RCSbase, baselen,
+ x, strlen(x), rcsopen, mustread
+ );
+ else {
+ /* No RCS pathname was given. */
+ /* Try each suffix in turn. */
+ dlen = base-arg;
+ x = suffixes;
+ while (! fin2open(arg, dlen, base, baselen,
+ x, xlen=suffixlen(x), rcsopen, mustread
+ )) {
+ x += xlen;
+ if (!*x++)
+ break;
+ }
+ }
+ }
+ RCSname = p = RCSbuf.string;
+ if (finptr) {
+ if (!S_ISREG(RCSstat.st_mode)) {
+ error("%s isn't a regular file -- ignored", p);
+ return 0;
+ }
+ Lexinit(); getadmin();
+ } else {
+ if (RCSerrno!=ENOENT || mustread || fdlock<0) {
+ if (RCSerrno == EEXIST)
+ error("RCS file %s is in use", p);
+ else if (!quiet || RCSerrno!=ENOENT)
+ enerror(RCSerrno, p);
+ return 0;
+ }
+ InitAdmin();
+ };
+
+ if (paired && workstdout)
+ workwarn("Working file ignored due to -p option");
+
+ prevkeys = false;
+ return finptr ? 1 : -1;
+}
+
+
+ char const *
+getfullRCSname()
+/*
+ * Return a pointer to the full pathname of the RCS file.
+ * Remove leading `./'.
+ */
+{
+ if (ROOTPATH(RCSname)) {
+ return RCSname;
+ } else {
+ static struct buf rcsbuf;
+# if needs_getabsname
+ bufalloc(&rcsbuf, SIZEABLE_PATH + 1);
+ while (getabsname(RCSname, rcsbuf.string, rcsbuf.size) != 0)
+ if (errno == ERANGE)
+ bufalloc(&rcsbuf, rcsbuf.size<<1);
+ else
+ efaterror("getabsname");
+# else
+ static char const *wdptr;
+ static struct buf wdbuf;
+ static size_t wdlen;
+
+ register char const *r;
+ register size_t dlen;
+ register char *d;
+ register char const *wd;
+
+ if (!(wd = wdptr)) {
+ /* Get working directory for the first time. */
+ char *PWD = cgetenv("PWD");
+ struct stat PWDstat, dotstat;
+ if (! (
+ (d = PWD) &&
+ ROOTPATH(PWD) &&
+ stat(PWD, &PWDstat) == 0 &&
+ stat(".", &dotstat) == 0 &&
+ same_file(PWDstat, dotstat, 1)
+ )) {
+ bufalloc(&wdbuf, SIZEABLE_PATH + 1);
+# if has_getcwd || !has_getwd
+ while (!(d = getcwd(wdbuf.string, wdbuf.size)))
+ if (errno == ERANGE)
+ bufalloc(&wdbuf, wdbuf.size<<1);
+ else if ((d = PWD))
+ break;
+ else
+ efaterror("getcwd");
+# else
+ d = getwd(wdbuf.string);
+ if (!d && !(d = PWD))
+ efaterror("getwd");
+# endif
+ }
+ wdlen = dir_useful_len(d);
+ d[wdlen] = 0;
+ wdptr = wd = d;
+ }
+ /*
+ * Remove leading `./'s from RCSname.
+ * Do not try to handle `../', since removing it may yield
+ * the wrong answer in the presence of symbolic links.
+ */
+ for (r = RCSname; r[0]=='.' && isSLASH(r[1]); r += 2)
+ /* `.////' is equivalent to `./'. */
+ while (isSLASH(r[2]))
+ r++;
+ /* Build full pathname. */
+ dlen = wdlen;
+ bufalloc(&rcsbuf, dlen + strlen(r) + 2);
+ d = rcsbuf.string;
+ VOID memcpy(d, wd, dlen);
+ d += dlen;
+ *d++ = SLASH;
+ VOID strcpy(d, r);
+# endif
+ return rcsbuf.string;
+ }
+}
+
+/* Derived from code from the XFree86 project */
+ char const *
+getfullCVSname()
+/* Function: returns a pointer to the path name of the RCS file with the
+ * CVSROOT part stripped off, and with 'Attic/' stripped off (if present).
+ */
+{
+
+#define ATTICDIR "/Attic"
+
+ char const *namebuf = getfullRCSname();
+ char *cvsroot = cgetenv("CVSROOT");
+ int cvsrootlen;
+ char *c = NULL;
+ int alen = strlen(ATTICDIR);
+
+ if ((c = strrchr(namebuf, '/')) != NULL) {
+ if (namebuf - c >= alen) {
+ if (!strncmp(c - alen, ATTICDIR, alen)) {
+ while(*c != '\0') {
+ *(c - alen) = *c;
+ c++;
+ }
+ *(c - alen) = '\0';
+ }
+ }
+ }
+
+ if (!cvsroot)
+ return(namebuf);
+ else
+ {
+ cvsrootlen = strlen(cvsroot);
+ if (!strncmp(namebuf, cvsroot, cvsrootlen) &&
+ namebuf[cvsrootlen] == '/')
+ return(namebuf + cvsrootlen + 1);
+ else
+ return(namebuf);
+ }
+}
+
+ static size_t
+dir_useful_len(d)
+ char const *d;
+/*
+* D names a directory; yield the number of characters of D's useful part.
+* To create a file in D, append a SLASH and a file name to D's useful part.
+* Ignore trailing slashes if possible; not only are they ugly,
+* but some non-Posix systems misbehave unless the slashes are omitted.
+*/
+{
+# ifndef SLASHSLASH_is_SLASH
+# define SLASHSLASH_is_SLASH 0
+# endif
+ size_t dlen = strlen(d);
+ if (!SLASHSLASH_is_SLASH && dlen==2 && isSLASH(d[0]) && isSLASH(d[1]))
+ --dlen;
+ else
+ while (dlen && isSLASH(d[dlen-1]))
+ --dlen;
+ return dlen;
+}
+
+#ifndef isSLASH
+ int
+isSLASH(c)
+ int c;
+{
+ switch (c) {
+ case SLASHes:
+ return true;
+ default:
+ return false;
+ }
+}
+#endif
+
+
+#if !has_getcwd && !has_getwd
+
+ char *
+getcwd(path, size)
+ char *path;
+ size_t size;
+{
+ static char const usrbinpwd[] = "/usr/bin/pwd";
+# define binpwd (usrbinpwd+4)
+
+ register FILE *fp;
+ register int c;
+ register char *p, *lim;
+ int closeerrno, closeerror, e, fd[2], readerror, toolong, wstatus;
+ pid_t child;
+
+ if (!size) {
+ errno = EINVAL;
+ return 0;
+ }
+ if (pipe(fd) != 0)
+ return 0;
+# if bad_wait_if_SIGCHLD_ignored
+# ifndef SIGCHLD
+# define SIGCHLD SIGCLD
+# endif
+ VOID signal(SIGCHLD, SIG_DFL);
+# endif
+ if (!(child = vfork())) {
+ if (
+ close(fd[0]) == 0 &&
+ (fd[1] == STDOUT_FILENO ||
+# ifdef F_DUPFD
+ (VOID close(STDOUT_FILENO),
+ fcntl(fd[1], F_DUPFD, STDOUT_FILENO))
+# else
+ dup2(fd[1], STDOUT_FILENO)
+# endif
+ == STDOUT_FILENO &&
+ close(fd[1]) == 0
+ )
+ ) {
+ VOID close(STDERR_FILENO);
+ VOID execl(binpwd, binpwd, (char *)0);
+ VOID execl(usrbinpwd, usrbinpwd, (char *)0);
+ }
+ _exit(EXIT_FAILURE);
+ }
+ e = errno;
+ closeerror = close(fd[1]);
+ closeerrno = errno;
+ fp = 0;
+ readerror = toolong = wstatus = 0;
+ p = path;
+ if (0 <= child) {
+ fp = fdopen(fd[0], "r");
+ e = errno;
+ if (fp) {
+ lim = p + size;
+ for (p = path; ; *p++ = c) {
+ if ((c=getc(fp)) < 0) {
+ if (feof(fp))
+ break;
+ if (ferror(fp)) {
+ readerror = 1;
+ e = errno;
+ break;
+ }
+ }
+ if (p == lim) {
+ toolong = 1;
+ break;
+ }
+ }
+ }
+# if has_waitpid
+ if (waitpid(child, &wstatus, 0) < 0)
+ wstatus = 1;
+# else
+ {
+ pid_t w;
+ do {
+ if ((w = wait(&wstatus)) < 0) {
+ wstatus = 1;
+ break;
+ }
+ } while (w != child);
+ }
+# endif
+ }
+ if (!fp) {
+ VOID close(fd[0]);
+ errno = e;
+ return 0;
+ }
+ if (fclose(fp) != 0)
+ return 0;
+ if (readerror) {
+ errno = e;
+ return 0;
+ }
+ if (closeerror) {
+ errno = closeerrno;
+ return 0;
+ }
+ if (toolong) {
+ errno = ERANGE;
+ return 0;
+ }
+ if (wstatus || p == path || *--p != '\n') {
+ errno = EACCES;
+ return 0;
+ }
+ *p = '\0';
+ return path;
+}
+#endif
+
+
+#ifdef PAIRTEST
+/* test program for pairnames() and getfullRCSname() */
+
+char const cmdid[] = "pair";
+
+main(argc, argv)
+int argc; char *argv[];
+{
+ int result;
+ int initflag;
+ quietflag = initflag = false;
+
+ while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
+ switch ((*argv)[1]) {
+
+ case 'p': workstdout = stdout;
+ break;
+ case 'i': initflag=true;
+ break;
+ case 'q': quietflag=true;
+ break;
+ default: error("unknown option: %s", *argv);
+ break;
+ }
+ }
+
+ do {
+ RCSname = workname = 0;
+ result = pairnames(argc,argv,rcsreadopen,!initflag,quietflag);
+ if (result!=0) {
+ diagnose("RCS pathname: %s; working pathname: %s\nFull RCS pathname: %s\n",
+ RCSname, workname, getfullRCSname()
+ );
+ }
+ switch (result) {
+ case 0: continue; /* already paired file */
+
+ case 1: if (initflag) {
+ rcserror("already exists");
+ } else {
+ diagnose("RCS file %s exists\n", RCSname);
+ }
+ Ifclose(finptr);
+ break;
+
+ case -1:diagnose("RCS file doesn't exist\n");
+ break;
+ }
+
+ } while (++argv, --argc>=1);
+
+}
+
+ void
+exiterr()
+{
+ dirtempunlink();
+ tempunlink();
+ _exit(EXIT_FAILURE);
+}
+#endif
diff --git a/gnu/usr.bin/rcs/lib/rcsgen.c b/gnu/usr.bin/rcs/lib/rcsgen.c
new file mode 100644
index 0000000..35d8702
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsgen.c
@@ -0,0 +1,681 @@
+/* Generate RCS revisions. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.16 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.15 1995/06/01 16:23:43 eggert
+ * (putadmin): Open RCS file with FOPEN_WB.
+ *
+ * Revision 5.14 1994/03/17 14:05:48 eggert
+ * Work around SVR4 stdio performance bug.
+ * Flush stderr after prompt. Remove lint.
+ *
+ * Revision 5.13 1993/11/03 17:42:27 eggert
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.12 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
+ * Be consistent about pathnames vs filenames.
+ *
+ * Revision 5.11 1992/01/24 18:44:19 eggert
+ * Move put routines here from rcssyn.c.
+ * Add support for bad_creat0.
+ *
+ * Revision 5.10 1991/10/07 17:32:46 eggert
+ * Fix log bugs, e.g. ci -t/dev/null when has_mmap.
+ *
+ * Revision 5.9 1991/09/10 22:15:46 eggert
+ * Fix test for redirected stdin.
+ *
+ * Revision 5.8 1991/08/19 03:13:55 eggert
+ * Add piece tables. Tune.
+ *
+ * Revision 5.7 1991/04/21 11:58:24 eggert
+ * Add MS-DOS support.
+ *
+ * Revision 5.6 1990/12/27 19:54:26 eggert
+ * Fix bug: rcs -t inserted \n, making RCS file grow.
+ *
+ * Revision 5.5 1990/12/04 05:18:45 eggert
+ * Use -I for prompts and -q for diagnostics.
+ *
+ * Revision 5.4 1990/11/01 05:03:47 eggert
+ * Add -I and new -t behavior. Permit arbitrary data in logs.
+ *
+ * Revision 5.3 1990/09/21 06:12:43 hammer
+ * made putdesc() treat stdin the same whether or not it was from a terminal
+ * by making it recognize that a single '.' was then end of the
+ * description always
+ *
+ * Revision 5.2 1990/09/04 08:02:25 eggert
+ * Fix `co -p1.1 -ko' bug. Standardize yes-or-no procedure.
+ *
+ * Revision 5.1 1990/08/29 07:14:01 eggert
+ * Clean old log messages too.
+ *
+ * Revision 5.0 1990/08/22 08:12:52 eggert
+ * Remove compile-time limits; use malloc instead.
+ * Ansify and Posixate.
+ *
+ * Revision 4.7 89/05/01 15:12:49 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.6 88/08/28 14:59:10 eggert
+ * Shrink stdio code size; allow cc -R; remove lint; isatty() -> ttystdin()
+ *
+ * Revision 4.5 87/12/18 11:43:25 narten
+ * additional lint cleanups, and a bug fix from the 4.3BSD version that
+ * keeps "ci" from sticking a '\377' into the description if you run it
+ * with a zero-length file as the description. (Guy Harris)
+ *
+ * Revision 4.4 87/10/18 10:35:10 narten
+ * Updating version numbers. Changes relative to 1.1 actually relative to
+ * 4.2
+ *
+ * Revision 1.3 87/09/24 13:59:51 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:27 jenkins
+ * Port to suns
+ *
+ * Revision 4.2 83/12/02 23:01:39 wft
+ * merged 4.1 and 3.3.1.1 (clearerr(stdin)).
+ *
+ * Revision 4.1 83/05/10 16:03:33 wft
+ * Changed putamin() to abort if trying to reread redirected stdin.
+ * Fixed getdesc() to output a prompt on initial newline.
+ *
+ * Revision 3.3.1.1 83/10/19 04:21:51 lepreau
+ * Added clearerr(stdin) for re-reading description from stdin.
+ *
+ * Revision 3.3 82/11/28 21:36:49 wft
+ * 4.2 prerelease
+ *
+ * Revision 3.3 82/11/28 21:36:49 wft
+ * Replaced ferror() followed by fclose() with ffclose().
+ * Putdesc() now suppresses the prompts if stdin
+ * is not a terminal. A pointer to the current log message is now
+ * inserted into the corresponding delta, rather than leaving it in a
+ * global variable.
+ *
+ * Revision 3.2 82/10/18 21:11:26 wft
+ * I added checks for write errors during editing, and improved
+ * the prompt on putdesc().
+ *
+ * Revision 3.1 82/10/13 15:55:09 wft
+ * corrected type of variables assigned to by getc (char --> int)
+ */
+
+
+
+
+#include "rcsbase.h"
+
+libId(genId, "$FreeBSD$")
+
+int interactiveflag; /* Should we act as if stdin is a tty? */
+struct buf curlogbuf; /* buffer for current log message */
+
+enum stringwork { enter, copy, edit, expand, edit_expand };
+
+static void putdelta P((struct hshentry const*,FILE*));
+static void scandeltatext P((struct hshentry*,enum stringwork,int));
+
+
+
+
+ char const *
+buildrevision(deltas, target, outfile, expandflag)
+ struct hshentries const *deltas;
+ struct hshentry *target;
+ FILE *outfile;
+ int expandflag;
+/* Function: Generates the revision given by target
+ * by retrieving all deltas given by parameter deltas and combining them.
+ * If outfile is set, the revision is output to it,
+ * otherwise written into a temporary file.
+ * Temporary files are allocated by maketemp().
+ * if expandflag is set, keyword expansion is performed.
+ * Return 0 if outfile is set, the name of the temporary file otherwise.
+ *
+ * Algorithm: Copy initial revision unchanged. Then edit all revisions but
+ * the last one into it, alternating input and output files (resultname and
+ * editname). The last revision is then edited in, performing simultaneous
+ * keyword substitution (this saves one extra pass).
+ * All this simplifies if only one revision needs to be generated,
+ * or no keyword expansion is necessary, or if output goes to stdout.
+ */
+{
+ if (deltas->first == target) {
+ /* only latest revision to generate */
+ openfcopy(outfile);
+ scandeltatext(target, expandflag?expand:copy, true);
+ if (outfile)
+ return 0;
+ else {
+ Ozclose(&fcopy);
+ return resultname;
+ }
+ } else {
+ /* several revisions to generate */
+ /* Get initial revision without keyword expansion. */
+ scandeltatext(deltas->first, enter, false);
+ while ((deltas=deltas->rest)->rest) {
+ /* do all deltas except last one */
+ scandeltatext(deltas->first, edit, false);
+ }
+ if (expandflag || outfile) {
+ /* first, get to beginning of file*/
+ finishedit((struct hshentry*)0, outfile, false);
+ }
+ scandeltatext(target, expandflag?edit_expand:edit, true);
+ finishedit(
+ expandflag ? target : (struct hshentry*)0,
+ outfile, true
+ );
+ if (outfile)
+ return 0;
+ Ozclose(&fcopy);
+ return resultname;
+ }
+}
+
+
+
+ static void
+scandeltatext(delta, func, needlog)
+ struct hshentry *delta;
+ enum stringwork func;
+ int needlog;
+/* Function: Scans delta text nodes up to and including the one given
+ * by delta. For the one given by delta, the log message is saved into
+ * delta->log if needlog is set; func specifies how to handle the text.
+ * Similarly, if needlog, delta->igtext is set to the ignored phrases.
+ * Assumes the initial lexeme must be read in first.
+ * Does not advance nexttok after it is finished.
+ */
+{
+ struct hshentry const *nextdelta;
+ struct cbuf cb;
+
+ for (;;) {
+ if (eoflex())
+ fatserror("can't find delta for revision %s", delta->num);
+ nextlex();
+ if (!(nextdelta=getnum())) {
+ fatserror("delta number corrupted");
+ }
+ getkeystring(Klog);
+ if (needlog && delta==nextdelta) {
+ cb = savestring(&curlogbuf);
+ delta->log = cleanlogmsg(curlogbuf.string, cb.size);
+ nextlex();
+ delta->igtext = getphrases(Ktext);
+ } else {readstring();
+ ignorephrases(Ktext);
+ }
+ getkeystring(Ktext);
+
+ if (delta==nextdelta)
+ break;
+ readstring(); /* skip over it */
+
+ }
+ switch (func) {
+ case enter: enterstring(); break;
+ case copy: copystring(); break;
+ case expand: xpandstring(delta); break;
+ case edit: editstring((struct hshentry *)0); break;
+ case edit_expand: editstring(delta); break;
+ }
+}
+
+ struct cbuf
+cleanlogmsg(m, s)
+ char *m;
+ size_t s;
+{
+ register char *t = m;
+ register char const *f = t;
+ struct cbuf r;
+ while (s) {
+ --s;
+ if ((*t++ = *f++) == '\n')
+ while (m < --t)
+ if (t[-1]!=' ' && t[-1]!='\t') {
+ *t++ = '\n';
+ break;
+ }
+ }
+ while (m < t && (t[-1]==' ' || t[-1]=='\t' || t[-1]=='\n'))
+ --t;
+ r.string = m;
+ r.size = t - m;
+ return r;
+}
+
+
+int ttystdin()
+{
+ static int initialized;
+ if (!initialized) {
+ if (!interactiveflag)
+ interactiveflag = isatty(STDIN_FILENO);
+ initialized = true;
+ }
+ return interactiveflag;
+}
+
+ int
+getcstdin()
+{
+ register FILE *in;
+ register int c;
+
+ in = stdin;
+ if (feof(in) && ttystdin())
+ clearerr(in);
+ c = getc(in);
+ if (c == EOF) {
+ testIerror(in);
+ if (feof(in) && ttystdin())
+ afputc('\n',stderr);
+ }
+ return c;
+}
+
+#if has_prototypes
+ int
+yesorno(int default_answer, char const *question, ...)
+#else
+ /*VARARGS2*/ int
+ yesorno(default_answer, question, va_alist)
+ int default_answer; char const *question; va_dcl
+#endif
+{
+ va_list args;
+ register int c, r;
+ if (!quietflag && ttystdin()) {
+ oflush();
+ vararg_start(args, question);
+ fvfprintf(stderr, question, args);
+ va_end(args);
+ eflush();
+ r = c = getcstdin();
+ while (c!='\n' && !feof(stdin))
+ c = getcstdin();
+ if (r=='y' || r=='Y')
+ return true;
+ if (r=='n' || r=='N')
+ return false;
+ }
+ return default_answer;
+}
+
+
+ void
+putdesc(textflag, textfile)
+ int textflag;
+ char *textfile;
+/* Function: puts the descriptive text into file frewrite.
+ * if finptr && !textflag, the text is copied from the old description.
+ * Otherwise, if textfile, the text is read from that
+ * file, or from stdin, if !textfile.
+ * A textfile with a leading '-' is treated as a string, not a pathname.
+ * If finptr, the old descriptive text is discarded.
+ * Always clears foutptr.
+ */
+{
+ static struct buf desc;
+ static struct cbuf desclean;
+
+ register FILE *txt;
+ register int c;
+ register FILE * frew;
+ register char *p;
+ register size_t s;
+ char const *plim;
+
+ frew = frewrite;
+ if (finptr && !textflag) {
+ /* copy old description */
+ aprintf(frew, "\n\n%s%c", Kdesc, nextc);
+ foutptr = frewrite;
+ getdesc(false);
+ foutptr = 0;
+ } else {
+ foutptr = 0;
+ /* get new description */
+ if (finptr) {
+ /*skip old description*/
+ getdesc(false);
+ }
+ aprintf(frew,"\n\n%s\n%c",Kdesc,SDELIM);
+ if (!textfile)
+ desclean = getsstdin(
+ "t-", "description",
+ "NOTE: This is NOT the log message!\n", &desc
+ );
+ else if (!desclean.string) {
+ if (*textfile == '-') {
+ p = textfile + 1;
+ s = strlen(p);
+ } else {
+ if (!(txt = fopenSafer(textfile, "r")))
+ efaterror(textfile);
+ bufalloc(&desc, 1);
+ p = desc.string;
+ plim = p + desc.size;
+ for (;;) {
+ if ((c=getc(txt)) == EOF) {
+ testIerror(txt);
+ if (feof(txt))
+ break;
+ }
+ if (plim <= p)
+ p = bufenlarge(&desc, &plim);
+ *p++ = c;
+ }
+ if (fclose(txt) != 0)
+ Ierror();
+ s = p - desc.string;
+ p = desc.string;
+ }
+ desclean = cleanlogmsg(p, s);
+ }
+ putstring(frew, false, desclean, true);
+ aputc_('\n', frew)
+ }
+}
+
+ struct cbuf
+getsstdin(option, name, note, buf)
+ char const *option, *name, *note;
+ struct buf *buf;
+{
+ register int c;
+ register char *p;
+ register size_t i;
+ register int tty = ttystdin();
+
+ if (tty) {
+ aprintf(stderr,
+ "enter %s, terminated with single '.' or end of file:\n%s>> ",
+ name, note
+ );
+ eflush();
+ } else if (feof(stdin))
+ rcsfaterror("can't reread redirected stdin for %s; use -%s<%s>",
+ name, option, name
+ );
+
+ for (
+ i = 0, p = 0;
+ c = getcstdin(), !feof(stdin);
+ bufrealloc(buf, i+1), p = buf->string, p[i++] = c
+ )
+ if (c == '\n')
+ if (i && p[i-1]=='.' && (i==1 || p[i-2]=='\n')) {
+ /* Remove trailing '.'. */
+ --i;
+ break;
+ } else if (tty) {
+ aputs(">> ", stderr);
+ eflush();
+ }
+ return cleanlogmsg(p, i);
+}
+
+
+ void
+putadmin()
+/* Output the admin node. */
+{
+ register FILE *fout;
+ struct assoc const *curassoc;
+ struct rcslock const *curlock;
+ struct access const *curaccess;
+
+ if (!(fout = frewrite)) {
+# if bad_creat0
+ ORCSclose();
+ fout = fopenSafer(makedirtemp(0), FOPEN_WB);
+# else
+ int fo = fdlock;
+ fdlock = -1;
+ fout = fdopen(fo, FOPEN_WB);
+# endif
+
+ if (!(frewrite = fout))
+ efaterror(RCSname);
+ }
+
+ /*
+ * Output the first character with putc, not printf.
+ * Otherwise, an SVR4 stdio bug buffers output inefficiently.
+ */
+ aputc_(*Khead, fout)
+ aprintf(fout, "%s\t%s;\n", Khead + 1, Head?Head->num:"");
+ if (Dbranch && VERSION(4)<=RCSversion)
+ aprintf(fout, "%s\t%s;\n", Kbranch, Dbranch);
+
+ aputs(Kaccess, fout);
+ curaccess = AccessList;
+ while (curaccess) {
+ aprintf(fout, "\n\t%s", curaccess->login);
+ curaccess = curaccess->nextaccess;
+ }
+ aprintf(fout, ";\n%s", Ksymbols);
+ curassoc = Symbols;
+ while (curassoc) {
+ aprintf(fout, "\n\t%s:%s", curassoc->symbol, curassoc->num);
+ curassoc = curassoc->nextassoc;
+ }
+ aprintf(fout, ";\n%s", Klocks);
+ curlock = Locks;
+ while (curlock) {
+ aprintf(fout, "\n\t%s:%s", curlock->login, curlock->delta->num);
+ curlock = curlock->nextlock;
+ }
+ if (StrictLocks) aprintf(fout, "; %s", Kstrict);
+ aprintf(fout, ";\n");
+ if (Comment.size) {
+ aprintf(fout, "%s\t", Kcomment);
+ putstring(fout, true, Comment, false);
+ aprintf(fout, ";\n");
+ }
+ if (Expand != KEYVAL_EXPAND)
+ aprintf(fout, "%s\t%c%s%c;\n",
+ Kexpand, SDELIM, expand_names[Expand], SDELIM
+ );
+ awrite(Ignored.string, Ignored.size, fout);
+ aputc_('\n', fout)
+}
+
+
+ static void
+putdelta(node, fout)
+ register struct hshentry const *node;
+ register FILE * fout;
+/* Output the delta NODE to FOUT. */
+{
+ struct branchhead const *nextbranch;
+
+ if (!node) return;
+
+ aprintf(fout, "\n%s\n%s\t%s;\t%s %s;\t%s %s;\nbranches",
+ node->num,
+ Kdate, node->date,
+ Kauthor, node->author,
+ Kstate, node->state?node->state:""
+ );
+ nextbranch = node->branches;
+ while (nextbranch) {
+ aprintf(fout, "\n\t%s", nextbranch->hsh->num);
+ nextbranch = nextbranch->nextbranch;
+ }
+
+ aprintf(fout, ";\n%s\t%s;\n", Knext, node->next?node->next->num:"");
+ awrite(node->ig.string, node->ig.size, fout);
+}
+
+
+ void
+puttree(root, fout)
+ struct hshentry const *root;
+ register FILE *fout;
+/* Output the delta tree with base ROOT in preorder to FOUT. */
+{
+ struct branchhead const *nextbranch;
+
+ if (!root) return;
+
+ if (root->selector)
+ putdelta(root, fout);
+
+ puttree(root->next, fout);
+
+ nextbranch = root->branches;
+ while (nextbranch) {
+ puttree(nextbranch->hsh, fout);
+ nextbranch = nextbranch->nextbranch;
+ }
+}
+
+
+ int
+putdtext(delta, srcname, fout, diffmt)
+ struct hshentry const *delta;
+ char const *srcname;
+ FILE *fout;
+ int diffmt;
+/*
+ * Output a deltatext node with delta number DELTA->num, log message DELTA->log,
+ * ignored phrases DELTA->igtext and text SRCNAME to FOUT.
+ * Double up all SDELIMs in both the log and the text.
+ * Make sure the log message ends in \n.
+ * Return false on error.
+ * If DIFFMT, also check that the text is valid diff -n output.
+ */
+{
+ RILE *fin;
+ if (!(fin = Iopen(srcname, "r", (struct stat*)0))) {
+ eerror(srcname);
+ return false;
+ }
+ putdftext(delta, fin, fout, diffmt);
+ Ifclose(fin);
+ return true;
+}
+
+ void
+putstring(out, delim, s, log)
+ register FILE *out;
+ struct cbuf s;
+ int delim, log;
+/*
+ * Output to OUT one SDELIM if DELIM, then the string S with SDELIMs doubled.
+ * If LOG is set then S is a log string; append a newline if S is nonempty.
+ */
+{
+ register char const *sp;
+ register size_t ss;
+
+ if (delim)
+ aputc_(SDELIM, out)
+ sp = s.string;
+ for (ss = s.size; ss; --ss) {
+ if (*sp == SDELIM)
+ aputc_(SDELIM, out)
+ aputc_(*sp++, out)
+ }
+ if (s.size && log)
+ aputc_('\n', out)
+ aputc_(SDELIM, out)
+}
+
+ void
+putdftext(delta, finfile, foutfile, diffmt)
+ struct hshentry const *delta;
+ RILE *finfile;
+ FILE *foutfile;
+ int diffmt;
+/* like putdtext(), except the source file is already open */
+{
+ declarecache;
+ register FILE *fout;
+ register int c;
+ register RILE *fin;
+ int ed;
+ struct diffcmd dc;
+
+ fout = foutfile;
+ aprintf(fout, DELNUMFORM, delta->num, Klog);
+
+ /* put log */
+ putstring(fout, true, delta->log, true);
+ aputc_('\n', fout)
+
+ /* put ignored phrases */
+ awrite(delta->igtext.string, delta->igtext.size, fout);
+
+ /* put text */
+ aprintf(fout, "%s\n%c", Ktext, SDELIM);
+
+ fin = finfile;
+ setupcache(fin);
+ if (!diffmt) {
+ /* Copy the file */
+ cache(fin);
+ for (;;) {
+ cachegeteof_(c, break;)
+ if (c==SDELIM) aputc_(SDELIM, fout) /*double up SDELIM*/
+ aputc_(c, fout)
+ }
+ } else {
+ initdiffcmd(&dc);
+ while (0 <= (ed = getdiffcmd(fin, false, fout, &dc)))
+ if (ed) {
+ cache(fin);
+ while (dc.nlines--)
+ do {
+ cachegeteof_(c, { if (!dc.nlines) goto OK_EOF; unexpected_EOF(); })
+ if (c == SDELIM)
+ aputc_(SDELIM, fout)
+ aputc_(c, fout)
+ } while (c != '\n');
+ uncache(fin);
+ }
+ }
+ OK_EOF:
+ aprintf(fout, "%c\n", SDELIM);
+}
diff --git a/gnu/usr.bin/rcs/lib/rcskeep.c b/gnu/usr.bin/rcs/lib/rcskeep.c
new file mode 100644
index 0000000..4a90f85
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcskeep.c
@@ -0,0 +1,452 @@
+/* Extract RCS keyword string values from working files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.10 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.9 1995/06/01 16:23:43 eggert
+ * (getoldkeys): Don't panic if a Name: is empty.
+ *
+ * Revision 5.8 1994/03/17 14:05:48 eggert
+ * Remove lint.
+ *
+ * Revision 5.7 1993/11/09 17:40:15 eggert
+ * Use simpler timezone parsing strategy now that we're using ISO 8601 format.
+ *
+ * Revision 5.6 1993/11/03 17:42:27 eggert
+ * Scan for Name keyword. Improve quality of diagnostics.
+ *
+ * Revision 5.5 1992/07/28 16:12:44 eggert
+ * Statement macro names now end in _.
+ *
+ * Revision 5.4 1991/08/19 03:13:55 eggert
+ * Tune.
+ *
+ * Revision 5.3 1991/04/21 11:58:25 eggert
+ * Shorten names to keep them distinct on shortname hosts.
+ *
+ * Revision 5.2 1990/10/04 06:30:20 eggert
+ * Parse time zone offsets; future RCS versions may output them.
+ *
+ * Revision 5.1 1990/09/20 02:38:56 eggert
+ * ci -k now checks dates more thoroughly.
+ *
+ * Revision 5.0 1990/08/22 08:12:53 eggert
+ * Retrieve old log message if there is one.
+ * Don't require final newline.
+ * Remove compile-time limits; use malloc instead. Tune.
+ * Permit dates past 1999/12/31. Ansify and Posixate.
+ *
+ * Revision 4.6 89/05/01 15:12:56 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.5 88/08/09 19:13:03 eggert
+ * Remove lint and speed up by making FILE *fp local, not global.
+ *
+ * Revision 4.4 87/12/18 11:44:21 narten
+ * more lint cleanups (Guy Harris)
+ *
+ * Revision 4.3 87/10/18 10:35:50 narten
+ * Updating version numbers. Changes relative to 1.1 actually relative
+ * to 4.1
+ *
+ * Revision 1.3 87/09/24 14:00:00 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:29 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/05/10 16:26:44 wft
+ * Added new markers Id and RCSfile; extraction added.
+ * Marker matching with trymatch().
+ *
+ * Revision 3.2 82/12/24 12:08:26 wft
+ * added missing #endif.
+ *
+ * Revision 3.1 82/12/04 13:22:41 wft
+ * Initial revision.
+ *
+ */
+
+#include "rcsbase.h"
+
+libId(keepId, "$FreeBSD$")
+
+static int badly_terminated P((void));
+static int checknum P((char const*));
+static int get0val P((int,RILE*,struct buf*,int));
+static int getval P((RILE*,struct buf*,int));
+static int keepdate P((RILE*));
+static int keepid P((int,RILE*,struct buf*));
+static int keeprev P((RILE*));
+
+int prevkeys;
+struct buf prevauthor, prevdate, prevname, prevrev, prevstate;
+
+ int
+getoldkeys(fp)
+ register RILE *fp;
+/* Function: Tries to read keyword values for author, date,
+ * revision number, and state out of the file fp.
+ * If fp is null, workname is opened and closed instead of using fp.
+ * The results are placed into
+ * prevauthor, prevdate, prevname, prevrev, prevstate.
+ * Aborts immediately if it finds an error and returns false.
+ * If it returns true, it doesn't mean that any of the
+ * values were found; instead, check to see whether the corresponding arrays
+ * contain the empty string.
+ */
+{
+ register int c;
+ char keyword[keylength+1];
+ register char * tp;
+ int needs_closing;
+ int prevname_found;
+
+ if (prevkeys)
+ return true;
+
+ needs_closing = false;
+ if (!fp) {
+ if (!(fp = Iopen(workname, FOPEN_R_WORK, (struct stat*)0))) {
+ eerror(workname);
+ return false;
+ }
+ needs_closing = true;
+ }
+
+ /* initialize to empty */
+ bufscpy(&prevauthor, "");
+ bufscpy(&prevdate, "");
+ bufscpy(&prevname, ""); prevname_found = 0;
+ bufscpy(&prevrev, "");
+ bufscpy(&prevstate, "");
+
+ c = '\0'; /* anything but KDELIM */
+ for (;;) {
+ if ( c==KDELIM) {
+ do {
+ /* try to get keyword */
+ tp = keyword;
+ for (;;) {
+ Igeteof_(fp, c, goto ok;)
+ switch (c) {
+ default:
+ if (keyword+keylength <= tp)
+ break;
+ *tp++ = c;
+ continue;
+
+ case '\n': case KDELIM: case VDELIM:
+ break;
+ }
+ break;
+ }
+ } while (c==KDELIM);
+ if (c!=VDELIM) continue;
+ *tp = c;
+ Igeteof_(fp, c, break;)
+ switch (c) {
+ case ' ': case '\t': break;
+ default: continue;
+ }
+
+ switch (trymatch(keyword)) {
+ case Author:
+ if (!keepid(0, fp, &prevauthor))
+ return false;
+ c = 0;
+ break;
+ case Date:
+ if (!(c = keepdate(fp)))
+ return false;
+ break;
+ case Header:
+ case Id:
+ case LocalId:
+ if (!(
+ getval(fp, (struct buf*)0, false) &&
+ keeprev(fp) &&
+ (c = keepdate(fp)) &&
+ keepid(c, fp, &prevauthor) &&
+ keepid(0, fp, &prevstate)
+ ))
+ return false;
+ /* Skip either ``who'' (new form) or ``Locker: who'' (old). */
+ if (getval(fp, (struct buf*)0, true) &&
+ getval(fp, (struct buf*)0, true))
+ c = 0;
+ else if (nerror)
+ return false;
+ else
+ c = KDELIM;
+ break;
+ case Locker:
+ (void) getval(fp, (struct buf*)0, false);
+ c = 0;
+ break;
+ case Log:
+ case RCSfile:
+ case Source:
+ if (!getval(fp, (struct buf*)0, false))
+ return false;
+ c = 0;
+ break;
+ case Name:
+ if (getval(fp, &prevname, false)) {
+ if (*prevname.string)
+ checkssym(prevname.string);
+ prevname_found = 1;
+ }
+ c = 0;
+ break;
+ case Revision:
+ if (!keeprev(fp))
+ return false;
+ c = 0;
+ break;
+ case State:
+ if (!keepid(0, fp, &prevstate))
+ return false;
+ c = 0;
+ break;
+ default:
+ continue;
+ }
+ if (!c)
+ Igeteof_(fp, c, c=0;)
+ if (c != KDELIM) {
+ workerror("closing %c missing on keyword", KDELIM);
+ return false;
+ }
+ if (prevname_found &&
+ *prevauthor.string && *prevdate.string &&
+ *prevrev.string && *prevstate.string
+ )
+ break;
+ }
+ Igeteof_(fp, c, break;)
+ }
+
+ ok:
+ if (needs_closing)
+ Ifclose(fp);
+ else
+ Irewind(fp);
+ prevkeys = true;
+ return true;
+}
+
+ static int
+badly_terminated()
+{
+ workerror("badly terminated keyword value");
+ return false;
+}
+
+ static int
+getval(fp, target, optional)
+ register RILE *fp;
+ struct buf *target;
+ int optional;
+/* Reads a keyword value from FP into TARGET.
+ * Returns true if one is found, false otherwise.
+ * Does not modify target if it is 0.
+ * Do not report an error if OPTIONAL is set and KDELIM is found instead.
+ */
+{
+ int c;
+ Igeteof_(fp, c, return badly_terminated();)
+ return get0val(c, fp, target, optional);
+}
+
+ static int
+get0val(c, fp, target, optional)
+ register int c;
+ register RILE *fp;
+ struct buf *target;
+ int optional;
+/* Reads a keyword value from C+FP into TARGET, perhaps OPTIONALly.
+ * Same as getval, except C is the lookahead character.
+ */
+{ register char * tp;
+ char const *tlim;
+ register int got1;
+
+ if (target) {
+ bufalloc(target, 1);
+ tp = target->string;
+ tlim = tp + target->size;
+ } else
+ tlim = tp = 0;
+ got1 = false;
+ for (;;) {
+ switch (c) {
+ default:
+ got1 = true;
+ if (tp) {
+ *tp++ = c;
+ if (tlim <= tp)
+ tp = bufenlarge(target, &tlim);
+ }
+ break;
+
+ case ' ':
+ case '\t':
+ if (tp) {
+ *tp = 0;
+# ifdef KEEPTEST
+ VOID printf("getval: %s\n", target);
+# endif
+ }
+ return got1;
+
+ case KDELIM:
+ if (!got1 && optional)
+ return false;
+ /* fall into */
+ case '\n':
+ case 0:
+ return badly_terminated();
+ }
+ Igeteof_(fp, c, return badly_terminated();)
+ }
+}
+
+
+ static int
+keepdate(fp)
+ RILE *fp;
+/* Function: reads a date prevdate; checks format
+ * Return 0 on error, lookahead character otherwise.
+ */
+{
+ struct buf prevday, prevtime;
+ register int c;
+
+ c = 0;
+ bufautobegin(&prevday);
+ if (getval(fp,&prevday,false)) {
+ bufautobegin(&prevtime);
+ if (getval(fp,&prevtime,false)) {
+ Igeteof_(fp, c, c=0;)
+ if (c) {
+ register char const *d = prevday.string, *t = prevtime.string;
+ bufalloc(&prevdate, strlen(d) + strlen(t) + 9);
+ VOID sprintf(prevdate.string, "%s%s %s%s",
+ /* Parse dates put out by old versions of RCS. */
+ isdigit(d[0]) && isdigit(d[1]) && !isdigit(d[2])
+ ? "19" : "",
+ d, t,
+ strchr(t,'-') || strchr(t,'+') ? "" : "+0000"
+ );
+ }
+ }
+ bufautoend(&prevtime);
+ }
+ bufautoend(&prevday);
+ return c;
+}
+
+ static int
+keepid(c, fp, b)
+ int c;
+ RILE *fp;
+ struct buf *b;
+/* Get previous identifier from C+FP into B. */
+{
+ if (!c)
+ Igeteof_(fp, c, return false;)
+ if (!get0val(c, fp, b, false))
+ return false;
+ checksid(b->string);
+ return !nerror;
+}
+
+ static int
+keeprev(fp)
+ RILE *fp;
+/* Get previous revision from FP into prevrev. */
+{
+ return getval(fp,&prevrev,false) && checknum(prevrev.string);
+}
+
+
+ static int
+checknum(s)
+ char const *s;
+{
+ register char const *sp;
+ register int dotcount = 0;
+ for (sp=s; ; sp++) {
+ switch (*sp) {
+ case 0:
+ if (dotcount & 1)
+ return true;
+ else
+ break;
+
+ case '.':
+ dotcount++;
+ continue;
+
+ default:
+ if (isdigit(*sp))
+ continue;
+ break;
+ }
+ break;
+ }
+ workerror("%s is not a revision number", s);
+ return false;
+}
+
+
+
+#ifdef KEEPTEST
+
+/* Print the keyword values found. */
+
+char const cmdid[] ="keeptest";
+
+ int
+main(argc, argv)
+int argc; char *argv[];
+{
+ while (*(++argv)) {
+ workname = *argv;
+ getoldkeys((RILE*)0);
+ VOID printf("%s: revision: %s, date: %s, author: %s, name: %s, state: %s\n",
+ *argv, prevrev.string, prevdate.string, prevauthor.string, prevname.string, prevstate.string);
+ }
+ exitmain(EXIT_SUCCESS);
+}
+#endif
diff --git a/gnu/usr.bin/rcs/lib/rcskeys.c b/gnu/usr.bin/rcs/lib/rcskeys.c
new file mode 100644
index 0000000..378f57d
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcskeys.c
@@ -0,0 +1,186 @@
+/* RCS keyword table and match operation */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.4 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.3 1993/11/03 17:42:27 eggert
+ * Add Name keyword.
+ *
+ * Revision 5.2 1991/08/19 03:13:55 eggert
+ * Say `T const' instead of `const T'; it's less confusing for pointer types.
+ * (This change was made in other source files too.)
+ *
+ * Revision 5.1 1991/04/21 11:58:25 eggert
+ * Don't put , just before } in initializer.
+ *
+ * Revision 5.0 1990/08/22 08:12:54 eggert
+ * Add -k. Ansify and Posixate.
+ *
+ * Revision 4.3 89/05/01 15:13:02 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.2 87/10/18 10:36:33 narten
+ * Updating version numbers. Changes relative to 1.1 actuallyt
+ * relative to 4.1
+ *
+ * Revision 1.2 87/09/24 14:00:10 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 4.1 83/05/04 10:06:53 wft
+ * Initial revision.
+ *
+ */
+
+
+#include "rcsbase.h"
+
+libId(keysId, "$FreeBSD$")
+
+
+char const *Keyword[] = {
+ /* This must be in the same order as rcsbase.h's enum markers type. */
+ 0,
+ AUTHOR, DATE, HEADER, IDH,
+ LOCKER, LOG, NAME, RCSFILE, REVISION, SOURCE, STATE, CVSHEADER,
+ NULL
+};
+
+/* Expand all keywords by default */
+static int ExpandKeyword[] = {
+ false,
+ true, true, true, true,
+ true, true, true, true, true, true, true, true,
+ true
+};
+enum markers LocalIdMode = Id;
+
+ enum markers
+trymatch(string)
+ char const *string;
+/* function: Checks whether string starts with a keyword followed
+ * by a KDELIM or a VDELIM.
+ * If successful, returns the appropriate marker, otherwise Nomatch.
+ */
+{
+ register int j;
+ register char const *p, *s;
+ for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); ) {
+ if (!ExpandKeyword[j])
+ continue;
+ /* try next keyword */
+ p = Keyword[j];
+ if (p == NULL)
+ continue;
+ s = string;
+ while (*p++ == *s++) {
+ if (!*p)
+ switch (*s) {
+ case KDELIM:
+ case VDELIM:
+ return (enum markers)j;
+ default:
+ return Nomatch;
+ }
+ }
+ }
+ return(Nomatch);
+}
+
+ void
+setIncExc(arg)
+ char const *arg;
+/* Sets up the ExpandKeyword table according to command-line flags */
+{
+ char *key;
+ char *copy, *next;
+ int include = 0, j;
+
+ copy = strdup(arg);
+ next = copy;
+ switch (*next++) {
+ case 'e':
+ include = false;
+ break;
+ case 'i':
+ include = true;
+ break;
+ default:
+ free(copy);
+ return;
+ }
+ if (include)
+ for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); )
+ ExpandKeyword[j] = false;
+ key = strtok(next, ",");
+ while (key) {
+ for (j = sizeof(Keyword)/sizeof(*Keyword); (--j); ) {
+ if (Keyword[j] == NULL)
+ continue;
+ if (!strcmp(key, Keyword[j]))
+ ExpandKeyword[j] = include;
+ }
+ key = strtok(NULL, ",");
+ }
+ free(copy);
+ return;
+}
+
+ void
+setRCSLocalId(string)
+ char const *string;
+/* function: sets local RCS id and RCSLOCALID envariable */
+{
+ static char local_id[keylength+1];
+ char *copy, *next, *key;
+ int j;
+
+ copy = strdup(string);
+ next = copy;
+ key = strtok(next, "=");
+ if (strlen(key) > keylength)
+ faterror("LocalId is too long");
+ VOID strcpy(local_id, key);
+ Keyword[LocalId] = local_id;
+
+ /* options? */
+ while (key = strtok(NULL, ",")) {
+ if (!strcmp(key, Keyword[Id]))
+ LocalIdMode=Id;
+ else if (!strcmp(key, Keyword[Header]))
+ LocalIdMode=Header;
+ else if (!strcmp(key, Keyword[CVSHeader]))
+ LocalIdMode=CVSHeader;
+ else
+ error("Unknown LocalId mode");
+ }
+ free(copy);
+}
diff --git a/gnu/usr.bin/rcs/lib/rcslex.c b/gnu/usr.bin/rcs/lib/rcslex.c
new file mode 100644
index 0000000..7a11f79
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcslex.c
@@ -0,0 +1,1568 @@
+/* lexical analysis of RCS files */
+
+/******************************************************************************
+ * Lexical Analysis.
+ * hashtable, Lexinit, nextlex, getlex, getkey,
+ * getid, getnum, readstring, printstring, savestring,
+ * checkid, fatserror, error, faterror, warn, diagnose
+ * Testprogram: define LEXDB
+ ******************************************************************************
+ */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+
+
+/*
+ * Revision 5.19 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (map_fd_deallocate,mmap_deallocate,read_deallocate,nothing_to_deallocate):
+ * New functions.
+ * (Iclose): If large_memory and maps_memory, use them to deallocate mapping.
+ * (fd2RILE): Use map_fd if available.
+ * If one mapping method fails, try the next instead of giving up;
+ * if they all fail, fall back on ordinary read.
+ * Work around bug: root mmap over NFS succeeds, but accessing dumps core.
+ * Use MAP_FAILED macro for mmap failure, and `char *' instead of caddr_t.
+ * (advise_access): Use madvise only if this instance used mmap.
+ * (Iopen): Use fdSafer to get safer file descriptor.
+ * (aflush): Moved here from rcsedit.c.
+ *
+ * Revision 5.17 1994/03/20 04:52:58 eggert
+ * Don't worry if madvise fails. Add Orewind. Remove lint.
+ *
+ * Revision 5.16 1993/11/09 17:55:29 eggert
+ * Fix `label: }' typo.
+ *
+ * Revision 5.15 1993/11/03 17:42:27 eggert
+ * Improve quality of diagnostics by putting file names in them more often.
+ * Don't discard ignored phrases.
+ *
+ * Revision 5.14 1992/07/28 16:12:44 eggert
+ * Identifiers may now start with a digit and (unless they are symbolic names)
+ * may contain `.'. Avoid `unsigned'. Statement macro names now end in _.
+ *
+ * Revision 5.13 1992/02/17 23:02:27 eggert
+ * Work around NFS mmap SIGBUS problem.
+ *
+ * Revision 5.12 1992/01/06 02:42:34 eggert
+ * Use OPEN_O_BINARY if mode contains 'b'.
+ *
+ * Revision 5.11 1991/11/03 03:30:44 eggert
+ * Fix porting bug to ancient hosts lacking vfprintf.
+ *
+ * Revision 5.10 1991/10/07 17:32:46 eggert
+ * Support piece tables even if !has_mmap.
+ *
+ * Revision 5.9 1991/09/24 00:28:42 eggert
+ * Don't export errsay().
+ *
+ * Revision 5.8 1991/08/19 03:13:55 eggert
+ * Add eoflex(), mmap support. Tune.
+ *
+ * Revision 5.7 1991/04/21 11:58:26 eggert
+ * Add MS-DOS support.
+ *
+ * Revision 5.6 1991/02/25 07:12:42 eggert
+ * Work around fputs bug. strsave -> str_save (DG/UX name clash)
+ *
+ * Revision 5.5 1990/12/04 05:18:47 eggert
+ * Use -I for prompts and -q for diagnostics.
+ *
+ * Revision 5.4 1990/11/19 20:05:28 hammer
+ * no longer gives warning about unknown keywords if -q is specified
+ *
+ * Revision 5.3 1990/11/01 05:03:48 eggert
+ * When ignoring unknown phrases, copy them to the output RCS file.
+ *
+ * Revision 5.2 1990/09/04 08:02:27 eggert
+ * Count RCS lines better.
+ *
+ * Revision 5.1 1990/08/29 07:14:03 eggert
+ * Work around buggy compilers with defective argument promotion.
+ *
+ * Revision 5.0 1990/08/22 08:12:55 eggert
+ * Remove compile-time limits; use malloc instead.
+ * Report errno-related errors with perror().
+ * Ansify and Posixate. Add support for ISO 8859.
+ * Use better hash function.
+ *
+ * Revision 4.6 89/05/01 15:13:07 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.5 88/08/28 15:01:12 eggert
+ * Don't loop when writing error messages to a full filesystem.
+ * Flush stderr/stdout when mixing output.
+ * Yield exit status compatible with diff(1).
+ * Shrink stdio code size; allow cc -R; remove lint.
+ *
+ * Revision 4.4 87/12/18 11:44:47 narten
+ * fixed to use "varargs" in "fprintf"; this is required if it is to
+ * work on a SPARC machine such as a Sun-4
+ *
+ * Revision 4.3 87/10/18 10:37:18 narten
+ * Updating version numbers. Changes relative to 1.1 actually relative
+ * to version 4.1
+ *
+ * Revision 1.3 87/09/24 14:00:17 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:33 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/03/25 18:12:51 wft
+ * Only changed $Header to $Id.
+ *
+ * Revision 3.3 82/12/10 16:22:37 wft
+ * Improved error messages, changed exit status on error to 1.
+ *
+ * Revision 3.2 82/11/28 21:27:10 wft
+ * Renamed ctab to map and included EOFILE; ctab is now a macro in rcsbase.h.
+ * Added fflsbuf(), fputs(), and fprintf(), which abort the RCS operations
+ * properly in case there is an IO-error (e.g., file system full).
+ *
+ * Revision 3.1 82/10/11 19:43:56 wft
+ * removed unused label out:;
+ * made sure all calls to getc() return into an integer, not a char.
+ */
+
+
+/*
+#define LEXDB
+*/
+/* version LEXDB is for testing the lexical analyzer. The testprogram
+ * reads a stream of lexemes, enters the revision numbers into the
+ * hashtable, and prints the recognized tokens. Keywords are recognized
+ * as identifiers.
+ */
+
+
+
+#include "rcsbase.h"
+
+libId(lexId, "$FreeBSD$")
+
+static char *checkidentifier P((char*,int,int));
+static void errsay P((char const*));
+static void fatsay P((char const*));
+static void lookup P((char const*));
+static void startsay P((const char*,const char*));
+static void warnsay P((char const*));
+
+static struct hshentry *nexthsh; /*pointer to next hash entry, set by lookup*/
+
+enum tokens nexttok; /*next token, set by nextlex */
+
+int hshenter; /*if true, next suitable lexeme will be entered */
+ /*into the symbol table. Handle with care. */
+int nextc; /*next input character, initialized by Lexinit */
+
+long rcsline; /*current line-number of input */
+int nerror; /*counter for errors */
+int quietflag; /*indicates quiet mode */
+RILE * finptr; /*input file descriptor */
+
+FILE * frewrite; /*file descriptor for echoing input */
+
+FILE * foutptr; /* copy of frewrite, but 0 to suppress echo */
+
+static struct buf tokbuf; /* token buffer */
+
+char const * NextString; /* next token */
+
+/*
+ * Our hash algorithm is h[0] = 0, h[i+1] = 4*h[i] + c,
+ * so hshsize should be odd.
+ * See B J McKenzie, R Harries & T Bell, Selecting a hashing algorithm,
+ * Software--practice & experience 20, 2 (Feb 1990), 209-224.
+ */
+#ifndef hshsize
+# define hshsize 511
+#endif
+
+static struct hshentry *hshtab[hshsize]; /*hashtable */
+
+static int ignored_phrases; /* have we ignored phrases in this RCS file? */
+
+ void
+warnignore()
+{
+ if (!ignored_phrases) {
+ ignored_phrases = true;
+ rcswarn("Unknown phrases like `%s ...;' are present.", NextString);
+ }
+}
+
+
+
+ static void
+lookup(str)
+ char const *str;
+/* Function: Looks up the character string pointed to by str in the
+ * hashtable. If the string is not present, a new entry for it is created.
+ * In any case, the address of the corresponding hashtable entry is placed
+ * into nexthsh.
+ */
+{
+ register unsigned ihash; /* index into hashtable */
+ register char const *sp;
+ register struct hshentry *n, **p;
+
+ /* calculate hash code */
+ sp = str;
+ ihash = 0;
+ while (*sp)
+ ihash = (ihash<<2) + *sp++;
+ ihash %= hshsize;
+
+ for (p = &hshtab[ihash]; ; p = &n->nexthsh)
+ if (!(n = *p)) {
+ /* empty slot found */
+ *p = n = ftalloc(struct hshentry);
+ n->num = fstr_save(str);
+ n->nexthsh = 0;
+# ifdef LEXDB
+ VOID printf("\nEntered: %s at %u ", str, ihash);
+# endif
+ break;
+ } else if (strcmp(str, n->num) == 0)
+ /* match found */
+ break;
+ nexthsh = n;
+ NextString = n->num;
+}
+
+
+
+
+
+
+ void
+Lexinit()
+/* Function: Initialization of lexical analyzer:
+ * initializes the hashtable,
+ * initializes nextc, nexttok if finptr != 0
+ */
+{ register int c;
+
+ for (c = hshsize; 0 <= --c; ) {
+ hshtab[c] = 0;
+ }
+
+ nerror = 0;
+ if (finptr) {
+ foutptr = 0;
+ hshenter = true;
+ ignored_phrases = false;
+ rcsline = 1;
+ bufrealloc(&tokbuf, 2);
+ Iget_(finptr, nextc)
+ nextlex(); /*initial token*/
+ }
+}
+
+
+
+
+
+
+
+ void
+nextlex()
+
+/* Function: Reads the next token and sets nexttok to the next token code.
+ * Only if hshenter is set, a revision number is entered into the
+ * hashtable and a pointer to it is placed into nexthsh.
+ * This is useful for avoiding that dates are placed into the hashtable.
+ * For ID's and NUM's, NextString is set to the character string.
+ * Assumption: nextc contains the next character.
+ */
+{ register c;
+ declarecache;
+ register FILE *frew;
+ register char * sp;
+ char const *limit;
+ register enum tokens d;
+ register RILE *fin;
+
+ fin=finptr; frew=foutptr;
+ setupcache(fin); cache(fin);
+ c = nextc;
+
+ for (;;) { switch ((d = ctab[c])) {
+
+ default:
+ fatserror("unknown character `%c'", c);
+ /*NOTREACHED*/
+
+ case NEWLN:
+ ++rcsline;
+# ifdef LEXDB
+ afputc('\n',stdout);
+# endif
+ /* Note: falls into next case */
+
+ case SPACE:
+ GETC_(frew, c)
+ continue;
+
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ d = ID;
+ /* fall into */
+ case DIGIT:
+ case PERIOD:
+ sp = tokbuf.string;
+ limit = sp + tokbuf.size;
+ *sp++ = c;
+ for (;;) {
+ GETC_(frew, c)
+ switch (ctab[c]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ d = ID;
+ /* fall into */
+ case DIGIT:
+ case PERIOD:
+ *sp++ = c;
+ if (limit <= sp)
+ sp = bufenlarge(&tokbuf, &limit);
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+ *sp = 0;
+ if (d == DIGIT || d == PERIOD) {
+ d = NUM;
+ if (hshenter) {
+ lookup(tokbuf.string);
+ break;
+ }
+ }
+ NextString = fstr_save(tokbuf.string);
+ break;
+
+ case SBEGIN: /* long string */
+ d = STRING;
+ /* note: only the initial SBEGIN has been read*/
+ /* read the string, and reset nextc afterwards*/
+ break;
+
+ case COLON:
+ case SEMI:
+ GETC_(frew, c)
+ break;
+ } break; }
+ nextc = c;
+ nexttok = d;
+ uncache(fin);
+}
+
+ int
+eoflex()
+/*
+ * Yield true if we look ahead to the end of the input, false otherwise.
+ * nextc becomes undefined at end of file.
+ */
+{
+ register int c;
+ declarecache;
+ register FILE *fout;
+ register RILE *fin;
+
+ c = nextc;
+ fin = finptr;
+ fout = foutptr;
+ setupcache(fin); cache(fin);
+
+ for (;;) {
+ switch (ctab[c]) {
+ default:
+ nextc = c;
+ uncache(fin);
+ return false;
+
+ case NEWLN:
+ ++rcsline;
+ /* fall into */
+ case SPACE:
+ cachegeteof_(c, {uncache(fin);return true;})
+ break;
+ }
+ if (fout)
+ aputc_(c, fout)
+ }
+}
+
+
+int getlex(token)
+enum tokens token;
+/* Function: Checks if nexttok is the same as token. If so,
+ * advances the input by calling nextlex and returns true.
+ * otherwise returns false.
+ * Doesn't work for strings and keywords; loses the character string for ids.
+ */
+{
+ if (nexttok==token) {
+ nextlex();
+ return(true);
+ } else return(false);
+}
+
+ int
+getkeyopt(key)
+ char const *key;
+/* Function: If the current token is a keyword identical to key,
+ * advances the input by calling nextlex and returns true;
+ * otherwise returns false.
+ */
+{
+ if (nexttok==ID && strcmp(key,NextString) == 0) {
+ /* match found */
+ ffree1(NextString);
+ nextlex();
+ return(true);
+ }
+ return(false);
+}
+
+ void
+getkey(key)
+ char const *key;
+/* Check that the current input token is a keyword identical to key,
+ * and advance the input by calling nextlex.
+ */
+{
+ if (!getkeyopt(key))
+ fatserror("missing '%s' keyword", key);
+}
+
+ void
+getkeystring(key)
+ char const *key;
+/* Check that the current input token is a keyword identical to key,
+ * and advance the input by calling nextlex; then look ahead for a string.
+ */
+{
+ getkey(key);
+ if (nexttok != STRING)
+ fatserror("missing string after '%s' keyword", key);
+}
+
+
+ char const *
+getid()
+/* Function: Checks if nexttok is an identifier. If so,
+ * advances the input by calling nextlex and returns a pointer
+ * to the identifier; otherwise returns 0.
+ * Treats keywords as identifiers.
+ */
+{
+ register char const *name;
+ if (nexttok==ID) {
+ name = NextString;
+ nextlex();
+ return name;
+ } else
+ return 0;
+}
+
+
+struct hshentry * getnum()
+/* Function: Checks if nexttok is a number. If so,
+ * advances the input by calling nextlex and returns a pointer
+ * to the hashtable entry. Otherwise returns 0.
+ * Doesn't work if hshenter is false.
+ */
+{
+ register struct hshentry * num;
+ if (nexttok==NUM) {
+ num=nexthsh;
+ nextlex();
+ return num;
+ } else
+ return 0;
+}
+
+ struct cbuf
+getphrases(key)
+ char const *key;
+/*
+* Get a series of phrases that do not start with KEY. Yield resulting buffer.
+* Stop when the next phrase starts with a token that is not an identifier,
+* or is KEY. Copy input to foutptr if it is set. Unlike ignorephrases(),
+* this routine assumes nextlex() has already been invoked before we start.
+*/
+{
+ declarecache;
+ register int c;
+ register char const *kn;
+ struct cbuf r;
+ register RILE *fin;
+ register FILE *frew;
+# if large_memory
+# define savech_(c) ;
+# else
+ register char *p;
+ char const *limit;
+ struct buf b;
+# define savech_(c) {if (limit<=p)p=bufenlarge(&b,&limit); *p++ =(c);}
+# endif
+
+ if (nexttok!=ID || strcmp(NextString,key) == 0)
+ clear_buf(&r);
+ else {
+ warnignore();
+ fin = finptr;
+ frew = foutptr;
+ setupcache(fin); cache(fin);
+# if large_memory
+ r.string = (char const*)cacheptr() - strlen(NextString) - 1;
+# else
+ bufautobegin(&b);
+ bufscpy(&b, NextString);
+ p = b.string + strlen(b.string);
+ limit = b.string + b.size;
+# endif
+ ffree1(NextString);
+ c = nextc;
+ for (;;) {
+ for (;;) {
+ savech_(c)
+ switch (ctab[c]) {
+ default:
+ fatserror("unknown character `%c'", c);
+ /*NOTREACHED*/
+ case NEWLN:
+ ++rcsline;
+ /* fall into */
+ case COLON: case DIGIT: case LETTER: case Letter:
+ case PERIOD: case SPACE:
+ GETC_(frew, c)
+ continue;
+ case SBEGIN: /* long string */
+ for (;;) {
+ for (;;) {
+ GETC_(frew, c)
+ savech_(c)
+ switch (c) {
+ case '\n':
+ ++rcsline;
+ /* fall into */
+ default:
+ continue;
+
+ case SDELIM:
+ break;
+ }
+ break;
+ }
+ GETC_(frew, c)
+ if (c != SDELIM)
+ break;
+ savech_(c)
+ }
+ continue;
+ case SEMI:
+ cacheget_(c)
+ if (ctab[c] == NEWLN) {
+ if (frew)
+ aputc_(c, frew)
+ ++rcsline;
+ savech_(c)
+ cacheget_(c)
+ }
+# if large_memory
+ r.size = (char const*)cacheptr() - 1 - r.string;
+# endif
+ for (;;) {
+ switch (ctab[c]) {
+ case NEWLN:
+ ++rcsline;
+ /* fall into */
+ case SPACE:
+ cacheget_(c)
+ continue;
+
+ default: break;
+ }
+ break;
+ }
+ if (frew)
+ aputc_(c, frew)
+ break;
+ }
+ break;
+ }
+ if (ctab[c] == Letter) {
+ for (kn = key; c && *kn==c; kn++)
+ GETC_(frew, c)
+ if (!*kn)
+ switch (ctab[c]) {
+ case DIGIT: case LETTER: case Letter:
+ case IDCHAR: case PERIOD:
+ break;
+ default:
+ nextc = c;
+ NextString = fstr_save(key);
+ nexttok = ID;
+ uncache(fin);
+ goto returnit;
+ }
+# if !large_memory
+ {
+ register char const *ki;
+ for (ki=key; ki<kn; )
+ savech_(*ki++)
+ }
+# endif
+ } else {
+ nextc = c;
+ uncache(fin);
+ nextlex();
+ break;
+ }
+ }
+ returnit:;
+# if !large_memory
+ return bufremember(&b, (size_t)(p - b.string));
+# endif
+ }
+ return r;
+}
+
+
+ void
+readstring()
+/* skip over characters until terminating single SDELIM */
+/* If foutptr is set, copy every character read to foutptr. */
+/* Does not advance nextlex at the end. */
+{ register c;
+ declarecache;
+ register FILE *frew;
+ register RILE *fin;
+ fin=finptr; frew=foutptr;
+ setupcache(fin); cache(fin);
+ for (;;) {
+ GETC_(frew, c)
+ switch (c) {
+ case '\n':
+ ++rcsline;
+ break;
+
+ case SDELIM:
+ GETC_(frew, c)
+ if (c != SDELIM) {
+ /* end of string */
+ nextc = c;
+ uncache(fin);
+ return;
+ }
+ break;
+ }
+ }
+}
+
+
+ void
+printstring()
+/* Function: copy a string to stdout, until terminated with a single SDELIM.
+ * Does not advance nextlex at the end.
+ */
+{
+ register c;
+ declarecache;
+ register FILE *fout;
+ register RILE *fin;
+ fin=finptr;
+ fout = stdout;
+ setupcache(fin); cache(fin);
+ for (;;) {
+ cacheget_(c)
+ switch (c) {
+ case '\n':
+ ++rcsline;
+ break;
+ case SDELIM:
+ cacheget_(c)
+ if (c != SDELIM) {
+ nextc=c;
+ uncache(fin);
+ return;
+ }
+ break;
+ }
+ aputc_(c,fout)
+ }
+}
+
+
+
+ struct cbuf
+savestring(target)
+ struct buf *target;
+/* Copies a string terminated with SDELIM from file finptr to buffer target.
+ * Double SDELIM is replaced with SDELIM.
+ * If foutptr is set, the string is also copied unchanged to foutptr.
+ * Does not advance nextlex at the end.
+ * Yield a copy of *TARGET, except with exact length.
+ */
+{
+ register c;
+ declarecache;
+ register FILE *frew;
+ register char *tp;
+ register RILE *fin;
+ char const *limit;
+ struct cbuf r;
+
+ fin=finptr; frew=foutptr;
+ setupcache(fin); cache(fin);
+ tp = target->string; limit = tp + target->size;
+ for (;;) {
+ GETC_(frew, c)
+ switch (c) {
+ case '\n':
+ ++rcsline;
+ break;
+ case SDELIM:
+ GETC_(frew, c)
+ if (c != SDELIM) {
+ /* end of string */
+ nextc=c;
+ r.string = target->string;
+ r.size = tp - r.string;
+ uncache(fin);
+ return r;
+ }
+ break;
+ }
+ if (tp == limit)
+ tp = bufenlarge(target, &limit);
+ *tp++ = c;
+ }
+}
+
+
+ static char *
+checkidentifier(id, delimiter, dotok)
+ register char *id;
+ int delimiter;
+ register int dotok;
+/* Function: check whether the string starting at id is an */
+/* identifier and return a pointer to the delimiter*/
+/* after the identifier. White space, delim and 0 */
+/* are legal delimiters. Aborts the program if not*/
+/* a legal identifier. Useful for checking commands*/
+/* If !delim, the only delimiter is 0. */
+/* Allow '.' in identifier only if DOTOK is set. */
+{
+ register char *temp;
+ register char c;
+ register char delim = delimiter;
+ int isid = false;
+
+ temp = id;
+ for (;; id++) {
+ switch (ctab[(unsigned char)(c = *id)]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ isid = true;
+ continue;
+
+ case DIGIT:
+ continue;
+
+ case PERIOD:
+ if (dotok)
+ continue;
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+ if ( ! isid
+ || (c && (!delim || (c!=delim && c!=' ' && c!='\t' && c!='\n')))
+ ) {
+ /* append \0 to end of id before error message */
+ while ((c = *id) && c!=' ' && c!='\t' && c!='\n' && c!=delim)
+ id++;
+ *id = '\0';
+ faterror("invalid %s `%s'",
+ dotok ? "identifier" : "symbol", temp
+ );
+ }
+ return id;
+}
+
+ char *
+checkid(id, delimiter)
+ char *id;
+ int delimiter;
+{
+ return checkidentifier(id, delimiter, true);
+}
+
+ char *
+checksym(sym, delimiter)
+ char *sym;
+ int delimiter;
+{
+ return checkidentifier(sym, delimiter, false);
+}
+
+ void
+checksid(id)
+ char *id;
+/* Check whether the string ID is an identifier. */
+{
+ VOID checkid(id, 0);
+}
+
+ void
+checkssym(sym)
+ char *sym;
+{
+ VOID checksym(sym, 0);
+}
+
+
+#if !large_memory
+# define Iclose(f) fclose(f)
+#else
+# if !maps_memory
+ static int Iclose P((RILE *));
+ static int
+ Iclose(f)
+ register RILE *f;
+ {
+ tfree(f->base);
+ f->base = 0;
+ return fclose(f->stream);
+ }
+# else
+ static int Iclose P((RILE *));
+ static int
+ Iclose(f)
+ register RILE *f;
+ {
+ (* f->deallocate) (f);
+ f->base = 0;
+ return close(f->fd);
+ }
+
+# if has_map_fd
+ static void map_fd_deallocate P((RILE *));
+ static void
+ map_fd_deallocate(f)
+ register RILE *f;
+ {
+ if (vm_deallocate(
+ task_self(),
+ (vm_address_t) f->base,
+ (vm_size_t) (f->lim - f->base)
+ ) != KERN_SUCCESS)
+ efaterror("vm_deallocate");
+ }
+# endif
+# if has_mmap
+ static void mmap_deallocate P((RILE *));
+ static void
+ mmap_deallocate(f)
+ register RILE *f;
+ {
+ if (munmap((char *) f->base, (size_t) (f->lim - f->base)) != 0)
+ efaterror("munmap");
+ }
+# endif
+ static void read_deallocate P((RILE *));
+ static void
+ read_deallocate(f)
+ RILE *f;
+ {
+ tfree(f->base);
+ }
+
+ static void nothing_to_deallocate P((RILE *));
+ static void
+ nothing_to_deallocate(f)
+ RILE *f;
+ {
+ }
+# endif
+#endif
+
+
+#if large_memory && maps_memory
+ static RILE *fd2_RILE P((int,char const*,struct stat*));
+ static RILE *
+fd2_RILE(fd, name, status)
+#else
+ static RILE *fd2RILE P((int,char const*,char const*,struct stat*));
+ static RILE *
+fd2RILE(fd, name, type, status)
+ char const *type;
+#endif
+ int fd;
+ char const *name;
+ register struct stat *status;
+{
+ struct stat st;
+
+ if (!status)
+ status = &st;
+ if (fstat(fd, status) != 0)
+ efaterror(name);
+ if (!S_ISREG(status->st_mode)) {
+ error("`%s' is not a regular file", name);
+ VOID close(fd);
+ errno = EINVAL;
+ return 0;
+ } else {
+
+# if !(large_memory && maps_memory)
+ FILE *stream;
+ if (!(stream = fdopen(fd, type)))
+ efaterror(name);
+# endif
+
+# if !large_memory
+ return stream;
+# else
+# define RILES 3
+ {
+ static RILE rilebuf[RILES];
+
+ register RILE *f;
+ size_t s = status->st_size;
+
+ if (s != status->st_size)
+ faterror("%s: too large", name);
+ for (f = rilebuf; f->base; f++)
+ if (f == rilebuf+RILES)
+ faterror("too many RILEs");
+# if maps_memory
+ f->deallocate = nothing_to_deallocate;
+# endif
+ if (!s) {
+ static unsigned char nothing;
+ f->base = &nothing; /* Any nonzero address will do. */
+ } else {
+ f->base = 0;
+# if has_map_fd
+ map_fd(
+ fd, (vm_offset_t)0, (vm_address_t*) &f->base,
+ TRUE, (vm_size_t)s
+ );
+ f->deallocate = map_fd_deallocate;
+# endif
+# if has_mmap
+ if (!f->base) {
+ catchmmapints();
+ f->base = (unsigned char *) mmap(
+ (char *)0, s, PROT_READ, MAP_SHARED,
+ fd, (off_t)0
+ );
+# ifndef MAP_FAILED
+# define MAP_FAILED (-1)
+# endif
+ if (f->base == (unsigned char *) MAP_FAILED)
+ f->base = 0;
+ else {
+# if has_NFS && mmap_signal
+ /*
+ * On many hosts, the superuser
+ * can mmap an NFS file it can't read.
+ * So access the first page now, and print
+ * a nice message if a bus error occurs.
+ */
+ readAccessFilenameBuffer(name, f->base);
+# endif
+ }
+ f->deallocate = mmap_deallocate;
+ }
+# endif
+ if (!f->base) {
+ f->base = tnalloc(unsigned char, s);
+# if maps_memory
+ {
+ /*
+ * We can't map the file into memory for some reason.
+ * Read it into main memory all at once; this is
+ * the simplest substitute for memory mapping.
+ */
+ char *bufptr = (char *) f->base;
+ size_t bufsiz = s;
+ do {
+ ssize_t r = read(fd, bufptr, bufsiz);
+ switch (r) {
+ case -1:
+ efaterror(name);
+
+ case 0:
+ /* The file must have shrunk! */
+ status->st_size = s -= bufsiz;
+ bufsiz = 0;
+ break;
+
+ default:
+ bufptr += r;
+ bufsiz -= r;
+ break;
+ }
+ } while (bufsiz);
+ if (lseek(fd, (off_t)0, SEEK_SET) == -1)
+ efaterror(name);
+ f->deallocate = read_deallocate;
+ }
+# endif
+ }
+ }
+ f->ptr = f->base;
+ f->lim = f->base + s;
+ f->fd = fd;
+# if !maps_memory
+ f->readlim = f->base;
+ f->stream = stream;
+# endif
+ if_advise_access(s, f, MADV_SEQUENTIAL);
+ return f;
+ }
+# endif
+ }
+}
+
+#if !maps_memory && large_memory
+ int
+Igetmore(f)
+ register RILE *f;
+{
+ register fread_type r;
+ register size_t s = f->lim - f->readlim;
+
+ if (BUFSIZ < s)
+ s = BUFSIZ;
+ if (!(r = Fread(f->readlim, sizeof(*f->readlim), s, f->stream))) {
+ testIerror(f->stream);
+ f->lim = f->readlim; /* The file might have shrunk! */
+ return 0;
+ }
+ f->readlim += r;
+ return 1;
+}
+#endif
+
+#if has_madvise && has_mmap && large_memory
+ void
+advise_access(f, advice)
+ register RILE *f;
+ int advice;
+{
+ if (f->deallocate == mmap_deallocate)
+ VOID madvise((char *)f->base, (size_t)(f->lim - f->base), advice);
+ /* Don't worry if madvise fails; it's only advisory. */
+}
+#endif
+
+ RILE *
+#if large_memory && maps_memory
+I_open(name, status)
+#else
+Iopen(name, type, status)
+ char const *type;
+#endif
+ char const *name;
+ struct stat *status;
+/* Open NAME for reading, yield its descriptor, and set *STATUS. */
+{
+ int fd = fdSafer(open(name, O_RDONLY
+# if OPEN_O_BINARY
+ | (strchr(type,'b') ? OPEN_O_BINARY : 0)
+# endif
+ ));
+
+ if (fd < 0)
+ return 0;
+# if large_memory && maps_memory
+ return fd2_RILE(fd, name, status);
+# else
+ return fd2RILE(fd, name, type, status);
+# endif
+}
+
+
+static int Oerrloop;
+
+ void
+Oerror()
+{
+ if (Oerrloop)
+ exiterr();
+ Oerrloop = true;
+ efaterror("output error");
+}
+
+void Ieof() { fatserror("unexpected end of file"); }
+void Ierror() { efaterror("input error"); }
+void testIerror(f) FILE *f; { if (ferror(f)) Ierror(); }
+void testOerror(o) FILE *o; { if (ferror(o)) Oerror(); }
+
+void Ifclose(f) RILE *f; { if (f && Iclose(f)!=0) Ierror(); }
+void Ofclose(f) FILE *f; { if (f && fclose(f)!=0) Oerror(); }
+void Izclose(p) RILE **p; { Ifclose(*p); *p = 0; }
+void Ozclose(p) FILE **p; { Ofclose(*p); *p = 0; }
+
+#if !large_memory
+ void
+testIeof(f)
+ FILE *f;
+{
+ testIerror(f);
+ if (feof(f))
+ Ieof();
+}
+void Irewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Ierror(); }
+#endif
+
+void Orewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Oerror(); }
+
+void aflush(f) FILE *f; { if (fflush(f) != 0) Oerror(); }
+void eflush() { if (fflush(stderr)!=0 && !Oerrloop) Oerror(); }
+void oflush()
+{
+ if (fflush(workstdout ? workstdout : stdout) != 0 && !Oerrloop)
+ Oerror();
+}
+
+ void
+fatcleanup(already_newline)
+ int already_newline;
+{
+ VOID fprintf(stderr, already_newline+"\n%s aborted\n", cmdid);
+ exiterr();
+}
+
+ static void
+startsay(s, t)
+ const char *s, *t;
+{
+ oflush();
+ if (s)
+ aprintf(stderr, "%s: %s: %s", cmdid, s, t);
+ else
+ aprintf(stderr, "%s: %s", cmdid, t);
+}
+
+ static void
+fatsay(s)
+ char const *s;
+{
+ startsay(s, "");
+}
+
+ static void
+errsay(s)
+ char const *s;
+{
+ fatsay(s);
+ nerror++;
+}
+
+ static void
+warnsay(s)
+ char const *s;
+{
+ startsay(s, "warning: ");
+}
+
+void eerror(s) char const *s; { enerror(errno,s); }
+
+ void
+enerror(e,s)
+ int e;
+ char const *s;
+{
+ errsay((char const*)0);
+ errno = e;
+ perror(s);
+ eflush();
+}
+
+void efaterror(s) char const *s; { enfaterror(errno,s); }
+
+ void
+enfaterror(e,s)
+ int e;
+ char const *s;
+{
+ fatsay((char const*)0);
+ errno = e;
+ perror(s);
+ fatcleanup(true);
+}
+
+#if has_prototypes
+ void
+error(char const *format,...)
+#else
+ /*VARARGS1*/ void error(format, va_alist) char const *format; va_dcl
+#endif
+/* non-fatal error */
+{
+ va_list args;
+ errsay((char const*)0);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n',stderr);
+ eflush();
+}
+
+#if has_prototypes
+ void
+rcserror(char const *format,...)
+#else
+ /*VARARGS1*/ void rcserror(format, va_alist) char const *format; va_dcl
+#endif
+/* non-fatal RCS file error */
+{
+ va_list args;
+ errsay(RCSname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n',stderr);
+ eflush();
+}
+
+#if has_prototypes
+ void
+workerror(char const *format,...)
+#else
+ /*VARARGS1*/ void workerror(format, va_alist) char const *format; va_dcl
+#endif
+/* non-fatal working file error */
+{
+ va_list args;
+ errsay(workname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n',stderr);
+ eflush();
+}
+
+#if has_prototypes
+ void
+fatserror(char const *format,...)
+#else
+ /*VARARGS1*/ void
+ fatserror(format, va_alist) char const *format; va_dcl
+#endif
+/* fatal RCS file syntax error */
+{
+ va_list args;
+ oflush();
+ VOID fprintf(stderr, "%s: %s:%ld: ", cmdid, RCSname, rcsline);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ fatcleanup(false);
+}
+
+#if has_prototypes
+ void
+faterror(char const *format,...)
+#else
+ /*VARARGS1*/ void faterror(format, va_alist)
+ char const *format; va_dcl
+#endif
+/* fatal error, terminates program after cleanup */
+{
+ va_list args;
+ fatsay((char const*)0);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ fatcleanup(false);
+}
+
+#if has_prototypes
+ void
+rcsfaterror(char const *format,...)
+#else
+ /*VARARGS1*/ void rcsfaterror(format, va_alist)
+ char const *format; va_dcl
+#endif
+/* fatal RCS file error, terminates program after cleanup */
+{
+ va_list args;
+ fatsay(RCSname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ fatcleanup(false);
+}
+
+#if has_prototypes
+ void
+warn(char const *format,...)
+#else
+ /*VARARGS1*/ void warn(format, va_alist) char const *format; va_dcl
+#endif
+/* warning */
+{
+ va_list args;
+ if (!quietflag) {
+ warnsay((char *)0);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n', stderr);
+ eflush();
+ }
+}
+
+#if has_prototypes
+ void
+rcswarn(char const *format,...)
+#else
+ /*VARARGS1*/ void rcswarn(format, va_alist) char const *format; va_dcl
+#endif
+/* RCS file warning */
+{
+ va_list args;
+ if (!quietflag) {
+ warnsay(RCSname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n', stderr);
+ eflush();
+ }
+}
+
+#if has_prototypes
+ void
+workwarn(char const *format,...)
+#else
+ /*VARARGS1*/ void workwarn(format, va_alist) char const *format; va_dcl
+#endif
+/* working file warning */
+{
+ va_list args;
+ if (!quietflag) {
+ warnsay(workname);
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ afputc('\n', stderr);
+ eflush();
+ }
+}
+
+ void
+redefined(c)
+ int c;
+{
+ warn("redefinition of -%c option", c);
+}
+
+#if has_prototypes
+ void
+diagnose(char const *format,...)
+#else
+ /*VARARGS1*/ void diagnose(format, va_alist) char const *format; va_dcl
+#endif
+/* prints a diagnostic message */
+/* Unlike the other routines, it does not append a newline. */
+/* This lets some callers suppress the newline, and is faster */
+/* in implementations that flush stderr just at the end of each printf. */
+{
+ va_list args;
+ if (!quietflag) {
+ oflush();
+ vararg_start(args, format);
+ fvfprintf(stderr, format, args);
+ va_end(args);
+ eflush();
+ }
+}
+
+
+
+ void
+afputc(c, f)
+/* afputc(c,f); acts like aputc_(c,f) but is smaller and slower. */
+ int c;
+ register FILE *f;
+{
+ aputc_(c,f)
+}
+
+
+ void
+aputs(s, iop)
+ char const *s;
+ FILE *iop;
+/* Function: Put string s on file iop, abort on error.
+ */
+{
+#if has_fputs
+ if (fputs(s, iop) < 0)
+ Oerror();
+#else
+ awrite(s, strlen(s), iop);
+#endif
+}
+
+
+
+ void
+#if has_prototypes
+fvfprintf(FILE *stream, char const *format, va_list args)
+#else
+ fvfprintf(stream,format,args) FILE *stream; char *format; va_list args;
+#endif
+/* like vfprintf, except abort program on error */
+{
+#if has_vfprintf
+ if (vfprintf(stream, format, args) < 0)
+ Oerror();
+#else
+# if has__doprintf
+ _doprintf(stream, format, args);
+# else
+# if has__doprnt
+ _doprnt(format, args, stream);
+# else
+ int *a = (int *)args;
+ VOID fprintf(stream, format,
+ a[0], a[1], a[2], a[3], a[4],
+ a[5], a[6], a[7], a[8], a[9]
+ );
+# endif
+# endif
+ if (ferror(stream))
+ Oerror();
+#endif
+}
+
+#if has_prototypes
+ void
+aprintf(FILE *iop, char const *fmt, ...)
+#else
+ /*VARARGS2*/ void
+aprintf(iop, fmt, va_alist)
+FILE *iop;
+char const *fmt;
+va_dcl
+#endif
+/* Function: formatted output. Same as fprintf in stdio,
+ * but aborts program on error
+ */
+{
+ va_list ap;
+ vararg_start(ap, fmt);
+ fvfprintf(iop, fmt, ap);
+ va_end(ap);
+}
+
+
+
+#ifdef LEXDB
+/* test program reading a stream of lexemes and printing the tokens.
+ */
+
+
+
+ int
+main(argc,argv)
+int argc; char * argv[];
+{
+ cmdid="lextest";
+ if (argc<2) {
+ aputs("No input file\n",stderr);
+ exitmain(EXIT_FAILURE);
+ }
+ if (!(finptr=Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
+ faterror("can't open input file %s",argv[1]);
+ }
+ Lexinit();
+ while (!eoflex()) {
+ switch (nexttok) {
+
+ case ID:
+ VOID printf("ID: %s",NextString);
+ break;
+
+ case NUM:
+ if (hshenter)
+ VOID printf("NUM: %s, index: %d",nexthsh->num, nexthsh-hshtab);
+ else
+ VOID printf("NUM, unentered: %s",NextString);
+ hshenter = !hshenter; /*alternate between dates and numbers*/
+ break;
+
+ case COLON:
+ VOID printf("COLON"); break;
+
+ case SEMI:
+ VOID printf("SEMI"); break;
+
+ case STRING:
+ readstring();
+ VOID printf("STRING"); break;
+
+ case UNKN:
+ VOID printf("UNKN"); break;
+
+ default:
+ VOID printf("DEFAULT"); break;
+ }
+ VOID printf(" | ");
+ nextlex();
+ }
+ exitmain(EXIT_SUCCESS);
+}
+
+void exiterr() { _exit(EXIT_FAILURE); }
+
+
+#endif
diff --git a/gnu/usr.bin/rcs/lib/rcsmap.c b/gnu/usr.bin/rcs/lib/rcsmap.c
new file mode 100644
index 0000000..89fb08d
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsmap.c
@@ -0,0 +1,69 @@
+/* RCS map of character types */
+
+/* Copyright (C) 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1995 by Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#include "rcsbase.h"
+
+libId(mapId, "$FreeBSD$")
+
+/* map of character types */
+/* ISO 8859/1 (Latin-1) */
+enum tokens const ctab[] = {
+ UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
+ SPACE, SPACE, NEWLN, SPACE, SPACE, SPACE, UNKN, UNKN,
+ UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
+ UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
+ SPACE, IDCHAR, IDCHAR, IDCHAR, DELIM, IDCHAR, IDCHAR, IDCHAR,
+ IDCHAR, IDCHAR, IDCHAR, IDCHAR, DELIM, IDCHAR, PERIOD, IDCHAR,
+ DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
+ DIGIT, DIGIT, COLON, SEMI, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
+ SBEGIN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+ LETTER, LETTER, LETTER, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
+ IDCHAR, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
+ Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
+ Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
+ Letter, Letter, Letter, IDCHAR, IDCHAR, IDCHAR, IDCHAR, UNKN,
+ UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
+ UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
+ UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
+ UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
+ IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
+ IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
+ IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
+ IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR, IDCHAR,
+ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
+ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, IDCHAR,
+ LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, Letter,
+ Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
+ Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter,
+ Letter, Letter, Letter, Letter, Letter, Letter, Letter, IDCHAR,
+ Letter, Letter, Letter, Letter, Letter, Letter, Letter, Letter
+};
diff --git a/gnu/usr.bin/rcs/lib/rcsrev.c b/gnu/usr.bin/rcs/lib/rcsrev.c
new file mode 100644
index 0000000..12c6c43
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsrev.c
@@ -0,0 +1,911 @@
+/* Handle RCS revision numbers. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.10 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.9 1995/06/01 16:23:43 eggert
+ * (cmpdate, normalizeyear): New functions work around MKS RCS incompatibility.
+ * (cmpnum, compartial): s[d] -> *(s+d) to work around Cray compiler bug.
+ * (genrevs, genbranch): cmpnum -> cmpdate
+ *
+ * Revision 5.8 1994/03/17 14:05:48 eggert
+ * Remove lint.
+ *
+ * Revision 5.7 1993/11/09 17:40:15 eggert
+ * Fix format string typos.
+ *
+ * Revision 5.6 1993/11/03 17:42:27 eggert
+ * Revision number `.N' now stands for `D.N', where D is the default branch.
+ * Add -z. Improve quality of diagnostics. Add `namedrev' for Name support.
+ *
+ * Revision 5.5 1992/07/28 16:12:44 eggert
+ * Identifiers may now start with a digit. Avoid `unsigned'.
+ *
+ * Revision 5.4 1992/01/06 02:42:34 eggert
+ * while (E) ; -> while (E) continue;
+ *
+ * Revision 5.3 1991/08/19 03:13:55 eggert
+ * Add `-r$', `-rB.'. Remove botches like `<now>' from messages. Tune.
+ *
+ * Revision 5.2 1991/04/21 11:58:28 eggert
+ * Add tiprev().
+ *
+ * Revision 5.1 1991/02/25 07:12:43 eggert
+ * Avoid overflow when comparing revision numbers.
+ *
+ * Revision 5.0 1990/08/22 08:13:43 eggert
+ * Remove compile-time limits; use malloc instead.
+ * Ansify and Posixate. Tune.
+ * Remove possibility of an internal error. Remove lint.
+ *
+ * Revision 4.5 89/05/01 15:13:22 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.4 87/12/18 11:45:22 narten
+ * more lint cleanups. Also, the NOTREACHED comment is no longer necessary,
+ * since there's now a return value there with a value. (Guy Harris)
+ *
+ * Revision 4.3 87/10/18 10:38:42 narten
+ * Updating version numbers. Changes relative to version 1.1 actually
+ * relative to 4.1
+ *
+ * Revision 1.3 87/09/24 14:00:37 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:37 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/03/25 21:10:45 wft
+ * Only changed $Header to $Id.
+ *
+ * Revision 3.4 82/12/04 13:24:08 wft
+ * Replaced getdelta() with gettree().
+ *
+ * Revision 3.3 82/11/28 21:33:15 wft
+ * fixed compartial() and compnum() for nil-parameters; fixed nils
+ * in error messages. Testprogram output shortenend.
+ *
+ * Revision 3.2 82/10/18 21:19:47 wft
+ * renamed compnum->cmpnum, compnumfld->cmpnumfld,
+ * numericrevno->numricrevno.
+ *
+ * Revision 3.1 82/10/11 19:46:09 wft
+ * changed expandsym() to check for source==nil; returns zero length string
+ * in that case.
+ */
+
+#include "rcsbase.h"
+
+libId(revId, "$FreeBSD$")
+
+static char const *branchtip P((char const*));
+static char const *lookupsym P((char const*));
+static char const *normalizeyear P((char const*,char[5]));
+static struct hshentry *genbranch P((struct hshentry const*,char const*,int,char const*,char const*,char const*,struct hshentries**));
+static void absent P((char const*,int));
+static void cantfindbranch P((char const*,char const[datesize],char const*,char const*));
+static void store1 P((struct hshentries***,struct hshentry*));
+
+
+
+ int
+countnumflds(s)
+ char const *s;
+/* Given a pointer s to a dotted number (date or revision number),
+ * countnumflds returns the number of digitfields in s.
+ */
+{
+ register char const *sp;
+ register int count;
+ if (!(sp=s) || !*sp)
+ return 0;
+ count = 1;
+ do {
+ if (*sp++ == '.') count++;
+ } while (*sp);
+ return(count);
+}
+
+ void
+getbranchno(revno,branchno)
+ char const *revno;
+ struct buf *branchno;
+/* Given a revision number revno, getbranchno copies the number of the branch
+ * on which revno is into branchno. If revno itself is a branch number,
+ * it is copied unchanged.
+ */
+{
+ register int numflds;
+ register char *tp;
+
+ bufscpy(branchno, revno);
+ numflds=countnumflds(revno);
+ if (!(numflds & 1)) {
+ tp = branchno->string;
+ while (--numflds)
+ while (*tp++ != '.')
+ continue;
+ *(tp-1)='\0';
+ }
+}
+
+
+
+int cmpnum(num1, num2)
+ char const *num1, *num2;
+/* compares the two dotted numbers num1 and num2 lexicographically
+ * by field. Individual fields are compared numerically.
+ * returns <0, 0, >0 if num1<num2, num1==num2, and num1>num2, resp.
+ * omitted fields are assumed to be higher than the existing ones.
+*/
+{
+ register char const *s1, *s2;
+ register size_t d1, d2;
+ register int r;
+
+ s1 = num1 ? num1 : "";
+ s2 = num2 ? num2 : "";
+
+ for (;;) {
+ /* Give precedence to shorter one. */
+ if (!*s1)
+ return (unsigned char)*s2;
+ if (!*s2)
+ return -1;
+
+ /* Strip leading zeros, then find number of digits. */
+ while (*s1=='0') ++s1;
+ while (*s2=='0') ++s2;
+ for (d1=0; isdigit(*(s1+d1)); d1++) continue;
+ for (d2=0; isdigit(*(s2+d2)); d2++) continue;
+
+ /* Do not convert to integer; it might overflow! */
+ if (d1 != d2)
+ return d1<d2 ? -1 : 1;
+ if ((r = memcmp(s1, s2, d1)))
+ return r;
+ s1 += d1;
+ s2 += d1;
+
+ /* skip '.' */
+ if (*s1) s1++;
+ if (*s2) s2++;
+ }
+}
+
+
+
+int cmpnumfld(num1, num2, fld)
+ char const *num1, *num2;
+ int fld;
+/* Compare the two dotted numbers at field fld.
+ * num1 and num2 must have at least fld fields.
+ * fld must be positive.
+*/
+{
+ register char const *s1, *s2;
+ register size_t d1, d2;
+
+ s1 = num1;
+ s2 = num2;
+ /* skip fld-1 fields */
+ while (--fld) {
+ while (*s1++ != '.')
+ continue;
+ while (*s2++ != '.')
+ continue;
+ }
+ /* Now s1 and s2 point to the beginning of the respective fields */
+ while (*s1=='0') ++s1; for (d1=0; isdigit(*(s1+d1)); d1++) continue;
+ while (*s2=='0') ++s2; for (d2=0; isdigit(*(s2+d2)); d2++) continue;
+
+ return d1<d2 ? -1 : d1==d2 ? memcmp(s1,s2,d1) : 1;
+}
+
+
+ int
+cmpdate(d1, d2)
+ char const *d1, *d2;
+/*
+* Compare the two dates. This is just like cmpnum,
+* except that for compatibility with old versions of RCS,
+* 1900 is added to dates with two-digit years.
+*/
+{
+ char year1[5], year2[5];
+ int r = cmpnumfld(normalizeyear(d1,year1), normalizeyear(d2,year2), 1);
+
+ if (r)
+ return r;
+ else {
+ while (isdigit(*d1)) d1++; d1 += *d1=='.';
+ while (isdigit(*d2)) d2++; d2 += *d2=='.';
+ return cmpnum(d1, d2);
+ }
+}
+
+ static char const *
+normalizeyear(date, year)
+ char const *date;
+ char year[5];
+{
+ if (isdigit(date[0]) && isdigit(date[1]) && !isdigit(date[2])) {
+ year[0] = '1';
+ year[1] = '9';
+ year[2] = date[0];
+ year[3] = date[1];
+ year[4] = 0;
+ return year;
+ } else
+ return date;
+}
+
+
+ static void
+cantfindbranch(revno, date, author, state)
+ char const *revno, date[datesize], *author, *state;
+{
+ char datebuf[datesize + zonelenmax];
+
+ rcserror("No revision on branch %s has%s%s%s%s%s%s.",
+ revno,
+ date ? " a date before " : "",
+ date ? date2str(date,datebuf) : "",
+ author ? " and author "+(date?0:4) : "",
+ author ? author : "",
+ state ? " and state "+(date||author?0:4) : "",
+ state ? state : ""
+ );
+}
+
+ static void
+absent(revno, field)
+ char const *revno;
+ int field;
+{
+ struct buf t;
+ bufautobegin(&t);
+ rcserror("%s %s absent", field&1?"revision":"branch",
+ partialno(&t,revno,field)
+ );
+ bufautoend(&t);
+}
+
+
+ int
+compartial(num1, num2, length)
+ char const *num1, *num2;
+ int length;
+
+/* compare the first "length" fields of two dot numbers;
+ the omitted field is considered to be larger than any number */
+/* restriction: at least one number has length or more fields */
+
+{
+ register char const *s1, *s2;
+ register size_t d1, d2;
+ register int r;
+
+ s1 = num1; s2 = num2;
+ if (!s1) return 1;
+ if (!s2) return -1;
+
+ for (;;) {
+ if (!*s1) return 1;
+ if (!*s2) return -1;
+
+ while (*s1=='0') ++s1; for (d1=0; isdigit(*(s1+d1)); d1++) continue;
+ while (*s2=='0') ++s2; for (d2=0; isdigit(*(s2+d2)); d2++) continue;
+
+ if (d1 != d2)
+ return d1<d2 ? -1 : 1;
+ if ((r = memcmp(s1, s2, d1)))
+ return r;
+ if (!--length)
+ return 0;
+
+ s1 += d1;
+ s2 += d1;
+
+ if (*s1 == '.') s1++;
+ if (*s2 == '.') s2++;
+ }
+}
+
+
+char * partialno(rev1,rev2,length)
+ struct buf *rev1;
+ char const *rev2;
+ register int length;
+/* Function: Copies length fields of revision number rev2 into rev1.
+ * Return rev1's string.
+ */
+{
+ register char *r1;
+
+ bufscpy(rev1, rev2);
+ r1 = rev1->string;
+ while (length) {
+ while (*r1!='.' && *r1)
+ ++r1;
+ ++r1;
+ length--;
+ }
+ /* eliminate last '.'*/
+ *(r1-1)='\0';
+ return rev1->string;
+}
+
+
+
+
+ static void
+store1(store, next)
+ struct hshentries ***store;
+ struct hshentry *next;
+/*
+ * Allocate a new list node that addresses NEXT.
+ * Append it to the list that **STORE is the end pointer of.
+ */
+{
+ register struct hshentries *p;
+
+ p = ftalloc(struct hshentries);
+ p->first = next;
+ **store = p;
+ *store = &p->rest;
+}
+
+struct hshentry * genrevs(revno,date,author,state,store)
+ char const *revno, *date, *author, *state;
+ struct hshentries **store;
+/* Function: finds the deltas needed for reconstructing the
+ * revision given by revno, date, author, and state, and stores pointers
+ * to these deltas into a list whose starting address is given by store.
+ * The last delta (target delta) is returned.
+ * If the proper delta could not be found, 0 is returned.
+ */
+{
+ int length;
+ register struct hshentry * next;
+ int result;
+ char const *branchnum;
+ struct buf t;
+ char datebuf[datesize + zonelenmax];
+
+ bufautobegin(&t);
+
+ if (!(next = Head)) {
+ rcserror("RCS file empty");
+ goto norev;
+ }
+
+ length = countnumflds(revno);
+
+ if (length >= 1) {
+ /* at least one field; find branch exactly */
+ while ((result=cmpnumfld(revno,next->num,1)) < 0) {
+ store1(&store, next);
+ next = next->next;
+ if (!next) {
+ rcserror("branch number %s too low", partialno(&t,revno,1));
+ goto norev;
+ }
+ }
+
+ if (result>0) {
+ absent(revno, 1);
+ goto norev;
+ }
+ }
+ if (length<=1){
+ /* pick latest one on given branch */
+ branchnum = next->num; /* works even for empty revno*/
+ while (next &&
+ cmpnumfld(branchnum,next->num,1) == 0 &&
+ (
+ (date && cmpdate(date,next->date) < 0) ||
+ (author && strcmp(author,next->author) != 0) ||
+ (state && strcmp(state,next->state) != 0)
+ )
+ )
+ {
+ store1(&store, next);
+ next=next->next;
+ }
+ if (!next ||
+ (cmpnumfld(branchnum,next->num,1)!=0))/*overshot*/ {
+ cantfindbranch(
+ length ? revno : partialno(&t,branchnum,1),
+ date, author, state
+ );
+ goto norev;
+ } else {
+ store1(&store, next);
+ }
+ *store = 0;
+ return next;
+ }
+
+ /* length >=2 */
+ /* find revision; may go low if length==2*/
+ while ((result=cmpnumfld(revno,next->num,2)) < 0 &&
+ (cmpnumfld(revno,next->num,1)==0) ) {
+ store1(&store, next);
+ next = next->next;
+ if (!next)
+ break;
+ }
+
+ if (!next || cmpnumfld(revno,next->num,1) != 0) {
+ rcserror("revision number %s too low", partialno(&t,revno,2));
+ goto norev;
+ }
+ if ((length>2) && (result!=0)) {
+ absent(revno, 2);
+ goto norev;
+ }
+
+ /* print last one */
+ store1(&store, next);
+
+ if (length>2)
+ return genbranch(next,revno,length,date,author,state,store);
+ else { /* length == 2*/
+ if (date && cmpdate(date,next->date)<0) {
+ rcserror("Revision %s has date %s.",
+ next->num,
+ date2str(next->date, datebuf)
+ );
+ return 0;
+ }
+ if (author && strcmp(author,next->author)!=0) {
+ rcserror("Revision %s has author %s.",
+ next->num, next->author
+ );
+ return 0;
+ }
+ if (state && strcmp(state,next->state)!=0) {
+ rcserror("Revision %s has state %s.",
+ next->num,
+ next->state ? next->state : "<empty>"
+ );
+ return 0;
+ }
+ *store = 0;
+ return next;
+ }
+
+ norev:
+ bufautoend(&t);
+ return 0;
+}
+
+
+
+
+ static struct hshentry *
+genbranch(bpoint, revno, length, date, author, state, store)
+ struct hshentry const *bpoint;
+ char const *revno;
+ int length;
+ char const *date, *author, *state;
+ struct hshentries **store;
+/* Function: given a branchpoint, a revision number, date, author, and state,
+ * genbranch finds the deltas necessary to reconstruct the given revision
+ * from the branch point on.
+ * Pointers to the found deltas are stored in a list beginning with store.
+ * revno must be on a side branch.
+ * Return 0 on error.
+ */
+{
+ int field;
+ register struct hshentry * next, * trail;
+ register struct branchhead const *bhead;
+ int result;
+ struct buf t;
+ char datebuf[datesize + zonelenmax];
+
+ field = 3;
+ bhead = bpoint->branches;
+
+ do {
+ if (!bhead) {
+ bufautobegin(&t);
+ rcserror("no side branches present for %s",
+ partialno(&t,revno,field-1)
+ );
+ bufautoend(&t);
+ return 0;
+ }
+
+ /*find branch head*/
+ /*branches are arranged in increasing order*/
+ while (0 < (result=cmpnumfld(revno,bhead->hsh->num,field))) {
+ bhead = bhead->nextbranch;
+ if (!bhead) {
+ bufautobegin(&t);
+ rcserror("branch number %s too high",
+ partialno(&t,revno,field)
+ );
+ bufautoend(&t);
+ return 0;
+ }
+ }
+
+ if (result<0) {
+ absent(revno, field);
+ return 0;
+ }
+
+ next = bhead->hsh;
+ if (length==field) {
+ /* pick latest one on that branch */
+ trail = 0;
+ do { if ((!date || cmpdate(date,next->date)>=0) &&
+ (!author || strcmp(author,next->author)==0) &&
+ (!state || strcmp(state,next->state)==0)
+ ) trail = next;
+ next=next->next;
+ } while (next);
+
+ if (!trail) {
+ cantfindbranch(revno, date, author, state);
+ return 0;
+ } else { /* print up to last one suitable */
+ next = bhead->hsh;
+ while (next!=trail) {
+ store1(&store, next);
+ next=next->next;
+ }
+ store1(&store, next);
+ }
+ *store = 0;
+ return next;
+ }
+
+ /* length > field */
+ /* find revision */
+ /* check low */
+ if (cmpnumfld(revno,next->num,field+1)<0) {
+ bufautobegin(&t);
+ rcserror("revision number %s too low",
+ partialno(&t,revno,field+1)
+ );
+ bufautoend(&t);
+ return 0;
+ }
+ do {
+ store1(&store, next);
+ trail = next;
+ next = next->next;
+ } while (next && cmpnumfld(revno,next->num,field+1)>=0);
+
+ if ((length>field+1) && /*need exact hit */
+ (cmpnumfld(revno,trail->num,field+1) !=0)){
+ absent(revno, field+1);
+ return 0;
+ }
+ if (length == field+1) {
+ if (date && cmpdate(date,trail->date)<0) {
+ rcserror("Revision %s has date %s.",
+ trail->num,
+ date2str(trail->date, datebuf)
+ );
+ return 0;
+ }
+ if (author && strcmp(author,trail->author)!=0) {
+ rcserror("Revision %s has author %s.",
+ trail->num, trail->author
+ );
+ return 0;
+ }
+ if (state && strcmp(state,trail->state)!=0) {
+ rcserror("Revision %s has state %s.",
+ trail->num,
+ trail->state ? trail->state : "<empty>"
+ );
+ return 0;
+ }
+ }
+ bhead = trail->branches;
+
+ } while ((field+=2) <= length);
+ *store = 0;
+ return trail;
+}
+
+
+ static char const *
+lookupsym(id)
+ char const *id;
+/* Function: looks up id in the list of symbolic names starting
+ * with pointer SYMBOLS, and returns a pointer to the corresponding
+ * revision number. Return 0 if not present.
+ */
+{
+ register struct assoc const *next;
+ for (next = Symbols; next; next = next->nextassoc)
+ if (strcmp(id, next->symbol)==0)
+ return next->num;
+ return 0;
+}
+
+int expandsym(source, target)
+ char const *source;
+ struct buf *target;
+/* Function: Source points to a revision number. Expandsym copies
+ * the number to target, but replaces all symbolic fields in the
+ * source number with their numeric values.
+ * Expand a branch followed by `.' to the latest revision on that branch.
+ * Ignore `.' after a revision. Remove leading zeros.
+ * returns false on error;
+ */
+{
+ return fexpandsym(source, target, (RILE*)0);
+}
+
+ int
+fexpandsym(source, target, fp)
+ char const *source;
+ struct buf *target;
+ RILE *fp;
+/* Same as expandsym, except if FP is nonzero, it is used to expand KDELIM. */
+{
+ register char const *sp, *bp;
+ register char *tp;
+ char const *tlim;
+ int dots;
+
+ sp = source;
+ bufalloc(target, 1);
+ tp = target->string;
+ if (!sp || !*sp) { /* Accept 0 pointer as a legal value. */
+ *tp='\0';
+ return true;
+ }
+ if (sp[0] == KDELIM && !sp[1]) {
+ if (!getoldkeys(fp))
+ return false;
+ if (!*prevrev.string) {
+ workerror("working file lacks revision number");
+ return false;
+ }
+ bufscpy(target, prevrev.string);
+ return true;
+ }
+ tlim = tp + target->size;
+ dots = 0;
+
+ for (;;) {
+ register char *p = tp;
+ size_t s = tp - target->string;
+ int id = false;
+ for (;;) {
+ switch (ctab[(unsigned char)*sp]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ id = true;
+ /* fall into */
+ case DIGIT:
+ if (tlim <= p)
+ p = bufenlarge(target, &tlim);
+ *p++ = *sp++;
+ continue;
+
+ default:
+ break;
+ }
+ break;
+ }
+ if (tlim <= p)
+ p = bufenlarge(target, &tlim);
+ *p = 0;
+ tp = target->string + s;
+
+ if (id) {
+ bp = lookupsym(tp);
+ if (!bp) {
+ rcserror("Symbolic name `%s' is undefined.",tp);
+ return false;
+ }
+ } else {
+ /* skip leading zeros */
+ for (bp = tp; *bp=='0' && isdigit(bp[1]); bp++)
+ continue;
+
+ if (!*bp)
+ if (s || *sp!='.')
+ break;
+ else {
+ /* Insert default branch before initial `.'. */
+ char const *b;
+ if (Dbranch)
+ b = Dbranch;
+ else if (Head)
+ b = Head->num;
+ else
+ break;
+ getbranchno(b, target);
+ bp = tp = target->string;
+ tlim = tp + target->size;
+ }
+ }
+
+ while ((*tp++ = *bp++))
+ if (tlim <= tp)
+ tp = bufenlarge(target, &tlim);
+
+ switch (*sp++) {
+ case '\0':
+ return true;
+
+ case '.':
+ if (!*sp) {
+ if (dots & 1)
+ break;
+ if (!(bp = branchtip(target->string)))
+ return false;
+ bufscpy(target, bp);
+ return true;
+ }
+ ++dots;
+ tp[-1] = '.';
+ continue;
+ }
+ break;
+ }
+
+ rcserror("improper revision number: %s", source);
+ return false;
+}
+
+ char const *
+namedrev(name, delta)
+ char const *name;
+ struct hshentry *delta;
+/* Yield NAME if it names DELTA, 0 otherwise. */
+{
+ if (name) {
+ char const *id = 0, *p, *val;
+ for (p = name; ; p++)
+ switch (ctab[(unsigned char)*p]) {
+ case IDCHAR:
+ case LETTER:
+ case Letter:
+ id = name;
+ break;
+
+ case DIGIT:
+ break;
+
+ case UNKN:
+ if (!*p && id &&
+ (val = lookupsym(id)) &&
+ strcmp(val, delta->num) == 0
+ )
+ return id;
+ /* fall into */
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+ static char const *
+branchtip(branch)
+ char const *branch;
+{
+ struct hshentry *h;
+ struct hshentries *hs;
+
+ h = genrevs(branch, (char*)0, (char*)0, (char*)0, &hs);
+ return h ? h->num : (char const*)0;
+}
+
+ char const *
+tiprev()
+{
+ return Dbranch ? branchtip(Dbranch) : Head ? Head->num : (char const*)0;
+}
+
+
+
+#ifdef REVTEST
+
+/*
+* Test the routines that generate a sequence of delta numbers
+* needed to regenerate a given delta.
+*/
+
+char const cmdid[] = "revtest";
+
+ int
+main(argc,argv)
+int argc; char * argv[];
+{
+ static struct buf numricrevno;
+ char symrevno[100]; /* used for input of revision numbers */
+ char author[20];
+ char state[20];
+ char date[20];
+ struct hshentries *gendeltas;
+ struct hshentry * target;
+ int i;
+
+ if (argc<2) {
+ aputs("No input file\n",stderr);
+ exitmain(EXIT_FAILURE);
+ }
+ if (!(finptr=Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
+ faterror("can't open input file %s", argv[1]);
+ }
+ Lexinit();
+ getadmin();
+
+ gettree();
+
+ getdesc(false);
+
+ do {
+ /* all output goes to stderr, to have diagnostics and */
+ /* errors in sequence. */
+ aputs("\nEnter revision number or <return> or '.': ",stderr);
+ if (!fgets(symrevno, 100, stdin)) break;
+ if (*symrevno == '.') break;
+ aprintf(stderr,"%s;\n",symrevno);
+ expandsym(symrevno,&numricrevno);
+ aprintf(stderr,"expanded number: %s; ",numricrevno.string);
+ aprintf(stderr,"Date: ");
+ fgets(date, 20, stdin); aprintf(stderr,"%s; ",date);
+ aprintf(stderr,"Author: ");
+ fgets(author, 20, stdin); aprintf(stderr,"%s; ",author);
+ aprintf(stderr,"State: ");
+ fgets(state, 20, stdin); aprintf(stderr, "%s;\n", state);
+ target = genrevs(numricrevno.string, *date?date:(char *)0, *author?author:(char *)0,
+ *state?state:(char*)0, &gendeltas);
+ if (target) {
+ while (gendeltas) {
+ aprintf(stderr,"%s\n",gendeltas->first->num);
+ gendeltas = gendeltas->next;
+ }
+ }
+ } while (true);
+ aprintf(stderr,"done\n");
+ exitmain(EXIT_SUCCESS);
+}
+
+void exiterr() { _exit(EXIT_FAILURE); }
+
+#endif
diff --git a/gnu/usr.bin/rcs/lib/rcssyn.c b/gnu/usr.bin/rcs/lib/rcssyn.c
new file mode 100644
index 0000000..07f155b
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcssyn.c
@@ -0,0 +1,681 @@
+/* RCS file syntactic analysis */
+
+/******************************************************************************
+ * Syntax Analysis.
+ * Keyword table
+ * Testprogram: define SYNTEST
+ * Compatibility with Release 2: define COMPAT2=1
+ ******************************************************************************
+ */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.15 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.14 1995/06/01 16:23:43 eggert
+ * (expand_names): Add "b" for -kb.
+ * (getdelta): Don't strip leading "19" from MKS RCS dates; see cmpdate.
+ *
+ * Revision 5.13 1994/03/20 04:52:58 eggert
+ * Remove lint.
+ *
+ * Revision 5.12 1993/11/03 17:42:27 eggert
+ * Parse MKS RCS dates; ignore \r in diff control lines.
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.11 1992/07/28 16:12:44 eggert
+ * Avoid `unsigned'. Statement macro names now end in _.
+ *
+ * Revision 5.10 1992/01/24 18:44:19 eggert
+ * Move put routines to rcsgen.c.
+ *
+ * Revision 5.9 1992/01/06 02:42:34 eggert
+ * ULONG_MAX/10 -> ULONG_MAX_OVER_10
+ * while (E) ; -> while (E) continue;
+ *
+ * Revision 5.8 1991/08/19 03:13:55 eggert
+ * Tune.
+ *
+ * Revision 5.7 1991/04/21 11:58:29 eggert
+ * Disambiguate names on shortname hosts.
+ * Fix errno bug. Add MS-DOS support.
+ *
+ * Revision 5.6 1991/02/28 19:18:51 eggert
+ * Fix null termination bug in reporting keyword expansion.
+ *
+ * Revision 5.5 1991/02/25 07:12:44 eggert
+ * Check diff output more carefully; avoid overflow.
+ *
+ * Revision 5.4 1990/11/01 05:28:48 eggert
+ * When ignoring unknown phrases, copy them to the output RCS file.
+ * Permit arbitrary data in logs and comment leaders.
+ * Don't check for nontext on initial checkin.
+ *
+ * Revision 5.3 1990/09/20 07:58:32 eggert
+ * Remove the test for non-text bytes; it caused more pain than it cured.
+ *
+ * Revision 5.2 1990/09/04 08:02:30 eggert
+ * Parse RCS files with no revisions.
+ * Don't strip leading white space from diff commands. Count RCS lines better.
+ *
+ * Revision 5.1 1990/08/29 07:14:06 eggert
+ * Add -kkvl. Clean old log messages too.
+ *
+ * Revision 5.0 1990/08/22 08:13:44 eggert
+ * Try to parse future RCS formats without barfing.
+ * Add -k. Don't require final newline.
+ * Remove compile-time limits; use malloc instead.
+ * Don't output branch keyword if there's no default branch,
+ * because RCS version 3 doesn't understand it.
+ * Tune. Remove lint.
+ * Add support for ISO 8859. Ansify and Posixate.
+ * Check that a newly checked-in file is acceptable as input to 'diff'.
+ * Check diff's output.
+ *
+ * Revision 4.6 89/05/01 15:13:32 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.5 88/08/09 19:13:21 eggert
+ * Allow cc -R; remove lint.
+ *
+ * Revision 4.4 87/12/18 11:46:16 narten
+ * more lint cleanups (Guy Harris)
+ *
+ * Revision 4.3 87/10/18 10:39:36 narten
+ * Updating version numbers. Changes relative to 1.1 actually relative to
+ * 4.1
+ *
+ * Revision 1.3 87/09/24 14:00:49 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:40 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/03/28 11:38:49 wft
+ * Added parsing and printing of default branch.
+ *
+ * Revision 3.6 83/01/15 17:46:50 wft
+ * Changed readdelta() to initialize selector and log-pointer.
+ * Changed puttree to check for selector==DELETE; putdtext() uses DELNUMFORM.
+ *
+ * Revision 3.5 82/12/08 21:58:58 wft
+ * renamed Commentleader to Commleader.
+ *
+ * Revision 3.4 82/12/04 13:24:40 wft
+ * Added routine gettree(), which updates keeplock after reading the
+ * delta tree.
+ *
+ * Revision 3.3 82/11/28 21:30:11 wft
+ * Reading and printing of Suffix removed; version COMPAT2 skips the
+ * Suffix for files of release 2 format. Fixed problems with printing nil.
+ *
+ * Revision 3.2 82/10/18 21:18:25 wft
+ * renamed putdeltatext to putdtext.
+ *
+ * Revision 3.1 82/10/11 19:45:11 wft
+ * made sure getc() returns into an integer.
+ */
+
+
+
+/* version COMPAT2 reads files of the format of release 2 and 3, but
+ * generates files of release 3 format. Need not be defined if no
+ * old RCS files generated with release 2 exist.
+ */
+
+#include "rcsbase.h"
+
+libId(synId, "$FreeBSD$")
+
+static char const *getkeyval P((char const*,enum tokens,int));
+static int getdelta P((void));
+static int strn2expmode P((char const*,size_t));
+static struct hshentry *getdnum P((void));
+static void badDiffOutput P((char const*)) exiting;
+static void diffLineNumberTooLarge P((char const*)) exiting;
+static void getsemi P((char const*));
+
+/* keyword table */
+
+char const
+ Kaccess[] = "access",
+ Kauthor[] = "author",
+ Kbranch[] = "branch",
+ Kcomment[] = "comment",
+ Kdate[] = "date",
+ Kdesc[] = "desc",
+ Kexpand[] = "expand",
+ Khead[] = "head",
+ Klocks[] = "locks",
+ Klog[] = "log",
+ Knext[] = "next",
+ Kstate[] = "state",
+ Kstrict[] = "strict",
+ Ksymbols[] = "symbols",
+ Ktext[] = "text";
+
+static char const
+#if COMPAT2
+ Ksuffix[] = "suffix",
+#endif
+ K_branches[]= "branches";
+
+static struct buf Commleader;
+struct cbuf Comment;
+struct cbuf Ignored;
+struct access * AccessList;
+struct assoc * Symbols;
+struct rcslock *Locks;
+int Expand;
+int StrictLocks;
+struct hshentry * Head;
+char const * Dbranch;
+int TotalDeltas;
+
+
+ static void
+getsemi(key)
+ char const *key;
+/* Get a semicolon to finish off a phrase started by KEY. */
+{
+ if (!getlex(SEMI))
+ fatserror("missing ';' after '%s'", key);
+}
+
+ static struct hshentry *
+getdnum()
+/* Get a delta number. */
+{
+ register struct hshentry *delta = getnum();
+ if (delta && countnumflds(delta->num)&1)
+ fatserror("%s isn't a delta number", delta->num);
+ return delta;
+}
+
+
+ void
+getadmin()
+/* Read an <admin> and initialize the appropriate global variables. */
+{
+ register char const *id;
+ struct access * newaccess;
+ struct assoc * newassoc;
+ struct rcslock *newlock;
+ struct hshentry * delta;
+ struct access **LastAccess;
+ struct assoc **LastSymbol;
+ struct rcslock **LastLock;
+ struct buf b;
+ struct cbuf cb;
+
+ TotalDeltas=0;
+
+ getkey(Khead);
+ Head = getdnum();
+ getsemi(Khead);
+
+ Dbranch = 0;
+ if (getkeyopt(Kbranch)) {
+ if ((delta = getnum()))
+ Dbranch = delta->num;
+ getsemi(Kbranch);
+ }
+
+
+#if COMPAT2
+ /* read suffix. Only in release 2 format */
+ if (getkeyopt(Ksuffix)) {
+ if (nexttok==STRING) {
+ readstring(); nextlex(); /* Throw away the suffix. */
+ } else if (nexttok==ID) {
+ nextlex();
+ }
+ getsemi(Ksuffix);
+ }
+#endif
+
+ getkey(Kaccess);
+ LastAccess = &AccessList;
+ while ((id = getid())) {
+ newaccess = ftalloc(struct access);
+ newaccess->login = id;
+ *LastAccess = newaccess;
+ LastAccess = &newaccess->nextaccess;
+ }
+ *LastAccess = 0;
+ getsemi(Kaccess);
+
+ getkey(Ksymbols);
+ LastSymbol = &Symbols;
+ while ((id = getid())) {
+ if (!getlex(COLON))
+ fatserror("missing ':' in symbolic name definition");
+ if (!(delta=getnum())) {
+ fatserror("missing number in symbolic name definition");
+ } else { /*add new pair to association list*/
+ newassoc = ftalloc(struct assoc);
+ newassoc->symbol=id;
+ newassoc->num = delta->num;
+ *LastSymbol = newassoc;
+ LastSymbol = &newassoc->nextassoc;
+ }
+ }
+ *LastSymbol = 0;
+ getsemi(Ksymbols);
+
+ getkey(Klocks);
+ LastLock = &Locks;
+ while ((id = getid())) {
+ if (!getlex(COLON))
+ fatserror("missing ':' in lock");
+ if (!(delta=getdnum())) {
+ fatserror("missing number in lock");
+ } else { /*add new pair to lock list*/
+ newlock = ftalloc(struct rcslock);
+ newlock->login=id;
+ newlock->delta=delta;
+ *LastLock = newlock;
+ LastLock = &newlock->nextlock;
+ }
+ }
+ *LastLock = 0;
+ getsemi(Klocks);
+
+ if ((StrictLocks = getkeyopt(Kstrict)))
+ getsemi(Kstrict);
+
+ clear_buf(&Comment);
+ if (getkeyopt(Kcomment)) {
+ if (nexttok==STRING) {
+ Comment = savestring(&Commleader);
+ nextlex();
+ }
+ getsemi(Kcomment);
+ }
+
+ Expand = KEYVAL_EXPAND;
+ if (getkeyopt(Kexpand)) {
+ if (nexttok==STRING) {
+ bufautobegin(&b);
+ cb = savestring(&b);
+ if ((Expand = strn2expmode(cb.string,cb.size)) < 0)
+ fatserror("unknown expand mode %.*s",
+ (int)cb.size, cb.string
+ );
+ bufautoend(&b);
+ nextlex();
+ }
+ getsemi(Kexpand);
+ }
+ Ignored = getphrases(Kdesc);
+}
+
+char const *const expand_names[] = {
+ /* These must agree with *_EXPAND in rcsbase.h. */
+ "kv", "kvl", "k", "v", "o", "b",
+ 0
+};
+
+ int
+str2expmode(s)
+ char const *s;
+/* Yield expand mode corresponding to S, or -1 if bad. */
+{
+ return strn2expmode(s, strlen(s));
+}
+
+ static int
+strn2expmode(s, n)
+ char const *s;
+ size_t n;
+{
+ char const *const *p;
+
+ for (p = expand_names; *p; ++p)
+ if (memcmp(*p,s,n) == 0 && !(*p)[n])
+ return p - expand_names;
+ return -1;
+}
+
+
+ void
+ignorephrases(key)
+ const char *key;
+/*
+* Ignore a series of phrases that do not start with KEY.
+* Stop when the next phrase starts with a token that is not an identifier,
+* or is KEY.
+*/
+{
+ for (;;) {
+ nextlex();
+ if (nexttok != ID || strcmp(NextString,key) == 0)
+ break;
+ warnignore();
+ hshenter=false;
+ for (;; nextlex()) {
+ switch (nexttok) {
+ case SEMI: hshenter=true; break;
+ case ID:
+ case NUM: ffree1(NextString); continue;
+ case STRING: readstring(); continue;
+ default: continue;
+ }
+ break;
+ }
+ }
+}
+
+
+ static int
+getdelta()
+/* Function: reads a delta block.
+ * returns false if the current block does not start with a number.
+ */
+{
+ register struct hshentry * Delta, * num;
+ struct branchhead **LastBranch, *NewBranch;
+
+ if (!(Delta = getdnum()))
+ return false;
+
+ hshenter = false; /*Don't enter dates into hashtable*/
+ Delta->date = getkeyval(Kdate, NUM, false);
+ hshenter=true; /*reset hshenter for revision numbers.*/
+
+ Delta->author = getkeyval(Kauthor, ID, false);
+
+ Delta->state = getkeyval(Kstate, ID, true);
+
+ getkey(K_branches);
+ LastBranch = &Delta->branches;
+ while ((num = getdnum())) {
+ NewBranch = ftalloc(struct branchhead);
+ NewBranch->hsh = num;
+ *LastBranch = NewBranch;
+ LastBranch = &NewBranch->nextbranch;
+ }
+ *LastBranch = 0;
+ getsemi(K_branches);
+
+ getkey(Knext);
+ Delta->next = num = getdnum();
+ getsemi(Knext);
+ Delta->lockedby = 0;
+ Delta->log.string = 0;
+ Delta->selector = true;
+ Delta->ig = getphrases(Kdesc);
+ TotalDeltas++;
+ return (true);
+}
+
+
+ void
+gettree()
+/* Function: Reads in the delta tree with getdelta(), then
+ * updates the lockedby fields.
+ */
+{
+ struct rcslock const *currlock;
+
+ while (getdelta())
+ continue;
+ currlock=Locks;
+ while (currlock) {
+ currlock->delta->lockedby = currlock->login;
+ currlock = currlock->nextlock;
+ }
+}
+
+
+ void
+getdesc(prdesc)
+int prdesc;
+/* Function: read in descriptive text
+ * nexttok is not advanced afterwards.
+ * If prdesc is set, the text is printed to stdout.
+ */
+{
+
+ getkeystring(Kdesc);
+ if (prdesc)
+ printstring(); /*echo string*/
+ else readstring(); /*skip string*/
+}
+
+
+
+
+
+
+ static char const *
+getkeyval(keyword, token, optional)
+ char const *keyword;
+ enum tokens token;
+ int optional;
+/* reads a pair of the form
+ * <keyword> <token> ;
+ * where token is one of <id> or <num>. optional indicates whether
+ * <token> is optional. A pointer to
+ * the actual character string of <id> or <num> is returned.
+ */
+{
+ register char const *val = 0;
+
+ getkey(keyword);
+ if (nexttok==token) {
+ val = NextString;
+ nextlex();
+ } else {
+ if (!optional)
+ fatserror("missing %s", keyword);
+ }
+ getsemi(keyword);
+ return(val);
+}
+
+
+ void
+unexpected_EOF()
+{
+ rcsfaterror("unexpected EOF in diff output");
+}
+
+ void
+initdiffcmd(dc)
+ register struct diffcmd *dc;
+/* Initialize *dc suitably for getdiffcmd(). */
+{
+ dc->adprev = 0;
+ dc->dafter = 0;
+}
+
+ static void
+badDiffOutput(buf)
+ char const *buf;
+{
+ rcsfaterror("bad diff output line: %s", buf);
+}
+
+ static void
+diffLineNumberTooLarge(buf)
+ char const *buf;
+{
+ rcsfaterror("diff line number too large: %s", buf);
+}
+
+ int
+getdiffcmd(finfile, delimiter, foutfile, dc)
+ RILE *finfile;
+ FILE *foutfile;
+ int delimiter;
+ struct diffcmd *dc;
+/* Get a editing command output by 'diff -n' from fin.
+ * The input is delimited by SDELIM if delimiter is set, EOF otherwise.
+ * Copy a clean version of the command to fout (if nonnull).
+ * Yield 0 for 'd', 1 for 'a', and -1 for EOF.
+ * Store the command's line number and length into dc->line1 and dc->nlines.
+ * Keep dc->adprev and dc->dafter up to date.
+ */
+{
+ register int c;
+ declarecache;
+ register FILE *fout;
+ register char *p;
+ register RILE *fin;
+ long line1, nlines, t;
+ char buf[BUFSIZ];
+
+ fin = finfile;
+ fout = foutfile;
+ setupcache(fin); cache(fin);
+ cachegeteof_(c, { if (delimiter) unexpected_EOF(); return -1; } )
+ if (delimiter) {
+ if (c==SDELIM) {
+ cacheget_(c)
+ if (c==SDELIM) {
+ buf[0] = c;
+ buf[1] = 0;
+ badDiffOutput(buf);
+ }
+ uncache(fin);
+ nextc = c;
+ if (fout)
+ aprintf(fout, "%c%c", SDELIM, c);
+ return -1;
+ }
+ }
+ p = buf;
+ do {
+ if (buf+BUFSIZ-2 <= p) {
+ rcsfaterror("diff output command line too long");
+ }
+ *p++ = c;
+ cachegeteof_(c, unexpected_EOF();)
+ } while (c != '\n');
+ uncache(fin);
+ if (delimiter)
+ ++rcsline;
+ *p = '\0';
+ for (p = buf+1; (c = *p++) == ' '; )
+ continue;
+ line1 = 0;
+ while (isdigit(c)) {
+ if (
+ LONG_MAX/10 < line1 ||
+ (t = line1 * 10, (line1 = t + (c - '0')) < t)
+ )
+ diffLineNumberTooLarge(buf);
+ c = *p++;
+ }
+ while (c == ' ')
+ c = *p++;
+ nlines = 0;
+ while (isdigit(c)) {
+ if (
+ LONG_MAX/10 < nlines ||
+ (t = nlines * 10, (nlines = t + (c - '0')) < t)
+ )
+ diffLineNumberTooLarge(buf);
+ c = *p++;
+ }
+ if (c == '\r')
+ c = *p++;
+ if (c || !nlines) {
+ badDiffOutput(buf);
+ }
+ if (line1+nlines < line1)
+ diffLineNumberTooLarge(buf);
+ switch (buf[0]) {
+ case 'a':
+ if (line1 < dc->adprev) {
+ rcsfaterror("backward insertion in diff output: %s", buf);
+ }
+ dc->adprev = line1 + 1;
+ break;
+ case 'd':
+ if (line1 < dc->adprev || line1 < dc->dafter) {
+ rcsfaterror("backward deletion in diff output: %s", buf);
+ }
+ dc->adprev = line1;
+ dc->dafter = line1 + nlines;
+ break;
+ default:
+ badDiffOutput(buf);
+ }
+ if (fout) {
+ aprintf(fout, "%s\n", buf);
+ }
+ dc->line1 = line1;
+ dc->nlines = nlines;
+ return buf[0] == 'a';
+}
+
+
+
+#ifdef SYNTEST
+
+/* Input an RCS file and print its internal data structures. */
+
+char const cmdid[] = "syntest";
+
+ int
+main(argc,argv)
+int argc; char * argv[];
+{
+
+ if (argc<2) {
+ aputs("No input file\n",stderr);
+ exitmain(EXIT_FAILURE);
+ }
+ if (!(finptr = Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
+ faterror("can't open input file %s", argv[1]);
+ }
+ Lexinit();
+ getadmin();
+ fdlock = STDOUT_FILENO;
+ putadmin();
+
+ gettree();
+
+ getdesc(true);
+
+ nextlex();
+
+ if (!eoflex()) {
+ fatserror("expecting EOF");
+ }
+ exitmain(EXIT_SUCCESS);
+}
+
+void exiterr() { _exit(EXIT_FAILURE); }
+
+#endif
diff --git a/gnu/usr.bin/rcs/lib/rcstime.c b/gnu/usr.bin/rcs/lib/rcstime.c
new file mode 100644
index 0000000..cfd4660
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcstime.c
@@ -0,0 +1,191 @@
+/* Convert between RCS time format and Posix and/or C formats. */
+
+/* Copyright 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#include "rcsbase.h"
+#include "partime.h"
+#include "maketime.h"
+
+libId(rcstimeId, "$FreeBSD$")
+
+static long zone_offset; /* seconds east of UTC, or TM_LOCAL_ZONE */
+static int use_zone_offset; /* if zero, use UTC without zone indication */
+
+/*
+* Convert Unix time to RCS format.
+* For compatibility with older versions of RCS,
+* dates from 1900 through 1999 are stored without the leading "19".
+*/
+ void
+time2date(unixtime,date)
+ time_t unixtime;
+ char date[datesize];
+{
+ register struct tm const *tm = time2tm(unixtime, RCSversion<VERSION(5));
+ VOID sprintf(date,
+# if has_printf_dot
+ "%.2d.%.2d.%.2d.%.2d.%.2d.%.2d",
+# else
+ "%02d.%02d.%02d.%02d.%02d.%02d",
+# endif
+ tm->tm_year + ((unsigned)tm->tm_year < 100 ? 0 : 1900),
+ tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec
+ );
+}
+
+/* Like str2time, except die if an error was found. */
+static time_t str2time_checked P((char const*,time_t,long));
+ static time_t
+str2time_checked(source, default_time, default_zone)
+ char const *source;
+ time_t default_time;
+ long default_zone;
+{
+ time_t t = str2time(source, default_time, default_zone);
+ if (t == -1)
+ faterror("unknown date/time: %s", source);
+ return t;
+}
+
+/*
+* Parse a free-format date in SOURCE, convert it
+* into RCS internal format, and store the result into TARGET.
+*/
+ void
+str2date(source, target)
+ char const *source;
+ char target[datesize];
+{
+ time2date(
+ str2time_checked(source, now(),
+ use_zone_offset ? zone_offset
+ : RCSversion<VERSION(5) ? TM_LOCAL_ZONE
+ : 0
+ ),
+ target
+ );
+}
+
+/* Convert an RCS internal format date to time_t. */
+ time_t
+date2time(source)
+ char const source[datesize];
+{
+ char s[datesize + zonelenmax];
+ return str2time_checked(date2str(source, s), (time_t)0, 0);
+}
+
+
+/* Set the time zone for date2str output. */
+ void
+zone_set(s)
+ char const *s;
+{
+ if ((use_zone_offset = *s)) {
+ long zone;
+ char const *zonetail = parzone(s, &zone);
+ if (!zonetail || *zonetail)
+ error("%s: not a known time zone", s);
+ else
+ zone_offset = zone;
+ }
+}
+
+
+/*
+* Format a user-readable form of the RCS format DATE into the buffer DATEBUF.
+* Yield DATEBUF.
+*/
+ char const *
+date2str(date, datebuf)
+ char const date[datesize];
+ char datebuf[datesize + zonelenmax];
+{
+ register char const *p = date;
+
+ while (*p++ != '.')
+ continue;
+ if (!use_zone_offset)
+ VOID sprintf(datebuf,
+ "19%.*s/%.2s/%.2s %.2s:%.2s:%s"
+ + (date[2]=='.' && VERSION(5)<=RCSversion ? 0 : 2),
+ (int)(p-date-1), date,
+ p, p+3, p+6, p+9, p+12
+ );
+ else {
+ struct tm t;
+ struct tm const *z;
+ int non_hour;
+ long zone;
+ char c;
+
+ t.tm_year = atoi(date) - (date[2]=='.' ? 0 : 1900);
+ t.tm_mon = atoi(p) - 1;
+ t.tm_mday = atoi(p+3);
+ t.tm_hour = atoi(p+6);
+ t.tm_min = atoi(p+9);
+ t.tm_sec = atoi(p+12);
+ t.tm_wday = -1;
+ zone = zone_offset;
+ if (zone == TM_LOCAL_ZONE) {
+ time_t u = tm2time(&t, 0), d;
+ z = localtime(&u);
+ d = difftm(z, &t);
+ zone = (time_t)-1 < 0 || d < -d ? d : -(long)-d;
+ } else {
+ adjzone(&t, zone);
+ z = &t;
+ }
+ c = '+';
+ if (zone < 0) {
+ zone = -zone;
+ c = '-';
+ }
+ VOID sprintf(datebuf,
+# if has_printf_dot
+ "%.2d-%.2d-%.2d %.2d:%.2d:%.2d%c%.2d",
+# else
+ "%02d-%02d-%02d %02d:%02d:%02d%c%02d",
+# endif
+ z->tm_year + 1900,
+ z->tm_mon + 1, z->tm_mday, z->tm_hour, z->tm_min, z->tm_sec,
+ c, (int) (zone / (60*60))
+ );
+ if ((non_hour = zone % (60*60))) {
+# if has_printf_dot
+ static char const fmt[] = ":%.2d";
+# else
+ static char const fmt[] = ":%02d";
+# endif
+ VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour / 60);
+ if ((non_hour %= 60))
+ VOID sprintf(datebuf + strlen(datebuf), fmt, non_hour);
+ }
+ }
+ return datebuf;
+}
diff --git a/gnu/usr.bin/rcs/lib/rcsutil.c b/gnu/usr.bin/rcs/lib/rcsutil.c
new file mode 100644
index 0000000..e10afff
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/rcsutil.c
@@ -0,0 +1,1398 @@
+/* RCS utility functions */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+
+
+
+/*
+ * Revision 5.20 1995/06/16 06:19:24 eggert
+ * (catchsig): Remove `return'.
+ * Update FSF address.
+ *
+ * Revision 5.19 1995/06/02 18:19:00 eggert
+ * (catchsigaction): New name for `catchsig', for sa_sigaction signature.
+ * Use nRCS even if !has_psiginfo, to remove unused variable warning.
+ * (setup_catchsig): Use sa_sigaction only if has_sa_sigaction.
+ * Use ENOTSUP only if defined.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (catchsig, restoreints, setup_catchsig): Use SA_SIGINFO, not has_psiginfo,
+ * to determine whether to use SA_SIGINFO feature,
+ * but also check at runtime whether the feature works.
+ * (catchsig): If an mmap_signal occurs, report the affected file name.
+ * (unsupported_SA_SIGINFO, accessName): New variables.
+ * (setup_catchsig): If using SA_SIGINFO, use sa_sigaction, not sa_handler.
+ * If SA_SIGINFO fails, fall back on sa_handler method.
+ *
+ * (readAccessFilenameBuffer, dupSafer, fdSafer, fopenSafer): New functions.
+ * (concatenate): Remove.
+ *
+ * (runv): Work around bad_wait_if_SIGCHLD_ignored bug.
+ * Remove reference to OPEN_O_WORK.
+ *
+ * Revision 5.17 1994/03/20 04:52:58 eggert
+ * Specify subprocess input via file descriptor, not file name.
+ * Avoid messing with I/O buffers in the child process.
+ * Define dup in terms of F_DUPFD if it exists.
+ * Move setmtime to rcsedit.c. Remove lint.
+ *
+ * Revision 5.16 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits.
+ *
+ * Revision 5.15 1993/11/03 17:42:27 eggert
+ * Use psiginfo and setreuid if available. Move date2str to maketime.c.
+ *
+ * Revision 5.14 1992/07/28 16:12:44 eggert
+ * Add -V. has_sigaction overrides sig_zaps_handler. Fix -M bug.
+ * Add mmap_signal, which minimizes signal handling for non-mmap hosts.
+ *
+ * Revision 5.13 1992/02/17 23:02:28 eggert
+ * Work around NFS mmap SIGBUS problem. Add -T support.
+ *
+ * Revision 5.12 1992/01/24 18:44:19 eggert
+ * Work around NFS mmap bug that leads to SIGBUS core dumps. lint -> RCS_lint
+ *
+ * Revision 5.11 1992/01/06 02:42:34 eggert
+ * O_BINARY -> OPEN_O_WORK
+ * while (E) ; -> while (E) continue;
+ *
+ * Revision 5.10 1991/10/07 17:32:46 eggert
+ * Support piece tables even if !has_mmap.
+ *
+ * Revision 5.9 1991/08/19 03:13:55 eggert
+ * Add spawn() support. Explicate assumptions about getting invoker's name.
+ * Standardize user-visible dates. Tune.
+ *
+ * Revision 5.8 1991/04/21 11:58:30 eggert
+ * Plug setuid security hole.
+ *
+ * Revision 5.6 1991/02/26 17:48:39 eggert
+ * Fix setuid bug. Use fread, fwrite more portably.
+ * Support waitpid. Don't assume -1 is acceptable to W* macros.
+ * strsave -> str_save (DG/UX name clash)
+ *
+ * Revision 5.5 1990/12/04 05:18:49 eggert
+ * Don't output a blank line after a signal diagnostic.
+ * Use -I for prompts and -q for diagnostics.
+ *
+ * Revision 5.4 1990/11/01 05:03:53 eggert
+ * Remove unneeded setid check. Add awrite(), fremember().
+ *
+ * Revision 5.3 1990/10/06 00:16:45 eggert
+ * Don't fread F if feof(F).
+ *
+ * Revision 5.2 1990/09/04 08:02:31 eggert
+ * Store fread()'s result in an fread_type object.
+ *
+ * Revision 5.1 1990/08/29 07:14:07 eggert
+ * Declare getpwuid() more carefully.
+ *
+ * Revision 5.0 1990/08/22 08:13:46 eggert
+ * Add setuid support. Permit multiple locks per user.
+ * Remove compile-time limits; use malloc instead.
+ * Switch to GMT. Permit dates past 1999/12/31.
+ * Add -V. Remove snooping. Ansify and Posixate.
+ * Tune. Some USG hosts define NSIG but not sys_siglist.
+ * Don't run /bin/sh if it's hopeless.
+ * Don't leave garbage behind if the output is an empty pipe.
+ * Clean up after SIGXCPU or SIGXFSZ. Print name of signal that caused cleanup.
+ *
+ * Revision 4.6 89/05/01 15:13:40 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.5 88/11/08 16:01:02 narten
+ * corrected use of varargs routines
+ *
+ * Revision 4.4 88/08/09 19:13:24 eggert
+ * Check for memory exhaustion.
+ * Permit signal handlers to yield either 'void' or 'int'; fix oldSIGINT botch.
+ * Use execv(), not system(); yield exit status like diff(1)'s.
+ *
+ * Revision 4.3 87/10/18 10:40:22 narten
+ * Updating version numbers. Changes relative to 1.1 actually
+ * relative to 4.1
+ *
+ * Revision 1.3 87/09/24 14:01:01 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:43 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/05/10 15:53:13 wft
+ * Added getcaller() and findlock().
+ * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
+ * (needed for background jobs in older shells). Added restoreints().
+ * Removed printing of full RCS path from logcommand().
+ *
+ * Revision 3.8 83/02/15 15:41:49 wft
+ * Added routine fastcopy() to copy remainder of a file in blocks.
+ *
+ * Revision 3.7 82/12/24 15:25:19 wft
+ * added catchints(), ignoreints() for catching and ingnoring interrupts;
+ * fixed catchsig().
+ *
+ * Revision 3.6 82/12/08 21:52:05 wft
+ * Using DATEFORM to format dates.
+ *
+ * Revision 3.5 82/12/04 18:20:49 wft
+ * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
+ * lockedby-field.
+ *
+ * Revision 3.4 82/12/03 17:17:43 wft
+ * Added check to addlock() ensuring only one lock per person.
+ * Addlock also returns a pointer to the lock created. Deleted fancydate().
+ *
+ * Revision 3.3 82/11/27 12:24:37 wft
+ * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
+ * Introduced macro SNOOP so that snoop can be placed in directory other than
+ * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
+ *
+ * Revision 3.2 82/10/18 21:15:11 wft
+ * added function getfullRCSname().
+ *
+ * Revision 3.1 82/10/13 16:17:37 wft
+ * Cleanup message is now suppressed in quiet mode.
+ */
+
+
+
+
+#include "rcsbase.h"
+
+libId(utilId, "$FreeBSD$")
+
+#if !has_memcmp
+ int
+memcmp(s1, s2, n)
+ void const *s1, *s2;
+ size_t n;
+{
+ register unsigned char const
+ *p1 = (unsigned char const*)s1,
+ *p2 = (unsigned char const*)s2;
+ register size_t i = n;
+ register int r = 0;
+ while (i-- && !(r = (*p1++ - *p2++)))
+ ;
+ return r;
+}
+#endif
+
+#if !has_memcpy
+ void *
+memcpy(s1, s2, n)
+ void *s1;
+ void const *s2;
+ size_t n;
+{
+ register char *p1 = (char*)s1;
+ register char const *p2 = (char const*)s2;
+ while (n--)
+ *p1++ = *p2++;
+ return s1;
+}
+#endif
+
+#if RCS_lint
+ malloc_type lintalloc;
+#endif
+
+/*
+ * list of blocks allocated with ftestalloc()
+ * These blocks can be freed by ffree when we're done with the current file.
+ * We could put the free block inside struct alloclist, rather than a pointer
+ * to the free block, but that would be less portable.
+ */
+struct alloclist {
+ malloc_type alloc;
+ struct alloclist *nextalloc;
+};
+static struct alloclist *alloced;
+
+
+ static malloc_type okalloc P((malloc_type));
+ static malloc_type
+okalloc(p)
+ malloc_type p;
+{
+ if (!p)
+ faterror("out of memory");
+ return p;
+}
+
+ malloc_type
+testalloc(size)
+ size_t size;
+/* Allocate a block, testing that the allocation succeeded. */
+{
+ return okalloc(malloc(size));
+}
+
+ malloc_type
+testrealloc(ptr, size)
+ malloc_type ptr;
+ size_t size;
+/* Reallocate a block, testing that the allocation succeeded. */
+{
+ return okalloc(realloc(ptr, size));
+}
+
+ malloc_type
+fremember(ptr)
+ malloc_type ptr;
+/* Remember PTR in 'alloced' so that it can be freed later. Yield PTR. */
+{
+ register struct alloclist *q = talloc(struct alloclist);
+ q->nextalloc = alloced;
+ alloced = q;
+ return q->alloc = ptr;
+}
+
+ malloc_type
+ftestalloc(size)
+ size_t size;
+/* Allocate a block, putting it in 'alloced' so it can be freed later. */
+{
+ return fremember(testalloc(size));
+}
+
+ void
+ffree()
+/* Free all blocks allocated with ftestalloc(). */
+{
+ register struct alloclist *p, *q;
+ for (p = alloced; p; p = q) {
+ q = p->nextalloc;
+ tfree(p->alloc);
+ tfree(p);
+ }
+ alloced = 0;
+}
+
+ void
+ffree1(f)
+ register char const *f;
+/* Free the block f, which was allocated by ftestalloc. */
+{
+ register struct alloclist *p, **a = &alloced;
+
+ while ((p = *a)->alloc != f)
+ a = &p->nextalloc;
+ *a = p->nextalloc;
+ tfree(p->alloc);
+ tfree(p);
+}
+
+ char *
+str_save(s)
+ char const *s;
+/* Save s in permanently allocated storage. */
+{
+ return strcpy(tnalloc(char, strlen(s)+1), s);
+}
+
+ char *
+fstr_save(s)
+ char const *s;
+/* Save s in storage that will be deallocated when we're done with this file. */
+{
+ return strcpy(ftnalloc(char, strlen(s)+1), s);
+}
+
+ char *
+cgetenv(name)
+ char const *name;
+/* Like getenv(), but yield a copy; getenv() can overwrite old results. */
+{
+ register char *p;
+
+ return (p=getenv(name)) ? str_save(p) : p;
+}
+
+ char const *
+getusername(suspicious)
+ int suspicious;
+/* Get the caller's login name. Trust only getwpuid if SUSPICIOUS. */
+{
+ static char *name;
+
+ if (!name) {
+ if (
+ /* Prefer getenv() unless suspicious; it's much faster. */
+# if getlogin_is_secure
+ (suspicious
+ || (
+ !(name = cgetenv("LOGNAME"))
+ && !(name = cgetenv("USER"))
+ ))
+ && !(name = getlogin())
+# else
+ suspicious
+ || (
+ !(name = cgetenv("LOGNAME"))
+ && !(name = cgetenv("USER"))
+ && !(name = getlogin())
+ )
+# endif
+ ) {
+#if has_getuid && has_getpwuid
+ struct passwd const *pw = getpwuid(ruid());
+ if (!pw)
+ faterror("no password entry for userid %lu",
+ (unsigned long)ruid()
+ );
+ name = pw->pw_name;
+#else
+#if has_setuid
+ faterror("setuid not supported");
+#else
+ faterror("Who are you? Please setenv LOGNAME.");
+#endif
+#endif
+ }
+ checksid(name);
+ }
+ return name;
+}
+
+
+
+
+#if has_signal
+
+/*
+ * Signal handling
+ *
+ * Standard C places too many restrictions on signal handlers.
+ * We obey as many of them as we can.
+ * Posix places fewer restrictions, and we are Posix-compatible here.
+ */
+
+static sig_atomic_t volatile heldsignal, holdlevel;
+#ifdef SA_SIGINFO
+ static int unsupported_SA_SIGINFO;
+ static siginfo_t bufsiginfo;
+ static siginfo_t *volatile heldsiginfo;
+#endif
+
+
+#if has_NFS && has_mmap && large_memory && mmap_signal
+ static char const *accessName;
+
+ void
+ readAccessFilenameBuffer(filename, p)
+ char const *filename;
+ unsigned char const *p;
+ {
+ unsigned char volatile t;
+ accessName = filename;
+ t = *p;
+ accessName = 0;
+ }
+#else
+# define accessName ((char const *) 0)
+#endif
+
+
+#if !has_psignal
+
+# define psignal my_psignal
+ static void my_psignal P((int,char const*));
+ static void
+my_psignal(sig, s)
+ int sig;
+ char const *s;
+{
+ char const *sname = "Unknown signal";
+# if has_sys_siglist && defined(NSIG)
+ if ((unsigned)sig < NSIG)
+ sname = sys_siglist[sig];
+# else
+ switch (sig) {
+# ifdef SIGHUP
+ case SIGHUP: sname = "Hangup"; break;
+# endif
+# ifdef SIGINT
+ case SIGINT: sname = "Interrupt"; break;
+# endif
+# ifdef SIGPIPE
+ case SIGPIPE: sname = "Broken pipe"; break;
+# endif
+# ifdef SIGQUIT
+ case SIGQUIT: sname = "Quit"; break;
+# endif
+# ifdef SIGTERM
+ case SIGTERM: sname = "Terminated"; break;
+# endif
+# ifdef SIGXCPU
+ case SIGXCPU: sname = "Cputime limit exceeded"; break;
+# endif
+# ifdef SIGXFSZ
+ case SIGXFSZ: sname = "Filesize limit exceeded"; break;
+# endif
+# if has_mmap && large_memory
+# if defined(SIGBUS) && mmap_signal==SIGBUS
+ case SIGBUS: sname = "Bus error"; break;
+# endif
+# if defined(SIGSEGV) && mmap_signal==SIGSEGV
+ case SIGSEGV: sname = "Segmentation fault"; break;
+# endif
+# endif
+ }
+# endif
+
+ /* Avoid calling sprintf etc., in case they're not reentrant. */
+ {
+ char const *p;
+ char buf[BUFSIZ], *b = buf;
+ for (p = s; *p; *b++ = *p++)
+ continue;
+ *b++ = ':';
+ *b++ = ' ';
+ for (p = sname; *p; *b++ = *p++)
+ continue;
+ *b++ = '\n';
+ VOID write(STDERR_FILENO, buf, b - buf);
+ }
+}
+#endif
+
+static signal_type catchsig P((int));
+#ifdef SA_SIGINFO
+ static signal_type catchsigaction P((int,siginfo_t*,void*));
+#endif
+
+ static signal_type
+catchsig(s)
+ int s;
+#ifdef SA_SIGINFO
+{
+ catchsigaction(s, (siginfo_t *)0, (void *)0);
+}
+ static signal_type
+catchsigaction(s, i, c)
+ int s;
+ siginfo_t *i;
+ void *c;
+#endif
+{
+# if sig_zaps_handler
+ /* If a signal arrives before we reset the handler, we lose. */
+ VOID signal(s, SIG_IGN);
+# endif
+
+# ifdef SA_SIGINFO
+ if (!unsupported_SA_SIGINFO)
+ i = 0;
+# endif
+
+ if (holdlevel) {
+ heldsignal = s;
+# ifdef SA_SIGINFO
+ if (i) {
+ bufsiginfo = *i;
+ heldsiginfo = &bufsiginfo;
+ }
+# endif
+ return;
+ }
+
+ ignoreints();
+ setrid();
+ if (!quietflag) {
+ /* Avoid calling sprintf etc., in case they're not reentrant. */
+ char const *p;
+ char buf[BUFSIZ], *b = buf;
+
+ if ( ! (
+# if has_mmap && large_memory && mmap_signal
+ /* Check whether this signal was planned. */
+ s == mmap_signal && accessName
+# else
+ 0
+# endif
+ )) {
+ char const *nRCS = "\nRCS";
+# if defined(SA_SIGINFO) && has_si_errno && has_mmap && large_memory && mmap_signal
+ if (s == mmap_signal && i && i->si_errno) {
+ errno = i->si_errno;
+ perror(nRCS++);
+ }
+# endif
+# if defined(SA_SIGINFO) && has_psiginfo
+ if (i)
+ psiginfo(i, nRCS);
+ else
+ psignal(s, nRCS);
+# else
+ psignal(s, nRCS);
+# endif
+ }
+
+ for (p = "RCS: "; *p; *b++ = *p++)
+ continue;
+# if has_mmap && large_memory && mmap_signal
+ if (s == mmap_signal) {
+ p = accessName;
+ if (!p)
+ p = "Was a file changed by some other process? ";
+ else {
+ char const *p1;
+ for (p1 = p; *p1; p1++)
+ continue;
+ VOID write(STDERR_FILENO, buf, b - buf);
+ VOID write(STDERR_FILENO, p, p1 - p);
+ b = buf;
+ p = ": Permission denied. ";
+ }
+ while (*p)
+ *b++ = *p++;
+ }
+# endif
+ for (p = "Cleaning up.\n"; *p; *b++ = *p++)
+ continue;
+ VOID write(STDERR_FILENO, buf, b - buf);
+ }
+ exiterr();
+}
+
+ void
+ignoreints()
+{
+ ++holdlevel;
+}
+
+ void
+restoreints()
+{
+ if (!--holdlevel && heldsignal)
+# ifdef SA_SIGINFO
+ VOID catchsigaction(heldsignal, heldsiginfo, (void *)0);
+# else
+ VOID catchsig(heldsignal);
+# endif
+}
+
+
+static void setup_catchsig P((int const*,int));
+
+#if has_sigaction
+
+ static void check_sig P((int));
+ static void
+ check_sig(r)
+ int r;
+ {
+ if (r != 0)
+ efaterror("signal handling");
+ }
+
+ static void
+ setup_catchsig(sig, sigs)
+ int const *sig;
+ int sigs;
+ {
+ register int i, j;
+ struct sigaction act;
+
+ for (i=sigs; 0<=--i; ) {
+ check_sig(sigaction(sig[i], (struct sigaction*)0, &act));
+ if (act.sa_handler != SIG_IGN) {
+ act.sa_handler = catchsig;
+# ifdef SA_SIGINFO
+ if (!unsupported_SA_SIGINFO) {
+# if has_sa_sigaction
+ act.sa_sigaction = catchsigaction;
+# else
+ act.sa_handler = catchsigaction;
+# endif
+ act.sa_flags |= SA_SIGINFO;
+ }
+# endif
+ for (j=sigs; 0<=--j; )
+ check_sig(sigaddset(&act.sa_mask, sig[j]));
+ if (sigaction(sig[i], &act, (struct sigaction*)0) != 0) {
+# if defined(SA_SIGINFO) && defined(ENOTSUP)
+ if (errno == ENOTSUP && !unsupported_SA_SIGINFO) {
+ /* Turn off use of SA_SIGINFO and try again. */
+ unsupported_SA_SIGINFO = 1;
+ i++;
+ continue;
+ }
+# endif
+ check_sig(-1);
+ }
+ }
+ }
+ }
+
+#else
+#if has_sigblock
+
+ static void
+ setup_catchsig(sig, sigs)
+ int const *sig;
+ int sigs;
+ {
+ register int i;
+ int mask;
+
+ mask = 0;
+ for (i=sigs; 0<=--i; )
+ mask |= sigmask(sig[i]);
+ mask = sigblock(mask);
+ for (i=sigs; 0<=--i; )
+ if (
+ signal(sig[i], catchsig) == SIG_IGN &&
+ signal(sig[i], SIG_IGN) != catchsig
+ )
+ faterror("signal catcher failure");
+ VOID sigsetmask(mask);
+ }
+
+#else
+
+ static void
+ setup_catchsig(sig, sigs)
+ int const *sig;
+ int sigs;
+ {
+ register i;
+
+ for (i=sigs; 0<=--i; )
+ if (
+ signal(sig[i], SIG_IGN) != SIG_IGN &&
+ signal(sig[i], catchsig) != SIG_IGN
+ )
+ faterror("signal catcher failure");
+ }
+
+#endif
+#endif
+
+
+static int const regsigs[] = {
+# ifdef SIGHUP
+ SIGHUP,
+# endif
+# ifdef SIGINT
+ SIGINT,
+# endif
+# ifdef SIGPIPE
+ SIGPIPE,
+# endif
+# ifdef SIGQUIT
+ SIGQUIT,
+# endif
+# ifdef SIGTERM
+ SIGTERM,
+# endif
+# ifdef SIGXCPU
+ SIGXCPU,
+# endif
+# ifdef SIGXFSZ
+ SIGXFSZ,
+# endif
+};
+
+ void
+catchints()
+{
+ static int catching_ints;
+ if (!catching_ints) {
+ catching_ints = true;
+ setup_catchsig(regsigs, (int) (sizeof(regsigs)/sizeof(*regsigs)));
+ }
+}
+
+#if has_mmap && large_memory && mmap_signal
+
+ /*
+ * If you mmap an NFS file, and someone on another client removes the last
+ * link to that file, and you later reference an uncached part of that file,
+ * you'll get a SIGBUS or SIGSEGV (depending on the operating system).
+ * Catch the signal and report the problem to the user.
+ * Unfortunately, there's no portable way to differentiate between this
+ * problem and actual bugs in the program.
+ * This NFS problem is rare, thank goodness.
+ *
+ * This can also occur if someone truncates the file, even without NFS.
+ */
+
+ static int const mmapsigs[] = { mmap_signal };
+
+ void
+ catchmmapints()
+ {
+ static int catching_mmap_ints;
+ if (!catching_mmap_ints) {
+ catching_mmap_ints = true;
+ setup_catchsig(mmapsigs, (int)(sizeof(mmapsigs)/sizeof(*mmapsigs)));
+ }
+ }
+#endif
+
+#endif /* has_signal */
+
+
+ void
+fastcopy(inf,outf)
+ register RILE *inf;
+ FILE *outf;
+/* Function: copies the remainder of file inf to outf.
+ */
+{
+#if large_memory
+# if maps_memory
+ awrite((char const*)inf->ptr, (size_t)(inf->lim - inf->ptr), outf);
+ inf->ptr = inf->lim;
+# else
+ for (;;) {
+ awrite((char const*)inf->ptr, (size_t)(inf->readlim - inf->ptr), outf);
+ inf->ptr = inf->readlim;
+ if (inf->ptr == inf->lim)
+ break;
+ VOID Igetmore(inf);
+ }
+# endif
+#else
+ char buf[BUFSIZ*8];
+ register fread_type rcount;
+
+ /*now read the rest of the file in blocks*/
+ while (!feof(inf)) {
+ if (!(rcount = Fread(buf,sizeof(*buf),sizeof(buf),inf))) {
+ testIerror(inf);
+ return;
+ }
+ awrite(buf, (size_t)rcount, outf);
+ }
+#endif
+}
+
+#ifndef SSIZE_MAX
+ /* This does not work in #ifs, but it's good enough for us. */
+ /* Underestimating SSIZE_MAX may slow us down, but it won't break us. */
+# define SSIZE_MAX ((unsigned)-1 >> 1)
+#endif
+
+ void
+awrite(buf, chars, f)
+ char const *buf;
+ size_t chars;
+ FILE *f;
+{
+ /* Posix 1003.1-1990 ssize_t hack */
+ while (SSIZE_MAX < chars) {
+ if (Fwrite(buf, sizeof(*buf), SSIZE_MAX, f) != SSIZE_MAX)
+ Oerror();
+ buf += SSIZE_MAX;
+ chars -= SSIZE_MAX;
+ }
+
+ if (Fwrite(buf, sizeof(*buf), chars, f) != chars)
+ Oerror();
+}
+
+/* dup a file descriptor; the result must not be stdin, stdout, or stderr. */
+ static int dupSafer P((int));
+ static int
+dupSafer(fd)
+ int fd;
+{
+# ifdef F_DUPFD
+ return fcntl(fd, F_DUPFD, STDERR_FILENO + 1);
+# else
+ int e, f, i, used = 0;
+ while (STDIN_FILENO <= (f = dup(fd)) && f <= STDERR_FILENO)
+ used |= 1<<f;
+ e = errno;
+ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++)
+ if (used & (1<<i))
+ VOID close(i);
+ errno = e;
+ return f;
+# endif
+}
+
+/* Renumber a file descriptor so that it's not stdin, stdout, or stderr. */
+ int
+fdSafer(fd)
+ int fd;
+{
+ if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) {
+ int f = dupSafer(fd);
+ int e = errno;
+ VOID close(fd);
+ errno = e;
+ fd = f;
+ }
+ return fd;
+}
+
+/* Like fopen, except the result is never stdin, stdout, or stderr. */
+ FILE *
+fopenSafer(filename, type)
+ char const *filename;
+ char const *type;
+{
+ FILE *stream = fopen(filename, type);
+ if (stream) {
+ int fd = fileno(stream);
+ if (STDIN_FILENO <= fd && fd <= STDERR_FILENO) {
+ int f = dupSafer(fd);
+ if (f < 0) {
+ int e = errno;
+ VOID fclose(stream);
+ errno = e;
+ return 0;
+ }
+ if (fclose(stream) != 0) {
+ int e = errno;
+ VOID close(f);
+ errno = e;
+ return 0;
+ }
+ stream = fdopen(f, type);
+ }
+ }
+ return stream;
+}
+
+
+#ifdef F_DUPFD
+# undef dup
+# define dup(fd) fcntl(fd, F_DUPFD, 0)
+#endif
+
+
+#if has_fork || has_spawn
+
+ static int movefd P((int,int));
+ static int
+movefd(old, new)
+ int old, new;
+{
+ if (old < 0 || old == new)
+ return old;
+# ifdef F_DUPFD
+ new = fcntl(old, F_DUPFD, new);
+# else
+ new = dup2(old, new);
+# endif
+ return close(old)==0 ? new : -1;
+}
+
+ static int fdreopen P((int,char const*,int));
+ static int
+fdreopen(fd, file, flags)
+ int fd;
+ char const *file;
+ int flags;
+{
+ int newfd;
+ VOID close(fd);
+ newfd =
+#if !open_can_creat
+ flags&O_CREAT ? creat(file, S_IRUSR|S_IWUSR) :
+#endif
+ open(file, flags, S_IRUSR|S_IWUSR);
+ return movefd(newfd, fd);
+}
+
+#if has_spawn
+ static void redirect P((int,int));
+ static void
+redirect(old, new)
+ int old, new;
+/*
+* Move file descriptor OLD to NEW.
+* If OLD is -1, do nothing.
+* If OLD is -2, just close NEW.
+*/
+{
+ if ((old != -1 && close(new) != 0) || (0 <= old && movefd(old,new) < 0))
+ efaterror("spawn I/O redirection");
+}
+#endif
+
+
+#else /* !has_fork && !has_spawn */
+
+ static void bufargcat P((struct buf*,int,char const*));
+ static void
+bufargcat(b, c, s)
+ register struct buf *b;
+ int c;
+ register char const *s;
+/* Append to B a copy of C, plus a quoted copy of S. */
+{
+ register char *p;
+ register char const *t;
+ size_t bl, sl;
+
+ for (t=s, sl=0; *t; )
+ sl += 3*(*t++=='\'') + 1;
+ bl = strlen(b->string);
+ bufrealloc(b, bl + sl + 4);
+ p = b->string + bl;
+ *p++ = c;
+ *p++ = '\'';
+ while (*s) {
+ if (*s == '\'') {
+ *p++ = '\'';
+ *p++ = '\\';
+ *p++ = '\'';
+ }
+ *p++ = *s++;
+ }
+ *p++ = '\'';
+ *p = 0;
+}
+
+#endif
+
+#if !has_spawn && has_fork
+/*
+* Output the string S to stderr, without touching any I/O buffers.
+* This is useful if you are a child process, whose buffers are usually wrong.
+* Exit immediately if the write does not completely succeed.
+*/
+static void write_stderr P((char const *));
+ static void
+write_stderr(s)
+ char const *s;
+{
+ size_t slen = strlen(s);
+ if (write(STDERR_FILENO, s, slen) != slen)
+ _exit(EXIT_TROUBLE);
+}
+#endif
+
+/*
+* Run a command.
+* infd, if not -1, is the input file descriptor.
+* outname, if nonzero, is the name of the output file.
+* args[1..] form the command to be run; args[0] might be modified.
+*/
+ int
+runv(infd, outname, args)
+ int infd;
+ char const *outname, **args;
+{
+ int wstatus;
+
+#if bad_wait_if_SIGCHLD_ignored
+ static int fixed_SIGCHLD;
+ if (!fixed_SIGCHLD) {
+ fixed_SIGCHLD = true;
+# ifndef SIGCHLD
+# define SIGCHLD SIGCLD
+# endif
+ VOID signal(SIGCHLD, SIG_DFL);
+ }
+#endif
+
+ oflush();
+ eflush();
+ {
+#if has_spawn
+ int in, out;
+ char const *file;
+
+ in = -1;
+ if (infd != -1 && infd != STDIN_FILENO) {
+ if ((in = dup(STDIN_FILENO)) < 0) {
+ if (errno != EBADF)
+ efaterror("spawn input setup");
+ in = -2;
+ } else {
+# ifdef F_DUPFD
+ if (close(STDIN_FILENO) != 0)
+ efaterror("spawn input close");
+# endif
+ }
+ if (
+# ifdef F_DUPFD
+ fcntl(infd, F_DUPFD, STDIN_FILENO) != STDIN_FILENO
+# else
+ dup2(infd, STDIN_FILENO) != STDIN_FILENO
+# endif
+ )
+ efaterror("spawn input redirection");
+ }
+
+ out = -1;
+ if (outname) {
+ if ((out = dup(STDOUT_FILENO)) < 0) {
+ if (errno != EBADF)
+ efaterror("spawn output setup");
+ out = -2;
+ }
+ if (fdreopen(
+ STDOUT_FILENO, outname,
+ O_CREAT | O_TRUNC | O_WRONLY
+ ) < 0)
+ efaterror(outname);
+ }
+
+ wstatus = spawn_RCS(0, args[1], (char**)(args + 1));
+# ifdef RCS_SHELL
+ if (wstatus == -1 && errno == ENOEXEC) {
+ args[0] = RCS_SHELL;
+ wstatus = spawnv(0, args[0], (char**)args);
+ }
+# endif
+ redirect(in, STDIN_FILENO);
+ redirect(out, STDOUT_FILENO);
+#else
+#if has_fork
+ pid_t pid;
+ if (!(pid = vfork())) {
+ char const *notfound;
+ if (infd != -1 && infd != STDIN_FILENO && (
+# ifdef F_DUPFD
+ (VOID close(STDIN_FILENO),
+ fcntl(infd, F_DUPFD, STDIN_FILENO) != STDIN_FILENO)
+# else
+ dup2(infd, STDIN_FILENO) != STDIN_FILENO
+# endif
+ )) {
+ /* Avoid perror since it may misuse buffers. */
+ write_stderr(args[1]);
+ write_stderr(": I/O redirection failed\n");
+ _exit(EXIT_TROUBLE);
+ }
+
+ if (outname)
+ if (fdreopen(
+ STDOUT_FILENO, outname,
+ O_CREAT | O_TRUNC | O_WRONLY
+ ) < 0) {
+ /* Avoid perror since it may misuse buffers. */
+ write_stderr(args[1]);
+ write_stderr(": ");
+ write_stderr(outname);
+ write_stderr(": cannot create\n");
+ _exit(EXIT_TROUBLE);
+ }
+ VOID exec_RCS(args[1], (char**)(args + 1));
+ notfound = args[1];
+# ifdef RCS_SHELL
+ if (errno == ENOEXEC) {
+ args[0] = notfound = RCS_SHELL;
+ VOID execv(args[0], (char**)args);
+ }
+# endif
+
+ /* Avoid perror since it may misuse buffers. */
+ write_stderr(notfound);
+ write_stderr(": not found\n");
+ _exit(EXIT_TROUBLE);
+ }
+ if (pid < 0)
+ efaterror("fork");
+# if has_waitpid
+ if (waitpid(pid, &wstatus, 0) < 0)
+ efaterror("waitpid");
+# else
+ {
+ pid_t w;
+ do {
+ if ((w = wait(&wstatus)) < 0)
+ efaterror("wait");
+ } while (w != pid);
+ }
+# endif
+#else
+ static struct buf b;
+ char const *p;
+
+ /* Use system(). On many hosts system() discards signals. Yuck! */
+ p = args + 1;
+ bufscpy(&b, *p);
+ while (*++p)
+ bufargcat(&b, ' ', *p);
+ if (infd != -1 && infd != STDIN_FILENO) {
+ char redirection[32];
+ VOID sprintf(redirection, "<&%d", infd);
+ bufscat(&b, redirection);
+ }
+ if (outname)
+ bufargcat(&b, '>', outname);
+ wstatus = system(b.string);
+#endif
+#endif
+ }
+ if (!WIFEXITED(wstatus)) {
+ if (WIFSIGNALED(wstatus)) {
+ psignal(WTERMSIG(wstatus), args[1]);
+ fatcleanup(1);
+ }
+ faterror("%s failed for unknown reason", args[1]);
+ }
+ return WEXITSTATUS(wstatus);
+}
+
+#define CARGSMAX 20
+/*
+* Run a command.
+* infd, if not -1, is the input file descriptor.
+* outname, if nonzero, is the name of the output file.
+* The remaining arguments specify the command and its arguments.
+*/
+ int
+#if has_prototypes
+run(int infd, char const *outname, ...)
+#else
+ /*VARARGS2*/
+run(infd, outname, va_alist)
+ int infd;
+ char const *outname;
+ va_dcl
+#endif
+{
+ va_list ap;
+ char const *rgargs[CARGSMAX];
+ register int i;
+ vararg_start(ap, outname);
+ for (i = 1; (rgargs[i++] = va_arg(ap, char const*)); )
+ if (CARGSMAX <= i)
+ faterror("too many command arguments");
+ va_end(ap);
+ return runv(infd, outname, rgargs);
+}
+
+
+int RCSversion;
+
+ void
+setRCSversion(str)
+ char const *str;
+{
+ static int oldversion;
+
+ register char const *s = str + 2;
+
+ if (*s) {
+ int v = VERSION_DEFAULT;
+
+ if (oldversion)
+ redefined('V');
+ oldversion = true;
+ v = 0;
+ while (isdigit(*s))
+ v = 10*v + *s++ - '0';
+ if (*s)
+ error("%s isn't a number", str);
+ else if (v < VERSION_min || VERSION_max < v)
+ error("%s out of range %d..%d",
+ str, VERSION_min, VERSION_max
+ );
+
+ RCSversion = VERSION(v);
+ } else {
+ printf("RCS version %s\n", RCS_version_string);
+ exit(0);
+ }
+}
+
+ int
+getRCSINIT(argc, argv, newargv)
+ int argc;
+ char **argv, ***newargv;
+{
+ register char *p, *q, **pp;
+ char const *ev;
+ size_t n;
+
+ if ((ev = cgetenv("RCSLOCALID")))
+ setRCSLocalId(ev);
+
+ if ((ev = cgetenv("RCSINCEXC")))
+ setIncExc(ev);
+
+ if (!(q = cgetenv("RCSINIT")))
+ *newargv = argv;
+ else {
+ n = argc + 2;
+ /*
+ * Count spaces in RCSINIT to allocate a new arg vector.
+ * This is an upper bound, but it's OK even if too large.
+ */
+ for (p = q; ; ) {
+ switch (*p++) {
+ default:
+ continue;
+
+ case ' ':
+ case '\b': case '\f': case '\n':
+ case '\r': case '\t': case '\v':
+ n++;
+ continue;
+
+ case '\0':
+ break;
+ }
+ break;
+ }
+ *newargv = pp = tnalloc(char*, n);
+ *pp++ = *argv++; /* copy program name */
+ for (p = q; ; ) {
+ for (;;) {
+ switch (*q) {
+ case '\0':
+ goto copyrest;
+
+ case ' ':
+ case '\b': case '\f': case '\n':
+ case '\r': case '\t': case '\v':
+ q++;
+ continue;
+ }
+ break;
+ }
+ *pp++ = p;
+ ++argc;
+ for (;;) {
+ switch ((*p++ = *q++)) {
+ case '\0':
+ goto copyrest;
+
+ case '\\':
+ if (!*q)
+ goto copyrest;
+ p[-1] = *q++;
+ continue;
+
+ default:
+ continue;
+
+ case ' ':
+ case '\b': case '\f': case '\n':
+ case '\r': case '\t': case '\v':
+ break;
+ }
+ break;
+ }
+ p[-1] = '\0';
+ }
+ copyrest:
+ while ((*pp++ = *argv++))
+ continue;
+ }
+ return argc;
+}
+
+
+#define cacheid(E) static uid_t i; static int s; if (!s){ s=1; i=(E); } return i
+
+#if has_getuid
+ uid_t ruid() { cacheid(getuid()); }
+#endif
+#if has_setuid
+ uid_t euid() { cacheid(geteuid()); }
+#endif
+
+
+#if has_setuid
+
+/*
+ * Setuid execution really works only with Posix 1003.1a Draft 5 seteuid(),
+ * because it lets us switch back and forth between arbitrary users.
+ * If seteuid() doesn't work, we fall back on setuid(),
+ * which works if saved setuid is supported,
+ * unless the real or effective user is root.
+ * This area is such a mess that we always check switches at runtime.
+ */
+
+ static void
+#if has_prototypes
+set_uid_to(uid_t u)
+#else
+ set_uid_to(u) uid_t u;
+#endif
+/* Become user u. */
+{
+ static int looping;
+
+ if (euid() == ruid())
+ return;
+#if (has_fork||has_spawn) && DIFF_ABSOLUTE
+# if has_setreuid
+ if (setreuid(u==euid() ? ruid() : euid(), u) != 0)
+ efaterror("setuid");
+# else
+ if (seteuid(u) != 0)
+ efaterror("setuid");
+# endif
+#endif
+ if (geteuid() != u) {
+ if (looping)
+ return;
+ looping = true;
+ faterror("root setuid not supported" + (u?5:0));
+ }
+}
+
+static int stick_with_euid;
+
+ void
+/* Ignore all calls to seteid() and setrid(). */
+nosetid()
+{
+ stick_with_euid = true;
+}
+
+ void
+seteid()
+/* Become effective user. */
+{
+ if (!stick_with_euid)
+ set_uid_to(euid());
+}
+
+ void
+setrid()
+/* Become real user. */
+{
+ if (!stick_with_euid)
+ set_uid_to(ruid());
+}
+#endif
+
+ time_t
+now()
+{
+ static time_t t;
+ if (!t && time(&t) == -1)
+ efaterror("time");
+ return t;
+}
diff --git a/gnu/usr.bin/rcs/lib/version.c b/gnu/usr.bin/rcs/lib/version.c
new file mode 100644
index 0000000..81f5585
--- /dev/null
+++ b/gnu/usr.bin/rcs/lib/version.c
@@ -0,0 +1,2 @@
+#include "rcsbase.h"
+char const RCS_version_string[] = "5.7";
diff --git a/gnu/usr.bin/rcs/merge/Makefile b/gnu/usr.bin/rcs/merge/Makefile
new file mode 100644
index 0000000..9022bc4
--- /dev/null
+++ b/gnu/usr.bin/rcs/merge/Makefile
@@ -0,0 +1,8 @@
+PROG= merge
+SRCS= merge.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/merge/merge.1 b/gnu/usr.bin/rcs/merge/merge.1
new file mode 100644
index 0000000..a4fd35b
--- /dev/null
+++ b/gnu/usr.bin/rcs/merge/merge.1
@@ -0,0 +1,137 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \&\s-1RCS\s0
+.TH MERGE 1 \*(Dt GNU
+.SH NAME
+merge \- three-way file merge
+.SH SYNOPSIS
+.B merge
+[
+.I "options"
+]
+.I "file1 file2 file3"
+.SH DESCRIPTION
+.B merge
+incorporates all changes that lead from
+.I file2
+to
+.I file3
+into
+.IR file1 .
+The result ordinarily goes into
+.IR file1 .
+.B merge
+is useful for combining separate changes to an original. Suppose
+.I file2
+is the original, and both
+.I file1
+and
+.I file3
+are modifications of
+.IR file2 .
+Then
+.B merge
+combines both changes.
+.PP
+A conflict occurs if both
+.I file1
+and
+.I file3
+have changes in a common segment of lines.
+If a conflict is found,
+.B merge
+normally outputs a warning and brackets the conflict with
+.B <<<<<<<
+and
+.B >>>>>>>
+lines.
+A typical conflict will look like this:
+.LP
+.RS
+.nf
+.BI <<<<<<< " file A"
+.I "lines in file A"
+.B "======="
+.I "lines in file B"
+.BI >>>>>>> " file B"
+.RE
+.fi
+.LP
+If there are conflicts, the user should edit the result and delete one of the
+alternatives.
+.SH OPTIONS
+.TP
+.B \-A
+Output conflicts using the
+.B \-A
+style of
+.BR diff3 (1),
+if supported by
+.BR diff3 .
+This merges all changes leading from
+.I file2
+to
+.I file3
+into
+.IR file1 ,
+and generates the most verbose output.
+.TP
+\f3\-E\fP, \f3\-e\fP
+These options specify conflict styles that generate less information
+than
+.BR \-A .
+See
+.BR diff3 (1)
+for details.
+The default is
+.BR \-E .
+With
+.BR \-e ,
+.B merge
+does not warn about conflicts.
+.TP
+.BI \-L " label"
+This option may be given up to three times, and specifies labels
+to be used in place of the corresponding file names in conflict reports.
+That is,
+.B "merge\ \-L\ x\ \-L\ y\ \-L\ z\ a\ b\ c"
+generates output that looks like it came from files
+.BR x ,
+.B y
+and
+.B z
+instead of from files
+.BR a ,
+.B b
+and
+.BR c .
+.TP
+.BI \-p
+Send results to standard output instead of overwriting
+.IR file1 .
+.TP
+.BI \-q
+Quiet; do not warn about conflicts.
+.TP
+.BI \-V
+Print \*r's version number.
+.SH DIAGNOSTICS
+Exit status is 0 for no conflicts, 1 for some conflicts, 2 for trouble.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
+.SH SEE ALSO
+diff3(1), diff(1), rcsmerge(1), co(1).
+.SH BUGS
+It normally does not make sense to merge binary files as if they were text, but
+.B merge
+tries to do it anyway.
+.br
diff --git a/gnu/usr.bin/rcs/merge/merge.c b/gnu/usr.bin/rcs/merge/merge.c
new file mode 100644
index 0000000..aa127bf
--- /dev/null
+++ b/gnu/usr.bin/rcs/merge/merge.c
@@ -0,0 +1,113 @@
+/* merge - three-way file merge */
+
+/* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#include "rcsbase.h"
+
+static void badoption P((char const*));
+
+static char const usage[] =
+ "\nmerge: usage: merge [-AeEpqxX3] [-L lab [-L lab [-L lab]]] file1 file2 file3";
+
+ static void
+badoption(a)
+ char const *a;
+{
+ error("unknown option: %s%s", a, usage);
+}
+
+
+mainProg(mergeId, "merge", "$FreeBSD$")
+{
+ register char const *a;
+ char const *arg[3], *label[3], *edarg = 0;
+ int labels, tostdout;
+
+ labels = 0;
+ tostdout = false;
+
+ for (; (a = *++argv) && *a++ == '-'; --argc) {
+ switch (*a++) {
+ case 'A': case 'E': case 'e':
+ if (edarg && edarg[1] != (*argv)[1])
+ error("%s and %s are incompatible",
+ edarg, *argv
+ );
+ edarg = *argv;
+ break;
+
+ case 'p': tostdout = true; break;
+ case 'q': quietflag = true; break;
+
+ case 'L':
+ if (3 <= labels)
+ faterror("too many -L options");
+ if (!(label[labels++] = *++argv))
+ faterror("-L needs following argument");
+ --argc;
+ break;
+
+ case 'V':
+ printf("RCS version %s\n", RCS_version_string);
+ exitmain(0);
+
+ default:
+ badoption(a - 2);
+ continue;
+ }
+ if (*a)
+ badoption(a - 2);
+ }
+
+ if (argc != 4)
+ faterror("%s arguments%s",
+ argc<4 ? "not enough" : "too many", usage
+ );
+
+ /* This copy keeps us `const'-clean. */
+ arg[0] = argv[0];
+ arg[1] = argv[1];
+ arg[2] = argv[2];
+
+ for (; labels < 3; labels++)
+ label[labels] = arg[labels];
+
+ if (nerror)
+ exiterr();
+ exitmain(merge(tostdout, edarg, label, arg));
+}
+
+
+#if RCS_lint
+# define exiterr mergeExit
+#endif
+ void
+exiterr()
+{
+ tempunlink();
+ _exit(DIFF_TROUBLE);
+}
diff --git a/gnu/usr.bin/rcs/rcs/Makefile b/gnu/usr.bin/rcs/rcs/Makefile
new file mode 100644
index 0000000..aa7cc5f
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcs/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG= rcs
+MAN= rcs.1 rcsintro.1 rcsfile.5
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/rcs/rcs.1 b/gnu/usr.bin/rcs/rcs/rcs.1
new file mode 100644
index 0000000..37fb59f
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcs/rcs.1
@@ -0,0 +1,454 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \&\s-1RCS\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.if !\n(.g \{\
+. if !\w|\*(lq| \{\
+. ds lq ``
+. if \w'\(lq' .ds lq "\(lq
+. \}
+. if !\w|\*(rq| \{\
+. ds rq ''
+. if \w'\(rq' .ds rq "\(rq
+. \}
+.\}
+.TH RCS 1 \*(Dt GNU
+.SH NAME
+rcs \- change RCS file attributes
+.SH SYNOPSIS
+.B rcs
+.IR "options file " .\|.\|.
+.SH DESCRIPTION
+.B rcs
+creates new \*r files or changes attributes of existing ones.
+An \*r file contains multiple revisions of text,
+an access list, a change log,
+descriptive text,
+and some control attributes.
+For
+.B rcs
+to work, the caller's login name must be on the access list,
+except if the access list is empty, the caller is the owner of the file
+or the superuser, or
+the
+.B \-i
+option is present.
+.PP
+Pathnames matching an \*r suffix denote \*r files;
+all others denote working files.
+Names are paired as explained in
+.BR ci (1).
+Revision numbers use the syntax described in
+.BR ci (1).
+.SH OPTIONS
+.TP
+.B \-i
+Create and initialize a new \*r file, but do not deposit any revision.
+If the \*r file has no path prefix, try to place it
+first into the subdirectory
+.BR ./RCS ,
+and then into the current directory.
+If the \*r file
+already exists, print an error message.
+.TP
+.BI \-a "logins"
+Append the login names appearing in the comma-separated list
+.I logins
+to the access list of the \*r file.
+.TP
+.BI \-A "oldfile"
+Append the access list of
+.I oldfile
+to the access list of the \*r file.
+.TP
+.BR \-e [\f2logins\fP]
+Erase the login names appearing in the comma-separated list
+.I logins
+from the access list of the \*r file.
+If
+.I logins
+is omitted, erase the entire access list.
+.TP
+.BR \-b [\f2rev\fP]
+Set the default branch to
+.IR rev .
+If
+.I rev
+is omitted, the default
+branch is reset to the (dynamically) highest branch on the trunk.
+.TP
+.BI \-c string
+Set the comment leader to
+.IR string .
+An initial
+.BR ci ,
+or an
+.B "rcs\ \-i"
+without
+.BR \-c ,
+guesses the comment leader from the suffix of the working filename.
+.RS
+.PP
+This option is obsolescent, since \*r normally uses the preceding
+.B $\&Log$
+line's prefix when inserting log lines during checkout (see
+.BR co (1)).
+However, older versions of \*r use the comment leader instead of the
+.B $\&Log$
+line's prefix, so
+if you plan to access a file with both old and new versions of \*r,
+make sure its comment leader matches its
+.B $\&Log$
+line prefix.
+.RE
+.TP
+.BI \-k subst
+Set the default keyword substitution to
+.IR subst .
+The effect of keyword substitution is described in
+.BR co (1).
+Giving an explicit
+.B \-k
+option to
+.BR co ,
+.BR rcsdiff ,
+and
+.B rcsmerge
+overrides this default.
+Beware
+.BR "rcs\ \-kv",
+because
+.B \-kv
+is incompatible with
+.BR "co\ \-l".
+Use
+.B "rcs\ \-kkv"
+to restore the normal default keyword substitution.
+.TP
+.BR \-l [\f2rev\fP]
+Lock the revision with number
+.IR rev .
+If a branch is given, lock the latest revision on that branch.
+If
+.I rev
+is omitted, lock the latest revision on the default branch.
+Locking prevents overlapping changes.
+If someone else already holds the lock, the lock is broken as with
+.B "rcs\ \-u"
+(see below).
+.TP
+.BR \-u [\f2rev\fP]
+Unlock the revision with number
+.IR rev .
+If a branch is given, unlock the latest revision on that branch.
+If
+.I rev
+is omitted, remove the latest lock held by the caller.
+Normally, only the locker of a revision can unlock it.
+Somebody else unlocking a revision breaks the lock.
+This causes a mail message to be sent to the original locker.
+The message contains a commentary solicited from the breaker.
+The commentary is terminated by end-of-file or by a line containing
+.BR \&. "\ by"
+itself.
+.TP
+.B \-L
+Set locking to
+.IR strict .
+Strict locking means that the owner
+of an \*r file is not exempt from locking for checkin.
+This option should be used for files that are shared.
+.TP
+.B \-U
+Set locking to non-strict. Non-strict locking means that the owner of
+a file need not lock a revision for checkin.
+This option should
+.I not
+be used for files that are shared.
+Whether default locking is strict is determined by your system administrator,
+but it is normally strict.
+.TP
+\f3\-m\fP\f2rev\fP\f3:\fP\f2msg\fP
+Replace revision
+.IR rev 's
+log message with
+.IR msg .
+.TP
+.B \-M
+Do not send mail when breaking somebody else's lock.
+This option is not meant for casual use;
+it is meant for programs that warn users by other means, and invoke
+.B "rcs\ \-u"
+only as a low-level lock-breaking operation.
+.TP
+\f3\-n\fP\f2name\fP[\f3:\fP[\f2rev\fP]]
+Associate the symbolic name
+.I name
+with the branch or
+revision
+.IR rev .
+Delete the symbolic name if both
+.B :
+and
+.I rev
+are omitted; otherwise, print an error message if
+.I name
+is already associated with
+another number.
+If
+.I rev
+is symbolic, it is expanded before association.
+A
+.I rev
+consisting of a branch number followed by a
+.B .\&
+stands for the current latest revision in the branch.
+A
+.B :
+with an empty
+.I rev
+stands for the current latest revision on the default branch,
+normally the trunk.
+For example,
+.BI "rcs\ \-n" name ":\ RCS/*"
+associates
+.I name
+with the current latest revision of all the named \*r files;
+this contrasts with
+.BI "rcs\ \-n" name ":$\ RCS/*"
+which associates
+.I name
+with the revision numbers extracted from keyword strings
+in the corresponding working files.
+.TP
+\f3\-N\fP\f2name\fP[\f3:\fP[\f2rev\fP]]
+Act like
+.BR \-n ,
+except override any previous assignment of
+.IR name .
+.TP
+.BI \-o range
+deletes (\*(lqoutdates\*(rq) the revisions given by
+.IR range .
+A range consisting of a single revision number means that revision.
+A range consisting of a branch number means the latest revision on that
+branch.
+A range of the form
+.IB rev1 : rev2
+means
+revisions
+.I rev1
+to
+.I rev2
+on the same branch,
+.BI : rev
+means from the beginning of the branch containing
+.I rev
+up to and including
+.IR rev ,
+and
+.IB rev :
+means
+from revision
+.I rev
+to the end of the branch containing
+.IR rev .
+None of the outdated revisions can have branches or locks.
+.TP
+.B \-q
+Run quietly; do not print diagnostics.
+.TP
+.B \-I
+Run interactively, even if the standard input is not a terminal.
+.TP
+.B \-s\f2state\fP\f1[\fP:\f2rev\fP\f1]\fP
+Set the state attribute of the revision
+.I rev
+to
+.IR state .
+If
+.I rev
+is a branch number, assume the latest revision on that branch.
+If
+.I rev
+is omitted, assume the latest revision on the default branch.
+Any identifier is acceptable for
+.IR state .
+A useful set of states
+is
+.B Exp
+(for experimental),
+.B Stab
+(for stable), and
+.B Rel
+(for
+released).
+By default,
+.BR ci (1)
+sets the state of a revision to
+.BR Exp .
+.TP
+.BR \-t [\f2file\fP]
+Write descriptive text from the contents of the named
+.I file
+into the \*r file, deleting the existing text.
+The
+.IR file
+pathname cannot begin with
+.BR \- .
+If
+.I file
+is omitted, obtain the text from standard input,
+terminated by end-of-file or by a line containing
+.BR \&. "\ by"
+itself.
+Prompt for the text if interaction is possible; see
+.BR \-I .
+With
+.BR \-i ,
+descriptive text is obtained
+even if
+.B \-t
+is not given.
+.TP
+.BI \-t\- string
+Write descriptive text from the
+.I string
+into the \*r file, deleting the existing text.
+.TP
+.B \-T
+Preserve the modification time on the \*r file
+unless a revision is removed.
+This option can suppress extensive recompilation caused by a
+.BR make (1)
+dependency of some copy of the working file on the \*r file.
+Use this option with care; it can suppress recompilation even when it is needed,
+i.e. when a change to the \*r file
+would mean a change to keyword strings in the working file.
+.TP
+.BI \-V
+Print \*r's version number.
+.TP
+.BI \-V n
+Emulate \*r version
+.IR n .
+See
+.BR co (1)
+for details.
+.TP
+.BI \-x "suffixes"
+Use
+.I suffixes
+to characterize \*r files.
+See
+.BR ci (1)
+for details.
+.TP
+.BI \-z zone
+Use
+.I zone
+as the default time zone.
+This option has no effect;
+it is present for compatibility with other \*r commands.
+.PP
+At least one explicit option must be given,
+to ensure compatibility with future planned extensions
+to the
+.B rcs
+command.
+.SH COMPATIBILITY
+The
+.BI \-b rev
+option generates an \*r file that cannot be parsed by \*r version 3 or earlier.
+.PP
+The
+.BI \-k subst
+options (except
+.BR \-kkv )
+generate an \*r file that cannot be parsed by \*r version 4 or earlier.
+.PP
+Use
+.BI "rcs \-V" n
+to make an \*r file acceptable to \*r version
+.I n
+by discarding information that would confuse version
+.IR n .
+.PP
+\*r version 5.5 and earlier does not support the
+.B \-x
+option, and requires a
+.B ,v
+suffix on an \*r pathname.
+.SH FILES
+.B rcs
+accesses files much as
+.BR ci (1)
+does,
+except that it uses the effective user for all accesses,
+it does not write the working file or its directory,
+and it does not even read the working file unless a revision number of
+.B $
+is specified.
+.SH ENVIRONMENT
+.TP
+.B \s-1RCSINIT\s0
+options prepended to the argument list, separated by spaces.
+See
+.BR ci (1)
+for details.
+.SH DIAGNOSTICS
+The \*r pathname and the revisions outdated are written to
+the diagnostic output.
+The exit status is zero if and only if all operations were successful.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
+.SH "SEE ALSO"
+rcsintro(1), co(1), ci(1), ident(1), rcsclean(1), rcsdiff(1),
+rcsmerge(1), rlog(1), rcsfile(5)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.SH BUGS
+A catastrophe (e.g. a system crash) can cause \*r to leave behind
+a semaphore file that causes later invocations of \*r to claim
+that the \*r file is in use.
+To fix this, remove the semaphore file.
+A semaphore file's name typically begins with
+.B ,
+or ends with
+.BR _ .
+.PP
+The separator for revision ranges in the
+.B \-o
+option used to be
+.B \-
+instead of
+.BR : ,
+but this leads to confusion when symbolic names contain
+.BR \- .
+For backwards compatibility
+.B "rcs \-o"
+still supports the old
+.B \-
+separator, but it warns about this obsolete use.
+.PP
+Symbolic names need not refer to existing revisions or branches.
+For example, the
+.B \-o
+option does not remove symbolic names for the outdated revisions; you must use
+.B \-n
+to remove the names.
+.br
diff --git a/gnu/usr.bin/rcs/rcs/rcs.c b/gnu/usr.bin/rcs/rcs/rcs.c
new file mode 100644
index 0000000..dfb622a
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcs/rcs.c
@@ -0,0 +1,1629 @@
+/* Change RCS file attributes. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.21 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.20 1995/06/01 16:23:43 eggert
+ * (main): Warn if no options were given. Punctuate messages properly.
+ *
+ * (sendmail): Rewind mailmess before flushing it.
+ * Output another warning if mail should work but fails.
+ *
+ * (buildeltatext): Pass "--binary" if -kb and if --binary makes a difference.
+ *
+ * Revision 5.19 1994/03/17 14:05:48 eggert
+ * Use ORCSerror to clean up after a fatal error. Remove lint.
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ * Flush stderr after prompt.
+ *
+ * Revision 5.18 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.17 1993/11/03 17:42:27 eggert
+ * Add -z. Don't lose track of -m or -t when there are no other changes.
+ * Don't discard ignored phrases. Improve quality of diagnostics.
+ *
+ * Revision 5.16 1992/07/28 16:12:44 eggert
+ * rcs -l now asks whether you want to break the lock.
+ * Add -V. Set RCS file's mode and time at right moment.
+ *
+ * Revision 5.15 1992/02/17 23:02:20 eggert
+ * Add -T.
+ *
+ * Revision 5.14 1992/01/27 16:42:53 eggert
+ * Add -M. Avoid invoking umask(); it's one less thing to configure.
+ * Add support for bad_creat0. lint -> RCS_lint
+ *
+ * Revision 5.13 1992/01/06 02:42:34 eggert
+ * Avoid changing RCS file in common cases where no change can occur.
+ *
+ * Revision 5.12 1991/11/20 17:58:08 eggert
+ * Don't read the delta tree from a nonexistent RCS file.
+ *
+ * Revision 5.11 1991/10/07 17:32:46 eggert
+ * Remove lint.
+ *
+ * Revision 5.10 1991/08/19 23:17:54 eggert
+ * Add -m, -r$, piece tables. Revision separator is `:', not `-'. Tune.
+ *
+ * Revision 5.9 1991/04/21 11:58:18 eggert
+ * Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.8 1991/02/25 07:12:38 eggert
+ * strsave -> str_save (DG/UX name clash)
+ * 0444 -> S_IRUSR|S_IRGRP|S_IROTH for portability
+ *
+ * Revision 5.7 1990/12/18 17:19:21 eggert
+ * Fix bug with multiple -n and -N options.
+ *
+ * Revision 5.6 1990/12/04 05:18:40 eggert
+ * Use -I for prompts and -q for diagnostics.
+ *
+ * Revision 5.5 1990/11/11 00:06:35 eggert
+ * Fix `rcs -e' core dump.
+ *
+ * Revision 5.4 1990/11/01 05:03:33 eggert
+ * Add -I and new -t behavior. Permit arbitrary data in logs.
+ *
+ * Revision 5.3 1990/10/04 06:30:16 eggert
+ * Accumulate exit status across files.
+ *
+ * Revision 5.2 1990/09/04 08:02:17 eggert
+ * Standardize yes-or-no procedure.
+ *
+ * Revision 5.1 1990/08/29 07:13:51 eggert
+ * Remove unused setuid support. Clean old log messages too.
+ *
+ * Revision 5.0 1990/08/22 08:12:42 eggert
+ * Don't lose names when applying -a option to multiple files.
+ * Remove compile-time limits; use malloc instead. Add setuid support.
+ * Permit dates past 1999/12/31. Make lock and temp files faster and safer.
+ * Ansify and Posixate. Add -V. Fix umask bug. Make linting easier. Tune.
+ * Yield proper exit status. Check diff's output.
+ *
+ * Revision 4.11 89/05/01 15:12:06 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.10 88/11/08 16:01:54 narten
+ * didn't install previous patch correctly
+ *
+ * Revision 4.9 88/11/08 13:56:01 narten
+ * removed include <sysexits.h> (not needed)
+ * minor fix for -A option
+ *
+ * Revision 4.8 88/08/09 19:12:27 eggert
+ * Don't access freed storage.
+ * Use execv(), not system(); yield proper exit status; remove lint.
+ *
+ * Revision 4.7 87/12/18 11:37:17 narten
+ * lint cleanups (Guy Harris)
+ *
+ * Revision 4.6 87/10/18 10:28:48 narten
+ * Updating verison numbers. Changes relative to 1.1 are actually
+ * relative to 4.3
+ *
+ * Revision 1.4 87/09/24 13:58:52 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.3 87/03/27 14:21:55 jenkins
+ * Port to suns
+ *
+ * Revision 1.2 85/12/17 13:59:09 albitz
+ * Changed setstate to rcs_setstate because of conflict with random.o.
+ *
+ * Revision 4.3 83/12/15 12:27:33 wft
+ * rcs -u now breaks most recent lock if it can't find a lock by the caller.
+ *
+ * Revision 4.2 83/12/05 10:18:20 wft
+ * Added conditional compilation for sending mail.
+ * Alternatives: V4_2BSD, V6, USG, and other.
+ *
+ * Revision 4.1 83/05/10 16:43:02 wft
+ * Simplified breaklock(); added calls to findlock() and getcaller().
+ * Added option -b (default branch). Updated -s and -w for -b.
+ * Removed calls to stat(); now done by pairfilenames().
+ * Replaced most catchints() calls with restoreints().
+ * Removed check for exit status of delivermail().
+ * Directed all interactive output to stderr.
+ *
+ * Revision 3.9.1.1 83/12/02 22:08:51 wft
+ * Added conditional compilation for 4.2 sendmail and 4.1 delivermail.
+ *
+ * Revision 3.9 83/02/15 15:38:39 wft
+ * Added call to fastcopy() to copy remainder of RCS file.
+ *
+ * Revision 3.8 83/01/18 17:37:51 wft
+ * Changed sendmail(): now uses delivermail, and asks whether to break the lock.
+ *
+ * Revision 3.7 83/01/15 18:04:25 wft
+ * Removed putree(); replaced with puttree() in rcssyn.c.
+ * Combined putdellog() and scanlogtext(); deleted putdellog().
+ * Cleaned up diagnostics and error messages. Fixed problem with
+ * mutilated files in case of deletions in 2 files in a single command.
+ * Changed marking of selector from 'D' to DELETE.
+ *
+ * Revision 3.6 83/01/14 15:37:31 wft
+ * Added ignoring of interrupts while new RCS file is renamed;
+ * Avoids deletion of RCS files by interrupts.
+ *
+ * Revision 3.5 82/12/10 21:11:39 wft
+ * Removed unused variables, fixed checking of return code from diff,
+ * introduced variant COMPAT2 for skipping Suffix on -A files.
+ *
+ * Revision 3.4 82/12/04 13:18:20 wft
+ * Replaced getdelta() with gettree(), changed breaklock to update
+ * field lockedby, added some diagnostics.
+ *
+ * Revision 3.3 82/12/03 17:08:04 wft
+ * Replaced getlogin() with getpwuid(), flcose() with ffclose(),
+ * /usr/ucb/Mail with macro MAIL. Removed handling of Suffix (-x).
+ * fixed -u for missing revno. Disambiguated structure members.
+ *
+ * Revision 3.2 82/10/18 21:05:07 wft
+ * rcs -i now generates a file mode given by the umask minus write permission;
+ * otherwise, rcs keeps the mode, but removes write permission.
+ * I added a check for write error, fixed call to getlogin(), replaced
+ * curdir() with getfullRCSname(), cleaned up handling -U/L, and changed
+ * conflicting, long identifiers.
+ *
+ * Revision 3.1 82/10/13 16:11:07 wft
+ * fixed type of variables receiving from getc() (char -> int).
+ */
+
+
+#include "rcsbase.h"
+
+struct Lockrev {
+ char const *revno;
+ struct Lockrev * nextrev;
+};
+
+struct Symrev {
+ char const *revno;
+ char const *ssymbol;
+ int override;
+ struct Symrev * nextsym;
+};
+
+struct Message {
+ char const *revno;
+ struct cbuf message;
+ struct Message *nextmessage;
+};
+
+struct Status {
+ char const *revno;
+ char const *status;
+ struct Status * nextstatus;
+};
+
+enum changeaccess {append, erase};
+struct chaccess {
+ char const *login;
+ enum changeaccess command;
+ struct chaccess *nextchaccess;
+};
+
+struct delrevpair {
+ char const *strt;
+ char const *end;
+ int code;
+};
+
+static int branchpoint P((struct hshentry*,struct hshentry*));
+static int breaklock P((struct hshentry const*));
+static int buildeltatext P((struct hshentries const*));
+static int doaccess P((void));
+static int doassoc P((void));
+static int dolocks P((void));
+static int domessages P((void));
+static int rcs_setstate P((char const*,char const*));
+static int removerevs P((void));
+static int sendmail P((char const*,char const*));
+static int setlock P((char const*));
+static struct Lockrev **rmnewlocklst P((char const*));
+static struct hshentry *searchcutpt P((char const*,int,struct hshentries*));
+static void buildtree P((void));
+static void cleanup P((void));
+static void getaccessor P((char*,enum changeaccess));
+static void getassoclst P((int,char*));
+static void getchaccess P((char const*,enum changeaccess));
+static void getdelrev P((char*));
+static void getmessage P((char*));
+static void getstates P((char*));
+static void scanlogtext P((struct hshentry*,int));
+
+static struct buf numrev;
+static char const *headstate;
+static int chgheadstate, exitstatus, lockhead, unlockcaller;
+static int suppress_mail;
+static struct Lockrev *newlocklst, *rmvlocklst;
+static struct Message *messagelst, **nextmessage;
+static struct Status *statelst, **nextstate;
+static struct Symrev *assoclst, **nextassoc;
+static struct chaccess *chaccess, **nextchaccess;
+static struct delrevpair delrev;
+static struct hshentry *cuthead, *cuttail, *delstrt;
+static struct hshentries *gendeltas;
+
+mainProg(rcsId, "rcs", "$FreeBSD$")
+{
+ static char const cmdusage[] =
+ "\nrcs usage: rcs -{ae}logins -Afile -{blu}[rev] -cstring -{iILqTU} -ksubst -mrev:msg -{nN}name[:[rev]] -orange -sstate[:rev] -t[text] -Vn -xsuff -zzone file ...";
+
+ char *a, **newargv, *textfile;
+ char const *branchsym, *commsyml;
+ int branchflag, changed, expmode, initflag;
+ int strictlock, strict_selected, textflag;
+ int keepRCStime, Ttimeflag;
+ size_t commsymlen;
+ struct buf branchnum;
+ struct Lockrev *lockpt;
+ struct Lockrev **curlock, **rmvlock;
+ struct Status * curstate;
+
+ nosetid();
+
+ nextassoc = &assoclst;
+ nextchaccess = &chaccess;
+ nextmessage = &messagelst;
+ nextstate = &statelst;
+ branchsym = commsyml = textfile = 0;
+ branchflag = strictlock = false;
+ bufautobegin(&branchnum);
+ commsymlen = 0;
+ curlock = &newlocklst;
+ rmvlock = &rmvlocklst;
+ expmode = -1;
+ suffixes = X_DEFAULT;
+ initflag= textflag = false;
+ strict_selected = 0;
+ Ttimeflag = false;
+
+ /* preprocessing command options */
+ if (1 < argc && argv[1][0] != '-')
+ warn("No options were given; this usage is obsolescent.");
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ while (a = *++argv, 0<--argc && *a++=='-') {
+ switch (*a++) {
+
+ case 'i': /* initial version */
+ initflag = true;
+ break;
+
+ case 'b': /* change default branch */
+ if (branchflag) redefined('b');
+ branchflag= true;
+ branchsym = a;
+ break;
+
+ case 'c': /* change comment symbol */
+ if (commsyml) redefined('c');
+ commsyml = a;
+ commsymlen = strlen(a);
+ break;
+
+ case 'a': /* add new accessor */
+ getaccessor(*argv+1, append);
+ break;
+
+ case 'A': /* append access list according to accessfile */
+ if (!*a) {
+ error("missing pathname after -A");
+ break;
+ }
+ *argv = a;
+ if (0 < pairnames(1,argv,rcsreadopen,true,false)) {
+ while (AccessList) {
+ getchaccess(str_save(AccessList->login),append);
+ AccessList = AccessList->nextaccess;
+ }
+ Izclose(&finptr);
+ }
+ break;
+
+ case 'e': /* remove accessors */
+ getaccessor(*argv+1, erase);
+ break;
+
+ case 'l': /* lock a revision if it is unlocked */
+ if (!*a) {
+ /* Lock head or default branch. */
+ lockhead = true;
+ break;
+ }
+ *curlock = lockpt = talloc(struct Lockrev);
+ lockpt->revno = a;
+ lockpt->nextrev = 0;
+ curlock = &lockpt->nextrev;
+ break;
+
+ case 'u': /* release lock of a locked revision */
+ if (!*a) {
+ unlockcaller=true;
+ break;
+ }
+ *rmvlock = lockpt = talloc(struct Lockrev);
+ lockpt->revno = a;
+ lockpt->nextrev = 0;
+ rmvlock = &lockpt->nextrev;
+ curlock = rmnewlocklst(lockpt->revno);
+ break;
+
+ case 'L': /* set strict locking */
+ if (strict_selected) {
+ if (!strictlock) /* Already selected -U? */
+ warn("-U overridden by -L");
+ }
+ strictlock = true;
+ strict_selected = true;
+ break;
+
+ case 'U': /* release strict locking */
+ if (strict_selected) {
+ if (strictlock) /* Already selected -L? */
+ warn("-L overridden by -U");
+ }
+ strict_selected = true;
+ break;
+
+ case 'n': /* add new association: error, if name exists */
+ if (!*a) {
+ error("missing symbolic name after -n");
+ break;
+ }
+ getassoclst(false, (*argv)+1);
+ break;
+
+ case 'N': /* add or change association */
+ if (!*a) {
+ error("missing symbolic name after -N");
+ break;
+ }
+ getassoclst(true, (*argv)+1);
+ break;
+
+ case 'm': /* change log message */
+ getmessage(a);
+ break;
+
+ case 'M': /* do not send mail */
+ suppress_mail = true;
+ break;
+
+ case 'o': /* delete revisions */
+ if (delrev.strt) redefined('o');
+ if (!*a) {
+ error("missing revision range after -o");
+ break;
+ }
+ getdelrev( (*argv)+1 );
+ break;
+
+ case 's': /* change state attribute of a revision */
+ if (!*a) {
+ error("state missing after -s");
+ break;
+ }
+ getstates( (*argv)+1);
+ break;
+
+ case 't': /* change descriptive text */
+ textflag=true;
+ if (*a) {
+ if (textfile) redefined('t');
+ textfile = a;
+ }
+ break;
+
+ case 'T': /* do not update last-mod time for minor changes */
+ if (*a)
+ goto unknown;
+ Ttimeflag = true;
+ break;
+
+ case 'I':
+ interactiveflag = true;
+ break;
+
+ case 'q':
+ quietflag = true;
+ break;
+
+ case 'x':
+ suffixes = a;
+ break;
+
+ case 'V':
+ setRCSversion(*argv);
+ break;
+
+ case 'z':
+ zone_set(a);
+ break;
+
+ case 'k': /* set keyword expand mode */
+ if (0 <= expmode) redefined('k');
+ if (0 <= (expmode = str2expmode(a)))
+ break;
+ /* fall into */
+ default:
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
+ };
+ } /* end processing of options */
+
+ /* Now handle all pathnames. */
+ if (nerror) cleanup();
+ else if (argc < 1) faterror("no input file%s", cmdusage);
+ else for (; 0 < argc; cleanup(), ++argv, --argc) {
+
+ ffree();
+
+ if ( initflag ) {
+ switch (pairnames(argc, argv, rcswriteopen, false, false)) {
+ case -1: break; /* not exist; ok */
+ case 0: continue; /* error */
+ case 1: rcserror("already exists");
+ continue;
+ }
+ }
+ else {
+ switch (pairnames(argc, argv, rcswriteopen, true, false)) {
+ case -1: continue; /* not exist */
+ case 0: continue; /* errors */
+ case 1: break; /* file exists; ok*/
+ }
+ }
+
+
+ /*
+ * RCSname contains the name of the RCS file, and
+ * workname contains the name of the working file.
+ * if !initflag, finptr contains the file descriptor for the
+ * RCS file. The admin node is initialized.
+ */
+
+ diagnose("RCS file: %s\n", RCSname);
+
+ changed = initflag | textflag;
+ keepRCStime = Ttimeflag;
+ if (!initflag) {
+ if (!checkaccesslist()) continue;
+ gettree(); /* Read the delta tree. */
+ }
+
+ /* update admin. node */
+ if (strict_selected) {
+ changed |= StrictLocks ^ strictlock;
+ StrictLocks = strictlock;
+ }
+ if (
+ commsyml &&
+ (
+ commsymlen != Comment.size ||
+ memcmp(commsyml, Comment.string, commsymlen) != 0
+ )
+ ) {
+ Comment.string = commsyml;
+ Comment.size = strlen(commsyml);
+ changed = true;
+ }
+ if (0 <= expmode && Expand != expmode) {
+ Expand = expmode;
+ changed = true;
+ }
+
+ /* update default branch */
+ if (branchflag && expandsym(branchsym, &branchnum)) {
+ if (countnumflds(branchnum.string)) {
+ if (cmpnum(Dbranch, branchnum.string) != 0) {
+ Dbranch = branchnum.string;
+ changed = true;
+ }
+ } else
+ if (Dbranch) {
+ Dbranch = 0;
+ changed = true;
+ }
+ }
+
+ changed |= doaccess(); /* Update access list. */
+
+ changed |= doassoc(); /* Update association list. */
+
+ changed |= dolocks(); /* Update locks. */
+
+ changed |= domessages(); /* Update log messages. */
+
+ /* update state attribution */
+ if (chgheadstate) {
+ /* change state of default branch or head */
+ if (!Dbranch) {
+ if (!Head)
+ rcswarn("can't change states in an empty tree");
+ else if (strcmp(Head->state, headstate) != 0) {
+ Head->state = headstate;
+ changed = true;
+ }
+ } else
+ changed |= rcs_setstate(Dbranch,headstate);
+ }
+ for (curstate = statelst; curstate; curstate = curstate->nextstatus)
+ changed |= rcs_setstate(curstate->revno,curstate->status);
+
+ cuthead = cuttail = 0;
+ if (delrev.strt && removerevs()) {
+ /* rebuild delta tree if some deltas are deleted */
+ if ( cuttail )
+ VOID genrevs(
+ cuttail->num, (char *)0, (char *)0, (char *)0,
+ &gendeltas
+ );
+ buildtree();
+ changed = true;
+ keepRCStime = false;
+ }
+
+ if (nerror)
+ continue;
+
+ putadmin();
+ if ( Head )
+ puttree(Head, frewrite);
+ putdesc(textflag,textfile);
+
+ if ( Head) {
+ if (delrev.strt || messagelst) {
+ if (!cuttail || buildeltatext(gendeltas)) {
+ advise_access(finptr, MADV_SEQUENTIAL);
+ scanlogtext((struct hshentry *)0, false);
+ /* copy rest of delta text nodes that are not deleted */
+ changed = true;
+ }
+ }
+ }
+
+ if (initflag) {
+ /* Adjust things for donerewrite's sake. */
+ if (stat(workname, &RCSstat) != 0) {
+# if bad_creat0
+ mode_t m = umask(0);
+ (void) umask(m);
+ RCSstat.st_mode = (S_IRUSR|S_IRGRP|S_IROTH) & ~m;
+# else
+ changed = -1;
+# endif
+ }
+ RCSstat.st_nlink = 0;
+ keepRCStime = false;
+ }
+ if (donerewrite(changed,
+ keepRCStime ? RCSstat.st_mtime : (time_t)-1
+ ) != 0)
+ break;
+
+ diagnose("done\n");
+ }
+
+ tempunlink();
+ exitmain(exitstatus);
+} /* end of main (rcs) */
+
+ static void
+cleanup()
+{
+ if (nerror) exitstatus = EXIT_FAILURE;
+ Izclose(&finptr);
+ Ozclose(&fcopy);
+ ORCSclose();
+ dirtempunlink();
+}
+
+ void
+exiterr()
+{
+ ORCSerror();
+ dirtempunlink();
+ tempunlink();
+ _exit(EXIT_FAILURE);
+}
+
+
+ static void
+getassoclst(flag, sp)
+int flag;
+char * sp;
+/* Function: associate a symbolic name to a revision or branch, */
+/* and store in assoclst */
+
+{
+ struct Symrev * pt;
+ char const *temp;
+ int c;
+
+ while ((c = *++sp) == ' ' || c == '\t' || c =='\n')
+ continue;
+ temp = sp;
+ sp = checksym(sp, ':'); /* check for invalid symbolic name */
+ c = *sp; *sp = '\0';
+ while( c == ' ' || c == '\t' || c == '\n') c = *++sp;
+
+ if ( c != ':' && c != '\0') {
+ error("invalid string %s after option -n or -N",sp);
+ return;
+ }
+
+ pt = talloc(struct Symrev);
+ pt->ssymbol = temp;
+ pt->override = flag;
+ if (c == '\0') /* delete symbol */
+ pt->revno = 0;
+ else {
+ while ((c = *++sp) == ' ' || c == '\n' || c == '\t')
+ continue;
+ pt->revno = sp;
+ }
+ pt->nextsym = 0;
+ *nextassoc = pt;
+ nextassoc = &pt->nextsym;
+}
+
+
+ static void
+getchaccess(login, command)
+ char const *login;
+ enum changeaccess command;
+{
+ register struct chaccess *pt;
+
+ pt = talloc(struct chaccess);
+ pt->login = login;
+ pt->command = command;
+ pt->nextchaccess = 0;
+ *nextchaccess = pt;
+ nextchaccess = &pt->nextchaccess;
+}
+
+
+
+ static void
+getaccessor(opt, command)
+ char *opt;
+ enum changeaccess command;
+/* Function: get the accessor list of options -e and -a, */
+/* and store in chaccess */
+
+
+{
+ register c;
+ register char *sp;
+
+ sp = opt;
+ while ((c = *++sp) == ' ' || c == '\n' || c == '\t' || c == ',')
+ continue;
+ if ( c == '\0') {
+ if (command == erase && sp-opt == 1) {
+ getchaccess((char*)0, command);
+ return;
+ }
+ error("missing login name after option -a or -e");
+ return;
+ }
+
+ while( c != '\0') {
+ getchaccess(sp, command);
+ sp = checkid(sp,',');
+ c = *sp; *sp = '\0';
+ while( c == ' ' || c == '\n' || c == '\t'|| c == ',')c =(*++sp);
+ }
+}
+
+
+ static void
+getmessage(option)
+ char *option;
+{
+ struct Message *pt;
+ struct cbuf cb;
+ char *m;
+
+ if (!(m = strchr(option, ':'))) {
+ error("-m option lacks revision number");
+ return;
+ }
+ *m++ = 0;
+ cb = cleanlogmsg(m, strlen(m));
+ if (!cb.size) {
+ error("-m option lacks log message");
+ return;
+ }
+ pt = talloc(struct Message);
+ pt->revno = option;
+ pt->message = cb;
+ pt->nextmessage = 0;
+ *nextmessage = pt;
+ nextmessage = &pt->nextmessage;
+}
+
+
+ static void
+getstates(sp)
+char *sp;
+/* Function: get one state attribute and the corresponding */
+/* revision and store in statelst */
+
+{
+ char const *temp;
+ struct Status *pt;
+ register c;
+
+ while ((c = *++sp) ==' ' || c == '\t' || c == '\n')
+ continue;
+ temp = sp;
+ sp = checkid(sp,':'); /* check for invalid state attribute */
+ c = *sp; *sp = '\0';
+ while( c == ' ' || c == '\t' || c == '\n' ) c = *++sp;
+
+ if ( c == '\0' ) { /* change state of def. branch or Head */
+ chgheadstate = true;
+ headstate = temp;
+ return;
+ }
+ else if ( c != ':' ) {
+ error("missing ':' after state in option -s");
+ return;
+ }
+
+ while ((c = *++sp) == ' ' || c == '\t' || c == '\n')
+ continue;
+ pt = talloc(struct Status);
+ pt->status = temp;
+ pt->revno = sp;
+ pt->nextstatus = 0;
+ *nextstate = pt;
+ nextstate = &pt->nextstatus;
+}
+
+
+
+ static void
+getdelrev(sp)
+char *sp;
+/* Function: get revision range or branch to be deleted, */
+/* and place in delrev */
+{
+ int c;
+ struct delrevpair *pt;
+ int separator;
+
+ pt = &delrev;
+ while ((c = (*++sp)) == ' ' || c == '\n' || c == '\t')
+ continue;
+
+ /* Support old ambiguous '-' syntax; this will go away. */
+ if (strchr(sp,':'))
+ separator = ':';
+ else {
+ if (strchr(sp,'-') && VERSION(5) <= RCSversion)
+ warn("`-' is obsolete in `-o%s'; use `:' instead", sp);
+ separator = '-';
+ }
+
+ if (c == separator) { /* -o:rev */
+ while ((c = (*++sp)) == ' ' || c == '\n' || c == '\t')
+ continue;
+ pt->strt = sp; pt->code = 1;
+ while( c != ' ' && c != '\n' && c != '\t' && c != '\0') c =(*++sp);
+ *sp = '\0';
+ pt->end = 0;
+ return;
+ }
+ else {
+ pt->strt = sp;
+ while( c != ' ' && c != '\n' && c != '\t' && c != '\0'
+ && c != separator ) c = *++sp;
+ *sp = '\0';
+ while( c == ' ' || c == '\n' || c == '\t' ) c = *++sp;
+ if ( c == '\0' ) { /* -o rev or branch */
+ pt->code = 0;
+ pt->end = 0;
+ return;
+ }
+ if (c != separator) {
+ error("invalid range %s %s after -o", pt->strt, sp);
+ }
+ while ((c = *++sp) == ' ' || c == '\n' || c == '\t')
+ continue;
+ if (!c) { /* -orev: */
+ pt->code = 2;
+ pt->end = 0;
+ return;
+ }
+ }
+ /* -orev1:rev2 */
+ pt->end = sp; pt->code = 3;
+ while( c!= ' ' && c != '\n' && c != '\t' && c != '\0') c = *++sp;
+ *sp = '\0';
+}
+
+
+
+
+ static void
+scanlogtext(delta,edit)
+ struct hshentry *delta;
+ int edit;
+/* Function: Scans delta text nodes up to and including the one given
+ * by delta, or up to last one present, if !delta.
+ * For the one given by delta (if delta), the log message is saved into
+ * delta->log if delta==cuttail; the text is edited if EDIT is set, else copied.
+ * Assumes the initial lexeme must be read in first.
+ * Does not advance nexttok after it is finished, except if !delta.
+ */
+{
+ struct hshentry const *nextdelta;
+ struct cbuf cb;
+
+ for (;;) {
+ foutptr = 0;
+ if (eoflex()) {
+ if(delta)
+ rcsfaterror("can't find delta for revision %s",
+ delta->num
+ );
+ return; /* no more delta text nodes */
+ }
+ nextlex();
+ if (!(nextdelta=getnum()))
+ fatserror("delta number corrupted");
+ if (nextdelta->selector) {
+ foutptr = frewrite;
+ aprintf(frewrite,DELNUMFORM,nextdelta->num,Klog);
+ }
+ getkeystring(Klog);
+ if (nextdelta == cuttail) {
+ cb = savestring(&curlogbuf);
+ if (!delta->log.string)
+ delta->log = cleanlogmsg(curlogbuf.string, cb.size);
+ nextlex();
+ delta->igtext = getphrases(Ktext);
+ } else {
+ if (nextdelta->log.string && nextdelta->selector) {
+ foutptr = 0;
+ readstring();
+ foutptr = frewrite;
+ putstring(foutptr, false, nextdelta->log, true);
+ afputc(nextc, foutptr);
+ } else
+ readstring();
+ ignorephrases(Ktext);
+ }
+ getkeystring(Ktext);
+
+ if (delta==nextdelta)
+ break;
+ readstring(); /* skip over it */
+
+ }
+ /* got the one we're looking for */
+ if (edit)
+ editstring((struct hshentry*)0);
+ else
+ enterstring();
+}
+
+
+
+ static struct Lockrev **
+rmnewlocklst(which)
+ char const *which;
+/* Remove lock to revision WHICH from newlocklst. */
+{
+ struct Lockrev *pt, **pre;
+
+ pre = &newlocklst;
+ while ((pt = *pre))
+ if (strcmp(pt->revno, which) != 0)
+ pre = &pt->nextrev;
+ else {
+ *pre = pt->nextrev;
+ tfree(pt);
+ }
+ return pre;
+}
+
+
+
+ static int
+doaccess()
+{
+ register struct chaccess *ch;
+ register struct access **p, *t;
+ register int changed = false;
+
+ for (ch = chaccess; ch; ch = ch->nextchaccess) {
+ switch (ch->command) {
+ case erase:
+ if (!ch->login) {
+ if (AccessList) {
+ AccessList = 0;
+ changed = true;
+ }
+ } else
+ for (p = &AccessList; (t = *p); p = &t->nextaccess)
+ if (strcmp(ch->login, t->login) == 0) {
+ *p = t->nextaccess;
+ changed = true;
+ break;
+ }
+ break;
+ case append:
+ for (p = &AccessList; ; p = &t->nextaccess)
+ if (!(t = *p)) {
+ *p = t = ftalloc(struct access);
+ t->login = ch->login;
+ t->nextaccess = 0;
+ changed = true;
+ break;
+ } else if (strcmp(ch->login, t->login) == 0)
+ break;
+ break;
+ }
+ }
+ return changed;
+}
+
+
+ static int
+sendmail(Delta, who)
+ char const *Delta, *who;
+/* Function: mail to who, informing him that his lock on delta was
+ * broken by caller. Ask first whether to go ahead. Return false on
+ * error or if user decides not to break the lock.
+ */
+{
+#ifdef SENDMAIL
+ char const *messagefile;
+ int old1, old2, c, status;
+ FILE * mailmess;
+#endif
+
+
+ aprintf(stderr, "Revision %s is already locked by %s.\n", Delta, who);
+ if (suppress_mail)
+ return true;
+ if (!yesorno(false, "Do you want to break the lock? [ny](n): "))
+ return false;
+
+ /* go ahead with breaking */
+#ifdef SENDMAIL
+ messagefile = maketemp(0);
+ if (!(mailmess = fopenSafer(messagefile, "w+"))) {
+ efaterror(messagefile);
+ }
+
+ aprintf(mailmess, "Subject: Broken lock on %s\n\nYour lock on revision %s of file %s\nhas been broken by %s for the following reason:\n",
+ basefilename(RCSname), Delta, getfullRCSname(), getcaller()
+ );
+ aputs("State the reason for breaking the lock:\n(terminate with single '.' or end of file)\n>> ", stderr);
+ eflush();
+
+ old1 = '\n'; old2 = ' ';
+ for (; ;) {
+ c = getcstdin();
+ if (feof(stdin)) {
+ aprintf(mailmess, "%c\n", old1);
+ break;
+ }
+ else if ( c == '\n' && old1 == '.' && old2 == '\n')
+ break;
+ else {
+ afputc(old1, mailmess);
+ old2 = old1; old1 = c;
+ if (c == '\n') {
+ aputs(">> ", stderr);
+ eflush();
+ }
+ }
+ }
+ Orewind(mailmess);
+ aflush(mailmess);
+ status = run(fileno(mailmess), (char*)0, SENDMAIL, who, (char*)0);
+ Ozclose(&mailmess);
+ if (status == 0)
+ return true;
+ warn("Mail failed.");
+#endif
+ warn("Mail notification of broken locks is not available.");
+ warn("Please tell `%s' why you broke the lock.", who);
+ return(true);
+}
+
+
+
+ static int
+breaklock(delta)
+ struct hshentry const *delta;
+/* function: Finds the lock held by caller on delta,
+ * and removes it.
+ * Sends mail if a lock different from the caller's is broken.
+ * Prints an error message if there is no such lock or error.
+ */
+{
+ register struct rcslock *next, **trail;
+ char const *num;
+
+ num=delta->num;
+ for (trail = &Locks; (next = *trail); trail = &next->nextlock)
+ if (strcmp(num, next->delta->num) == 0) {
+ if (
+ strcmp(getcaller(),next->login) != 0
+ && !sendmail(num, next->login)
+ ) {
+ rcserror("revision %s still locked by %s",
+ num, next->login
+ );
+ return false;
+ }
+ diagnose("%s unlocked\n", next->delta->num);
+ *trail = next->nextlock;
+ next->delta->lockedby = 0;
+ return true;
+ }
+ rcserror("no lock set on revision %s", num);
+ return false;
+}
+
+
+
+ static struct hshentry *
+searchcutpt(object, length, store)
+ char const *object;
+ int length;
+ struct hshentries *store;
+/* Function: Search store and return entry with number being object. */
+/* cuttail = 0, if the entry is Head; otherwise, cuttail */
+/* is the entry point to the one with number being object */
+
+{
+ cuthead = 0;
+ while (compartial(store->first->num, object, length)) {
+ cuthead = store->first;
+ store = store->rest;
+ }
+ return store->first;
+}
+
+
+
+ static int
+branchpoint(strt, tail)
+struct hshentry *strt, *tail;
+/* Function: check whether the deltas between strt and tail */
+/* are locked or branch point, return 1 if any is */
+/* locked or branch point; otherwise, return 0 and */
+/* mark deleted */
+
+{
+ struct hshentry *pt;
+ struct rcslock const *lockpt;
+
+ for (pt = strt; pt != tail; pt = pt->next) {
+ if ( pt->branches ){ /* a branch point */
+ rcserror("can't remove branch point %s", pt->num);
+ return true;
+ }
+ for (lockpt = Locks; lockpt; lockpt = lockpt->nextlock)
+ if (lockpt->delta == pt) {
+ rcserror("can't remove locked revision %s", pt->num);
+ return true;
+ }
+ pt->selector = false;
+ diagnose("deleting revision %s\n",pt->num);
+ }
+ return false;
+}
+
+
+
+ static int
+removerevs()
+/* Function: get the revision range to be removed, and place the */
+/* first revision removed in delstrt, the revision before */
+/* delstrt in cuthead (0, if delstrt is head), and the */
+/* revision after the last removed revision in cuttail (0 */
+/* if the last is a leaf */
+
+{
+ struct hshentry *target, *target2, *temp;
+ int length;
+ int cmp;
+
+ if (!expandsym(delrev.strt, &numrev)) return 0;
+ target = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&gendeltas);
+ if ( ! target ) return 0;
+ cmp = cmpnum(target->num, numrev.string);
+ length = countnumflds(numrev.string);
+
+ if (delrev.code == 0) { /* -o rev or -o branch */
+ if (length & 1)
+ temp=searchcutpt(target->num,length+1,gendeltas);
+ else if (cmp) {
+ rcserror("Revision %s doesn't exist.", numrev.string);
+ return 0;
+ }
+ else
+ temp = searchcutpt(numrev.string, length, gendeltas);
+ cuttail = target->next;
+ if ( branchpoint(temp, cuttail) ) {
+ cuttail = 0;
+ return 0;
+ }
+ delstrt = temp; /* first revision to be removed */
+ return 1;
+ }
+
+ if (length & 1) { /* invalid branch after -o */
+ rcserror("invalid branch range %s after -o", numrev.string);
+ return 0;
+ }
+
+ if (delrev.code == 1) { /* -o -rev */
+ if ( length > 2 ) {
+ temp = searchcutpt( target->num, length-1, gendeltas);
+ cuttail = target->next;
+ }
+ else {
+ temp = searchcutpt(target->num, length, gendeltas);
+ cuttail = target;
+ while( cuttail && ! cmpnumfld(target->num,cuttail->num,1) )
+ cuttail = cuttail->next;
+ }
+ if ( branchpoint(temp, cuttail) ){
+ cuttail = 0;
+ return 0;
+ }
+ delstrt = temp;
+ return 1;
+ }
+
+ if (delrev.code == 2) { /* -o rev- */
+ if ( length == 2 ) {
+ temp = searchcutpt(target->num, 1,gendeltas);
+ if (cmp)
+ cuttail = target;
+ else
+ cuttail = target->next;
+ }
+ else {
+ if (cmp) {
+ cuthead = target;
+ if ( !(temp = target->next) ) return 0;
+ }
+ else
+ temp = searchcutpt(target->num, length, gendeltas);
+ getbranchno(temp->num, &numrev); /* get branch number */
+ VOID genrevs(numrev.string, (char*)0, (char*)0, (char*)0, &gendeltas);
+ }
+ if ( branchpoint( temp, cuttail ) ) {
+ cuttail = 0;
+ return 0;
+ }
+ delstrt = temp;
+ return 1;
+ }
+
+ /* -o rev1-rev2 */
+ if (!expandsym(delrev.end, &numrev)) return 0;
+ if (
+ length != countnumflds(numrev.string)
+ || (length>2 && compartial(numrev.string, target->num, length-1))
+ ) {
+ rcserror("invalid revision range %s-%s",
+ target->num, numrev.string
+ );
+ return 0;
+ }
+
+ target2 = genrevs(numrev.string,(char*)0,(char*)0,(char*)0,&gendeltas);
+ if ( ! target2 ) return 0;
+
+ if ( length > 2) { /* delete revisions on branches */
+ if ( cmpnum(target->num, target2->num) > 0) {
+ cmp = cmpnum(target2->num, numrev.string);
+ temp = target;
+ target = target2;
+ target2 = temp;
+ }
+ if (cmp) {
+ if ( ! cmpnum(target->num, target2->num) ) {
+ rcserror("Revisions %s-%s don't exist.",
+ delrev.strt, delrev.end
+ );
+ return 0;
+ }
+ cuthead = target;
+ temp = target->next;
+ }
+ else
+ temp = searchcutpt(target->num, length, gendeltas);
+ cuttail = target2->next;
+ }
+ else { /* delete revisions on trunk */
+ if ( cmpnum( target->num, target2->num) < 0 ) {
+ temp = target;
+ target = target2;
+ target2 = temp;
+ }
+ else
+ cmp = cmpnum(target2->num, numrev.string);
+ if (cmp) {
+ if ( ! cmpnum(target->num, target2->num) ) {
+ rcserror("Revisions %s-%s don't exist.",
+ delrev.strt, delrev.end
+ );
+ return 0;
+ }
+ cuttail = target2;
+ }
+ else
+ cuttail = target2->next;
+ temp = searchcutpt(target->num, length, gendeltas);
+ }
+ if ( branchpoint(temp, cuttail) ) {
+ cuttail = 0;
+ return 0;
+ }
+ delstrt = temp;
+ return 1;
+}
+
+
+
+ static int
+doassoc()
+/* Add or delete (if !revno) association that is stored in assoclst. */
+{
+ char const *p;
+ int changed = false;
+ struct Symrev const *curassoc;
+ struct assoc **pre, *pt;
+
+ /* add new associations */
+ for (curassoc = assoclst; curassoc; curassoc = curassoc->nextsym) {
+ char const *ssymbol = curassoc->ssymbol;
+
+ if (!curassoc->revno) { /* delete symbol */
+ for (pre = &Symbols; ; pre = &pt->nextassoc)
+ if (!(pt = *pre)) {
+ rcswarn("can't delete nonexisting symbol %s", ssymbol);
+ break;
+ } else if (strcmp(pt->symbol, ssymbol) == 0) {
+ *pre = pt->nextassoc;
+ changed = true;
+ break;
+ }
+ }
+ else {
+ if (curassoc->revno[0]) {
+ p = 0;
+ if (expandsym(curassoc->revno, &numrev))
+ p = fstr_save(numrev.string);
+ } else if (!(p = tiprev()))
+ rcserror("no latest revision to associate with symbol %s",
+ ssymbol
+ );
+ if (p)
+ changed |= addsymbol(p, ssymbol, curassoc->override);
+ }
+ }
+ return changed;
+}
+
+
+
+ static int
+dolocks()
+/* Function: remove lock for caller or first lock if unlockcaller is set;
+ * remove locks which are stored in rmvlocklst,
+ * add new locks which are stored in newlocklst,
+ * add lock for Dbranch or Head if lockhead is set.
+ */
+{
+ struct Lockrev const *lockpt;
+ struct hshentry *target;
+ int changed = false;
+
+ if (unlockcaller) { /* find lock for caller */
+ if ( Head ) {
+ if (Locks) {
+ switch (findlock(true, &target)) {
+ case 0:
+ /* remove most recent lock */
+ changed |= breaklock(Locks->delta);
+ break;
+ case 1:
+ diagnose("%s unlocked\n",target->num);
+ changed = true;
+ break;
+ }
+ } else {
+ rcswarn("No locks are set.");
+ }
+ } else {
+ rcswarn("can't unlock an empty tree");
+ }
+ }
+
+ /* remove locks which are stored in rmvlocklst */
+ for (lockpt = rmvlocklst; lockpt; lockpt = lockpt->nextrev)
+ if (expandsym(lockpt->revno, &numrev)) {
+ target = genrevs(numrev.string, (char *)0, (char *)0, (char *)0, &gendeltas);
+ if ( target )
+ if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string))
+ rcserror("can't unlock nonexisting revision %s",
+ lockpt->revno
+ );
+ else
+ changed |= breaklock(target);
+ /* breaklock does its own diagnose */
+ }
+
+ /* add new locks which stored in newlocklst */
+ for (lockpt = newlocklst; lockpt; lockpt = lockpt->nextrev)
+ changed |= setlock(lockpt->revno);
+
+ if (lockhead) /* lock default branch or head */
+ if (Dbranch)
+ changed |= setlock(Dbranch);
+ else if (Head)
+ changed |= setlock(Head->num);
+ else
+ rcswarn("can't lock an empty tree");
+ return changed;
+}
+
+
+
+ static int
+setlock(rev)
+ char const *rev;
+/* Function: Given a revision or branch number, finds the corresponding
+ * delta and locks it for caller.
+ */
+{
+ struct hshentry *target;
+ int r;
+
+ if (expandsym(rev, &numrev)) {
+ target = genrevs(numrev.string, (char*)0, (char*)0,
+ (char*)0, &gendeltas);
+ if ( target )
+ if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string))
+ rcserror("can't lock nonexisting revision %s",
+ numrev.string
+ );
+ else {
+ if ((r = addlock(target, false)) < 0 && breaklock(target))
+ r = addlock(target, true);
+ if (0 <= r) {
+ if (r)
+ diagnose("%s locked\n", target->num);
+ return r;
+ }
+ }
+ }
+ return 0;
+}
+
+
+ static int
+domessages()
+{
+ struct hshentry *target;
+ struct Message *p;
+ int changed = false;
+
+ for (p = messagelst; p; p = p->nextmessage)
+ if (
+ expandsym(p->revno, &numrev) &&
+ (target = genrevs(
+ numrev.string, (char*)0, (char*)0, (char*)0, &gendeltas
+ ))
+ ) {
+ /*
+ * We can't check the old log -- it's much later in the file.
+ * We pessimistically assume that it changed.
+ */
+ target->log = p->message;
+ changed = true;
+ }
+ return changed;
+}
+
+
+ static int
+rcs_setstate(rev,status)
+ char const *rev, *status;
+/* Function: Given a revision or branch number, finds the corresponding delta
+ * and sets its state to status.
+ */
+{
+ struct hshentry *target;
+
+ if (expandsym(rev, &numrev)) {
+ target = genrevs(numrev.string, (char*)0, (char*)0,
+ (char*)0, &gendeltas);
+ if ( target )
+ if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string))
+ rcserror("can't set state of nonexisting revision %s",
+ numrev.string
+ );
+ else if (strcmp(target->state, status) != 0) {
+ target->state = status;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+
+
+ static int
+buildeltatext(deltas)
+ struct hshentries const *deltas;
+/* Function: put the delta text on frewrite and make necessary */
+/* change to delta text */
+{
+ register FILE *fcut; /* temporary file to rebuild delta tree */
+ char const *cutname;
+
+ fcut = 0;
+ cuttail->selector = false;
+ scanlogtext(deltas->first, false);
+ if ( cuthead ) {
+ cutname = maketemp(3);
+ if (!(fcut = fopenSafer(cutname, FOPEN_WPLUS_WORK))) {
+ efaterror(cutname);
+ }
+
+ while (deltas->first != cuthead) {
+ deltas = deltas->rest;
+ scanlogtext(deltas->first, true);
+ }
+
+ snapshotedit(fcut);
+ Orewind(fcut);
+ aflush(fcut);
+ }
+
+ while (deltas->first != cuttail)
+ scanlogtext((deltas = deltas->rest)->first, true);
+ finishedit((struct hshentry*)0, (FILE*)0, true);
+ Ozclose(&fcopy);
+
+ if (fcut) {
+ char const *diffname = maketemp(0);
+ char const *diffv[6 + !!OPEN_O_BINARY];
+ char const **diffp = diffv;
+ *++diffp = DIFF;
+ *++diffp = DIFFFLAGS;
+# if OPEN_O_BINARY
+ if (Expand == BINARY_EXPAND)
+ *++diffp == "--binary";
+# endif
+ *++diffp = "-";
+ *++diffp = resultname;
+ *++diffp = 0;
+ switch (runv(fileno(fcut), diffname, diffv)) {
+ case DIFF_FAILURE: case DIFF_SUCCESS: break;
+ default: rcsfaterror("diff failed");
+ }
+ Ofclose(fcut);
+ return putdtext(cuttail,diffname,frewrite,true);
+ } else
+ return putdtext(cuttail,resultname,frewrite,false);
+}
+
+
+
+ static void
+buildtree()
+/* Function: actually removes revisions whose selector field */
+/* is false, and rebuilds the linkage of deltas. */
+/* asks for reconfirmation if deleting last revision*/
+{
+ struct hshentry * Delta;
+ struct branchhead *pt, *pre;
+
+ if ( cuthead )
+ if ( cuthead->next == delstrt )
+ cuthead->next = cuttail;
+ else {
+ pre = pt = cuthead->branches;
+ while( pt && pt->hsh != delstrt ) {
+ pre = pt;
+ pt = pt->nextbranch;
+ }
+ if ( cuttail )
+ pt->hsh = cuttail;
+ else if ( pt == pre )
+ cuthead->branches = pt->nextbranch;
+ else
+ pre->nextbranch = pt->nextbranch;
+ }
+ else {
+ if (!cuttail && !quietflag) {
+ if (!yesorno(false, "Do you really want to delete all revisions? [ny](n): ")) {
+ rcserror("No revision deleted");
+ Delta = delstrt;
+ while( Delta) {
+ Delta->selector = true;
+ Delta = Delta->next;
+ }
+ return;
+ }
+ }
+ Head = cuttail;
+ }
+ return;
+}
+
+#if RCS_lint
+/* This lets us lint everything all at once. */
+
+char const cmdid[] = "";
+
+#define go(p,e) {int p P((int,char**)); void e P((void)); if(*argv)return p(argc,argv);if(*argv[1])e();}
+
+ int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ go(ciId, ciExit);
+ go(coId, coExit);
+ go(identId, identExit);
+ go(mergeId, mergeExit);
+ go(rcsId, exiterr);
+ go(rcscleanId, rcscleanExit);
+ go(rcsdiffId, rdiffExit);
+ go(rcsmergeId, rmergeExit);
+ go(rlogId, rlogExit);
+ return 0;
+}
+#endif
diff --git a/gnu/usr.bin/rcs/rcs/rcsfile.5 b/gnu/usr.bin/rcs/rcs/rcsfile.5
new file mode 100644
index 0000000..0d8aac8
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcs/rcsfile.5
@@ -0,0 +1,425 @@
+.lf 1 ./rcsfile.5in
+.\" Set p to 1 if your formatter can handle pic output.
+.if t .nr p 1
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \s-1RCS\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH RCSFILE 5 \*(Dt GNU
+.SH NAME
+rcsfile \- format of RCS file
+.SH DESCRIPTION
+An \*r file's
+contents are described by the grammar
+below.
+.PP
+The text is free format: space, backspace, tab, newline, vertical
+tab, form feed, and carriage return (collectively,
+.IR "white space")
+have no significance except in strings.
+However, white space cannot appear within an id, num, or sym,
+and an \*r file must end with a newline.
+.PP
+Strings are enclosed by
+.BR @ .
+If a string contains a
+.BR @ ,
+it must be doubled;
+otherwise, strings can contain arbitrary binary data.
+.PP
+The meta syntax uses the following conventions: `|' (bar) separates
+alternatives; `{' and `}' enclose optional phrases; `{' and `}*' enclose
+phrases that can be repeated zero or more times;
+`{' and '}+' enclose phrases that must appear at least once and can be
+repeated;
+Terminal symbols are in
+.BR boldface ;
+nonterminal symbols are in
+.IR italics .
+.LP
+.nr w \w'\f3deltatext\fP '
+.nr y \w'\f3newphrase\fP '
+.if \nw<\ny .nr w \ny
+.nr x \w'\f3branches\fP'
+.nr y \w'{ \f3comment\fP'
+.if \nx<\ny .nr x \ny
+.nr y \w'\f3{ branch\fP'
+.if \nx<\ny .nr x \ny
+.ta \nwu +\w'::= 'u +\nxu+\w' 'u
+.fc #
+.nf
+\f2rcstext\fP ::= \f2admin\fP {\f2delta\fP}* \f2desc\fP {\f2deltatext\fP}*
+.LP
+\f2admin\fP ::= \f3head\fP {\f2num\fP}\f3;\fP
+ { \f3branch\fP {\f2num\fP}\f3;\fP }
+ \f3access\fP {\f2id\fP}*\f3;\fP
+ \f3symbols\fP {\f2sym\fP \f3:\fP \f2num\fP}*\f3;\fP
+ \f3locks\fP {\f2id\fP \f3:\fP \f2num\fP}*\f3;\fP {\f3strict ;\fP}
+ { \f3comment\fP {\f2string\fP}\f3;\fP }
+ { \f3expand\fP {\f2string\fP}\f3;\fP }
+ { \f2newphrase\fP }*
+.LP
+\f2delta\fP ::= \f2num\fP
+ \f3date\fP \f2num\fP\f3;\fP
+ \f3author\fP \f2id\fP\f3;\fP
+ \f3state\fP {\f2id\fP}\f3;\fP
+ \f3branches\fP {\f2num\fP}*\f3;\fP
+ \f3next\fP {\f2num\fP}\f3;\fP
+ { \f2newphrase\fP }*
+.LP
+\f2desc\fP ::= \f3desc\fP \f2string\fP
+.LP
+\f2deltatext\fP ::= \f2num\fP
+ \f3log\fP \f2string\fP
+ { \f2newphrase\fP }*
+ \f3text\fP \f2string\fP
+.LP
+\f2num\fP ::= {\f2digit\fP | \f3.\fP}+
+.LP
+\f2digit\fP ::= \f30\fP | \f31\fP | \f32\fP | \f33\fP | \f34\fP | \f35\fP | \f36\fP | \f37\fP | \f38\fP | \f39\fP
+.LP
+\f2id\fP ::= {\f2num\fP} \f2idchar\fP {\f2idchar\fP | \f2num\fP}*
+.LP
+\f2sym\fP ::= {\f2digit\fP}* \f2idchar\fP {\f2idchar\fP | \f2digit\fP}*
+.LP
+\f2idchar\fP ::= any visible graphic character except \f2special\fP
+.LP
+\f2special\fP ::= \f3$\fP | \f3,\fP | \f3.\fP | \f3:\fP | \f3;\fP | \f3@\fP
+.LP
+\f2string\fP ::= \f3@\fP{any character, with \f3@\fP doubled}*\f3@\fP
+.LP
+\f2newphrase\fP ::= \f2id\fP \f2word\fP* \f3;\fP
+.LP
+\f2word\fP ::= \f2id\fP | \f2num\fP | \f2string\fP | \f3:\fP
+.fi
+.PP
+Identifiers are case sensitive. Keywords are in lower case only.
+The sets of keywords and identifiers can overlap.
+In most environments \*r uses the \s-1ISO\s0 8859/1 encoding:
+visible graphic characters are codes 041\-176 and 240\-377,
+and white space characters are codes 010\-015 and 040.
+.PP
+Dates, which appear after the
+.B date
+keyword, are of the form
+\f2Y\fP\f3.\fP\f2mm\fP\f3.\fP\f2dd\fP\f3.\fP\f2hh\fP\f3.\fP\f2mm\fP\f3.\fP\f2ss\fP,
+where
+.I Y
+is the year,
+.I mm
+the month (01\-12),
+.I dd
+the day (01\-31),
+.I hh
+the hour (00\-23),
+.I mm
+the minute (00\-59),
+and
+.I ss
+the second (00\-60).
+.I Y
+contains just the last two digits of the year
+for years from 1900 through 1999,
+and all the digits of years thereafter.
+Dates use the Gregorian calendar; times use UTC.
+.PP
+The
+.I newphrase
+productions in the grammar are reserved for future extensions
+to the format of \*r files.
+No
+.I newphrase
+will begin with any keyword already in use.
+.PP
+The
+.I delta
+nodes form a tree. All nodes whose numbers
+consist of a single pair
+(e.g., 2.3, 2.1, 1.3, etc.)
+are on the trunk, and are linked through the
+.B next
+field in order of decreasing numbers.
+The
+.B head
+field in the
+.I admin
+node points to the head of that sequence (i.e., contains
+the highest pair).
+The
+.B branch
+node in the admin node indicates the default
+branch (or revision) for most \*r operations.
+If empty, the default
+branch is the highest branch on the trunk.
+.PP
+All
+.I delta
+nodes whose numbers consist of
+.RI 2 n
+fields
+.RI ( n \(>=2)
+(e.g., 3.1.1.1, 2.1.2.2, etc.)
+are linked as follows.
+All nodes whose first
+.RI 2 n \-1
+number fields are identical are linked through the
+.B next
+field in order of increasing numbers.
+For each such sequence,
+the
+.I delta
+node whose number is identical to the first
+.RI 2 n \-2
+number fields of the deltas on that sequence is called the branchpoint.
+The
+.B branches
+field of a node contains a list of the
+numbers of the first nodes of all sequences for which it is a branchpoint.
+This list is ordered in increasing numbers.
+.LP
+The following diagram shows an example of an \*r file's organization.
+.if !\np \{\
+.nf
+.vs 12
+.ne 36
+.cs 1 20
+.eo
+
+ Head
+ |
+ |
+ v / \
+ --------- / \
+ / \ / \ | | / \ / \
+ / \ / \ | 2.1 | / \ / \
+ / \ / \ | | / \ / \
+/1.2.1.3\ /1.3.1.1\ | | /1.2.2.2\ /1.2.2.1.1.1\
+--------- --------- --------- --------- -------------
+ ^ ^ | ^ ^
+ | | | | |
+ | | v | |
+ / \ | --------- / \ |
+ / \ | \ 1.3 / / \ |
+ / \ ---------\ / / \-----------
+/1.2.1.1\ \ / /1.2.2.1\
+--------- \ / ---------
+ ^ | ^
+ | | |
+ | v |
+ | --------- |
+ | \ 1.2 / |
+ ----------------------\ /---------
+ \ /
+ \ /
+ |
+ |
+ v
+ ---------
+ \ 1.1 /
+ \ /
+ \ /
+ \ /
+
+.ec
+.cs 1
+.vs
+.fi
+.\}
+.if \np \{\
+.lf 232
+.PS 4.250i 3.812i
+.\" -2.0625 -4.25 1.75 0
+.\" 0.000i 4.250i 3.812i 0.000i
+.nr 00 \n(.u
+.nf
+.nr 0x 1
+\h'3.812i'
+.sp -1
+.lf 242
+\h'2.062i-(\w'Head'u/2u)'\v'0.125i-(0v/2u)+0v+0.22m'Head
+.sp -1
+\h'2.062i'\v'0.250i'\D'l0.000i 0.500i'
+.sp -1
+\h'2.087i'\v'0.650i'\D'l-0.025i 0.100i'
+.sp -1
+\h'2.062i'\v'0.750i'\D'l-0.025i -0.100i'
+.sp -1
+\h'1.688i'\v'1.250i'\D'l0.750i 0.000i'
+.sp -1
+\h'2.438i'\v'1.250i'\D'l0.000i -0.500i'
+.sp -1
+\h'2.438i'\v'0.750i'\D'l-0.750i 0.000i'
+.sp -1
+\h'1.688i'\v'0.750i'\D'l0.000i 0.500i'
+.sp -1
+.lf 244
+\h'2.062i-(\w'2.1'u/2u)'\v'1.000i-(0v/2u)+0v+0.22m'2.1
+.sp -1
+\h'2.062i'\v'1.250i'\D'l0.000i 0.500i'
+.sp -1
+\h'2.087i'\v'1.650i'\D'l-0.025i 0.100i'
+.sp -1
+\h'2.062i'\v'1.750i'\D'l-0.025i -0.100i'
+.sp -1
+.lf 246
+\h'2.062i-(\w'1.3'u/2u)'\v'2.000i-(1v/2u)+0v+0.22m'1.3
+.sp -1
+\h'2.062i'\v'2.250i'\D'l-0.375i -0.500i'
+.sp -1
+\h'1.688i'\v'1.750i'\D'l0.750i 0.000i'
+.sp -1
+\h'2.438i'\v'1.750i'\D'l-0.375i 0.500i'
+.sp -1
+\h'1.875i'\v'2.000i'\D'~-0.500i 0.000i 0.000i -0.500i'
+.sp -1
+\h'1.350i'\v'1.600i'\D'l0.025i -0.100i'
+.sp -1
+\h'1.375i'\v'1.500i'\D'l0.025i 0.100i'
+.sp -1
+.lf 249
+\h'1.375i-(\w'1.3.1.1'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.3.1.1
+.sp -1
+\h'1.375i'\v'1.000i'\D'l-0.375i 0.500i'
+.sp -1
+\h'1.000i'\v'1.500i'\D'l0.750i 0.000i'
+.sp -1
+\h'1.750i'\v'1.500i'\D'l-0.375i -0.500i'
+.sp -1
+\h'2.062i'\v'2.250i'\D'l0.000i 0.500i'
+.sp -1
+\h'2.087i'\v'2.650i'\D'l-0.025i 0.100i'
+.sp -1
+\h'2.062i'\v'2.750i'\D'l-0.025i -0.100i'
+.sp -1
+.lf 252
+\h'2.062i-(\w'1.2'u/2u)'\v'3.000i-(1v/2u)+0v+0.22m'1.2
+.sp -1
+\h'2.062i'\v'3.250i'\D'l-0.375i -0.500i'
+.sp -1
+\h'1.688i'\v'2.750i'\D'l0.750i 0.000i'
+.sp -1
+\h'2.438i'\v'2.750i'\D'l-0.375i 0.500i'
+.sp -1
+\h'1.875i'\v'3.000i'\D'~-0.500i 0.000i -0.500i 0.000i -0.500i 0.000i 0.000i -0.500i'
+.sp -1
+\h'0.350i'\v'2.600i'\D'l0.025i -0.100i'
+.sp -1
+\h'0.375i'\v'2.500i'\D'l0.025i 0.100i'
+.sp -1
+.lf 255
+\h'0.375i-(\w'1.2.1.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.1.1
+.sp -1
+\h'0.375i'\v'2.000i'\D'l-0.375i 0.500i'
+.sp -1
+\h'0.000i'\v'2.500i'\D'l0.750i 0.000i'
+.sp -1
+\h'0.750i'\v'2.500i'\D'l-0.375i -0.500i'
+.sp -1
+\h'0.375i'\v'2.000i'\D'l0.000i -0.500i'
+.sp -1
+\h'0.350i'\v'1.600i'\D'l0.025i -0.100i'
+.sp -1
+\h'0.375i'\v'1.500i'\D'l0.025i 0.100i'
+.sp -1
+.lf 257
+\h'0.375i-(\w'1.2.1.3'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.1.3
+.sp -1
+\h'0.375i'\v'1.000i'\D'l-0.375i 0.500i'
+.sp -1
+\h'0.000i'\v'1.500i'\D'l0.750i 0.000i'
+.sp -1
+\h'0.750i'\v'1.500i'\D'l-0.375i -0.500i'
+.sp -1
+\h'2.250i'\v'3.000i'\D'~0.500i 0.000i 0.000i -0.500i'
+.sp -1
+\h'2.725i'\v'2.600i'\D'l0.025i -0.100i'
+.sp -1
+\h'2.750i'\v'2.500i'\D'l0.025i 0.100i'
+.sp -1
+.lf 261
+\h'2.750i-(\w'1.2.2.1'u/2u)'\v'2.250i-(1v/2u)+1v+0.22m'1.2.2.1
+.sp -1
+\h'2.750i'\v'2.000i'\D'l-0.375i 0.500i'
+.sp -1
+\h'2.375i'\v'2.500i'\D'l0.750i 0.000i'
+.sp -1
+\h'3.125i'\v'2.500i'\D'l-0.375i -0.500i'
+.sp -1
+\h'2.938i'\v'2.250i'\D'~0.500i 0.000i 0.000i -0.500i 0.000i -0.500i'
+.sp -1
+\h'3.413i'\v'1.350i'\D'l0.025i -0.100i'
+.sp -1
+\h'3.438i'\v'1.250i'\D'l0.025i 0.100i'
+.sp -1
+.lf 264
+\h'3.438i-(\w'\s-21.2.2.1.1.1\s0'u/2u)'\v'1.000i-(1v/2u)+1v+0.22m'\s-21.2.2.1.1.1\s0
+.sp -1
+\h'3.438i'\v'0.750i'\D'l-0.375i 0.500i'
+.sp -1
+\h'3.062i'\v'1.250i'\D'l0.750i 0.000i'
+.sp -1
+\h'3.812i'\v'1.250i'\D'l-0.375i -0.500i'
+.sp -1
+\h'2.750i'\v'2.000i'\D'l0.000i -0.500i'
+.sp -1
+\h'2.725i'\v'1.600i'\D'l0.025i -0.100i'
+.sp -1
+\h'2.750i'\v'1.500i'\D'l0.025i 0.100i'
+.sp -1
+.lf 267
+\h'2.750i-(\w'1.2.2.2'u/2u)'\v'1.250i-(1v/2u)+1v+0.22m'1.2.2.2
+.sp -1
+\h'2.750i'\v'1.000i'\D'l-0.375i 0.500i'
+.sp -1
+\h'2.375i'\v'1.500i'\D'l0.750i 0.000i'
+.sp -1
+\h'3.125i'\v'1.500i'\D'l-0.375i -0.500i'
+.sp -1
+\h'2.062i'\v'3.250i'\D'l0.000i 0.500i'
+.sp -1
+\h'2.087i'\v'3.650i'\D'l-0.025i 0.100i'
+.sp -1
+\h'2.062i'\v'3.750i'\D'l-0.025i -0.100i'
+.sp -1
+.lf 270
+\h'2.062i-(\w'1.1'u/2u)'\v'4.000i-(1v/2u)+0v+0.22m'1.1
+.sp -1
+\h'2.062i'\v'4.250i'\D'l-0.375i -0.500i'
+.sp -1
+\h'1.688i'\v'3.750i'\D'l0.750i 0.000i'
+.sp -1
+\h'2.438i'\v'3.750i'\D'l-0.375i 0.500i'
+.sp -1
+.sp 4.250i+1
+.if \n(00 .fi
+.br
+.nr 0x 0
+.lf 271
+.PE
+.lf 272
+.\}
+.SH IDENTIFICATION
+.de VL
+\\$2
+..
+Author: Walter F. Tichy,
+Purdue University, West Lafayette, IN, 47907.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
+.SH SEE ALSO
+rcsintro(1), ci(1), co(1), ident(1), rcs(1), rcsclean(1), rcsdiff(1),
+rcsmerge(1), rlog(1)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
diff --git a/gnu/usr.bin/rcs/rcs/rcsintro.1 b/gnu/usr.bin/rcs/rcs/rcsintro.1
new file mode 100644
index 0000000..edcd9ee
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcs/rcsintro.1
@@ -0,0 +1,302 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \&\s-1RCS\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.if !\n(.g \{\
+. if !\w|\*(lq| \{\
+. ds lq ``
+. if \w'\(lq' .ds lq "\(lq
+. \}
+. if !\w|\*(rq| \{\
+. ds rq ''
+. if \w'\(rq' .ds rq "\(rq
+. \}
+.\}
+.am SS
+.LP
+..
+.TH RCSINTRO 1 \*(Dt GNU
+.SH NAME
+rcsintro \- introduction to RCS commands
+.SH DESCRIPTION
+The Revision Control System (\*r) manages multiple revisions of files.
+\*r automates the storing, retrieval, logging, identification, and merging
+of revisions. \*r is useful for text that is revised frequently, for example
+programs, documentation, graphics, papers, and form letters.
+.PP
+The basic user interface is extremely simple. The novice only needs
+to learn two commands:
+.BR ci (1)
+and
+.BR co (1).
+.BR ci ,
+short for \*(lqcheck in\*(rq, deposits the contents of a
+file into an archival file called an \*r file. An \*r file
+contains all revisions of a particular file.
+.BR co ,
+short for \*(lqcheck out\*(rq, retrieves revisions from an \*r file.
+.SS "Functions of \*r"
+.IP \(bu
+Store and retrieve multiple revisions of text. \*r saves all old
+revisions in a space efficient way.
+Changes no longer destroy the original, because the
+previous revisions remain accessible. Revisions can be retrieved according to
+ranges of revision numbers, symbolic names, dates, authors, and
+states.
+.IP \(bu
+Maintain a complete history of changes.
+\*r logs all changes automatically.
+Besides the text of each revision, \*r stores the author, the date and time of
+check-in, and a log message summarizing the change.
+The logging makes it easy to find out
+what happened to a module, without having to compare
+source listings or having to track down colleagues.
+.IP \(bu
+Resolve access conflicts. When two or more programmers wish to
+modify the same revision, \*r alerts the programmers and prevents one
+modification from corrupting the other.
+.IP \(bu
+Maintain a tree of revisions. \*r can maintain separate lines of development
+for each module. It stores a tree structure that represents the
+ancestral relationships among revisions.
+.IP \(bu
+Merge revisions and resolve conflicts.
+Two separate lines of development of a module can be coalesced by merging.
+If the revisions to be merged affect the same sections of code, \*r alerts the
+user about the overlapping changes.
+.IP \(bu
+Control releases and configurations.
+Revisions can be assigned symbolic names
+and marked as released, stable, experimental, etc.
+With these facilities, configurations of modules can be
+described simply and directly.
+.IP \(bu
+Automatically identify each revision with name, revision number,
+creation time, author, etc.
+The identification is like a stamp that can be embedded at an appropriate place
+in the text of a revision.
+The identification makes it simple to determine which
+revisions of which modules make up a given configuration.
+.IP \(bu
+Minimize secondary storage. \*r needs little extra space for
+the revisions (only the differences). If intermediate revisions are
+deleted, the corresponding deltas are compressed accordingly.
+.SS "Getting Started with \*r"
+Suppose you have a file
+.B f.c
+that you wish to put under control of \*r.
+If you have not already done so, make an \*r directory with the command
+.IP
+.B "mkdir RCS"
+.LP
+Then invoke the check-in command
+.IP
+.B "ci f.c"
+.LP
+This command creates an \*r file in the
+.B RCS
+directory,
+stores
+.B f.c
+into it as revision 1.1, and
+deletes
+.BR f.c .
+It also asks you for a description. The description
+should be a synopsis of the contents of the file. All later check-in
+commands will ask you for a log entry, which should summarize the
+changes that you made.
+.PP
+Files in the \*r directory are called \*r files;
+the others are called working files.
+To get back the working file
+.B f.c
+in the previous example, use the check-out
+command
+.IP
+.B "co f.c"
+.LP
+This command extracts the latest revision from the \*r file
+and writes
+it into
+.BR f.c .
+If you want to edit
+.BR f.c ,
+you must lock it as you check it out with the command
+.IP
+.B "co \-l f.c"
+.LP
+You can now edit
+.BR f.c .
+.PP
+Suppose after some editing you want to know what changes that you have made.
+The command
+.IP
+.B "rcsdiff f.c"
+.LP
+tells you the difference between the most recently checked-in version
+and the working file.
+You can check the file back in by invoking
+.IP
+.B "ci f.c"
+.LP
+This increments the revision number properly.
+.PP
+If
+.B ci
+complains with the message
+.IP
+.BI "ci error: no lock set by " "your name"
+.LP
+then you have tried to check in a file even though you did not
+lock it when you checked it out.
+Of course, it is too late now to do the check-out with locking, because
+another check-out would
+overwrite your modifications. Instead, invoke
+.IP
+.B "rcs \-l f.c"
+.LP
+This command will lock the latest revision for you, unless somebody
+else got ahead of you already. In this case, you'll have to negotiate with
+that person.
+.PP
+Locking assures that you, and only you, can check in the next update, and
+avoids nasty problems if several people work on the same file.
+Even if a revision is locked, it can still be checked out for
+reading, compiling, etc. All that locking
+prevents is a
+.I "check-in"
+by anybody but the locker.
+.PP
+If your \*r file is private, i.e., if you are the only person who is going
+to deposit revisions into it, strict locking is not needed and you
+can turn it off.
+If strict locking is turned off,
+the owner of the \*r file need not have a lock for check-in; all others
+still do. Turning strict locking off and on is done with the commands
+.IP
+.BR "rcs \-U f.c" " and " "rcs \-L f.c"
+.LP
+If you don't want to clutter your working directory with \*r files, create
+a subdirectory called
+.B RCS
+in your working directory, and move all your \*r
+files there. \*r commands will look first into that directory to find
+needed files. All the commands discussed above will still work, without any
+modification.
+(Actually, pairs of \*r and working files can be specified in three ways:
+(a) both are given, (b) only the working file is given, (c) only the
+\*r file is given. Both \*r and working files may have arbitrary path prefixes;
+\*r commands pair them up intelligently.)
+.PP
+To avoid the deletion of the working file during check-in (in case you want to
+continue editing or compiling), invoke
+.IP
+.BR "ci \-l f.c" " or " "ci \-u f.c"
+.LP
+These commands check in
+.B f.c
+as usual, but perform an implicit
+check-out. The first form also locks the checked in revision, the second one
+doesn't. Thus, these options save you one check-out operation.
+The first form is useful if you want to continue editing,
+the second one if you just want to read the file.
+Both update the identification markers in your working file (see below).
+.PP
+You can give
+.B ci
+the number you want assigned to a checked in
+revision. Assume all your revisions were numbered 1.1, 1.2, 1.3, etc.,
+and you would like to start release 2.
+The command
+.IP
+.BR "ci \-r2 f.c" " or " "ci \-r2.1 f.c"
+.LP
+assigns the number 2.1 to the new revision.
+From then on,
+.B ci
+will number the subsequent revisions
+with 2.2, 2.3, etc. The corresponding
+.B co
+commands
+.IP
+.BR "co \-r2 f.c" " and " "co \-r2.1 f.c"
+.PP
+retrieve the latest revision numbered
+.RI 2. x
+and the revision 2.1,
+respectively.
+.B co
+without a revision number selects
+the latest revision on the
+.IR trunk ,
+i.e. the highest
+revision with a number consisting of two fields. Numbers with more than two
+fields are needed for branches.
+For example, to start a branch at revision 1.3, invoke
+.IP
+.B "ci \-r1.3.1 f.c"
+.LP
+This command starts a branch numbered 1 at revision 1.3, and assigns
+the number 1.3.1.1 to the new revision. For more information about
+branches, see
+.BR rcsfile (5).
+.SS "Automatic Identification"
+\*r can put special strings for identification into your source and object
+code. To obtain such identification, place the marker
+.IP
+.B "$\&Id$"
+.LP
+into your text, for instance inside a comment.
+\*r will replace this marker with a string of the form
+.IP
+.BI $\&Id: " filename revision date time author state " $
+.LP
+With such a marker on the first page of each module, you can
+always see with which revision you are working.
+\*r keeps the markers up to date automatically.
+To propagate the markers into your object code, simply put
+them into literal character strings. In C, this is done as follows:
+.IP
+.ft 3
+static char rcsid[] = \&"$\&Id$\&";
+.ft
+.LP
+The command
+.B ident
+extracts such markers from any file, even object code
+and dumps.
+Thus,
+.B ident
+lets you find out
+which revisions of which modules were used in a given program.
+.PP
+You may also find it useful to put the marker
+.B $\&Log$
+into your text, inside a comment. This marker accumulates
+the log messages that are requested during check-in.
+Thus, you can maintain the complete history of your file directly inside it.
+There are several additional identification markers; see
+.BR co (1)
+for
+details.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993 Paul Eggert.
+.SH "SEE ALSO"
+ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.br
diff --git a/gnu/usr.bin/rcs/rcsclean/Makefile b/gnu/usr.bin/rcs/rcsclean/Makefile
new file mode 100644
index 0000000..fe538a0
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsclean/Makefile
@@ -0,0 +1,8 @@
+PROG= rcsclean
+SRCS= rcsclean.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/rcsclean/rcsclean.1 b/gnu/usr.bin/rcs/rcsclean/rcsclean.1
new file mode 100644
index 0000000..3111915
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsclean/rcsclean.1
@@ -0,0 +1,203 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \&\s-1RCS\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH RCSCLEAN 1 \*(Dt GNU
+.SH NAME
+rcsclean \- clean up working files
+.SH SYNOPSIS
+.B rcsclean
+.RI [ options "] [ " file " .\|.\|. ]"
+.SH DESCRIPTION
+.B rcsclean
+removes files that are not being worked on.
+.B "rcsclean \-u"
+also unlocks and removes files that are being worked on
+but have not changed.
+.PP
+For each
+.I file
+given,
+.B rcsclean
+compares the working file and a revision in the corresponding
+\*r file. If it finds a difference, it does nothing.
+Otherwise, it first unlocks the revision if the
+.B \-u
+option is given,
+and then removes the working file
+unless the working file is writable and the revision is locked.
+It logs its actions by outputting the corresponding
+.B "rcs \-u"
+and
+.B "rm \-f"
+commands on the standard output.
+.PP
+Files are paired as explained in
+.BR ci (1).
+If no
+.I file
+is given, all working files in the current directory are cleaned.
+Pathnames matching an \*r suffix denote \*r files;
+all others denote working files.
+.PP
+The number of the revision to which the working file is compared
+may be attached to any of the options
+.BR \-n ,
+.BR \-q ,
+.BR \-r ,
+or
+.BR \-u .
+If no revision number is specified, then if the
+.B \-u
+option is given and the caller has one revision locked,
+.B rcsclean
+uses that revision; otherwise
+.B rcsclean
+uses the latest revision on the default branch, normally the root.
+.PP
+.B rcsclean
+is useful for
+.B clean
+targets in makefiles.
+See also
+.BR rcsdiff (1),
+which prints out the differences,
+and
+.BR ci (1),
+which
+normally reverts to the previous revision
+if a file was not changed.
+.SH OPTIONS
+.TP
+.BI \-k subst
+Use
+.I subst
+style keyword substitution when retrieving the revision for comparison.
+See
+.BR co (1)
+for details.
+.TP
+.BR \-n [\f2rev\fP]
+Do not actually remove any files or unlock any revisions.
+Using this option will tell you what
+.B rcsclean
+would do without actually doing it.
+.TP
+.BR \-q [\f2rev\fP]
+Do not log the actions taken on standard output.
+.TP
+.BR \-r [\f2rev\fP]
+This option has no effect other than specifying the revision for comparison.
+.TP
+.B \-T
+Preserve the modification time on the \*r file
+even if the \*r file changes because a lock is removed.
+This option can suppress extensive recompilation caused by a
+.BR make (1)
+dependency of some other copy of the working file on the \*r file.
+Use this option with care; it can suppress recompilation even when it is needed,
+i.e. when the lock removal
+would mean a change to keyword strings in the other working file.
+.TP
+.BR \-u [\f2rev\fP]
+Unlock the revision if it is locked and no difference is found.
+.TP
+.BI \-V
+Print \*r's version number.
+.TP
+.BI \-V n
+Emulate \*r version
+.IR n .
+See
+.BR co (1)
+for details.
+.TP
+.BI \-x "suffixes"
+Use
+.I suffixes
+to characterize \*r files.
+See
+.BR ci (1)
+for details.
+.TP
+.BI \-z zone
+Use
+.I zone
+as the time zone for keyword substitution;
+see
+.BR co (1)
+for details.
+.SH EXAMPLES
+.LP
+.RS
+.ft 3
+rcsclean *.c *.h
+.ft
+.RE
+.LP
+removes all working files ending in
+.B .c
+or
+.B .h
+that were not changed
+since their checkout.
+.LP
+.RS
+.ft 3
+rcsclean
+.ft
+.RE
+.LP
+removes all working files in the current directory
+that were not changed since their checkout.
+.SH FILES
+.B rcsclean
+accesses files much as
+.BR ci (1)
+does.
+.SH ENVIRONMENT
+.TP
+.B \s-1RCSINIT\s0
+options prepended to the argument list, separated by spaces.
+A backslash escapes spaces within an option.
+The
+.B \s-1RCSINIT\s0
+options are prepended to the argument lists of most \*r commands.
+Useful
+.B \s-1RCSINIT\s0
+options include
+.BR \-q ,
+.BR \-V ,
+.BR \-x ,
+and
+.BR \-z .
+.SH DIAGNOSTICS
+The exit status is zero if and only if all operations were successful.
+Missing working files and \*r files are silently ignored.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993 Paul Eggert.
+.SH "SEE ALSO"
+ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1), rlog(1),
+rcsfile(5)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.SH BUGS
+At least one
+.I file
+must be given in older Unix versions that
+do not provide the needed directory scanning operations.
+.br
diff --git a/gnu/usr.bin/rcs/rcsclean/rcsclean.c b/gnu/usr.bin/rcs/rcsclean/rcsclean.c
new file mode 100644
index 0000000..32c8e7d
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsclean/rcsclean.c
@@ -0,0 +1,333 @@
+/* Clean up working files. */
+
+/* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#include "rcsbase.h"
+
+#if has_dirent
+ static int get_directory P((char const*,char***));
+#endif
+
+static int unlock P((struct hshentry *));
+static void cleanup P((void));
+
+static RILE *workptr;
+static int exitstatus;
+
+mainProg(rcscleanId, "rcsclean", "$FreeBSD$")
+{
+ static char const usage[] =
+ "\nrcsclean: usage: rcsclean -ksubst -{nqru}[rev] -T -Vn -xsuff -zzone file ...";
+
+ static struct buf revision;
+
+ char *a, **newargv;
+ char const *rev, *p;
+ int dounlock, expmode, perform, unlocked, unlockflag, waslocked;
+ int Ttimeflag;
+ struct hshentries *deltas;
+ struct hshentry *delta;
+ struct stat workstat;
+
+ setrid();
+
+ expmode = -1;
+ rev = 0;
+ suffixes = X_DEFAULT;
+ perform = true;
+ unlockflag = false;
+ Ttimeflag = false;
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ for (;;) {
+ if (--argc < 1) {
+# if has_dirent
+ argc = get_directory(".", &newargv);
+ argv = newargv;
+ break;
+# else
+ faterror("no pathnames specified");
+# endif
+ }
+ a = *++argv;
+ if (!*a || *a++ != '-')
+ break;
+ switch (*a++) {
+ case 'k':
+ if (0 <= expmode)
+ redefined('k');
+ if ((expmode = str2expmode(a)) < 0)
+ goto unknown;
+ break;
+
+ case 'n':
+ perform = false;
+ goto handle_revision;
+
+ case 'q':
+ quietflag = true;
+ /* fall into */
+ case 'r':
+ handle_revision:
+ if (*a) {
+ if (rev)
+ warn("redefinition of revision number");
+ rev = a;
+ }
+ break;
+
+ case 'T':
+ if (*a)
+ goto unknown;
+ Ttimeflag = true;
+ break;
+
+ case 'u':
+ unlockflag = true;
+ goto handle_revision;
+
+ case 'V':
+ setRCSversion(*argv);
+ break;
+
+ case 'x':
+ suffixes = a;
+ break;
+
+ case 'z':
+ zone_set(a);
+ break;
+
+ default:
+ unknown:
+ error("unknown option: %s%s", *argv, usage);
+ }
+ }
+
+ dounlock = perform & unlockflag;
+
+ if (nerror)
+ cleanup();
+ else
+ for (; 0 < argc; cleanup(), ++argv, --argc) {
+
+ ffree();
+
+ if (!(
+ 0 < pairnames(
+ argc, argv,
+ dounlock ? rcswriteopen : rcsreadopen,
+ true, true
+ ) &&
+ (workptr = Iopen(workname, FOPEN_R_WORK, &workstat))
+ ))
+ continue;
+
+ if (same_file(RCSstat, workstat, 0)) {
+ rcserror("RCS file is the same as working file %s.",
+ workname
+ );
+ continue;
+ }
+
+ gettree();
+
+ p = 0;
+ if (rev) {
+ if (!fexpandsym(rev, &revision, workptr))
+ continue;
+ p = revision.string;
+ } else if (Head)
+ switch (unlockflag ? findlock(false,&delta) : 0) {
+ default:
+ continue;
+ case 0:
+ p = Dbranch ? Dbranch : "";
+ break;
+ case 1:
+ p = delta->num;
+ break;
+ }
+ delta = 0;
+ deltas = 0; /* Keep lint happy. */
+ if (p && !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
+ continue;
+
+ waslocked = delta && delta->lockedby;
+ locker_expansion = unlock(delta);
+ unlocked = locker_expansion & unlockflag;
+ if (unlocked<waslocked && workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
+ continue;
+
+ if (unlocked && !checkaccesslist())
+ continue;
+
+ if (dorewrite(dounlock, unlocked) != 0)
+ continue;
+
+ if (0 <= expmode)
+ Expand = expmode;
+ else if (
+ waslocked &&
+ Expand == KEYVAL_EXPAND &&
+ WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
+ )
+ Expand = KEYVALLOCK_EXPAND;
+
+ getdesc(false);
+
+ if (
+ !delta ? workstat.st_size!=0 :
+ 0 < rcsfcmp(
+ workptr, &workstat,
+ buildrevision(deltas, delta, (FILE*)0, false),
+ delta
+ )
+ )
+ continue;
+
+ if (quietflag < unlocked)
+ aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSname);
+
+ if (perform & unlocked) {
+ if_advise_access(deltas->first != delta, finptr, MADV_SEQUENTIAL);
+ if (donerewrite(true,
+ Ttimeflag ? RCSstat.st_mtime : (time_t)-1
+ ) != 0)
+ continue;
+ }
+
+ if (!quietflag)
+ aprintf(stdout, "rm -f %s\n", workname);
+ Izclose(&workptr);
+ if (perform && un_link(workname) != 0)
+ eerror(workname);
+
+ }
+
+ tempunlink();
+ if (!quietflag)
+ Ofclose(stdout);
+ exitmain(exitstatus);
+}
+
+ static void
+cleanup()
+{
+ if (nerror) exitstatus = EXIT_FAILURE;
+ Izclose(&finptr);
+ Izclose(&workptr);
+ Ozclose(&fcopy);
+ ORCSclose();
+ dirtempunlink();
+}
+
+#if RCS_lint
+# define exiterr rcscleanExit
+#endif
+ void
+exiterr()
+{
+ ORCSerror();
+ dirtempunlink();
+ tempunlink();
+ _exit(EXIT_FAILURE);
+}
+
+ static int
+unlock(delta)
+ struct hshentry *delta;
+{
+ register struct rcslock **al, *l;
+
+ if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
+ for (al = &Locks; (l = *al); al = &l->nextlock)
+ if (l->delta == delta) {
+ *al = l->nextlock;
+ delta->lockedby = 0;
+ return true;
+ }
+ return false;
+}
+
+#if has_dirent
+ static int
+get_directory(dirname, aargv)
+ char const *dirname;
+ char ***aargv;
+/*
+ * Put a vector of all DIRNAME's directory entries names into *AARGV.
+ * Ignore names of RCS files.
+ * Yield the number of entries found. Terminate the vector with 0.
+ * Allocate the storage for the vector and entry names.
+ * Do not sort the names. Do not include '.' and '..'.
+ */
+{
+ int i, entries = 0, entries_max = 64;
+ size_t chars = 0, chars_max = 1024;
+ size_t *offset = tnalloc(size_t, entries_max);
+ char *a = tnalloc(char, chars_max), **p;
+ DIR *d;
+ struct dirent *e;
+
+ if (!(d = opendir(dirname)))
+ efaterror(dirname);
+ while ((errno = 0, e = readdir(d))) {
+ char const *en = e->d_name;
+ size_t s = strlen(en) + 1;
+ if (en[0]=='.' && (!en[1] || (en[1]=='.' && !en[2])))
+ continue;
+ if (rcssuffix(en))
+ continue;
+ while (chars_max < s + chars)
+ a = trealloc(char, a, chars_max<<=1);
+ if (entries == entries_max)
+ offset = trealloc(size_t, offset, entries_max<<=1);
+ offset[entries++] = chars;
+ VOID strcpy(a+chars, en);
+ chars += s;
+ }
+# if void_closedir
+# define close_directory(d) (closedir(d), 0)
+# else
+# define close_directory(d) closedir(d)
+# endif
+ if (errno || close_directory(d) != 0)
+ efaterror(dirname);
+ if (chars)
+ a = trealloc(char, a, chars);
+ else
+ tfree(a);
+ *aargv = p = tnalloc(char*, entries+1);
+ for (i=0; i<entries; i++)
+ *p++ = a + offset[i];
+ *p = 0;
+ tfree(offset);
+ return entries;
+}
+#endif
diff --git a/gnu/usr.bin/rcs/rcsdiff/Makefile b/gnu/usr.bin/rcs/rcsdiff/Makefile
new file mode 100644
index 0000000..45ce23f
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsdiff/Makefile
@@ -0,0 +1,8 @@
+PROG= rcsdiff
+SRCS= rcsdiff.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.1 b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.1
new file mode 100644
index 0000000..74117c2
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.1
@@ -0,0 +1,158 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \&\s-1RCS\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH RCSDIFF 1 \*(Dt GNU
+.SH NAME
+rcsdiff \- compare RCS revisions
+.SH SYNOPSIS
+.B rcsdiff
+[
+.BI \-k subst
+] [
+.B \-q
+] [
+.BI \-r rev1
+[
+.BI \-r rev2
+] ] [
+.B \-T
+] [
+.RI "\f3\-V\fP[" n ]
+] [
+.BI \-x suffixes
+] [
+.BI \-z zone
+] [
+.I "diff options"
+]
+.I "file .\|.\|."
+.SH DESCRIPTION
+.B rcsdiff
+runs
+.BR diff (1)
+to compare two revisions of each \*r file given.
+.PP
+Pathnames matching an \*r suffix denote \*r files;
+all others denote working files.
+Names are paired as explained in
+.BR ci (1).
+.PP
+The option
+.B \-q
+suppresses diagnostic output.
+Zero, one, or two revisions may be specified with
+.BR \-r .
+The option
+.BI \-k subst
+affects keyword substitution when extracting
+revisions, as described in
+.BR co (1);
+for example,
+.B "\-kk\ \-r1.1\ \-r1.2"
+ignores differences in keyword values when comparing revisions
+.B 1.1
+and
+.BR 1.2 .
+To avoid excess output from locker name substitution,
+.B \-kkvl
+is assumed if (1) at most one revision option is given,
+(2) no
+.B \-k
+option is given, (3)
+.B \-kkv
+is the default keyword substitution, and
+(4) the working file's mode would be produced by
+.BR "co\ \-l".
+See
+.BR co (1)
+for details
+about
+.BR \-T ,
+.BR \-V ,
+.B \-x
+and
+.BR \-z .
+Otherwise, all options of
+.BR diff (1)
+that apply to regular files are accepted, with the same meaning as for
+.BR diff .
+.PP
+If both
+.I rev1
+and
+.I rev2
+are omitted,
+.B rcsdiff
+compares the latest revision on the
+default branch (by default the trunk)
+with the contents of the corresponding working file. This is useful
+for determining what you changed since the last checkin.
+.PP
+If
+.I rev1
+is given, but
+.I rev2
+is omitted,
+.B rcsdiff
+compares revision
+.I rev1
+of the \*r file with
+the contents of the corresponding working file.
+.PP
+If both
+.I rev1
+and
+.I rev2
+are given,
+.B rcsdiff
+compares revisions
+.I rev1
+and
+.I rev2
+of the \*r file.
+.PP
+Both
+.I rev1
+and
+.I rev2
+may be given numerically or symbolically.
+.SH EXAMPLE
+The command
+.LP
+.B " rcsdiff f.c"
+.LP
+compares the latest revision on the default branch of the \*r file
+to the contents of the working file
+.BR f.c .
+.SH ENVIRONMENT
+.TP
+.B \s-1RCSINIT\s0
+options prepended to the argument list, separated by spaces.
+See
+.BR ci (1)
+for details.
+.SH DIAGNOSTICS
+Exit status is 0 for no differences during any comparison,
+1 for some differences, 2 for trouble.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993 Paul Eggert.
+.SH "SEE ALSO"
+ci(1), co(1), diff(1), ident(1), rcs(1), rcsintro(1), rcsmerge(1), rlog(1)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.br
diff --git a/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
new file mode 100644
index 0000000..7d3c0a3
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsdiff/rcsdiff.c
@@ -0,0 +1,480 @@
+/* Compare RCS revisions. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.19 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.18 1995/06/01 16:23:43 eggert
+ * (main): Pass "--binary" if -kb and if --binary makes a difference.
+ * Don't treat + options specially.
+ *
+ * Revision 5.17 1994/03/17 14:05:48 eggert
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ *
+ * Revision 5.16 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.15 1993/11/03 17:42:27 eggert
+ * Add -z. Ignore -T. Pass -Vn to `co'. Add Name keyword.
+ * Put revision numbers in -c output. Improve quality of diagnostics.
+ *
+ * Revision 5.14 1992/07/28 16:12:44 eggert
+ * Add -V. Use co -M for better dates with traditional diff -c.
+ *
+ * Revision 5.13 1992/02/17 23:02:23 eggert
+ * Output more readable context diff headers.
+ * Suppress needless checkout and comparison of identical revisions.
+ *
+ * Revision 5.12 1992/01/24 18:44:19 eggert
+ * Add GNU diff 1.15.2's new options. lint -> RCS_lint
+ *
+ * Revision 5.11 1992/01/06 02:42:34 eggert
+ * Update usage string.
+ *
+ * Revision 5.10 1991/10/07 17:32:46 eggert
+ * Remove lint.
+ *
+ * Revision 5.9 1991/08/19 03:13:55 eggert
+ * Add RCSINIT, -r$. Tune.
+ *
+ * Revision 5.8 1991/04/21 11:58:21 eggert
+ * Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.7 1990/12/13 06:54:07 eggert
+ * GNU diff 1.15 has -u.
+ *
+ * Revision 5.6 1990/11/01 05:03:39 eggert
+ * Remove unneeded setid check.
+ *
+ * Revision 5.5 1990/10/04 06:30:19 eggert
+ * Accumulate exit status across files.
+ *
+ * Revision 5.4 1990/09/27 01:31:43 eggert
+ * Yield 1, not EXIT_FAILURE, when diffs are found.
+ *
+ * Revision 5.3 1990/09/11 02:41:11 eggert
+ * Simplify -kkvl test.
+ *
+ * Revision 5.2 1990/09/04 17:07:19 eggert
+ * Diff's argv was too small by 1.
+ *
+ * Revision 5.1 1990/08/29 07:13:55 eggert
+ * Add -kkvl.
+ *
+ * Revision 5.0 1990/08/22 08:12:46 eggert
+ * Add -k, -V. Don't use access(). Add setuid support.
+ * Remove compile-time limits; use malloc instead.
+ * Don't pass arguments with leading '+' to diff; GNU DIFF treats them as options.
+ * Add GNU diff's flags. Make lock and temp files faster and safer.
+ * Ansify and Posixate.
+ *
+ * Revision 4.6 89/05/01 15:12:27 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.5 88/08/09 19:12:41 eggert
+ * Use execv(), not system(); yield exit status like diff(1)s; allow cc -R.
+ *
+ * Revision 4.4 87/12/18 11:37:46 narten
+ * changes Jay Lepreau made in the 4.3 BSD version, to add support for
+ * "-i", "-w", and "-t" flags and to permit flags to be bundled together,
+ * merged in.
+ *
+ * Revision 4.3 87/10/18 10:31:42 narten
+ * Updating version numbers. Changes relative to 1.1 actually
+ * relative to 4.1
+ *
+ * Revision 1.3 87/09/24 13:59:21 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:15 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/05/03 22:13:19 wft
+ * Added default branch, option -q, exit status like diff.
+ * Added fterror() to replace faterror().
+ *
+ * Revision 3.6 83/01/15 17:52:40 wft
+ * Expanded mainprogram to handle multiple RCS files.
+ *
+ * Revision 3.5 83/01/06 09:33:45 wft
+ * Fixed passing of -c (context) option to diff.
+ *
+ * Revision 3.4 82/12/24 15:28:38 wft
+ * Added call to catchsig().
+ *
+ * Revision 3.3 82/12/10 16:08:17 wft
+ * Corrected checking of return code from diff; improved error msgs.
+ *
+ * Revision 3.2 82/12/04 13:20:09 wft
+ * replaced getdelta() with gettree(). Changed diagnostics.
+ *
+ * Revision 3.1 82/11/28 19:25:04 wft
+ * Initial revision.
+ *
+ */
+#include "rcsbase.h"
+
+#if DIFF_L
+static char const *setup_label P((struct buf*,char const*,char const[datesize]));
+#endif
+static void cleanup P((void));
+
+static int exitstatus;
+static RILE *workptr;
+static struct stat workstat;
+
+mainProg(rcsdiffId, "rcsdiff", "$FreeBSD$")
+{
+ static char const cmdusage[] =
+ "\nrcsdiff usage: rcsdiff -ksubst -q -rrev1 [-rrev2] -Vn -xsuff -zzone [diff options] file ...";
+
+ int revnums; /* counter for revision numbers given */
+ char const *rev1, *rev2; /* revision numbers from command line */
+ char const *xrev1, *xrev2; /* expanded revision numbers */
+ char const *expandarg, *lexpandarg, *suffixarg, *versionarg, *zonearg;
+#if DIFF_L
+ static struct buf labelbuf[2];
+ int file_labels;
+ char const **diff_label1, **diff_label2;
+ char date2[datesize];
+#endif
+ char const *cov[10 + !DIFF_L];
+ char const **diffv, **diffp, **diffpend; /* argv for subsidiary diff */
+ char const **pp, *p, *diffvstr;
+ struct buf commarg;
+ struct buf numericrev; /* expanded revision number */
+ struct hshentries *gendeltas; /* deltas to be generated */
+ struct hshentry * target;
+ char *a, *dcp, **newargv;
+ int no_diff_means_no_output;
+ register c;
+
+ exitstatus = DIFF_SUCCESS;
+
+ bufautobegin(&commarg);
+ bufautobegin(&numericrev);
+ revnums = 0;
+ rev1 = rev2 = xrev2 = 0;
+#if DIFF_L
+ file_labels = 0;
+#endif
+ expandarg = suffixarg = versionarg = zonearg = 0;
+ no_diff_means_no_output = true;
+ suffixes = X_DEFAULT;
+
+ /*
+ * Room for runv extra + args [+ --binary] [+ 2 labels]
+ * + 1 file + 1 trailing null.
+ */
+ diffv = tnalloc(char const*, 1 + argc + !!OPEN_O_BINARY + 2*DIFF_L + 2);
+ diffp = diffv + 1;
+ *diffp++ = DIFF;
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ while (a = *++argv, 0<--argc && *a++=='-') {
+ dcp = a;
+ while ((c = *a++)) switch (c) {
+ case 'r':
+ switch (++revnums) {
+ case 1: rev1=a; break;
+ case 2: rev2=a; break;
+ default: error("too many revision numbers");
+ }
+ goto option_handled;
+ case '-': case 'D':
+ no_diff_means_no_output = false;
+ /* fall into */
+ case 'C': case 'F': case 'I': case 'L': case 'W':
+#if DIFF_L
+ if (c == 'L' && file_labels++ == 2)
+ faterror("too many -L options");
+#endif
+ *dcp++ = c;
+ if (*a)
+ do *dcp++ = *a++;
+ while (*a);
+ else {
+ if (!--argc)
+ faterror("-%c needs following argument%s",
+ c, cmdusage
+ );
+ *diffp++ = *argv++;
+ }
+ break;
+ case 'y':
+ no_diff_means_no_output = false;
+ /* fall into */
+ case 'B': case 'H':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'h': case 'i': case 'n': case 'p':
+ case 't': case 'u': case 'w':
+ *dcp++ = c;
+ break;
+ case 'q':
+ quietflag=true;
+ break;
+ case 'x':
+ suffixarg = *argv;
+ suffixes = *argv + 2;
+ goto option_handled;
+ case 'z':
+ zonearg = *argv;
+ zone_set(*argv + 2);
+ goto option_handled;
+ case 'T':
+ /* Ignore -T, so that RCSINIT can contain -T. */
+ if (*a)
+ goto unknown;
+ break;
+ case 'V':
+ versionarg = *argv;
+ setRCSversion(versionarg);
+ goto option_handled;
+ case 'k':
+ expandarg = *argv;
+ if (0 <= str2expmode(expandarg+2))
+ goto option_handled;
+ /* fall into */
+ default:
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
+ };
+ option_handled:
+ if (dcp != *argv+1) {
+ *dcp = 0;
+ *diffp++ = *argv;
+ }
+ } /* end of option processing */
+
+ for (pp = diffv+2, c = 0; pp<diffp; )
+ c += strlen(*pp++) + 1;
+ diffvstr = a = tnalloc(char, c + 1);
+ for (pp = diffv+2; pp<diffp; ) {
+ p = *pp++;
+ *a++ = ' ';
+ while ((*a = *p++))
+ a++;
+ }
+ *a = 0;
+
+#if DIFF_L
+ diff_label1 = diff_label2 = 0;
+ if (file_labels < 2) {
+ if (!file_labels)
+ diff_label1 = diffp++;
+ diff_label2 = diffp++;
+ }
+#endif
+ diffpend = diffp;
+
+ cov[1] = CO;
+ cov[2] = "-q";
+# if !DIFF_L
+ cov[3] = "-M";
+# endif
+
+ /* Now handle all pathnames. */
+ if (nerror)
+ cleanup();
+ else if (argc < 1)
+ faterror("no input file%s", cmdusage);
+ else
+ for (; 0 < argc; cleanup(), ++argv, --argc) {
+ ffree();
+
+ if (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
+ continue;
+ diagnose("===================================================================\nRCS file: %s\n",RCSname);
+ if (!rev2) {
+ /* Make sure work file is readable, and get its status. */
+ if (!(workptr = Iopen(workname, FOPEN_R_WORK, &workstat))) {
+ eerror(workname);
+ continue;
+ }
+ }
+
+
+ gettree(); /* reads in the delta tree */
+
+ if (!Head) {
+ rcserror("no revisions present");
+ continue;
+ }
+ if (revnums==0 || !*rev1)
+ rev1 = Dbranch ? Dbranch : Head->num;
+
+ if (!fexpandsym(rev1, &numericrev, workptr)) continue;
+ if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
+ xrev1=target->num;
+#if DIFF_L
+ if (diff_label1)
+ *diff_label1 = setup_label(&labelbuf[0], target->num, target->date);
+#endif
+
+ lexpandarg = expandarg;
+ if (revnums==2) {
+ if (!fexpandsym(
+ *rev2 ? rev2 : Dbranch ? Dbranch : Head->num,
+ &numericrev,
+ workptr
+ ))
+ continue;
+ if (!(target=genrevs(numericrev.string,(char *)0,(char *)0,(char *)0,&gendeltas))) continue;
+ xrev2=target->num;
+ if (no_diff_means_no_output && xrev1 == xrev2)
+ continue;
+ } else if (
+ target->lockedby
+ && !lexpandarg
+ && Expand == KEYVAL_EXPAND
+ && WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
+ )
+ lexpandarg = "-kkvl";
+ Izclose(&workptr);
+#if DIFF_L
+ if (diff_label2)
+ if (revnums == 2)
+ *diff_label2 = setup_label(&labelbuf[1], target->num, target->date);
+ else {
+ time2date(workstat.st_mtime, date2);
+ *diff_label2 = setup_label(&labelbuf[1], (char*)0, date2);
+ }
+#endif
+
+ diagnose("retrieving revision %s\n", xrev1);
+ bufscpy(&commarg, "-p");
+ bufscat(&commarg, rev1); /* not xrev1, for $Name's sake */
+
+ pp = &cov[3 + !DIFF_L];
+ *pp++ = commarg.string;
+ if (lexpandarg) *pp++ = lexpandarg;
+ if (suffixarg) *pp++ = suffixarg;
+ if (versionarg) *pp++ = versionarg;
+ if (zonearg) *pp++ = zonearg;
+ *pp++ = RCSname;
+ *pp = 0;
+
+ diffp = diffpend;
+# if OPEN_O_BINARY
+ if (Expand == BINARY_EXPAND)
+ *diffp++ = "--binary";
+# endif
+ diffp[0] = maketemp(0);
+ if (runv(-1, diffp[0], cov)) {
+ rcserror("co failed");
+ continue;
+ }
+ if (!rev2) {
+ diffp[1] = workname;
+ if (*workname == '-') {
+ char *dp = ftnalloc(char, strlen(workname)+3);
+ diffp[1] = dp;
+ *dp++ = '.';
+ *dp++ = SLASH;
+ VOID strcpy(dp, workname);
+ }
+ } else {
+ diagnose("retrieving revision %s\n",xrev2);
+ bufscpy(&commarg, "-p");
+ bufscat(&commarg, rev2); /* not xrev2, for $Name's sake */
+ cov[3 + !DIFF_L] = commarg.string;
+ diffp[1] = maketemp(1);
+ if (runv(-1, diffp[1], cov)) {
+ rcserror("co failed");
+ continue;
+ }
+ }
+ if (!rev2)
+ diagnose("diff%s -r%s %s\n", diffvstr, xrev1, workname);
+ else
+ diagnose("diff%s -r%s -r%s\n", diffvstr, xrev1, xrev2);
+
+ diffp[2] = 0;
+ switch (runv(-1, (char*)0, diffv)) {
+ case DIFF_SUCCESS:
+ break;
+ case DIFF_FAILURE:
+ if (exitstatus == DIFF_SUCCESS)
+ exitstatus = DIFF_FAILURE;
+ break;
+ default:
+ workerror("diff failed");
+ }
+ }
+
+ tempunlink();
+ exitmain(exitstatus);
+}
+
+ static void
+cleanup()
+{
+ if (nerror) exitstatus = DIFF_TROUBLE;
+ Izclose(&finptr);
+ Izclose(&workptr);
+}
+
+#if RCS_lint
+# define exiterr rdiffExit
+#endif
+ void
+exiterr()
+{
+ tempunlink();
+ _exit(DIFF_TROUBLE);
+}
+
+#if DIFF_L
+ static char const *
+setup_label(b, num, date)
+ struct buf *b;
+ char const *num;
+ char const date[datesize];
+{
+ char *p;
+ char datestr[datesize + zonelenmax];
+ VOID date2str(date, datestr);
+ bufalloc(b,
+ strlen(workname)
+ + sizeof datestr + 4
+ + (num ? strlen(num) : 0)
+ );
+ p = b->string;
+ if (num)
+ VOID sprintf(p, "-L%s\t%s\t%s", workname, datestr, num);
+ else
+ VOID sprintf(p, "-L%s\t%s", workname, datestr);
+ return p;
+}
+#endif
diff --git a/gnu/usr.bin/rcs/rcsfreeze/Makefile b/gnu/usr.bin/rcs/rcsfreeze/Makefile
new file mode 100644
index 0000000..c52f93e
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsfreeze/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+MAN= rcsfreeze.1
+
+afterinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/rcsfreeze.sh ${DESTDIR}${BINDIR}/rcsfreeze
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.1 b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.1
new file mode 100644
index 0000000..3f513c4
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.1
@@ -0,0 +1,68 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \s-1RCS\s0
+.TH RCSFREEZE 1 \*(Dt GNU
+.SH NAME
+rcsfreeze \- freeze a configuration of sources checked in under RCS
+.SH SYNOPSIS
+.B rcsfreeze
+.RI [ "name" ]
+.SH DESCRIPTION
+.B rcsfreeze
+assigns a symbolic revision
+number to a set of \*r files that form a valid configuration.
+.PP
+The idea is to run
+.B rcsfreeze
+each time a new version is checked
+in. A unique symbolic name (\c
+.BI C_ number,
+where
+.I number
+is increased each time
+.B rcsfreeze
+is run) is then assigned to the most
+recent revision of each \*r file of the main trunk.
+.PP
+An optional
+.I name
+argument to
+.B rcsfreeze
+gives a symbolic name to the configuration.
+The unique identifier is still generated
+and is listed in the log file but it will not appear as
+part of the symbolic revision name in the actual \*r files.
+.PP
+A log message is requested from the user for future reference.
+.PP
+The shell script works only on all \*r files at one time.
+All changed files must be checked in already.
+Run
+.IR rcsclean (1)
+first and see whether any sources remain in the current directory.
+.SH FILES
+.TP
+.B RCS/.rcsfreeze.ver
+version number
+.TP
+.B RCS/.rcsfreeze.log
+log messages, most recent first
+.SH AUTHOR
+Stephan v. Bechtolsheim
+.SH "SEE ALSO"
+co(1), rcs(1), rcsclean(1), rlog(1)
+.SH BUGS
+.B rcsfreeze
+does not check whether any sources are checked out and modified.
+.PP
+Although both source file names and RCS file names are accepted,
+they are not paired as usual with RCS commands.
+.PP
+Error checking is rudimentary.
+.PP
+.B rcsfreeze
+is just an optional example shell script, and should not be taken too seriously.
+See \s-1CVS\s0 for a more complete solution.
diff --git a/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh
new file mode 100644
index 0000000..be79406
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsfreeze/rcsfreeze.sh
@@ -0,0 +1,99 @@
+#! /bin/sh
+
+# rcsfreeze - assign a symbolic revision number to a configuration of RCS files
+
+# $FreeBSD$
+
+# The idea is to run rcsfreeze each time a new version is checked
+# in. A unique symbolic revision number (C_[number], where number
+# is increased each time rcsfreeze is run) is then assigned to the most
+# recent revision of each RCS file of the main trunk.
+#
+# If the command is invoked with an argument, then this
+# argument is used as the symbolic name to freeze a configuration.
+# The unique identifier is still generated
+# and is listed in the log file but it will not appear as
+# part of the symbolic revision name in the actual RCS file.
+#
+# A log message is requested from the user which is saved for future
+# references.
+#
+# The shell script works only on all RCS files at one time.
+# It is important that all changed files are checked in (there are
+# no precautions against any error in this respect).
+# file names:
+# {RCS/}.rcsfreeze.ver version number
+# {RCS/}.rscfreeze.log log messages, most recent first
+
+PATH=/bin:/usr/bin:$PATH
+export PATH
+
+DATE=`LC_ALL=C date` || exit
+# Check whether we have an RCS subdirectory, so we can have the right
+# prefix for our paths.
+if test -d RCS
+then RCSDIR=RCS/ EXT=
+else RCSDIR= EXT=,v
+fi
+
+# Version number stuff, log message file
+VERSIONFILE=${RCSDIR}.rcsfreeze.ver
+LOGFILE=${RCSDIR}.rcsfreeze.log
+# Initialize, rcsfreeze never run before in the current directory
+test -r $VERSIONFILE || { echo 0 >$VERSIONFILE && >>$LOGFILE; } || exit
+
+# Get Version number, increase it, write back to file.
+VERSIONNUMBER=`cat $VERSIONFILE` &&
+VERSIONNUMBER=`expr $VERSIONNUMBER + 1` &&
+echo $VERSIONNUMBER >$VERSIONFILE || exit
+
+# Symbolic Revision Number
+SYMREV=C_$VERSIONNUMBER
+# Allow the user to give a meaningful symbolic name to the revision.
+SYMREVNAME=${1-$SYMREV}
+echo >&2 "rcsfreeze: symbolic revision number computed: \"${SYMREV}\"
+rcsfreeze: symbolic revision number used: \"${SYMREVNAME}\"
+rcsfreeze: the two differ only when rcsfreeze invoked with argument
+rcsfreeze: give log message, summarizing changes (end with EOF or single '.')" \
+ || exit
+
+# Stamp the logfile. Because we order the logfile the most recent
+# first we will have to save everything right now in a temporary file.
+TMPLOG=/tmp/rcsfrz$$
+trap 'rm -f $TMPLOG; exit 1' 1 2 13 15
+# Now ask for a log message, continously add to the log file
+(
+ echo "Version: $SYMREVNAME($SYMREV), Date: $DATE
+-----------" || exit
+ while read MESS
+ do
+ case $MESS in
+ .) break
+ esac
+ echo " $MESS" || exit
+ done
+ echo "-----------
+" &&
+ cat $LOGFILE
+) >$TMPLOG &&
+
+# combine old and new logfiles
+cp $TMPLOG $LOGFILE &&
+rm -f $TMPLOG &&
+
+# Now the real work begins by assigning a symbolic revision number
+# to each rcs file. Take the most recent version on the default branch.
+
+# If there are any .*,v files, throw them in too.
+# But ignore RCS/.* files that do not end in ,v.
+DOTFILES=
+for DOTFILE in ${RCSDIR}.*,v
+do
+ if test -f "$DOTFILE"
+ then
+ DOTFILES="${RCSDIR}.*,v"
+ break
+ fi
+done
+
+exec rcs -q -n$SYMREVNAME: ${RCSDIR}*$EXT $DOTFILES
diff --git a/gnu/usr.bin/rcs/rcsmerge/Makefile b/gnu/usr.bin/rcs/rcsmerge/Makefile
new file mode 100644
index 0000000..9fd8afa
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsmerge/Makefile
@@ -0,0 +1,8 @@
+PROG= rcsmerge
+SRCS= rcsmerge.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.1 b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.1
new file mode 100644
index 0000000..aff6f66
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.1
@@ -0,0 +1,189 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds r \&\s-1RCS\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH RCSMERGE 1 \*(Dt GNU
+.SH NAME
+rcsmerge \- merge RCS revisions
+.SH SYNOPSIS
+.B rcsmerge
+.RI [ options ] " file"
+.SH DESCRIPTION
+.B rcsmerge
+incorporates the changes between two revisions
+of an \*r file into the corresponding working file.
+.PP
+Pathnames matching an \*r suffix denote \*r files;
+all others denote working files.
+Names are paired as explained in
+.BR ci (1).
+.PP
+At least one revision must be specified with one of the options
+described below, usually
+.BR \-r .
+At most two revisions may be specified.
+If only one revision is specified, the latest
+revision on the default branch (normally the highest branch on the trunk)
+is assumed for the second revision.
+Revisions may be specified numerically or symbolically.
+.PP
+.B rcsmerge
+prints a warning if there are overlaps, and delimits
+the overlapping regions as explained in
+.BR merge (1).
+The command is useful for incorporating changes into a checked-out revision.
+.SH OPTIONS
+.TP
+.B \-A
+Output conflicts using the
+.B \-A
+style of
+.BR diff3 (1),
+if supported by
+.BR diff3 .
+This merges all changes leading from
+.I file2
+to
+.I file3
+into
+.IR file1 ,
+and generates the most verbose output.
+.TP
+\f3\-E\fP, \f3\-e\fP
+These options specify conflict styles that generate less information
+than
+.BR \-A .
+See
+.BR diff3 (1)
+for details.
+The default is
+.BR \-E .
+With
+.BR \-e ,
+.B rcsmerge
+does not warn about conflicts.
+.TP
+.BI \-k subst
+Use
+.I subst
+style keyword substitution.
+See
+.BR co (1)
+for details.
+For example,
+.B "\-kk\ \-r1.1\ \-r1.2"
+ignores differences in keyword values when merging the changes from
+.B 1.1
+to
+.BR 1.2 .
+It normally does not make sense to merge binary files as if they were text, so
+.B rcsmerge
+refuses to merge files if
+.B \-kb
+expansion is used.
+.TP
+.BR \-p [\f2rev\fP]
+Send the result to standard output instead of overwriting the working file.
+.TP
+.BR \-q [\f2rev\fP]
+Run quietly; do not print diagnostics.
+.TP
+.BR \-r [\f2rev\fP]
+Merge with respect to revision
+.IR rev .
+Here an empty
+.I rev
+stands for the latest revision on the default branch, normally the head.
+.TP
+.B \-T
+This option has no effect;
+it is present for compatibility with other \*r commands.
+.TP
+.BI \-V
+Print \*r's version number.
+.TP
+.BI \-V n
+Emulate \*r version
+.IR n .
+See
+.BR co (1)
+for details.
+.TP
+.BI \-x "suffixes"
+Use
+.I suffixes
+to characterize \*r files.
+See
+.BR ci (1)
+for details.
+.TP
+.BI \-z zone
+Use
+.I zone
+as the time zone for keyword substitution.
+See
+.BR co (1)
+for details.
+.SH EXAMPLES
+Suppose you have released revision 2.8 of
+.BR f.c .
+Assume
+furthermore that after you complete an unreleased revision 3.4, you receive
+updates to release 2.8 from someone else.
+To combine the updates to 2.8 and your changes between 2.8 and 3.4,
+put the updates to 2.8 into file f.c and execute
+.LP
+.B " rcsmerge \-p \-r2.8 \-r3.4 f.c >f.merged.c"
+.PP
+Then examine
+.BR f.merged.c .
+Alternatively, if you want to save the updates to 2.8 in the \*r file,
+check them in as revision 2.8.1.1 and execute
+.BR "co \-j":
+.LP
+.B " ci \-r2.8.1.1 f.c"
+.br
+.B " co \-r3.4 \-j2.8:2.8.1.1 f.c"
+.PP
+As another example, the following command undoes the changes
+between revision 2.4 and 2.8 in your currently checked out revision
+in
+.BR f.c .
+.LP
+.B " rcsmerge \-r2.8 \-r2.4 f.c"
+.PP
+Note the order of the arguments, and that
+.B f.c
+will be
+overwritten.
+.SH ENVIRONMENT
+.TP
+.B \s-1RCSINIT\s0
+options prepended to the argument list, separated by spaces.
+See
+.BR ci (1)
+for details.
+.SH DIAGNOSTICS
+Exit status is 0 for no overlaps, 1 for some overlaps, 2 for trouble.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
+.SH "SEE ALSO"
+ci(1), co(1), ident(1), merge(1), rcs(1), rcsdiff(1), rcsintro(1), rlog(1),
+rcsfile(5)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.br
diff --git a/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
new file mode 100644
index 0000000..e09dc24
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsmerge/rcsmerge.c
@@ -0,0 +1,286 @@
+/* Merge RCS revisions. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.15 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.14 1995/06/01 16:23:43 eggert
+ * (main): Report an error if -kb, so don't worry about binary stdout.
+ * Punctuate messages properly. Rewrite to avoid `goto end'.
+ *
+ * Revision 5.13 1994/03/17 14:05:48 eggert
+ * Specify subprocess input via file descriptor, not file name. Remove lint.
+ *
+ * Revision 5.12 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits. Don't print usage twice.
+ *
+ * Revision 5.11 1993/11/03 17:42:27 eggert
+ * Add -A, -E, -e, -z. Ignore -T. Allow up to three file labels.
+ * Pass -Vn to `co'. Pass unexpanded revision name to `co', so that Name works.
+ *
+ * Revision 5.10 1992/07/28 16:12:44 eggert
+ * Add -V.
+ *
+ * Revision 5.9 1992/01/24 18:44:19 eggert
+ * lint -> RCS_lint
+ *
+ * Revision 5.8 1992/01/06 02:42:34 eggert
+ * Update usage string.
+ *
+ * Revision 5.7 1991/11/20 17:58:09 eggert
+ * Don't Iopen(f, "r+"); it's not portable.
+ *
+ * Revision 5.6 1991/08/19 03:13:55 eggert
+ * Add -r$. Tune.
+ *
+ * Revision 5.5 1991/04/21 11:58:27 eggert
+ * Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.4 1991/02/25 07:12:43 eggert
+ * Merging a revision to itself is no longer an error.
+ *
+ * Revision 5.3 1990/11/01 05:03:50 eggert
+ * Remove unneeded setid check.
+ *
+ * Revision 5.2 1990/09/04 08:02:28 eggert
+ * Check for I/O error when reading working file.
+ *
+ * Revision 5.1 1990/08/29 07:14:04 eggert
+ * Add -q. Pass -L options to merge.
+ *
+ * Revision 5.0 1990/08/22 08:13:41 eggert
+ * Propagate merge's exit status.
+ * Remove compile-time limits; use malloc instead.
+ * Make lock and temp files faster and safer. Ansify and Posixate. Add -V.
+ * Don't use access(). Tune.
+ *
+ * Revision 4.5 89/05/01 15:13:16 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.4 88/08/09 19:13:13 eggert
+ * Beware merging into a readonly file.
+ * Beware merging a revision to itself (no change).
+ * Use execv(), not system(); yield exit status like diff(1)'s.
+ *
+ * Revision 4.3 87/10/18 10:38:02 narten
+ * Updating version numbers. Changes relative to version 1.1
+ * actually relative to 4.1
+ *
+ * Revision 1.3 87/09/24 14:00:31 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:36 jenkins
+ * Port to suns
+ *
+ * Revision 4.1 83/03/28 11:14:57 wft
+ * Added handling of default branch.
+ *
+ * Revision 3.3 82/12/24 15:29:00 wft
+ * Added call to catchsig().
+ *
+ * Revision 3.2 82/12/10 21:32:02 wft
+ * Replaced getdelta() with gettree(); improved error messages.
+ *
+ * Revision 3.1 82/11/28 19:27:44 wft
+ * Initial revision.
+ *
+ */
+#include "rcsbase.h"
+
+static char const co[] = CO;
+
+mainProg(rcsmergeId, "rcsmerge", "$FreeBSD$")
+{
+ static char const cmdusage[] =
+ "\nrcsmerge usage: rcsmerge -rrev1 [-rrev2] -ksubst -{pq}[rev] -Vn -xsuff -zzone file";
+ static char const quietarg[] = "-q";
+
+ register int i;
+ char *a, **newargv;
+ char const *arg[3];
+ char const *rev[3], *xrev[3]; /*revision numbers*/
+ char const *edarg, *expandarg, *suffixarg, *versionarg, *zonearg;
+ int tostdout;
+ int status;
+ RILE *workptr;
+ struct buf commarg;
+ struct buf numericrev; /* holds expanded revision number */
+ struct hshentries *gendeltas; /* deltas to be generated */
+ struct hshentry * target;
+
+ bufautobegin(&commarg);
+ bufautobegin(&numericrev);
+ edarg = rev[1] = rev[2] = 0;
+ status = 0; /* Keep lint happy. */
+ tostdout = false;
+ expandarg = suffixarg = versionarg = zonearg = quietarg; /* no-op */
+ suffixes = X_DEFAULT;
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ while (a = *++argv, 0<--argc && *a++=='-') {
+ switch (*a++) {
+ case 'p':
+ tostdout=true;
+ goto revno;
+
+ case 'q':
+ quietflag = true;
+ revno:
+ if (!*a)
+ break;
+ /* falls into -r */
+ case 'r':
+ if (!rev[1])
+ rev[1] = a;
+ else if (!rev[2])
+ rev[2] = a;
+ else
+ error("too many revision numbers");
+ break;
+
+ case 'A': case 'E': case 'e':
+ if (*a)
+ goto unknown;
+ edarg = *argv;
+ break;
+
+ case 'x':
+ suffixarg = *argv;
+ suffixes = a;
+ break;
+ case 'z':
+ zonearg = *argv;
+ zone_set(a);
+ break;
+ case 'T':
+ /* Ignore -T, so that RCSINIT can contain -T. */
+ if (*a)
+ goto unknown;
+ break;
+ case 'V':
+ versionarg = *argv;
+ setRCSversion(versionarg);
+ break;
+
+ case 'k':
+ expandarg = *argv;
+ if (0 <= str2expmode(expandarg+2))
+ break;
+ /* fall into */
+ default:
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
+ };
+ } /* end of option processing */
+
+ if (!rev[1]) faterror("no base revision number given");
+
+ /* Now handle all pathnames. */
+
+ if (!nerror) {
+ if (argc < 1)
+ faterror("no input file%s", cmdusage);
+ if (0 < pairnames(argc, argv, rcsreadopen, true, false)) {
+
+ if (argc>2 || (argc==2 && argv[1]))
+ warn("excess arguments ignored");
+ if (Expand == BINARY_EXPAND)
+ workerror("merging binary files");
+ diagnose("RCS file: %s\n", RCSname);
+ if (!(workptr = Iopen(workname, FOPEN_R_WORK, (struct stat*)0)))
+ efaterror(workname);
+
+ gettree(); /* reads in the delta tree */
+
+ if (!Head) rcsfaterror("no revisions present");
+
+ if (!*rev[1])
+ rev[1] = Dbranch ? Dbranch : Head->num;
+ if (fexpandsym(rev[1], &numericrev, workptr)
+ && (target=genrevs(numericrev.string, (char *)0, (char *)0, (char*)0, &gendeltas))
+ ) {
+ xrev[1] = target->num;
+ if (!rev[2] || !*rev[2])
+ rev[2] = Dbranch ? Dbranch : Head->num;
+ if (fexpandsym(rev[2], &numericrev, workptr)
+ && (target=genrevs(numericrev.string, (char *)0, (char *)0, (char *)0, &gendeltas))
+ ) {
+ xrev[2] = target->num;
+
+ if (strcmp(xrev[1],xrev[2]) == 0) {
+ if (tostdout) {
+ fastcopy(workptr, stdout);
+ Ofclose(stdout);
+ }
+ } else {
+ Izclose(&workptr);
+
+ for (i=1; i<=2; i++) {
+ diagnose("retrieving revision %s\n", xrev[i]);
+ bufscpy(&commarg, "-p");
+ bufscat(&commarg, rev[i]); /* not xrev[i], for $Name's sake */
+ if (run(
+ -1,
+ /* Do not collide with merger.c maketemp(). */
+ arg[i] = maketemp(i+2),
+ co, quietarg, commarg.string,
+ expandarg, suffixarg, versionarg, zonearg,
+ RCSname, (char*)0
+ ))
+ rcsfaterror("co failed");
+ }
+ diagnose("Merging differences between %s and %s into %s%s\n",
+ xrev[1], xrev[2], workname,
+ tostdout?"; result to stdout":"");
+
+ arg[0] = xrev[0] = workname;
+ status = merge(tostdout, edarg, xrev, arg);
+ }
+ }
+ }
+
+ Izclose(&workptr);
+ }
+ }
+ tempunlink();
+ exitmain(nerror ? DIFF_TROUBLE : status);
+}
+
+#if RCS_lint
+# define exiterr rmergeExit
+#endif
+ void
+exiterr()
+{
+ tempunlink();
+ _exit(DIFF_TROUBLE);
+}
diff --git a/gnu/usr.bin/rcs/rcstest b/gnu/usr.bin/rcs/rcstest
new file mode 100755
index 0000000..75165f1
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcstest
@@ -0,0 +1,454 @@
+#! /bin/sh
+
+# Test RCS's functions.
+# The RCS commands are searched for in the PATH as usual;
+# to test the working directory's commands, prepend . to your PATH.
+
+# Test RCS by creating files RCS/a.* and RCS/a.c.
+# If all goes well, output nothing, and remove the temporary files.
+# Otherwise, send a message to standard output.
+# Exit status is 0 if OK, 1 if an RCS bug is found, and 2 if scaffolding fails.
+# With the -v option, output more debugging info.
+
+# If diff outputs `No differences encountered' when comparing identical files,
+# then rcstest may also output these noise lines; ignore them.
+
+# The current directory and ./RCS must be readable, writable, and searchable.
+
+# $FreeBSD$
+
+
+# Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+# Distributed under license by the Free Software Foundation, Inc.
+#
+# This file is part of RCS.
+#
+# RCS is free software; you can redistribute 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.
+#
+# RCS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with RCS; see the file COPYING.
+# If not, write to the Free Software Foundation,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Report problems and direct all questions to:
+#
+# rcs-bugs@cs.purdue.edu
+
+# The Makefile overrides the following defaults.
+: ${ALL_CFLAGS=-Dhas_conf_h}
+: ${CC=cc}
+: ${DIFF=diff}
+# : ${LDFLAGS=} ${LIBS=} tickles old shell bug
+
+CL="$CC $ALL_CFLAGS $LDFLAGS -o a.out"
+L=$LIBS
+
+RCSINIT=-x
+export RCSINIT
+
+SLASH=/
+RCSfile=RCS${SLASH}a.c
+RCS_alt=RCS${SLASH}a.d
+lockfile=RCS${SLASH}a._
+
+case $1 in
+-v) q=; set -x;;
+'') q=-q;;
+*) echo >&2 "$0: usage: $0 [-v]"; exit 2
+esac
+
+if test -d RCS
+then rmdir=:
+else rmdir=rmdir; mkdir RCS || exit
+fi
+
+rm -f a.* $RCSfile $RCS_alt $lockfile &&
+echo 1.1 >a.11 &&
+echo 1.1.1.1 >a.3x1 &&
+echo 1.2 >a.12 || { echo "#initialization failed"; exit 2; }
+
+case "`$DIFF -c a.11 a.3x1`" in
+*!\ 1.1.1.1)
+ diff="$DIFF -c";;
+*)
+ echo "#warning: $DIFF -c does not work, so diagnostics may be cryptic"
+ diff=$DIFF
+esac
+
+rcs -i -L -ta.11 $q a.c &&
+test -r $RCSfile || {
+ echo "#rcs -i -L failed; perhaps RCS is not properly installed."
+ exit 1
+}
+
+rlog a.c >/dev/null || { echo "#rlog failed on empty RCS file"; exit 1; }
+rm -f $RCSfile || exit 2
+
+cp a.11 a.c &&
+ci -ta.11 -mm $q a.c &&
+test -r $RCSfile &&
+rcs -L $q a.c || { echo "#ci+rcs -L failed"; exit 1; }
+test ! -f a.c || { echo "#ci did not remove working file"; exit 1; }
+for l in '' '-l'
+do
+ co $l $q a.c &&
+ test -f a.c || { echo '#co' $l did not create working file; exit 1; }
+ $diff a.11 a.c || { echo '#ci' followed by co $l is not a no-op; exit 1; }
+done
+
+cp a.12 a.c &&
+ci -mm $q a.c &&
+co $q a.c &&
+$diff a.12 a.c || { echo "#ci+co failed"; exit 1; }
+
+rm -f a.c &&
+co -r1.1 $q a.c &&
+$diff a.11 a.c || { echo "#can't retrieve first revision"; exit 1; }
+
+rm -f a.c &&
+cp a.3x1 a.c &&
+ci -r1.1.1 -mm $q a.c &&
+co -r1.1.1.1 $q a.c &&
+$diff a.3x1 a.c || { echo "#branches failed"; exit 1; }
+
+rm -f a.c &&
+co -l $q a.c &&
+ci -f -mm $q a.c &&
+co -r1.3 $q a.c &&
+$diff a.12 a.c || { echo "#(co -l; ci -f) failed"; exit 1; }
+
+rm -f a.c &&
+co -l $q a.c &&
+echo 1.4 >a.c &&
+ci -l -mm $q a.c &&
+echo error >a.c &&
+ci -mm $q a.c || { echo "#ci -l failed"; exit 1; }
+
+rm -f a.c &&
+co -l $q a.c &&
+echo 1.5 >a.c &&
+ci -u -mm $q a.c &&
+test -r a.c || { echo "#ci -u didn't create a working file"; exit 1; }
+rm -f a.c &&
+echo error >a.c || exit 2
+ci -mm $q a.c 2>/dev/null && { echo "#ci -u didn't unlock the file"; exit 1; }
+
+rm -f a.c &&
+rcs -l $q a.c &&
+co -u $q a.c || { echo "#rcs -l + co -u failed"; exit 1; }
+rm -f a.c &&
+echo error >a.c || exit 2
+ci -mm $q a.c 2>/dev/null && { echo "#co -u didn't unlock the file"; exit 1; }
+
+rm -f a.c &&
+cp a.11 a.c &&
+co -f $q a.c || { echo "#co -f failed"; exit 1; }
+$diff a.11 a.c >/dev/null && { echo "#co -f had no effect"; exit 1; }
+
+co -p1.1 $q a.c >a.t &&
+$diff a.11 a.t || { echo "#co -p failed"; exit 1; }
+
+for n in n N
+do
+ rm -f a.c &&
+ co -l $q a.c &&
+ echo $n >a.$n &&
+ cp a.$n a.c &&
+ ci -${n}n -mm $q a.c &&
+ co -rn $q a.c &&
+ $diff a.$n a.c || { echo "#ci -$n failed"; exit 1; }
+done
+
+case $LOGNAME in
+?*) me=$LOGNAME;;
+*)
+ case $USER in
+ ?*) me=$USER;;
+ *)
+ me=`who am i` || exit 2
+ me=`echo "$me" | sed -e 's/ .*//' -e 's/.*!//'`
+ case $me in
+ '') echo >&2 "$0: cannot deduce user name"; exit 2
+ esac
+ esac
+esac
+
+
+# Get the date of the previous revision in UTC.
+date=`rlog -r a.c | sed -n '/^date: /{ s///; s/;.*//; p; q; }'` || exit
+case $date in
+[0-9][0-9][0-9]*[0-9]/[0-1][0-9]/[0-3][0-9]\ [0-2][0-9]:[0-5][0-9]:[0-6][0-9]);;
+*) echo >&2 "$0: $date: bad rlog date output"; exit 1
+esac
+PWD=`pwd` && export PWD &&
+rm -f a.c &&
+co -l $q a.c &&
+sed 's/@/$/g' >a.kv <<EOF
+@Author: w @
+@Date: $date @
+@Header: $PWD$SLASH$RCSfile 2.1 $date w s @
+@Id: a.c 2.1 $date w s @
+@Locker: @
+ * @Log: a.c @
+ * Revision 2.1 $date w
+ * m
+ *
+@Name: Oz @
+@RCSfile: a.c @
+@Revision: 2.1 @
+@Source: $PWD$SLASH$RCSfile @
+@State: s @
+EOF
+test $? = 0 &&
+sed 's/:.*\$/$/' a.kv >a.k &&
+sed -e 's/w s [$]/w s '"$me"' $/' -e 's/[$]Locker: /&'"$me/" a.kv >a.kvl &&
+sed s/Oz//g a.kv >a.e &&
+sed s/Oz/N/g a.kv >a.N &&
+sed -e '/\$/!d' -e 's/\$$/: old $/' a.k >a.o &&
+sed -e 's/\$[^ ]*: //' -e 's/ \$//' a.kv >a.v &&
+cp a.o a.c &&
+ci -d"$date" -nOz -ss -ww -u2.1 -mm $q a.c &&
+$diff a.kv a.c || { echo "#keyword expansion failed"; exit 1; }
+co -pOz -ko $q a.c >a.oo &&
+$diff a.o a.oo || { echo "#co -p -ko failed"; exit 1; }
+cp a.kv a.o && cp a.o a.b || exit 2
+rcs -oOz $q a.c &&
+rcs -l $q a.c &&
+ci -k -u $q a.c &&
+$diff a.kv a.c || { echo "#ci -k failed"; exit 1; }
+sed -n 's/^[^$]*\$/$/p' a.kv >a.i &&
+ident a.c >a.i1 &&
+sed -e 1d -e 's/^[ ]*//' a.i1 >a.i2 &&
+$diff a.i a.i2 || { echo "#ident failed"; exit 1; }
+
+rcs -i $q a.c 2>/dev/null && { echo "#rcs -i permitted existing file"; exit 1; }
+
+rm -f a.c &&
+co -l $q a.c &&
+echo 2.2 >a.c &&
+ci -mm $q a.c &&
+echo 1.1.1.2 >a.c &&
+rcs -l1.1.1 $q a.c &&
+ci -r1.1.1.2 -mm $q a.c &&
+rcs -b1.1.1 $q a.c &&
+test " `co -p $q a.c`" = ' 1.1.1.2' || { echo "#rcs -b1.1.1 failed"; exit 1; }
+rcs -b $q a.c &&
+test " `co -p $q a.c`" = ' 2.2' || { echo "#rcs -b failed"; exit 1; }
+
+echo 2.3 >a.c || exit 2
+rcs -U $q a.c || { echo "#rcs -U failed"; exit 1; }
+ci -mm $q a.c || { echo "#rcs -U didn't unset strict locking"; exit 1; }
+rcs -L $q a.c || { echo "#rcs -L failed"; exit 1; }
+echo error >a.c || exit 2
+ci -mm $q a.c 2>/dev/null && { echo "#ci retest failed"; exit 1; }
+
+rm -f a.c &&
+log0=`rlog -h a.c` &&
+co -l $q a.c &&
+ci -mm $q a.c &&
+log1=`rlog -h a.c` &&
+test " $log0" = " $log1" || { echo "#unchanged ci didn't revert"; exit 1; }
+
+rm -f a.c &&
+rcs -nN:1.1 $q a.c &&
+co -rN $q a.c &&
+$diff a.11 a.c || { echo "#rcs -n failed"; exit 1; }
+
+rm -f a.c &&
+rcs -NN:2.1 $q a.c &&
+co -rN $q a.c &&
+$diff a.N a.c || { echo "#rcs -N failed"; exit 1; }
+
+rm -f a.c &&
+co -l $q a.c &&
+echo ':::$''Log$' >a.c &&
+ci -u -mm $q a.c &&
+test " `sed '$!d' a.c`" = ' :::' || { echo "#comment leader failed"; exit 1; }
+
+rm -f a.c &&
+rcs -o2.2: $q a.c &&
+co $q a.c &&
+$diff a.e a.c || { echo "#rcs -o failed"; exit 1; }
+
+rcsdiff -r1.1 -rOz $q a.c >a.0
+case $? in
+1) ;;
+*) echo "#rcsdiff bad status"; exit 1
+esac
+$DIFF a.11 a.kv >a.1
+$diff a.0 a.1 || { echo "#rcsdiff failed"; exit 1; }
+
+rcs -l2.1 $q a.c || { echo "#rcs -l2.1 failed"; exit 1; }
+for i in b k kv kvl o v
+do
+ rm -f a.c &&
+ cp a.$i a.c &&
+ rcsdiff -k$i -rOz $q a.c || { echo "#rcsdiff -k$i failed"; exit 1; }
+done
+co -p1.1 -ko $q a.c >a.t &&
+$diff a.11 a.t || { echo "#co -p1.1 -ko failed"; exit 1; }
+rcs -u2.1 $q a.c || { echo "#rcs -u2.1 failed"; exit 1; }
+
+rm -f a.c &&
+rcsclean $q a.c &&
+rcsclean -u $q a.c || { echo "#rcsclean botched a nonexistent file"; exit 1; }
+
+rm -f a.c &&
+co $q a.c &&
+rcsclean -n $q a.c &&
+rcsclean -n -u $q a.c &&
+test -f a.c || { echo "#rcsclean -n removed a file"; exit 1; }
+
+rm -f a.c &&
+co $q a.c &&
+rcsclean $q a.c &&
+test ! -f a.c || { echo "#rcsclean missed an unlocked file"; exit 1; }
+
+rm -f a.c &&
+co -l $q a.c &&
+rcsclean $q a.c &&
+test -f a.c || { echo "#rcsclean removed a locked file"; exit 1; }
+rcsclean -u $q a.c &&
+test ! -f a.c || {
+ echo "#rcsclean -u missed an unchanged locked file"; exit 1;
+}
+
+rm -f a.c &&
+co -l $q a.c &&
+echo change >>a.c &&
+rcsclean $q a.c &&
+rcsclean $q -u a.c &&
+test -f a.c || { echo "#rcsclean removed a changed file"; exit 1; }
+
+rm -f a.c &&
+co -l $q a.c &&
+cat >a.c <<'EOF'
+2.2
+a
+b
+c
+d
+EOF
+test $? = 0 &&
+ci -l -mm $q a.c &&
+co -p2.2 $q a.c | sed -e s/2.2/2.3/ -e s/b/b1/ >a.c &&
+ci -l -mm $q a.c &&
+co -p2.2 $q a.c | sed -e s/2.2/new/ -e s/d/d1/ >a.c || exit 2
+cat >a.0 <<'EOF'
+2.3
+a
+b1
+c
+d1
+EOF
+cat >a.1 <<'EOF'
+<<<<<<< a.c
+new
+=======
+2.3
+>>>>>>> 2.3
+a
+b1
+c
+d1
+EOF
+rcsmerge -E -r2.2 -r2.3 $q a.c
+case $? in
+0)
+ if $diff a.0 a.c >/dev/null
+ then echo "#warning: diff3 -E does not work, " \
+ "so merge and rcsmerge ignore overlaps and suppress overlap lines."
+ else
+ $diff a.1 a.c || { echo "#rcsmerge failed (status 0)"; exit 1; }
+ echo "#warning: The diff3 lib program exit status ignores overlaps," \
+ "so rcsmerge does not warn about overlap lines that it generates."
+ fi
+ ;;
+1)
+ $diff a.1 a.c || { echo "#rcsmerge failed (status 1)"; exit 1; }
+ ;;
+*)
+ echo "#rcsmerge bad status"; exit 1
+esac
+
+# Avoid `tr' if possible; it's not portable, and it can't handle null bytes.
+# Our substitute exclusive-ORs with '\n';
+# this ensures null bytes on output, which is even better than `tr',
+# since some diffs think a file is binary only if it contains null bytes.
+cat >a.c <<'EOF'
+#include <stdio.h>
+int main() {
+ int c;
+ while ((c=getchar()) != EOF)
+ putchar(c ^ '\n');
+ return 0;
+}
+EOF
+tr=tr
+if (rm -f a.exe a.out && $CL a.c $L >&2) >/dev/null 2>&1
+then
+ if test -s a.out
+ then tr=./a.out
+ elif test -s a.exe
+ then tr=./a.exe
+ fi
+fi
+{
+ co -p $q a.c | $tr '\012' '\200' >a.24 &&
+ cp a.24 a.c &&
+ ciOut=`(ci -l -mm $q a.c 2>&1)` &&
+ case $ciOut in
+ ?*) echo >&2 "$ciOut"
+ esac &&
+ co -p $q a.c | $tr '\200' '\012' >a.c &&
+ rcsdiff -r2.3 $q a.c >/dev/null &&
+
+ echo 2.5 >a.c &&
+ ci -l -mm $q a.c &&
+ cp a.24 a.c &&
+ rcsdiff -r2.4 $q a.c >/dev/null
+} || echo "#warning: Traditional diff is used, so RCS is limited to text files."
+
+rcs -u -o2.4: $q a.c || { echo "#rcs -u -o failed"; exit 1; }
+
+rcs -i -Aa.c -t- $q a.d || { echo "#rcs -i -A failed"; exit 1; }
+
+rlog -r2.1 a.c >a.t &&
+grep '^checked in with -k' a.t >/dev/null &&
+sed '/^checked in with -k/d' a.t >a.u &&
+$diff - a.u <<EOF
+
+RCS file: $RCSfile
+Working file: a.c
+head: 2.3
+branch:
+locks: strict
+access list:
+symbolic names:
+ N: 2.1
+ Oz: 2.1
+ n: 1.8
+keyword substitution: kv
+total revisions: 13; selected revisions: 1
+description:
+1.1
+----------------------------
+revision 2.1
+date: $date; author: w; state: s; lines: +14 -1
+=============================================================================
+EOF
+test $? = 0 || { echo "#rlog failed"; exit 1; }
+
+
+test ! -f $lockfile || { echo "#lock file not removed"; exit 1; }
+
+rm -f a.* $RCSfile $RCS_alt
+$rmdir RCS
diff --git a/gnu/usr.bin/rcs/rlog/Makefile b/gnu/usr.bin/rcs/rlog/Makefile
new file mode 100644
index 0000000..bdbf68f
--- /dev/null
+++ b/gnu/usr.bin/rcs/rlog/Makefile
@@ -0,0 +1,8 @@
+PROG= rlog
+SRCS= rlog.c
+CFLAGS+= -I${.CURDIR}/../lib
+LDADD= ${LIBRCS}
+DPADD= ${LIBRCS}
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/rcs/rlog/rlog.1 b/gnu/usr.bin/rcs/rlog/rlog.1
new file mode 100644
index 0000000..26bf08a
--- /dev/null
+++ b/gnu/usr.bin/rcs/rlog/rlog.1
@@ -0,0 +1,318 @@
+.de Id
+.ds Rv \\$3
+.ds Dt \\$4
+..
+.Id $FreeBSD$
+.ds i \&\s-1ISO\s0
+.ds r \&\s-1RCS\s0
+.ds u \&\s-1UTC\s0
+.if n .ds - \%--
+.if t .ds - \(em
+.TH RLOG 1 \*(Dt GNU
+.SH NAME
+rlog \- print log messages and other information about RCS files
+.SH SYNOPSIS
+.B rlog
+.RI [ " options " ] " file " .\|.\|.
+.SH DESCRIPTION
+.B rlog
+prints information about \*r files.
+.PP
+Pathnames matching an \*r suffix denote \*r files;
+all others denote working files.
+Names are paired as explained in
+.BR ci (1).
+.PP
+.B rlog
+prints the following information for each
+\*r file: \*r pathname, working pathname, head (i.e., the number
+of the latest revision on the trunk), default branch, access list, locks,
+symbolic names, suffix, total number of revisions,
+number of revisions selected for printing, and
+descriptive text. This is followed by entries for the selected revisions in
+reverse chronological order for each branch. For each revision,
+.B rlog
+prints revision number, author, date/time, state, number of
+lines added/deleted (with respect to the previous revision),
+locker of the revision (if any), and log message.
+All times are displayed in Coordinated Universal Time (\*u) by default;
+this can be overridden with
+.BR \-z .
+Without options,
+.B rlog
+prints complete information.
+The options below restrict this output.
+.nr n \w'\f3\-V\fP\f2n\fP'+2n-1/1n
+.ds n \nn
+.if \n(.g .if r an-tag-sep .ds n \w'\f3\-V\fP\f2n\fP'u+\n[an-tag-sep]u
+.TP \*n
+.B \-L
+Ignore \*r files that have no locks set.
+This is convenient in combination with
+.BR \-h ,
+.BR \-l ,
+and
+.BR \-R .
+.TP
+.B \-R
+Print only the name of the \*r file.
+This is convenient for translating a
+working pathname into an \*r pathname.
+.TP
+.BI \-v "[string]"
+Print only the working pathname and tip-revision.
+The optional string is prepended to the outputline.
+.TP
+.B \-h
+Print only the \*r pathname, working pathname, head,
+default branch, access list, locks,
+symbolic names, and suffix.
+.TP
+.B \-t
+Print the same as
+.BR \-h ,
+plus the descriptive text.
+.TP
+.B \-N
+Do not print the symbolic names.
+.TP
+.B \-b
+Print information about the revisions on the default branch, normally
+the highest branch on the trunk.
+.TP
+.BI \-d "dates"
+Print information about revisions with a checkin date/time in the ranges given by
+the semicolon-separated list of
+.IR dates .
+A range of the form
+.IB d1 < d2
+or
+.IB d2 > d1
+selects the revisions that were deposited between
+.I d1
+and
+.I d2
+exclusive.
+A range of the form
+.BI < d
+or
+.IB d >
+selects
+all revisions earlier than
+.IR d .
+A range of the form
+.IB d <
+or
+.BI > d
+selects
+all revisions dated later than
+.IR d .
+If
+.B <
+or
+.B >
+is followed by
+.B =
+then the ranges are inclusive, not exclusive.
+A range of the form
+.I d
+selects the single, latest revision dated
+.I d
+or earlier.
+The date/time strings
+.IR d ,
+.IR d1 ,
+and
+.I d2
+are in the free format explained in
+.BR co (1).
+Quoting is normally necessary, especially for
+.B <
+and
+.BR > .
+Note that the separator is
+a semicolon.
+.TP
+.BR \-l [\f2lockers\fP]
+Print information about locked revisions only.
+In addition, if the comma-separated list
+.I lockers
+of login names is given,
+ignore all locks other than those held by the
+.IR lockers .
+For example,
+.B "rlog\ \-L\ \-R\ \-lwft\ RCS/*"
+prints the name of \*r files locked by the user
+.BR wft .
+.TP
+.BR \-r [\f2revisions\fP]
+prints information about revisions given in the comma-separated list
+.I revisions
+of revisions and ranges.
+A range
+.IB rev1 : rev2
+means revisions
+.I rev1
+to
+.I rev2
+on the same branch,
+.BI : rev
+means revisions from the beginning of the branch up to and including
+.IR rev ,
+and
+.IB rev :
+means revisions starting with
+.I rev
+to the end of the branch containing
+.IR rev .
+An argument that is a branch means all
+revisions on that branch.
+A range of branches means all revisions
+on the branches in that range.
+A branch followed by a
+.B .\&
+means the latest revision in that branch.
+A bare
+.B \-r
+with no
+.I revisions
+means the latest revision on the default branch, normally the trunk.
+.TP
+.BI \-s states
+prints information about revisions whose state attributes match one of the
+states given in the comma-separated list
+.IR states .
+.TP
+.BR \-w [\f2logins\fP]
+prints information about revisions checked in by users with
+login names appearing in the comma-separated list
+.IR logins .
+If
+.I logins
+is omitted, the user's login is assumed.
+.TP
+.B \-T
+This option has no effect;
+it is present for compatibility with other \*r commands.
+.TP
+.BI \-V
+Print \*r's version number.
+.TP
+.BI \-V n
+Emulate \*r version
+.I n
+when generating logs.
+See
+.BR co (1)
+for more.
+.TP
+.BI \-x "suffixes"
+Use
+.I suffixes
+to characterize \*r files.
+See
+.BR ci (1)
+for details.
+.PP
+.B rlog
+prints the intersection of the revisions selected with
+the options
+.BR \-d ,
+.BR \-l ,
+.BR \-s ,
+and
+.BR \-w ,
+intersected
+with the union of the revisions selected by
+.B \-b
+and
+.BR \-r .
+.TP
+.BI \-z zone
+specifies the date output format,
+and specifies the default time zone for
+.I date
+in the
+.BI \-d dates
+option.
+The
+.I zone
+should be empty, a numeric \*u offset, or the special string
+.B LT
+for local time.
+The default is an empty
+.IR zone ,
+which uses the traditional \*r format of \*u without any time zone indication
+and with slashes separating the parts of the date;
+otherwise, times are output in \*i 8601 format with time zone indication.
+For example, if local time is January 11, 1990, 8pm Pacific Standard Time,
+eight hours west of \*u,
+then the time is output as follows:
+.RS
+.LP
+.RS
+.nf
+.ta \w'\f3\-z+05:30\fP 'u +\w'\f31990-01-11 09:30:00+05:30\fP 'u
+.ne 4
+\f2option\fP \f2time output\fP
+\f3\-z\fP \f31990/01/12 04:00:00\fP \f2(default)\fP
+\f3\-zLT\fP \f31990-01-11 20:00:00\-08\fP
+\f3\-z+05:30\fP \f31990-01-12 09:30:00+05:30\fP
+.ta 4n +4n +4n +4n
+.fi
+.RE
+.SH EXAMPLES
+.LP
+.nf
+.B " rlog \-L \-R RCS/*"
+.B " rlog \-L \-h RCS/*"
+.B " rlog \-L \-l RCS/*"
+.B " rlog RCS/*"
+.fi
+.LP
+The first command prints the names of all \*r files in the subdirectory
+.B RCS
+that have locks. The second command prints the headers of those files,
+and the third prints the headers plus the log messages of the locked revisions.
+The last command prints complete information.
+.SH ENVIRONMENT
+.TP
+.B \s-1RCSINIT\s0
+options prepended to the argument list, separated by spaces.
+See
+.BR ci (1)
+for details.
+.SH DIAGNOSTICS
+The exit status is zero if and only if all operations were successful.
+.SH IDENTIFICATION
+Author: Walter F. Tichy.
+.br
+Manual Page Revision: \*(Rv; Release Date: \*(Dt.
+.br
+Copyright \(co 1982, 1988, 1989 Walter F. Tichy.
+.br
+Copyright \(co 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert.
+.SH "SEE ALSO"
+ci(1), co(1), ident(1), rcs(1), rcsdiff(1), rcsintro(1), rcsmerge(1),
+rcsfile(5)
+.br
+Walter F. Tichy,
+\*r\*-A System for Version Control,
+.I "Software\*-Practice & Experience"
+.BR 15 ,
+7 (July 1985), 637-654.
+.SH BUGS
+The separator for revision ranges in the
+.B \-r
+option used to be
+.B \-
+instead of
+.BR : ,
+but this leads to confusion when symbolic names contain
+.BR \- .
+For backwards compatibility
+.B "rlog \-r"
+still supports the old
+.B \-
+separator, but it warns about this obsolete use.
+.br
diff --git a/gnu/usr.bin/rcs/rlog/rlog.c b/gnu/usr.bin/rcs/rlog/rlog.c
new file mode 100644
index 0000000..f8872fe
--- /dev/null
+++ b/gnu/usr.bin/rcs/rlog/rlog.c
@@ -0,0 +1,1290 @@
+/* Print log messages and other information about RCS files. */
+
+/* Copyright 1982, 1988, 1989 Walter Tichy
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute 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.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING.
+If not, write to the Free Software Foundation,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+/*
+ * Revision 5.18 1995/06/16 06:19:24 eggert
+ * Update FSF address.
+ *
+ * Revision 5.17 1995/06/01 16:23:43 eggert
+ * (struct rcslockers): Renamed from `struct lockers'.
+ * (getnumericrev): Return error indication instead of ignoring errors.
+ * (main): Check it. Don't use dateform.
+ * (recentdate, extdate): cmpnum -> cmpdate
+ *
+ * Revision 5.16 1994/04/13 16:30:34 eggert
+ * Fix bug; `rlog -lxxx' inverted the sense of -l.
+ *
+ * Revision 5.15 1994/03/17 14:05:48 eggert
+ * -d'<DATE' now excludes DATE; the new syntax -d'<=DATE' includes it.
+ * Emulate -V4's white space generation more precisely.
+ * Work around SVR4 stdio performance bug. Remove lint.
+ *
+ * Revision 5.14 1993/11/09 17:40:15 eggert
+ * -V now prints version on stdout and exits.
+ *
+ * Revision 5.13 1993/11/03 17:42:27 eggert
+ * Add -N, -z. Ignore -T.
+ *
+ * Revision 5.12 1992/07/28 16:12:44 eggert
+ * Don't miss B.0 when handling branch B. Diagnose missing `,' in -r.
+ * Add -V. Avoid `unsigned'. Statement macro names now end in _.
+ *
+ * Revision 5.11 1992/01/24 18:44:19 eggert
+ * Don't duplicate unexpected_EOF's function. lint -> RCS_lint
+ *
+ * Revision 5.10 1992/01/06 02:42:34 eggert
+ * Update usage string.
+ * while (E) ; -> while (E) continue;
+ *
+ * Revision 5.9 1991/09/17 19:07:40 eggert
+ * Getscript() didn't uncache partial lines.
+ *
+ * Revision 5.8 1991/08/19 03:13:55 eggert
+ * Revision separator is `:', not `-'.
+ * Check for missing and duplicate logs. Tune.
+ * Permit log messages that do not end in newline (including empty logs).
+ *
+ * Revision 5.7 1991/04/21 11:58:31 eggert
+ * Add -x, RCSINIT, MS-DOS support.
+ *
+ * Revision 5.6 1991/02/26 17:07:17 eggert
+ * Survive RCS files with missing logs.
+ * strsave -> str_save (DG/UX name clash)
+ *
+ * Revision 5.5 1990/11/01 05:03:55 eggert
+ * Permit arbitrary data in logs and comment leaders.
+ *
+ * Revision 5.4 1990/10/04 06:30:22 eggert
+ * Accumulate exit status across files.
+ *
+ * Revision 5.3 1990/09/11 02:41:16 eggert
+ * Plug memory leak.
+ *
+ * Revision 5.2 1990/09/04 08:02:33 eggert
+ * Count RCS lines better.
+ *
+ * Revision 5.0 1990/08/22 08:13:48 eggert
+ * Remove compile-time limits; use malloc instead. Add setuid support.
+ * Switch to GMT.
+ * Report dates in long form, to warn about dates past 1999/12/31.
+ * Change "added/del" message to make room for the longer dates.
+ * Don't generate trailing white space. Add -V. Ansify and Posixate.
+ *
+ * Revision 4.7 89/05/01 15:13:48 narten
+ * changed copyright header to reflect current distribution rules
+ *
+ * Revision 4.6 88/08/09 19:13:28 eggert
+ * Check for memory exhaustion; don't access freed storage.
+ * Shrink stdio code size; remove lint.
+ *
+ * Revision 4.5 87/12/18 11:46:38 narten
+ * more lint cleanups (Guy Harris)
+ *
+ * Revision 4.4 87/10/18 10:41:12 narten
+ * Updating version numbers
+ * Changes relative to 1.1 actually relative to 4.2
+ *
+ * Revision 1.3 87/09/24 14:01:10 narten
+ * Sources now pass through lint (if you ignore printf/sprintf/fprintf
+ * warnings)
+ *
+ * Revision 1.2 87/03/27 14:22:45 jenkins
+ * Port to suns
+ *
+ * Revision 4.2 83/12/05 09:18:09 wft
+ * changed rewriteflag to external.
+ *
+ * Revision 4.1 83/05/11 16:16:55 wft
+ * Added -b, updated getnumericrev() accordingly.
+ * Replaced getpwuid() with getcaller().
+ *
+ * Revision 3.7 83/05/11 14:24:13 wft
+ * Added options -L and -R;
+ * Fixed selection bug with -l on multiple files.
+ * Fixed error on dates of the form -d'>date' (rewrote getdatepair()).
+ *
+ * Revision 3.6 82/12/24 15:57:53 wft
+ * shortened output format.
+ *
+ * Revision 3.5 82/12/08 21:45:26 wft
+ * removed call to checkaccesslist(); used DATEFORM to format all dates;
+ * removed unused variables.
+ *
+ * Revision 3.4 82/12/04 13:26:25 wft
+ * Replaced getdelta() with gettree(); removed updating of field lockedby.
+ *
+ * Revision 3.3 82/12/03 14:08:20 wft
+ * Replaced getlogin with getpwuid(), %02d with %.2d, fancydate with PRINTDATE.
+ * Fixed printing of nil, removed printing of Suffix,
+ * added shortcut if no revisions are printed, disambiguated struct members.
+ *
+ * Revision 3.2 82/10/18 21:09:06 wft
+ * call to curdir replaced with getfullRCSname(),
+ * fixed call to getlogin(), cosmetic changes on output,
+ * changed conflicting long identifiers.
+ *
+ * Revision 3.1 82/10/13 16:07:56 wft
+ * fixed type of variables receiving from getc() (char -> int).
+ */
+
+
+
+#include "rcsbase.h"
+
+struct rcslockers { /* lockers in locker option; stored */
+ char const * login; /* lockerlist */
+ struct rcslockers * lockerlink;
+ } ;
+
+struct stateattri { /* states in state option; stored in */
+ char const * status; /* statelist */
+ struct stateattri * nextstate;
+ } ;
+
+struct authors { /* login names in author option; */
+ char const * login; /* stored in authorlist */
+ struct authors * nextauthor;
+ } ;
+
+struct Revpairs{ /* revision or branch range in -r */
+ int numfld; /* option; stored in revlist */
+ char const * strtrev;
+ char const * endrev;
+ struct Revpairs * rnext;
+ } ;
+
+struct Datepairs{ /* date range in -d option; stored in */
+ struct Datepairs *dnext;
+ char strtdate[datesize]; /* duelst and datelist */
+ char enddate[datesize];
+ char ne_date; /* datelist only; distinguishes < from <= */
+ };
+
+static char extractdelta P((struct hshentry const*));
+static int checkrevpair P((char const*,char const*));
+static int extdate P((struct hshentry*));
+static int getnumericrev P((void));
+static struct hshentry const *readdeltalog P((void));
+static void cleanup P((void));
+static void exttree P((struct hshentry*));
+static void getauthor P((char*));
+static void getdatepair P((char*));
+static void getlocker P((char*));
+static void getrevpairs P((char*));
+static void getscript P((struct hshentry*));
+static void getstate P((char*));
+static void putabranch P((struct hshentry const*));
+static void putadelta P((struct hshentry const*,struct hshentry const*,int));
+static void putforest P((struct branchhead const*));
+static void putree P((struct hshentry const*));
+static void putrunk P((void));
+static void recentdate P((struct hshentry const*,struct Datepairs*));
+static void trunclocks P((void));
+
+static char const *insDelFormat;
+static int branchflag; /*set on -b */
+static int exitstatus;
+static int lockflag;
+static struct Datepairs *datelist, *duelst;
+static struct Revpairs *revlist, *Revlst;
+static struct authors *authorlist;
+static struct rcslockers *lockerlist;
+static struct stateattri *statelist;
+
+
+mainProg(rlogId, "rlog", "$FreeBSD$")
+{
+ static char const cmdusage[] =
+ "\nrlog usage: rlog -{bhLNRt} -v[string] -ddates -l[lockers] -r[revs] -sstates -Vn -w[logins] -xsuff -zzone file ...";
+
+ register FILE *out;
+ char *a, **newargv;
+ struct Datepairs *currdate;
+ char const *accessListString, *accessFormat;
+ char const *headFormat, *symbolFormat;
+ struct access const *curaccess;
+ struct assoc const *curassoc;
+ struct hshentry const *delta;
+ struct rcslock const *currlock;
+ int descflag, selectflag;
+ int onlylockflag; /* print only files with locks */
+ int onlyRCSflag; /* print only RCS pathname */
+ int pre5;
+ int shownames;
+ int revno;
+ int versionlist;
+ char *vstring;
+
+ descflag = selectflag = shownames = true;
+ versionlist = onlylockflag = onlyRCSflag = false;
+ vstring=0;
+ out = stdout;
+ suffixes = X_DEFAULT;
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ while (a = *++argv, 0<--argc && *a++=='-') {
+ switch (*a++) {
+
+ case 'L':
+ onlylockflag = true;
+ break;
+
+ case 'N':
+ shownames = false;
+ break;
+
+ case 'R':
+ onlyRCSflag =true;
+ break;
+
+ case 'l':
+ lockflag = true;
+ getlocker(a);
+ break;
+
+ case 'b':
+ branchflag = true;
+ break;
+
+ case 'r':
+ getrevpairs(a);
+ break;
+
+ case 'd':
+ getdatepair(a);
+ break;
+
+ case 's':
+ getstate(a);
+ break;
+
+ case 'w':
+ getauthor(a);
+ break;
+
+ case 'h':
+ descflag = false;
+ break;
+
+ case 't':
+ selectflag = false;
+ break;
+
+ case 'q':
+ /* This has no effect; it's here for consistency. */
+ quietflag = true;
+ break;
+
+ case 'x':
+ suffixes = a;
+ break;
+
+ case 'z':
+ zone_set(a);
+ break;
+
+ case 'T':
+ /* Ignore -T, so that RCSINIT can contain -T. */
+ if (*a)
+ goto unknown;
+ break;
+
+ case 'V':
+ setRCSversion(*argv);
+ break;
+
+ case 'v':
+ versionlist = true;
+ vstring = a;
+ break;
+
+ default:
+ unknown:
+ error("unknown option: %s%s", *argv, cmdusage);
+
+ };
+ } /* end of option processing */
+
+ if (! (descflag|selectflag)) {
+ warn("-t overrides -h.");
+ descflag = true;
+ }
+
+ pre5 = RCSversion < VERSION(5);
+ if (pre5) {
+ accessListString = "\naccess list: ";
+ accessFormat = " %s";
+ headFormat = "RCS file: %s; Working file: %s\nhead: %s%s\nbranch: %s%s\nlocks: ";
+ insDelFormat = " lines added/del: %ld/%ld";
+ symbolFormat = " %s: %s;";
+ } else {
+ accessListString = "\naccess list:";
+ accessFormat = "\n\t%s";
+ headFormat = "RCS file: %s\nWorking file: %s\nhead:%s%s\nbranch:%s%s\nlocks:%s";
+ insDelFormat = " lines: +%ld -%ld";
+ symbolFormat = "\n\t%s: %s";
+ }
+
+ /* Now handle all pathnames. */
+ if (nerror)
+ cleanup();
+ else if (argc < 1)
+ faterror("no input file%s", cmdusage);
+ else
+ for (; 0 < argc; cleanup(), ++argv, --argc) {
+ ffree();
+
+ if (pairnames(argc, argv, rcsreadopen, true, false) <= 0)
+ continue;
+
+ /*
+ * RCSname contains the name of the RCS file,
+ * and finptr the file descriptor;
+ * workname contains the name of the working file.
+ */
+
+ /* Keep only those locks given by -l. */
+ if (lockflag)
+ trunclocks();
+
+ /* do nothing if -L is given and there are no locks*/
+ if (onlylockflag && !Locks)
+ continue;
+
+ if ( versionlist ) {
+ gettree();
+ aprintf(out, "%s%s %s\n", vstring, workname, tiprev());
+ continue;
+ }
+
+ if ( onlyRCSflag ) {
+ aprintf(out, "%s\n", RCSname);
+ continue;
+ }
+
+ gettree();
+
+ if (!getnumericrev())
+ continue;
+
+ /*
+ * Output the first character with putc, not printf.
+ * Otherwise, an SVR4 stdio bug buffers output inefficiently.
+ */
+ aputc_('\n', out)
+
+ /* print RCS pathname, working pathname and optional
+ administrative information */
+ /* could use getfullRCSname() here, but that is very slow */
+ aprintf(out, headFormat, RCSname, workname,
+ Head ? " " : "", Head ? Head->num : "",
+ Dbranch ? " " : "", Dbranch ? Dbranch : "",
+ StrictLocks ? " strict" : ""
+ );
+ currlock = Locks;
+ while( currlock ) {
+ aprintf(out, symbolFormat, currlock->login,
+ currlock->delta->num);
+ currlock = currlock->nextlock;
+ }
+ if (StrictLocks && pre5)
+ aputs(" ; strict" + (Locks?3:0), out);
+
+ aputs(accessListString, out); /* print access list */
+ curaccess = AccessList;
+ while(curaccess) {
+ aprintf(out, accessFormat, curaccess->login);
+ curaccess = curaccess->nextaccess;
+ }
+
+ if (shownames) {
+ aputs("\nsymbolic names:", out); /* print symbolic names */
+ for (curassoc=Symbols; curassoc; curassoc=curassoc->nextassoc)
+ aprintf(out, symbolFormat, curassoc->symbol, curassoc->num);
+ }
+ if (pre5) {
+ aputs("\ncomment leader: \"", out);
+ awrite(Comment.string, Comment.size, out);
+ afputc('\"', out);
+ }
+ if (!pre5 || Expand != KEYVAL_EXPAND)
+ aprintf(out, "\nkeyword substitution: %s",
+ expand_names[Expand]
+ );
+
+ aprintf(out, "\ntotal revisions: %d", TotalDeltas);
+
+ revno = 0;
+
+ if (Head && selectflag & descflag) {
+
+ exttree(Head);
+
+ /* get most recently date of the dates pointed by duelst */
+ currdate = duelst;
+ while( currdate) {
+ VOID strcpy(currdate->strtdate, "0.0.0.0.0.0");
+ recentdate(Head, currdate);
+ currdate = currdate->dnext;
+ }
+
+ revno = extdate(Head);
+
+ aprintf(out, ";\tselected revisions: %d", revno);
+ }
+
+ afputc('\n',out);
+ if (descflag) {
+ aputs("description:\n", out);
+ getdesc(true);
+ }
+ if (revno) {
+ while (! (delta = readdeltalog())->selector || --revno)
+ continue;
+ if (delta->next && countnumflds(delta->num)==2)
+ /* Read through delta->next to get its insertlns. */
+ while (readdeltalog() != delta->next)
+ continue;
+ putrunk();
+ putree(Head);
+ }
+ aputs("----------------------------\n", out);
+ aputs("=============================================================================\n",out);
+ }
+ Ofclose(out);
+ exitmain(exitstatus);
+}
+
+ static void
+cleanup()
+{
+ if (nerror) exitstatus = EXIT_FAILURE;
+ Izclose(&finptr);
+}
+
+#if RCS_lint
+# define exiterr rlogExit
+#endif
+ void
+exiterr()
+{
+ _exit(EXIT_FAILURE);
+}
+
+
+
+ static void
+putrunk()
+/* function: print revisions chosen, which are in trunk */
+
+{
+ register struct hshentry const *ptr;
+
+ for (ptr = Head; ptr; ptr = ptr->next)
+ putadelta(ptr, ptr->next, true);
+}
+
+
+
+ static void
+putree(root)
+ struct hshentry const *root;
+/* function: print delta tree (not including trunk) in reverse
+ order on each branch */
+
+{
+ if (!root) return;
+
+ putree(root->next);
+
+ putforest(root->branches);
+}
+
+
+
+
+ static void
+putforest(branchroot)
+ struct branchhead const *branchroot;
+/* function: print branches that has the same direct ancestor */
+{
+ if (!branchroot) return;
+
+ putforest(branchroot->nextbranch);
+
+ putabranch(branchroot->hsh);
+ putree(branchroot->hsh);
+}
+
+
+
+
+ static void
+putabranch(root)
+ struct hshentry const *root;
+/* function : print one branch */
+
+{
+ if (!root) return;
+
+ putabranch(root->next);
+
+ putadelta(root, root, false);
+}
+
+
+
+
+
+ static void
+putadelta(node,editscript,trunk)
+ register struct hshentry const *node, *editscript;
+ int trunk;
+/* function: Print delta node if node->selector is set. */
+/* editscript indicates where the editscript is stored */
+/* trunk indicated whether this node is in trunk */
+{
+ static char emptych[] = EMPTYLOG;
+
+ register FILE *out;
+ char const *s;
+ size_t n;
+ struct branchhead const *newbranch;
+ struct buf branchnum;
+ char datebuf[datesize + zonelenmax];
+ int pre5 = RCSversion < VERSION(5);
+
+ if (!node->selector)
+ return;
+
+ out = stdout;
+ aprintf(out,
+ "----------------------------\nrevision %s%s",
+ node->num, pre5 ? " " : ""
+ );
+ if ( node->lockedby )
+ aprintf(out, pre5+"\tlocked by: %s;", node->lockedby);
+
+ aprintf(out, "\ndate: %s; author: %s; state: %s;",
+ date2str(node->date, datebuf),
+ node->author, node->state
+ );
+
+ if ( editscript )
+ if(trunk)
+ aprintf(out, insDelFormat,
+ editscript->deletelns, editscript->insertlns);
+ else
+ aprintf(out, insDelFormat,
+ editscript->insertlns, editscript->deletelns);
+
+ newbranch = node->branches;
+ if ( newbranch ) {
+ bufautobegin(&branchnum);
+ aputs("\nbranches:", out);
+ while( newbranch ) {
+ getbranchno(newbranch->hsh->num, &branchnum);
+ aprintf(out, " %s;", branchnum.string);
+ newbranch = newbranch->nextbranch;
+ }
+ bufautoend(&branchnum);
+ }
+
+ afputc('\n', out);
+ s = node->log.string;
+ if (!(n = node->log.size)) {
+ s = emptych;
+ n = sizeof(emptych)-1;
+ }
+ awrite(s, n, out);
+ if (s[n-1] != '\n')
+ afputc('\n', out);
+}
+
+
+ static struct hshentry const *
+readdeltalog()
+/* Function : get the log message and skip the text of a deltatext node.
+ * Return the delta found.
+ * Assumes the current lexeme is not yet in nexttok; does not
+ * advance nexttok.
+ */
+{
+ register struct hshentry * Delta;
+ struct buf logbuf;
+ struct cbuf cb;
+
+ if (eoflex())
+ fatserror("missing delta log");
+ nextlex();
+ if (!(Delta = getnum()))
+ fatserror("delta number corrupted");
+ getkeystring(Klog);
+ if (Delta->log.string)
+ fatserror("duplicate delta log");
+ bufautobegin(&logbuf);
+ cb = savestring(&logbuf);
+ Delta->log = bufremember(&logbuf, cb.size);
+
+ ignorephrases(Ktext);
+ getkeystring(Ktext);
+ Delta->insertlns = Delta->deletelns = 0;
+ if ( Delta != Head)
+ getscript(Delta);
+ else
+ readstring();
+ return Delta;
+}
+
+
+ static void
+getscript(Delta)
+struct hshentry * Delta;
+/* function: read edit script of Delta and count how many lines added */
+/* and deleted in the script */
+
+{
+ int ed; /* editor command */
+ declarecache;
+ register RILE *fin;
+ register int c;
+ register long i;
+ struct diffcmd dc;
+
+ fin = finptr;
+ setupcache(fin);
+ initdiffcmd(&dc);
+ while (0 <= (ed = getdiffcmd(fin,true,(FILE *)0,&dc)))
+ if (!ed)
+ Delta->deletelns += dc.nlines;
+ else {
+ /* skip scripted lines */
+ i = dc.nlines;
+ Delta->insertlns += i;
+ cache(fin);
+ do {
+ for (;;) {
+ cacheget_(c)
+ switch (c) {
+ default:
+ continue;
+ case SDELIM:
+ cacheget_(c)
+ if (c == SDELIM)
+ continue;
+ if (--i)
+ unexpected_EOF();
+ nextc = c;
+ uncache(fin);
+ return;
+ case '\n':
+ break;
+ }
+ break;
+ }
+ ++rcsline;
+ } while (--i);
+ uncache(fin);
+ }
+}
+
+
+
+
+
+
+
+ static void
+exttree(root)
+struct hshentry *root;
+/* function: select revisions , starting with root */
+
+{
+ struct branchhead const *newbranch;
+
+ if (!root) return;
+
+ root->selector = extractdelta(root);
+ root->log.string = 0;
+ exttree(root->next);
+
+ newbranch = root->branches;
+ while( newbranch ) {
+ exttree(newbranch->hsh);
+ newbranch = newbranch->nextbranch;
+ }
+}
+
+
+
+
+ static void
+getlocker(argv)
+char * argv;
+/* function : get the login names of lockers from command line */
+/* and store in lockerlist. */
+
+{
+ register char c;
+ struct rcslockers *newlocker;
+ argv--;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
+ if ( c == '\0') {
+ lockerlist = 0;
+ return;
+ }
+
+ while( c != '\0' ) {
+ newlocker = talloc(struct rcslockers);
+ newlocker->lockerlink = lockerlist;
+ newlocker->login = argv;
+ lockerlist = newlocker;
+ while ((c = *++argv) && c!=',' && c!=' ' && c!='\t' && c!='\n' && c!=';')
+ continue;
+ *argv = '\0';
+ if ( c == '\0' ) return;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
+ }
+}
+
+
+
+ static void
+getauthor(argv)
+char *argv;
+/* function: get the author's name from command line */
+/* and store in authorlist */
+
+{
+ register c;
+ struct authors * newauthor;
+
+ argv--;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
+ if ( c == '\0' ) {
+ authorlist = talloc(struct authors);
+ authorlist->login = getusername(false);
+ authorlist->nextauthor = 0;
+ return;
+ }
+
+ while( c != '\0' ) {
+ newauthor = talloc(struct authors);
+ newauthor->nextauthor = authorlist;
+ newauthor->login = argv;
+ authorlist = newauthor;
+ while ((c = *++argv) && c!=',' && c!=' ' && c!='\t' && c!='\n' && c!=';')
+ continue;
+ * argv = '\0';
+ if ( c == '\0') return;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
+ }
+}
+
+
+
+
+ static void
+getstate(argv)
+char * argv;
+/* function : get the states of revisions from command line */
+/* and store in statelist */
+
+{
+ register char c;
+ struct stateattri *newstate;
+
+ argv--;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
+ if ( c == '\0'){
+ error("missing state attributes after -s options");
+ return;
+ }
+
+ while( c != '\0' ) {
+ newstate = talloc(struct stateattri);
+ newstate->nextstate = statelist;
+ newstate->status = argv;
+ statelist = newstate;
+ while ((c = *++argv) && c!=',' && c!=' ' && c!='\t' && c!='\n' && c!=';')
+ continue;
+ *argv = '\0';
+ if ( c == '\0' ) return;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
+ }
+}
+
+
+
+ static void
+trunclocks()
+/* Function: Truncate the list of locks to those that are held by the */
+/* id's on lockerlist. Do not truncate if lockerlist empty. */
+
+{
+ struct rcslockers const *plocker;
+ struct rcslock *p, **pp;
+
+ if (!lockerlist) return;
+
+ /* shorten Locks to those contained in lockerlist */
+ for (pp = &Locks; (p = *pp); )
+ for (plocker = lockerlist; ; )
+ if (strcmp(plocker->login, p->login) == 0) {
+ pp = &p->nextlock;
+ break;
+ } else if (!(plocker = plocker->lockerlink)) {
+ *pp = p->nextlock;
+ break;
+ }
+}
+
+
+
+ static void
+recentdate(root, pd)
+ struct hshentry const *root;
+ struct Datepairs *pd;
+/* function: Finds the delta that is closest to the cutoff date given by */
+/* pd among the revisions selected by exttree. */
+/* Successively narrows down the interval given by pd, */
+/* and sets the strtdate of pd to the date of the selected delta */
+{
+ struct branchhead const *newbranch;
+
+ if (!root) return;
+ if (root->selector) {
+ if ( cmpdate(root->date, pd->strtdate) >= 0 &&
+ cmpdate(root->date, pd->enddate) <= 0)
+ VOID strcpy(pd->strtdate, root->date);
+ }
+
+ recentdate(root->next, pd);
+ newbranch = root->branches;
+ while( newbranch) {
+ recentdate(newbranch->hsh, pd);
+ newbranch = newbranch->nextbranch;
+ }
+}
+
+
+
+
+
+
+ static int
+extdate(root)
+struct hshentry * root;
+/* function: select revisions which are in the date range specified */
+/* in duelst and datelist, start at root */
+/* Yield number of revisions selected, including those already selected. */
+{
+ struct branchhead const *newbranch;
+ struct Datepairs const *pdate;
+ int revno, ne;
+
+ if (!root)
+ return 0;
+
+ if ( datelist || duelst) {
+ pdate = datelist;
+ while( pdate ) {
+ ne = pdate->ne_date;
+ if (
+ (!pdate->strtdate[0]
+ || ne <= cmpdate(root->date, pdate->strtdate))
+ &&
+ (!pdate->enddate[0]
+ || ne <= cmpdate(pdate->enddate, root->date))
+ )
+ break;
+ pdate = pdate->dnext;
+ }
+ if (!pdate) {
+ pdate = duelst;
+ for (;;) {
+ if (!pdate) {
+ root->selector = false;
+ break;
+ }
+ if (cmpdate(root->date, pdate->strtdate) == 0)
+ break;
+ pdate = pdate->dnext;
+ }
+ }
+ }
+ revno = root->selector + extdate(root->next);
+
+ newbranch = root->branches;
+ while( newbranch ) {
+ revno += extdate(newbranch->hsh);
+ newbranch = newbranch->nextbranch;
+ }
+ return revno;
+}
+
+
+
+ static char
+extractdelta(pdelta)
+ struct hshentry const *pdelta;
+/* function: compare information of pdelta to the authorlist, lockerlist,*/
+/* statelist, revlist and yield true if pdelta is selected. */
+
+{
+ struct rcslock const *plock;
+ struct stateattri const *pstate;
+ struct authors const *pauthor;
+ struct Revpairs const *prevision;
+ int length;
+
+ if ((pauthor = authorlist)) /* only certain authors wanted */
+ while (strcmp(pauthor->login, pdelta->author) != 0)
+ if (!(pauthor = pauthor->nextauthor))
+ return false;
+ if ((pstate = statelist)) /* only certain states wanted */
+ while (strcmp(pstate->status, pdelta->state) != 0)
+ if (!(pstate = pstate->nextstate))
+ return false;
+ if (lockflag) /* only locked revisions wanted */
+ for (plock = Locks; ; plock = plock->nextlock)
+ if (!plock)
+ return false;
+ else if (plock->delta == pdelta)
+ break;
+ if ((prevision = Revlst)) /* only certain revs or branches wanted */
+ for (;;) {
+ length = prevision->numfld;
+ if (
+ countnumflds(pdelta->num) == length+(length&1) &&
+ 0 <= compartial(pdelta->num, prevision->strtrev, length) &&
+ 0 <= compartial(prevision->endrev, pdelta->num, length)
+ )
+ break;
+ if (!(prevision = prevision->rnext))
+ return false;
+ }
+ return true;
+}
+
+
+
+ static void
+getdatepair(argv)
+ char * argv;
+/* function: get time range from command line and store in datelist if */
+/* a time range specified or in duelst if a time spot specified */
+
+{
+ register char c;
+ struct Datepairs * nextdate;
+ char const * rawdate;
+ int switchflag;
+
+ argv--;
+ while ((c = *++argv)==',' || c==' ' || c=='\t' || c=='\n' || c==';')
+ continue;
+ if ( c == '\0' ) {
+ error("missing date/time after -d");
+ return;
+ }
+
+ while( c != '\0' ) {
+ switchflag = false;
+ nextdate = talloc(struct Datepairs);
+ if ( c == '<' ) { /* case: -d <date */
+ c = *++argv;
+ if (!(nextdate->ne_date = c!='='))
+ c = *++argv;
+ (nextdate->strtdate)[0] = '\0';
+ } else if (c == '>') { /* case: -d'>date' */
+ c = *++argv;
+ if (!(nextdate->ne_date = c!='='))
+ c = *++argv;
+ (nextdate->enddate)[0] = '\0';
+ switchflag = true;
+ } else {
+ rawdate = argv;
+ while( c != '<' && c != '>' && c != ';' && c != '\0')
+ c = *++argv;
+ *argv = '\0';
+ if ( c == '>' ) switchflag=true;
+ str2date(rawdate,
+ switchflag ? nextdate->enddate : nextdate->strtdate);
+ if ( c == ';' || c == '\0') { /* case: -d date */
+ VOID strcpy(nextdate->enddate,nextdate->strtdate);
+ nextdate->dnext = duelst;
+ duelst = nextdate;
+ goto end;
+ } else {
+ /* case: -d date< or -d date>; see switchflag */
+ int eq = argv[1]=='=';
+ nextdate->ne_date = !eq;
+ argv += eq;
+ while ((c = *++argv) == ' ' || c=='\t' || c=='\n')
+ continue;
+ if ( c == ';' || c == '\0') {
+ /* second date missing */
+ if (switchflag)
+ *nextdate->strtdate= '\0';
+ else
+ *nextdate->enddate= '\0';
+ nextdate->dnext = datelist;
+ datelist = nextdate;
+ goto end;
+ }
+ }
+ }
+ rawdate = argv;
+ while( c != '>' && c != '<' && c != ';' && c != '\0')
+ c = *++argv;
+ *argv = '\0';
+ str2date(rawdate,
+ switchflag ? nextdate->strtdate : nextdate->enddate);
+ nextdate->dnext = datelist;
+ datelist = nextdate;
+ end:
+ if (RCSversion < VERSION(5))
+ nextdate->ne_date = 0;
+ if ( c == '\0') return;
+ while ((c = *++argv) == ';' || c == ' ' || c == '\t' || c =='\n')
+ continue;
+ }
+}
+
+
+
+ static int
+getnumericrev()
+/* function: get the numeric name of revisions which stored in revlist */
+/* and then stored the numeric names in Revlst */
+/* if branchflag, also add default branch */
+
+{
+ struct Revpairs * ptr, *pt;
+ int n;
+ struct buf s, e;
+ char const *lrev;
+ struct buf const *rstart, *rend;
+
+ Revlst = 0;
+ ptr = revlist;
+ bufautobegin(&s);
+ bufautobegin(&e);
+ while( ptr ) {
+ n = 0;
+ rstart = &s;
+ rend = &e;
+
+ switch (ptr->numfld) {
+
+ case 1: /* -rREV */
+ if (!expandsym(ptr->strtrev, &s))
+ goto freebufs;
+ rend = &s;
+ n = countnumflds(s.string);
+ if (!n && (lrev = tiprev())) {
+ bufscpy(&s, lrev);
+ n = countnumflds(lrev);
+ }
+ break;
+
+ case 2: /* -rREV: */
+ if (!expandsym(ptr->strtrev, &s))
+ goto freebufs;
+ bufscpy(&e, s.string);
+ n = countnumflds(s.string);
+ (n<2 ? e.string : strrchr(e.string,'.'))[0] = 0;
+ break;
+
+ case 3: /* -r:REV */
+ if (!expandsym(ptr->endrev, &e))
+ goto freebufs;
+ if ((n = countnumflds(e.string)) < 2)
+ bufscpy(&s, ".0");
+ else {
+ bufscpy(&s, e.string);
+ VOID strcpy(strrchr(s.string,'.'), ".0");
+ }
+ break;
+
+ default: /* -rREV1:REV2 */
+ if (!(
+ expandsym(ptr->strtrev, &s)
+ && expandsym(ptr->endrev, &e)
+ && checkrevpair(s.string, e.string)
+ ))
+ goto freebufs;
+ n = countnumflds(s.string);
+ /* Swap if out of order. */
+ if (compartial(s.string,e.string,n) > 0) {
+ rstart = &e;
+ rend = &s;
+ }
+ break;
+ }
+
+ if (n) {
+ pt = ftalloc(struct Revpairs);
+ pt->numfld = n;
+ pt->strtrev = fstr_save(rstart->string);
+ pt->endrev = fstr_save(rend->string);
+ pt->rnext = Revlst;
+ Revlst = pt;
+ }
+ ptr = ptr->rnext;
+ }
+ /* Now take care of branchflag */
+ if (branchflag && (Dbranch||Head)) {
+ pt = ftalloc(struct Revpairs);
+ pt->strtrev = pt->endrev =
+ Dbranch ? Dbranch : fstr_save(partialno(&s,Head->num,1));
+ pt->rnext=Revlst; Revlst=pt;
+ pt->numfld = countnumflds(pt->strtrev);
+ }
+
+ freebufs:
+ bufautoend(&s);
+ bufautoend(&e);
+ return !ptr;
+}
+
+
+
+ static int
+checkrevpair(num1,num2)
+ char const *num1, *num2;
+/* function: check whether num1, num2 are legal pair,i.e.
+ only the last field are different and have same number of
+ fields( if length <= 2, may be different if first field) */
+
+{
+ int length = countnumflds(num1);
+
+ if (
+ countnumflds(num2) != length
+ || (2 < length && compartial(num1, num2, length-1) != 0)
+ ) {
+ rcserror("invalid branch or revision pair %s : %s", num1, num2);
+ return false;
+ }
+
+ return true;
+}
+
+
+
+ static void
+getrevpairs(argv)
+register char * argv;
+/* function: get revision or branch range from command line, and */
+/* store in revlist */
+
+{
+ register char c;
+ struct Revpairs * nextrevpair;
+ int separator;
+
+ c = *argv;
+
+ /* Support old ambiguous '-' syntax; this will go away. */
+ if (strchr(argv,':'))
+ separator = ':';
+ else {
+ if (strchr(argv,'-') && VERSION(5) <= RCSversion)
+ warn("`-' is obsolete in `-r%s'; use `:' instead", argv);
+ separator = '-';
+ }
+
+ for (;;) {
+ while (c==' ' || c=='\t' || c=='\n')
+ c = *++argv;
+ nextrevpair = talloc(struct Revpairs);
+ nextrevpair->rnext = revlist;
+ revlist = nextrevpair;
+ nextrevpair->numfld = 1;
+ nextrevpair->strtrev = argv;
+ for (;; c = *++argv) {
+ switch (c) {
+ default:
+ continue;
+ case '\0': case ' ': case '\t': case '\n':
+ case ',': case ';':
+ break;
+ case ':': case '-':
+ if (c == separator)
+ break;
+ continue;
+ }
+ break;
+ }
+ *argv = '\0';
+ while (c==' ' || c=='\t' || c=='\n')
+ c = *++argv;
+ if (c == separator) {
+ while ((c = *++argv) == ' ' || c == '\t' || c =='\n')
+ continue;
+ nextrevpair->endrev = argv;
+ for (;; c = *++argv) {
+ switch (c) {
+ default:
+ continue;
+ case '\0': case ' ': case '\t': case '\n':
+ case ',': case ';':
+ break;
+ case ':': case '-':
+ if (c == separator)
+ break;
+ continue;
+ }
+ break;
+ }
+ *argv = '\0';
+ while (c==' ' || c=='\t' || c =='\n')
+ c = *++argv;
+ nextrevpair->numfld =
+ !nextrevpair->endrev[0] ? 2 /* -rREV: */ :
+ !nextrevpair->strtrev[0] ? 3 /* -r:REV */ :
+ 4 /* -rREV1:REV2 */;
+ }
+ if (!c)
+ break;
+ else if (c==',' || c==';')
+ c = *++argv;
+ else
+ error("missing `,' near `%c%s'", c, argv+1);
+ }
+}
diff --git a/gnu/usr.bin/sdiff/Makefile b/gnu/usr.bin/sdiff/Makefile
new file mode 100644
index 0000000..2312bb2
--- /dev/null
+++ b/gnu/usr.bin/sdiff/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../contrib/diff
+
+PROG= sdiff
+SRCS= sdiff.c getopt.c getopt1.c version.c
+
+# Important for ctype macros!
+CFLAGS+=-funsigned-char
+
+CFLAGS+=-I${.CURDIR}/../../../contrib/diff
+CFLAGS+=-DHAVE_CONFIG_H
+CFLAGS+=-DDIFF_PROGRAM=\"/usr/bin/diff\"
+CFLAGS+=-DDEFAULT_EDITOR_PROGRAM=\"/usr/bin/vi\"
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/sdiff/sdiff.1 b/gnu/usr.bin/sdiff/sdiff.1
new file mode 100644
index 0000000..8b7e88c
--- /dev/null
+++ b/gnu/usr.bin/sdiff/sdiff.1
@@ -0,0 +1,198 @@
+.TH SDIFF 1 "22sep1993" "GNU Tools" "GNU Tools"
+.SH NAME
+sdiff \- find differences between two files and merge interactively
+.SH SYNOPSIS
+.B sdiff
+.B -o
+outfile [options] from-file to-file
+.SH DESCRIPTION
+The
+.I sdiff
+command merges two files and interactively outputs the
+results to
+.IR outfile .
+
+If
+.I from-file
+is a directory and
+.I to-file
+is not,
+.I sdiff
+compares the file in
+.I from-file
+whose file name is that of
+.IR to-file ,
+and vice versa.
+.I from-file
+and
+.I to-file
+may not both be
+directories.
+
+.I sdiff
+options begin with
+.BR \- ,
+so normally
+.I from-file
+and
+.I to-file
+may not begin with
+.BR \- .
+However,
+.B \-\-
+as an
+argument by itself treats the remaining arguments as file names even if
+they begin with
+.BR \- .
+You may not use
+.B \-
+as an input file.
+
+.I sdiff
+without
+.B \-o
+(or
+.BR \-\-output )
+produces a
+side-by-side difference. This usage is obsolete; use
+.B "diff \-\-side\-by\-side"
+instead.
+.SS Options
+Below is a summary of all of the options that GNU
+.I sdiff
+accepts.
+Each option has two equivalent names, one of which is a single
+letter preceded by
+.BR \- ,
+and the other of which is a long name
+preceded by
+.BR \-\- .
+Multiple single letter options (unless they take
+an argument) can be combined into a single command line argument. Long
+named options can be abbreviated to any unique prefix of their name.
+.TP
+.B \-a
+Treat all files as text and compare them line-by-line, even if they
+do not appear to be text.
+.TP
+.B \-b
+Ignore changes in amount of white space.
+.TP
+.B \-B
+Ignore changes that just insert or delete blank lines.
+.TP
+.B \-d
+Change the algorithm to perhaps find a smaller set of changes. This
+makes
+.I sdiff
+slower (sometimes much slower).
+.TP
+.B \-H
+Use heuristics to speed handling of large files that have numerous
+scattered small changes.
+.TP
+.B \-\-expand\-tabs
+Expand tabs to spaces in the output, to preserve the alignment of tabs
+in the input files.
+.TP
+.B \-i
+Ignore changes in case; consider upper- and lower-case to be the same.
+.TP
+.BI "\-I " regexp
+Ignore changes that just insert or delete lines that match
+.IR regexp .
+.TP
+.B \-\-ignore\-all\-space
+Ignore white space when comparing lines.
+.TP
+.B \-\-ignore\-blank\-lines
+Ignore changes that just insert or delete blank lines.
+.TP
+.B \-\-ignore\-case
+Ignore changes in case; consider upper- and lower-case to be the same.
+.TP
+.BI \-\-ignore\-matching\-lines= regexp
+Ignore changes that just insert or delete lines that match
+.IR regexp .
+.TP
+.B \-\-ignore\-space\-change
+Ignore changes in amount of white space.
+.TP
+.B \-l
+.br
+.ns
+.TP
+.B \-\-left\-column
+Print only the left column of two common lines.
+.TP
+.B \-\-minimal
+Change the algorithm to perhaps find a smaller set of changes. This
+makes
+.I sdiff
+slower (sometimes much slower).
+.TP
+.BI "\-o " file
+.br
+.ns
+.TP
+.BI \-\-output= file
+Put merged output into
+.IR file .
+This option is required for merging.
+.TP
+.B \-s
+.br
+.ns
+.TP
+.B \-\-suppress\-common\-lines
+Do not print common lines.
+.TP
+.B \-\-speed\-large\-files
+Use heuristics to speed handling of large files that have numerous
+scattered small changes.
+.TP
+.B \-t
+Expand tabs to spaces in the output, to preserve the alignment of tabs
+in the input files.
+.TP
+.B \-\-text
+Treat all files as text and compare them line-by-line, even if they
+do not appear to be text.
+.TP
+.B \-v
+.br
+.ns
+.TP
+.B \-\-version
+Output the version number of
+.IR sdiff .
+.TP
+.BI "\-w " columns
+.br
+.ns
+.TP
+.BI \-\-width= columns
+Use an output width of
+.IR columns .
+Note that for historical reasons, this option is
+.B \-W
+in
+.IR diff ,
+.B \-w
+in
+.IR sdiff .
+.TP
+.B \-W
+Ignore horizontal white space when comparing lines.
+Note that for historical reasons, this option is
+.B \-w
+in
+.IR diff ,
+.B \-W
+in
+.IR sdiff .
+.SH SEE ALSO
+cmp(1), comm(1), diff(1), diff3(1).
+.SH DIAGNOSTICS
+An exit status of 0 means no differences were found, 1 means some
+differences were found, and 2 means trouble.
diff --git a/gnu/usr.bin/send-pr/COPYING b/gnu/usr.bin/send-pr/COPYING
new file mode 100644
index 0000000..515b6d3
--- /dev/null
+++ b/gnu/usr.bin/send-pr/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+he GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/send-pr/Makefile b/gnu/usr.bin/send-pr/Makefile
new file mode 100644
index 0000000..55aa5e6
--- /dev/null
+++ b/gnu/usr.bin/send-pr/Makefile
@@ -0,0 +1,35 @@
+# $FreeBSD$
+#
+# Makefile for building a standalone send-pr.
+#
+
+SCRIPTS= send-pr
+MAN= send-pr.1
+SUBMITTERS= current-users
+RELEASE= `uname -rsm`
+RELEASE_EV!= uname -rsm
+CLEANFILES+= send-pr send-pr.el
+
+SUBDIR+= doc
+
+LINKS= ${BINDIR}/send-pr ${BINDIR}/sendbug
+MLINKS= send-pr.1 sendbug.1
+
+send-pr: send-pr.sh Makefile
+ sed -e 's,@DATADIR@,/etc,g' \
+ -e 's/@DEFAULT_RELEASE@/$(RELEASE)/g' \
+ -e 's/^SUBMITTER=.*/SUBMITTER=$(SUBMITTERS)/' \
+ ${.ALLSRC:N*Makefile} > ${.TARGET}
+
+send-pr.el: send-pr-el.in Makefile
+ sed -e 's,@DATADIR@,/etc,g' \
+ -e 's/@DEFAULT_RELEASE@/$(RELEASE_EV)/g' \
+ -e 's/"unknown"/"$(SUBMITTERS)"/g' \
+ ${.ALLSRC:N*Makefile} > ${.TARGET}
+
+# called from /usr/src/etc/Makefile
+etc-gnats-freefall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 0644 \
+ ${.CURDIR}/categories ${DESTDIR}/etc/gnats/freefall
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/send-pr/README b/gnu/usr.bin/send-pr/README
new file mode 100644
index 0000000..b479179
--- /dev/null
+++ b/gnu/usr.bin/send-pr/README
@@ -0,0 +1,43 @@
+ send-pr - sends bug reports to a central support site
+
+`send-pr' uses electronic mail to submit support questions and
+software bugs to a central site. No piece of software is perfect, and
+software organizations understand this `send-pr' is designed to allow
+users who have problems to submit reports of these problems to sites
+responsible for supporting the software in question, in a defined form
+which can be read by an electronically managed database.
+
+`send-pr' is part of a suite of programs known collectively as GNATS,
+an acronym for Problem Report Management System. GNATS consists of
+several programs which, used in concert, formulate and partially
+administer a database of Problem Reports, or PRs, at a central support
+site. A PR goes through several states in its lifetime; GNATS tracks
+the PR and all information associated with it through each state and
+finally acts as an archive for PRs which have been resolved.
+
+The same engine can be used to submit bugs to any number of support
+sites by setting up aliases for each of them; `send-pr' error-checks
+each PR as it is sent to be sure that the category specified matches a
+category supported by the site in question.
+
+`send-pr' invokes an editor on a problem report template (after trying
+to fill in some fields with reasonable default values). When you exit
+the editor, `send-pr' sends the completed form to the support site.
+At the support site, the PR is assigned a unique number and is stored
+in the GNATS database according to its category and customer-id. GNATS
+automatically replies with an acknowledgement, citing the category and
+the PR number.
+
+See the Texinfo file `send-pr.texi' or the Info file `send-pr.info'
+for detailed installation and usage information.
+
+See the file MANIFEST for a list of the files which should have
+accompanied this distribution.
+
+See `send-pr.texi', `send-pr.info', or the file INSTALL for the
+installation procedure for `send-pr'.
+
+
+Copyright (c) 1993, Free Software Foundation, Inc.
+See the file COPYING for copyright information concerning this
+distribution and all its components.
diff --git a/gnu/usr.bin/send-pr/categories b/gnu/usr.bin/send-pr/categories
new file mode 100644
index 0000000..f873dea
--- /dev/null
+++ b/gnu/usr.bin/send-pr/categories
@@ -0,0 +1,16 @@
+# $FreeBSD$
+advocacy
+alpha
+bin
+conf
+docs
+gnu
+i386
+ia64
+kern
+misc
+ports
+powerpc
+sparc64
+standards
+www
diff --git a/gnu/usr.bin/send-pr/doc/Makefile b/gnu/usr.bin/send-pr/doc/Makefile
new file mode 100644
index 0000000..1de7064
--- /dev/null
+++ b/gnu/usr.bin/send-pr/doc/Makefile
@@ -0,0 +1,4 @@
+INFO = send-pr
+INFOSECTION="System Utilities"
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/send-pr/doc/categ.texi b/gnu/usr.bin/send-pr/doc/categ.texi
new file mode 100644
index 0000000..fe84918
--- /dev/null
+++ b/gnu/usr.bin/send-pr/doc/categ.texi
@@ -0,0 +1,125 @@
+@c $FreeBSD$
+
+@node Valid Categories
+@unnumberedsec Valid Categories
+@cindex valid categories
+@cindex example of a list of valid categories
+
+@table @code
+@item bfd
+@sc{gnu} binary file descriptor library.
+
+@item bifrabulator
+This one doesn't actually exist.
+
+@item binutils
+@sc{gnu} utilities for binary files (@code{ar}, @code{nm}, @code{size}@dots{}).
+
+@item bison
+@sc{gnu} parser generator.
+
+@item byacc
+Free parser generator.
+
+@item config
+Cygnus Solutions Software configuration and installation.
+
+@item cvs
+Concurrent Version System.
+
+@item diff
+@sc{gnu} @code{diff} program.
+
+@item doc
+Documentation and manuals.
+
+@item emacs
+@sc{gnu} Emacs editor and related functions.
+
+@item flex
+@sc{gnu} lexical analyzer.
+
+@item g++
+@sc{gnu} C++ compiler.
+
+@item gas
+@sc{gnu} assembler.
+
+@item gcc
+@sc{gnu} C compiler.
+
+@item gdb
+@sc{gnu} source code debugger.
+
+@item glob
+The filename globbing functions.
+
+@item gprof
+@sc{gnu} profiler.
+
+@item grep
+@sc{gnu} @code{grep} program.
+
+@item info
+@sc{gnu} @code{info} hypertext reader.
+
+@item ispell
+@sc{gnu} spelling checker.
+
+@item kerberos
+Kerberos authentication system.
+
+@item ld
+@sc{gnu} linker.
+
+@item libc
+Cygnus Solutions C Support Library.
+
+@item libg++
+@sc{gnu} C++ class library.
+
+@item libiberty
+@sc{gnu} @samp{libiberty} library.
+
+@item libm
+Cygnus Solutions C Math Library.
+
+@item make
+@sc{gnu} @code{make} program.
+
+@item makeinfo
+@sc{gnu} utility to build Info files from Texinfo documents.
+
+@item mas
+@sc{gnu} Motorola syntax assembler.
+
+@item newlib
+Cygnus Solutions C Support and Math Libraries.
+
+@item patch
+@sc{gnu} bug patch program.
+
+@item gnats
+@sc{gnu} Problem Report Management System.
+
+@item rcs
+Revision Control System.
+
+@item readline
+@sc{gnu} @code{readline} library.
+
+@item send-pr
+@sc{gnu} Problem Report submitting program.
+
+@item test
+Category to use when testing @code{send-pr}.
+
+@item texindex
+@sc{gnu} documentation indexing utility.
+
+@item texinfo
+@sc{gnu} documentation macros.
+
+@item other
+Anything which is not covered by the above categories.
+@end table
diff --git a/gnu/usr.bin/send-pr/doc/fields.texi b/gnu/usr.bin/send-pr/doc/fields.texi
new file mode 100644
index 0000000..a9bb65e
--- /dev/null
+++ b/gnu/usr.bin/send-pr/doc/fields.texi
@@ -0,0 +1,522 @@
+@c $FreeBSD$
+
+@node Fields
+@section Problem Report format
+@cindex Problem Report format
+@cindex format
+@cindex database similarities
+@cindex fields
+
+The format of a PR is designed to reflect the nature of @sc{gnats} as a
+database. Information is arranged into @dfn{fields}, and kept in
+individual records (Problem Reports).
+
+A Problem Report contains two different types of fields: @dfn{Mail
+Header} fields, which are used by the mail handler for delivery, and
+@dfn{Problem Report} fields, which contain information relevant to the
+Problem Report and its submitter. A Problem Report is essentially a
+specially formatted electronic mail message.
+
+Problem Report fields are denoted by a keyword which begins with
+@samp{>} and ends with @samp{:}, as in @samp{>Confidential:}. Fields
+belong to one of three data types:
+
+@table @asis
+@cindex Problem Report data types
+@cindex @emph{Enumerated} data types
+@item @sc{Enumerated}
+One of a specific set of values, which vary according to the field. The
+value for each keyword must be on the same line as the keyword. These
+values are not configurable (yet).
+
+@ifset SENDPR
+For each @sc{Enumerated} keyword, the possible choices are listed in the
+@code{send-pr} template as a comment.
+@end ifset
+The following fields are @sc{Enumerated} format; see the descriptions of
+fields below for explanations of each field in detail:
+
+@smallexample
+@group
+>Confidential: >Severity: >Priority:
+>Class: >State: >Number:
+@end group
+@end smallexample
+
+@cindex @emph{Text} data types
+@item @sc{Text}
+One single line of text which must begin and end on the same line (i.e.,
+before a newline) as the keyword. See the descriptions of fields below
+for explanations of each field in detail. The following fields are
+@sc{Text} format:
+
+@smallexample
+@group
+>Submitter-Id: >Originator: >Synopsis:
+>Category: >Release: >Responsible:
+>Arrival-Date:
+@end group
+@end smallexample
+
+@cindex @emph{MultiText} data types
+@item @sc{MultiText}
+Text of any length may occur in this field. @sc{MultiText} may span
+multiple lines and may also include blank lines. A @sc{MultiText} field
+ends only when another keyword appears. See the descriptions of fields
+below for explanations of each field in detail.
+
+The following fields are @sc{MultiText} format:
+
+@smallexample
+@group
+>Organization: >Environment: >Description:
+>How-To-Repeat: >Fix: >Audit-Trail:
+>Unformatted:
+@end group
+@end smallexample
+
+@end table
+
+@ifclear SENDPR
+@subheading Example Problem Report
+@end ifclear
+
+The following is an example Problem Report. Mail headers are at the
+top, followed by @sc{gnats} fields, which begin with @samp{>} and end
+with @samp{:}. The @samp{Subject:} line in the mail header and the
+@samp{>Synopsis:} field are usually duplicates of each other.
+
+@cindex sample Problem Report
+@cindex example Problem Report
+@cindex Problem Report template
+@cartouche
+@smallexample
+@group
+Message-Id: @var{message-id}
+Date: @var{date}
+From: @var{address}
+Reply-To: @var{address}
+To: @var{bug-address}
+Subject: @var{subject}
+
+>Number: @var{gnats-id}
+>Category: @var{category}
+>Synopsis: @var{synopsis}
+>Confidential: yes @emph{or} no
+>Severity: critical, serious, @emph{or} non-critical
+>Priority: high, medium @emph{or} low
+>Responsible: @var{responsible}
+>State: open, analyzed, suspended, feedback, @emph{or} closed
+>Class: sw-bug, doc-bug, change-request, support,
+@ifset SENDPR
+@emph{or} duplicate
+@end ifset
+@ifclear SENDPR
+duplicate, @emph{or} mistaken
+@end ifclear
+>Submitter-Id: @var{submitter-id}
+>Arrival-Date: @var{date}
+>Originator: @var{name}
+>Organization: @var{organization}
+>Release: @var{release}
+>Environment:
+ @var{environment}
+>Description:
+ @var{description}
+>How-To-Repeat:
+ @var{how-to-repeat}
+>Fix:
+ @var{fix}
+>Audit-Trail:
+@var{appended-messages@dots{}}
+State-Changed-From-To: @var{from}-@var{to}
+State-Changed-When: @var{date}
+State-Changed-Why:
+ @var{reason}
+Responsible-Changed-From-To: @var{from}-@var{to}
+Responsible-Changed-When: @var{date}
+Responsible-Changed-Why:
+ @var{reason}
+>Unformatted:
+ @var{miscellaneous}
+@end group
+@end smallexample
+@end cartouche
+
+@menu
+* Mail header fields::
+* Problem Report fields::
+@end menu
+
+@c ----------------------
+@node Mail header fields
+@subsection Mail header fields
+@cindex mail header fields
+@cindex Internet standard RFC-822
+
+A Problem Report may contain any mail header field described in the
+Internet standard RFC-822. However, only the fields which identify the
+sender and the subject are required by @code{send-pr}:
+
+@table @code
+@cindex @code{To:} header
+@item To:
+The preconfigured mail address for the Support Site where the PR is to
+be sent, automatically supplied by @code{send-pr}.
+
+@cindex @code{Subject:} header
+@item Subject:
+A terse description of the problem. This field normally contains the
+same information as the @samp{>Synopsis:} field.
+
+@cindex @code{From:} header
+@item From:
+Usually supplied automatically by the originator's mailer; should
+contain the originator's electronic mail address.
+
+@cindex @code{Reply-To:} header
+@item Reply-To:
+A return address to which electronic replies can be sent; in most cases,
+the same address as the @code{From:} field.
+@end table
+
+@ifclear SENDPR
+@cindex @code{Received-By:} headers
+One of the configurable options for @sc{gnats} is whether or not to
+retain @w{@samp{Received-By:}} headers, which often consume a lot of
+space and are not often used. @xref{Local configuration,,Changing your
+local configuration}.
+@end ifclear
+
+@c ----------------------
+@node Problem Report fields
+@subsection Problem Report fields
+@cindex GNATS database fields
+@cindex field format
+
+@c FIXME - this node is loooooooooooooooong...
+
+@subheading Field descriptions
+
+The following fields are present whenever a PR is submitted via the
+program @code{send-pr}. @sc{gnats} adds additional fields when the PR
+arrives at the Support Site; explanations of them follow this list.
+
+@cindex fields - list
+@cindex GNATS fields - list
+@table @code
+@cindex @code{Submitter-Id} field
+@cindex @code{>Submitter-Id:}
+@item >Submitter-Id:
+(@sc{Text}) A unique identification code assigned by the Support Site.
+It is used to identify all Problem Reports coming from a particular
+site. (Submitters without a value for this field can invoke
+@code{send-pr} with the @samp{--request-id} option to apply for one from
+the support organization. Problem Reports from those not affiliated
+with the support organization should use the default value of @samp{net}
+for this field.)
+
+@cindex @code{Originator} field
+@cindex @code{>Originator:}
+@item >Originator:
+(@sc{Text}) Originator's real name. The default is the value of the
+originator's environment variable @code{NAME}.
+
+@cindex @code{>Organization:}
+@cindex @code{Organization} field
+@item >Organization:
+(@sc{MultiText}) The originator's organization. The default value is
+set with the variable @w{@code{DEFAULT_ORGANIZATION}} in the
+@ifclear SENDPR
+@file{config} file (@pxref{config file,,The @code{config} file}).
+@end ifclear
+@ifset SENDPR
+@code{send-pr} shell script.
+@end ifset
+
+@cindex @code{Confidential} field
+@cindex @code{>Confidential:}
+@cindex confidentiality in PRs
+@cindex PR confidentiality
+@item >Confidential:
+(@sc{Enumerated}) Use of this field depends on the originator's
+relationship with the support organization; contractual agreements often
+have provisions for preserving confidentiality. Conversely, a lack of a
+contract often means that any data provided will not be considered
+confidential. Submitters should be advised to contact the support
+organization directly if this is an issue.
+
+If the originator's relationship to the support organization provides
+for confidentiality, then if the value of this field is @samp{yes} the
+support organization treats the PR as confidential; any code samples
+provided are not made publicly available (e.g., in regression test
+suites). The default value is @samp{yes}.
+
+@cindex @code{Synopsis} field
+@cindex @code{>Synopsis:}
+@item >Synopsis:
+(@sc{Text}) One-line summary of the problem. @w{@code{send-pr}} copies
+this information to the @samp{Subject:} line when you submit a Problem
+Report.
+
+@cindex @code{Severity} field
+@cindex @code{>Severity:}
+@item >Severity:
+(@sc{Enumerated}) The severity of the problem. Accepted values include:
+
+@table @code
+@cindex @emph{critical} severity problems
+@item critical
+The product, component or concept is completely non-operational or some
+essential functionality is missing. No workaround is known.
+
+@cindex @emph{serious} severity problems
+@item serious
+The product, component or concept is not working properly or significant
+functionality is missing. Problems that would otherwise be considered
+@samp{critical} are rated @samp{serious} when a workaround is known.
+
+@cindex @emph{non-critical} severity problems
+@item non-critical
+The product, component or concept is working in general, but lacks
+features, has irritating behavior, does something wrong, or doesn't
+match its documentation.
+@end table
+@noindent
+The default value is @samp{serious}.
+@sp 1
+
+@cindex @code{Priority} field
+@cindex @code{>Priority:}
+@item >Priority:
+(@sc{Enumerated}) How soon the originator requires a solution. Accepted
+values include:
+
+@table @code
+@cindex @emph{high} priority problems
+@item high
+A solution is needed as soon as possible.
+
+@cindex @emph{medium} priority problems
+@item medium
+The problem should be solved in the next release.
+
+@cindex @emph{low} priority problems
+@item low
+The problem should be solved in a future release.
+@end table
+@noindent
+The default value is @samp{medium}.
+@sp 1
+
+@cindex @code{Category} field
+@cindex @code{>Category:}
+@item >Category:
+(@sc{Text}) The name of the product, component or concept where
+the problem lies. The values for this field are defined by the Support
+Site.
+@ifclear SENDPR
+@xref{categories file,,The @code{categories} file}, for details.
+@end ifclear
+
+@cindex @code{Class} field
+@cindex @code{>Class:}
+@item >Class:
+(@sc{Enumerated}) The class of a problem can be one of the following:
+
+@table @code
+@cindex @emph{sw-bug} class
+@item sw-bug
+A general product problem. (@samp{sw} stands for ``software''.)
+
+@cindex @emph{doc-bug} class
+@item doc-bug
+A problem with the documentation.
+
+@cindex @emph{change-request} class
+@item change-request
+A request for a change in behavior, etc.
+
+@cindex @emph{support} class
+@item support
+A support problem or question.
+
+@cindex @emph{duplicate} class
+@item duplicate (@var{pr-number})
+Duplicate PR. @var{pr-number} should be the number of the original PR.
+
+@ifclear SENDPR
+@cindex @emph{mistaken} class
+@item mistaken
+No problem, user error or misunderstanding. This value is valid only at
+the Support Site.
+@end ifclear
+@end table
+
+@noindent
+The default is @samp{sw-bug}.
+@sp 1
+
+@cindex @code{Release} field
+@cindex @code{>Release:}
+@item >Release:
+(@sc{Text}) Release or version number of the product, component or
+concept.
+
+@cindex @code{Environment} field
+@cindex @code{>Environment:}
+@item >Environment:
+(@sc{MultiText}) Description of the environment where the problem occured:
+machine architecture, operating system, host and target types,
+libraries, pathnames, etc.
+
+@cindex @code{Description} field
+@cindex @code{>Description:}
+@item >Description:
+(@sc{MultiText}) Precise description of the problem.
+
+@cindex @code{How-To-Repeat} field
+@cindex @code{>How-To-Repeat:}
+@item >How-To-Repeat:
+(@sc{MultiText}) Example code, input, or activities to reproduce the
+problem. The support organization uses example code both to reproduce
+the problem and to test whether the problem is fixed. Include all
+preconditions, inputs, outputs, conditions after the problem, and
+symptoms. Any additional important information should be included.
+Include all the details that would be necessary for someone else to
+recreate the problem reported, however obvious. Sometimes seemingly
+arbitrary or obvious information can point the way toward a solution.
+See also @ref{Helpful hints,,Helpful hints}.
+
+@cindex @code{Fix} field
+@cindex @code{>Fix:}
+@item >Fix:
+(@sc{MultiText}) A description of a solution to the problem, or a patch
+which solves the problem. (This field is most often filled in at the
+Support Site; we provide it to the submitter in case she has solved the
+problem.)
+
+@end table
+
+@noindent
+@sc{gnats} adds the following fields when the PR arrives at the Support
+Site:
+
+@table @code
+@cindex @code{Number} field
+@cindex @code{>Number:}
+@item >Number:
+(@sc{Enumerated}) The incremental identification number for this PR.
+@ifclear SENDPR
+This is included in the automated reply to the submitter (if that
+feature of @sc{gnats} is activated; @pxref{Local configuration,,Changing
+your local configuration}). It is also included in the copy of the PR
+that is sent to the maintainer.
+@end ifclear
+
+The @samp{>Number:} field is often paired with the @samp{>Category:}
+field as
+
+@smallexample
+@var{category}/@var{number}
+@end smallexample
+
+@noindent
+in subsequent email messages. This is for historical reasons, as well
+as because Problem Reports are stored in subdirectories which are named
+by category.
+
+@cindex @code{State} field
+@cindex @code{>State:}
+@item >State:
+(@sc{Enumerated}) The current state of the PR. Accepted values are:
+
+@table @code
+@item open
+The PR has been filed and the responsible person notified.
+
+@item analyzed
+The responsible person has analyzed the problem.
+
+@item feedback
+The problem has been solved, and the originator has been given a patch
+or other fix.
+
+@item closed
+The changes have been integrated, documented, and tested, and the
+originator has confirmed that the solution works.
+
+@item suspended
+Work on the problem has been postponed.
+@end table
+
+@noindent
+The initial state of a PR is @samp{open}. @xref{States,,States of
+Problem Reports}.
+
+@cindex @code{Responsible} field
+@cindex @code{>Responsible:}
+@item >Responsible:
+(@sc{Text}) The person responsible for this category.
+@ifclear SENDPR
+@sc{gnats} retrieves this information from the @file{categories} file
+(@pxref{categories file,,The @code{categories} file}).
+@end ifclear
+
+@cindex @code{>Arrival-Date:}
+@cindex @code{Arrival-Date} field
+@item >Arrival-Date:
+(@sc{Text}) The time that this PR was received by @sc{gnats}. The date
+is provided automatically by @sc{gnats}.
+
+@cindex @code{>Audit-Trail:}
+@cindex @code{Audit-Trail} field
+@item >Audit-Trail:
+(@sc{MultiText}) Tracks related electronic mail as well as changes in
+the @samp{>State:} and @samp{>Responsible:} fields with the sub-fields:
+
+@table @code
+@cindex @code{State-Changed-<From>-<To>:} in @code{>Audit-Trail:}
+@item @w{State-Changed-<From>-<To>: @var{oldstate}>-<@var{newstate}}
+The old and new @samp{>State:} field values.
+
+@cindex @code{Responsible-Changed-<From>-<To>:} in @code{>Audit-Trail:}
+@item @w{Responsible-Changed-<From>-<To>: @var{oldresp}>-<@var{newresp}}
+The old and new @samp{>Responsible:} field values.
+
+@cindex @code{State-Changed-By:} in @code{>Audit-Trail:}
+@cindex @code{Responsible-Changed-By:} in @code{>Audit-Trail:}
+@item State-Changed-By: @var{name}
+@itemx Responsible-Changed-By: @var{name}
+The name of the maintainer who effected the change.
+
+@cindex @code{State-Changed-When:} in @code{>Audit-Trail:}
+@cindex @code{Responsible-Changed-When:} in @code{>Audit-Trail:}
+@item State-Changed-When: @var{timestamp}
+@itemx Responsible-Changed-When: @var{timestamp}
+The time the change was made.
+
+@cindex @code{State-Changed-Why:} in @code{>Audit-Trail:}
+@cindex @code{Responsible-Changed-Why:} in @code{>Audit-Trail:}
+@item State-Changed-Why: @var{reason@dots{}}
+@itemx Responsible-Changed-Why: @var{reason@dots{}}
+The reason for the change.
+@end table
+
+@cindex subsequent mail
+@cindex other mail
+@cindex appending PRs
+@cindex saving related mail
+@cindex related mail
+@noindent
+The @samp{>Audit-Trail:} field also contains any mail messages received
+by @sc{gnats} related to this PR, in the order received.
+
+@cindex @code{>Unformatted:}
+@cindex @code{Unformatted} field
+@item
+ >Unformatted:
+(@sc{MultiText}) Any random text found outside the fields in the
+original Problem Report.
+@end table
+
diff --git a/gnu/usr.bin/send-pr/doc/s-usage.texi b/gnu/usr.bin/send-pr/doc/s-usage.texi
new file mode 100644
index 0000000..5c9006b
--- /dev/null
+++ b/gnu/usr.bin/send-pr/doc/s-usage.texi
@@ -0,0 +1,570 @@
+@c $FreeBSD$
+
+@c This is the usage section for send-pr. It is called as
+@c chapter (Invoking send-pr) by send-pr.texi, and also as
+@c section (Submitting Problem Reports) by gnats.texi (chapter/section
+@c identifiers are adjusted accordingly)
+
+@c FIXME! This still seems jumbled...
+
+You can invoke @code{send-pr} from a shell prompt, or from within
+@sc{gnu} Emacs using @w{@samp{M-x send-pr}}.
+
+@menu
+* using send-pr:: Creating new Problem Reports
+* send-pr in Emacs:: Using send-pr from within Emacs
+* send-pr from the shell:: Invoking send-pr from the shell
+* Submitting via e-mail:: Submitting a Problem Report via direct e-mail
+* Helpful hints::
+@end menu
+
+@node using send-pr
+@section Creating new Problem Reports
+
+@c FIXME - this is a long node
+Invoking @code{send-pr} presents a PR @dfn{template} with a number of
+fields already filled in. Complete the template as thoroughly as
+possible to make a useful bug report. Submit only one bug with each PR.
+
+@cindex template
+A template consists of three sections:
+
+@table @dfn
+@item Comments
+The top several lines of a blank template consist of a series of
+comments that provide some basic instructions for completing the Problem
+Report, as well as a list of valid entries for the @samp{>Category:}
+field. These comments are all preceded by the string @samp{SEND-PR:}
+and are erased automatically when the PR is submitted. The
+instructional comments within @samp{<} and @samp{>} are also removed.
+(Only these comments are removed; lines you provide that happen to have
+those characters in them, such as examples of shell-level redirection,
+are not affected.)
+
+@item Mail Header
+@code{send-pr} creates a standard mail header. @code{send-pr} completes
+all fields except the @samp{Subject:} line with default values.
+(@xref{Fields,,Problem Report format}.)
+
+@item @sc{gnats} fields
+These are the informational fields that @sc{gnats} uses to route your
+Problem Report to the responsible party for further action. They should
+be filled out as completely as possible. (@xref{Fields,,Problem Report
+format}. Also see @ref{Helpful hints,,Helpful hints}.)
+@end table
+
+@ifset SENDPR
+@noindent
+For examples of a Problem Report template and complete Problem Report,
+see @ref{An Example}.
+@end ifset
+
+The default template contains your preconfigured @samp{>Submitter-Id:}.
+@code{send-pr} attempts to determine values for the @samp{>Originator:}
+and @samp{>Organization:} fields (@pxref{Fields,,Problem Report
+format}). @code{send-pr} will set the @samp{>Originator:} field to
+the value of the @code{NAME} environment variable if it has been set;
+similarly, @samp{>Organization:} will be set to the value of @code{ORGANIZATION}.
+@code{send-pr} also attempts to find out some information
+about your system and architecture, and places this information in the
+@samp{>Environment:} field if it finds any.
+
+You may submit problem reports to different Support Sites from the
+default site by specifying the alternate site when you invoke
+@code{send-pr}. @xref{send-pr from the shell}.
+Each @code{site} has its own list of categories for
+which it accepts Problem Reports.
+@c FIXME! This should go in..
+@c For a list of sites to whom @code{send-pr} is configured to send
+@c Problem Reports, type @w{@samp{send-pr -S}}.
+@ifset SENDPR
+(@xref{default site,,Setting a default @var{site}}.)
+@end ifset
+
+@code{send-pr} also provides the mail header section of the template
+with default values in the @samp{To:}, @samp{From:}, and
+@samp{Reply-To:} fields. The @samp{Subject:} field is empty.
+
+The template begins with a comment section:
+
+@cindex template comment section
+@cindex comment section in the PR template
+@smallexample
+@group
+SEND-PR: -*- send-pr -*-
+SEND-PR: Lines starting with `SEND-PR' will be removed
+SEND-PR: automatically as well as all comments (the text
+SEND-PR: below enclosed in `<' and `>').
+SEND-PR:
+SEND-PR: Please consult the document `Reporting Problems
+SEND-PR: Using send-pr' if you are not sure how to fill out
+SEND-PR: a problem report.
+SEND-PR:
+SEND-PR: Choose from the following categories:
+@end group
+@end smallexample
+
+@noindent
+and also contains a list of valid @code{>Category:} values for the
+Support Site to whom you are submitting this Problem Report. One (and
+only one) of these values should be placed in the @code{>Category:}
+field.
+@ifset SENDPR
+A complete sample bug report, from template to completed PR, is shown in
+@ref{An Example}. For a complete list of valid categories, type
+@w{@samp{send-pr -L}} at your prompt. @xref{Valid Categories,,Valid
+Categories}, for a sample list of categories, .
+@end ifset
+
+@c FIXME.. this sounds awkward
+The mail header is just below the comment section. Fill out the
+@samp{Subject:} field, if it is not already completed using the value of
+@samp{>Synopsis:}. The other mail header fields contain default values.
+
+@cindex mail header section
+@smallexample
+@group
+To: @var{support-site}
+Subject: @emph{complete this field}
+From: @var{your-login}@@@var{your-site}
+Reply-To: @var{your-login}@@@var{your-site}
+X-send-pr-version: send-pr @value{VERSION}
+@end group
+@end smallexample
+
+@noindent
+where @var{support-site} is an alias on your local machine for the
+Support Site you wish to submit this PR to.
+
+The rest of the template contains @sc{gnats} fields. Each field is
+either automatically completed with valid information (such as your
+@samp{>Submitter-Id:}) or contains a one-line instruction specifying the
+information that field requires in order to be correct. For example,
+the @samp{>Confidential:} field expects a value of @samp{yes} or
+@samp{no}, and the answer must fit on one line; similarly, the
+@samp{>Synopsis:} field expects a short synopsis of the problem, which
+must also fit on one line. Fill out the fields as completely as
+possible. @xref{Helpful hints,,Helpful hints}, for suggestions as to
+what kinds of information to include.
+
+In this example, words in @emph{italics} are filled in with
+pre-configured information:
+
+@cindex @code{send-pr} fields
+@smallexample
+@group
+>Submitter-Id: @emph{your submitter-id}
+>Originator: @emph{your name here}
+>Organization:
+ @emph{your organization}
+>Confidential:<[ yes | no ] (one line)>
+>Synopsis: <synopsis of the problem (one line)>
+>Severity: <[non-critical | serious | critical](one line)>
+>Priority: <[ low | medium | high ] (one line)>
+>Category: <name of the product (one line)>
+>Class: <[sw-bug | doc-bug | change-request | support]>
+>Release: <release number (one line)>
+>Environment:
+ <machine, os, target, libraries (multiple lines)>
+
+>Description:
+ <precise description of the problem (multiple lines)>
+>How-To-Repeat:
+ <code/input/activities to reproduce (multiple lines)>
+>Fix:
+ <how to correct or work around the problem, if known
+ (multiple lines)>
+@end group
+@end smallexample
+
+@cindex @code{Submitter-Id} field
+@cindex @code{>Submitter-Id:}
+When you finish editing the Problem Report, @code{send-pr} mails it to
+the address named in the @samp{To:} field in the mail header.
+@code{send-pr} checks that the complete form contains a valid
+@samp{>Category:}.
+
+@ifset SENDPR
+Your copy of @code{send-pr} should have already been customized on
+installation to reflect your @samp{>Submitter-Id:}. (@xref{Installing
+send-pr, , Installing @code{send-pr} on your system}.) If you don't
+know your @samp{>Submitter-Id:}, you can request it using
+@w{@samp{send-pr --request-id}}. If your organization is not affiliated
+with the site you send Problem Reports to, a good generic
+@samp{>Submitter-Id:} to use is @samp{net}. @emph{NOTE:} If you are using
+send-pr to send problem reports to the FreeBSD Project, this version of
+send-pr already has a customer ID in it and you do not need to request a
+new one.
+@end ifset
+
+@cindex bad Problem Reports
+@cindex errors
+@cindex invalid Problem Reports
+If your PR has an invalid value in one of the @sc{Enumerated} fields
+(@pxref{Fields,,Problem Report format}), @code{send-pr} places the PR in
+a temporary file named @samp{/tmp/pbad@var{nnnn}} on your machine.
+@var{nnnn} is the process identification number given to your current
+@code{send-pr} session. If you are running @code{send-pr} from the
+shell, you are prompted as to whether or not you wish to try editing the
+same Problem Report again. If you are running @code{send-pr} from
+Emacs, the Problem Report is placed in the buffer
+@w{@samp{*send-pr-error*}}; you can edit this file and then submit it
+with
+
+@smallexample
+M-x gnats-submit-pr
+@end smallexample
+
+@cindex subsequent mail
+@cindex other mail
+@cindex appending PRs
+@cindex saving related mail
+@cindex related mail
+Any further mail concerning this Problem Report should be carbon-copied
+to the @sc{gnats} mailing address as well, with the category and
+identification number in the @samp{Subject:} line of the message.
+
+@smallexample
+Subject: Re: PR @var{category}/@var{gnats-id}: @var{original message subject}
+@end smallexample
+
+@noindent
+Messages which arrive with @samp{Subject:} lines of this form are
+automatically appended to the Problem Report in the @samp{>Audit-Trail:}
+field in the order received.
+
+@c ---------------------------------------------------------------
+@node send-pr in Emacs
+@section Using @code{send-pr} from within Emacs
+@cindex using @code{send-pr} from within Emacs
+@cindex @code{send-pr} within Emacs
+@cindex invoking @code{send-pr} from Emacs
+@cindex interactive interface
+
+You can use an interactive @code{send-pr} interface from within @sc{gnu}
+Emacs to fill out your Problem Report. We recommend that you
+familiarize yourself with Emacs before using this feature
+(@pxref{Introduction,,Introduction,emacs,GNU Emacs}).
+
+Call @code{send-pr} with @w{@samp{M-x send-pr}}.@footnote{If typing
+@w{@samp{M-x send-pr}} doesn't work, see your system administrator for
+help loading @code{send-pr} into Emacs.} @code{send-pr} responds with a
+Problem Report template preconfigured for the Support Site from which
+you received @code{send-pr}. (If you use @code{send-pr} locally, the
+default Support Site is probably your local site.)
+
+You may also submit problem reports to different Support Sites from the
+default site. To use this feature, invoke @code{send-pr} with
+
+@smallexample
+C-u M-x send-pr
+@end smallexample
+
+@code{send-pr} prompts you for the name of a @var{site}. @var{site} is
+an alias on your local machine which points to an alternate Support
+Site.
+
+@cindex Emacs
+@code{send-pr} displays the template and prompts you in the minibuffer
+with the line:
+@smallexample
+>Category: other
+@end smallexample
+
+@noindent
+Delete the default value @samp{other} @emph{in the minibuffer} and
+replace it with the keyword corresponding to your problem (the list of
+valid categories is in the topmost section of the PR template). For
+example, if the problem you wish to report has to do with the @sc{gnu} C
+compiler, and your support organization accepts bugs submitted for this
+program under the category @samp{gcc}, delete @samp{other} and then type
+@w{@samp{gcc[@key{RET}]}}. @code{send-pr} replaces the line
+
+@smallexample
+>Category: <name of the product (one line)>
+@end smallexample
+
+@noindent
+in the template with
+
+@smallexample
+>Category: gcc
+@end smallexample
+
+@noindent
+and moves on to another field.
+
+@cindex completion in Emacs
+@cindex name completion in Emacs
+@w{@code{send-pr}} provides name completion in the minibuffer. For
+instance, you can also type @w{@samp{gc[@key{TAB}]}}, and @code{send-pr}
+attempts to complete the entry for you. Typing @w{@samp{g[@key{TAB}]}}
+may not have the same effect if several possible entries begin with
+@samp{g}. In that case @code{send-pr} cannot complete the entry because
+it cannot determine whether you mean @samp{gcc} or, for example,
+@samp{gdb}, if both of those are possible categories.
+@w{@code{send-pr}} continues to prompt you for a valid entry until you
+enter one.
+
+@w{@code{send-pr}} prompts you interactively to enter each field for
+which there is a range of specific choices. If you attempt to enter a
+value which is not in the range of acceptable entries, @code{send-pr}
+responds with @w{@samp{[No match]}} and allows you to change the entry
+until it contains an acceptable value. This avoids unusable information
+(at least in these fields) and also avoids typographical errors which
+could cause problems later.
+
+@code{send-pr} prompts you for the following fields:
+
+@c FIXME - should these go before the discussion on completion?
+@example
+@group
+>Category:
+>Confidential: (@emph{default}: no)
+>Severity: (@emph{default}: serious)
+>Priority: (@emph{default}: medium)
+>Class: (@emph{default}: sw-bug)
+>Release:
+>Synopsis: (@emph{this value is copied to @code{Subject:}})
+@end group
+@end example
+
+@noindent
+After you complete these fields, @w{@code{send-pr}} places the cursor in
+the @samp{>Description:} field and displays the message
+
+@smallexample
+To send the problem report use: C-c C-c
+@end smallexample
+
+@noindent
+in the minibuffer. At this point, edit the file in the main buffer to
+reflect your specific problem, putting relevant information in the
+proper fields.
+@ifset SENDPR
+@xref{An Example}, for a sample Problem Report.
+@end ifset
+
+@w{@samp{send-pr}} provides a few key bindings to make moving
+around in a template buffer more simple:
+
+@table @code
+@item C-c C-f
+@itemx M-x change-field
+Changes the field under the cursor. @code{edit-pr} prompts you for a
+new value.
+
+@item M-C-b
+@itemx M-x gnats-backward-field
+Moves the cursor to the beginning of the value of the current field.
+
+@item M-C-f
+@itemx M-x gnats-forward-field
+Moves the cursor to the end of the value of the current field.
+
+@item M-p
+@itemx M-x gnats-previous-field
+Moves the cursor back one field to the beginning of the value of the
+previous field.
+
+@item M-n
+@itemx M-x gnats-next-field
+Moves the cursor forward one field to the beginning of the value of the
+next field.
+@end table
+
+@code{send-pr} takes over again when you type @samp{C-c C-c} to send the
+message. @code{send-pr} reports any errors in a separate buffer, which
+remains in existence until you send the PR properly (or, of course,
+until you explicitly kill the buffer).
+
+For detailed instructions on using Emacs, see
+@ref{Introduction,,,emacs,GNU Emacs}.
+
+@node send-pr from the shell
+@section Invoking @code{send-pr} from the shell
+@cindex command line options
+@cindex invoking @code{send-pr} from the shell
+@cindex shell invocation
+
+@c FIXME! Add [ -S ] right after [ -L ]...
+@smallexample
+send-pr [ @var{site} ]
+ [ -f @var{problem-report} | --file @var{problem-report} ]
+ [ -t @var{mail-address} | --to @var{mail-address} ]
+ [ --request-id ]
+ [ -L | --list ] [ -P | --print ]
+ [ -V | --version] [ -h | --help ]
+@end smallexample
+
+@var{site} is an alias on your local machine which points to an address
+used by a Support Site. If this argument is not present, the default
+@var{site} is usually the site which you received @code{send-pr} from,
+or your local site if you use @sc{gnats} locally.
+@ifset SENDPR
+(@xref{default site,,Setting a default @var{site}}.)
+@end ifset
+
+Invoking @code{send-pr} with no options calls the editor named in your
+environment variable @code{EDITOR} on a default PR template. If the
+environment variable @code{PR_FORM} is set, its value is used as a file
+name which contains a valid template. If @code{PR_FORM} points to a
+missing or unreadable file, or if the file is empty, @code{send-pr}
+generates an error message and opens the editor on a default template.
+
+@table @code
+@item -f @var{problem-report}
+@itemx --file @var{problem-report}
+Specifies a file, @var{problem-report}, where a completed Problem Report
+already exists. @code{send-pr} sends the contents of the file without
+invoking an editor. If @var{problem-report} is @samp{-},
+@w{@code{send-pr}} reads from standard input.
+
+@item -t @var{mail-address}
+@itemx --to @var{mail-address}
+Sends the PR to @var{mail-address}. The default is preset when
+@code{send-pr} is configured. @emph{This option is not recommended};
+instead, use the argument @var{site} on the command line.
+
+@item -c @var{mail-address}
+@itemx --cc @var{mail-address}
+Places @var{mail-address} in the @code{Cc:} header field of the message
+to be sent.
+
+@item --request-id
+Sends a request for a @code{>Submitter-Id:} to the Support Site.
+
+@cindex listing valid categories
+@item -L
+@itemx --list
+Prints the list of valid @code{>Category:} values on standard output.
+No mail is sent.
+
+@item -s @var{severity}
+@itemx --severity @var{severity}
+@cindex @code{send-pr} fields
+Sets the initial value of the @code{>Severity:} field to @var{severity}.
+
+@ignore
+@item -S
+@itemx --sites
+Displays a list of valid @var{site} values on standard output. No mail
+is sent.
+@end ignore
+
+@item -P
+@itemx --print
+Displays the PR template. If the variable @code{PR_FORM} is set in your
+environment, the file it specifies is printed. If @code{PR_FORM} is not
+set, @code{send-pr} prints the standard blank form. If the file
+specified by @code{PR_FORM} doesn't exist, @code{send-pr} displays an
+error message. No mail is sent.
+
+@item -V
+@itemx --version
+Displays the @code{send-pr} version number and a usage summary. No mail
+is sent.
+
+@item -h
+@itemx --help
+Displays a usage summary for @code{send-pr}. No mail is sent.
+@end table
+
+@c -------------------------------------------------------------------------
+@node Submitting via e-mail
+@section Submitting a Problem Report via direct e-mail
+@cindex Direct e-mail
+@cindex Submitting a PR via e-mail
+In addition to using @code{send-pr}, there is another way to submit a problem
+report. You can simply send an e-mail message to the support site.
+
+To do this, look at the address in the @samp{To:} field of the @code{send-pr}
+template. When you send unformatted e-mail to this address, @sc{gnats}
+processes the message as a new problem report, filling in as many fields from
+defaults as it can:
+
+@table @code
+@item Synopsis
+The @samp{>Synopsis} field is filled in by the @samp{Subject:} header.
+
+@item Submitter ID
+@sc{gnats} will try to derive the @samp{>Submitter} field from the address
+in the @samp{From:} header.
+
+@item Description
+All of the text in the body of the e-mail message is put into the
+@samp{>Description} field. Each line of the text is indented by one space,
+indicating that it is "quoted text" from the sender.
+@end table
+
+Other fields, such as category, version, severity, etc. are set to default
+values (if the @sc{gnats} administrator has set them).
+
+@c --------------------------------------------------------------------------
+@node Helpful hints
+@section Helpful hints
+@cindex helpful hints
+@cindex Using and Porting @sc{gnu} CC
+@cindex effective problem reporting
+@cindex kinds of helpful information
+@cindex information to submit
+@cindex Report all the facts!
+
+There is no orthodox standard for submitting effective bug reports,
+though you might do well to consult the section on submitting bugs for
+@sc{gnu} @code{gcc} in @ref{Bugs, , Reporting Bugs, gcc, Using and
+Porting GNU CC}, by Richard Stallman. This section contains
+instructions on what kinds of information to include and what kinds of
+mistakes to avoid.
+
+In general, common sense (assuming such an animal exists) dictates the
+kind of information that would be most helpful in tracking down and
+resolving problems in software.
+@itemize @bullet
+@item
+Include anything @emph{you} would want to know if you were looking at
+the report from the other end. There's no need to include every minute
+detail about your environment, although anything that might be different
+from someone else's environment should be included (your path, for
+instance).
+
+@item
+Narratives are often useful, given a certain degree of restraint. If a
+person responsible for a bug can see that A was executed, and then B and
+then C, knowing that sequence of events might trigger the realization of
+an intermediate step that was missing, or an extra step that might have
+changed the environment enough to cause a visible problem. Again,
+restraint is always in order (``I set the build running, went to get a
+cup of coffee (Columbian, cream but no sugar), talked to Sheila on the
+phone, and then THIS happened@dots{}'') but be sure to include anything
+relevant.
+
+@item
+Richard Stallman writes, ``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!'' This holds true
+across all problem reporting systems, for computer software or social
+injustice or motorcycle maintenance. It is especially important in the
+software field due to the major differences seemingly insignificant
+changes can make (a changed variable, a missing semicolon, etc.).
+
+@item
+Submit only @emph{one} problem with each Problem Report. If you have
+multiple problems, use multiple PRs. This aids in tracking each problem
+and also in analyzing the problems associated with a given program.
+
+@item
+It never hurts to do a little research to find out if the bug you've
+found has already been reported. Most software releases contain lists
+of known bugs in the Release Notes which come with the software; see
+your system administrator if you don't have a copy of these.
+
+@item
+The more closely a PR adheres to the standard format, the less
+interaction is required by a database administrator to route the
+information to the proper place. Keep in mind that anything that
+requires human interaction also requires time that might be better spent
+in actually fixing the problem. It is therefore in everyone's best
+interest that the information contained in a PR be as correct as
+possible (in both format and content) at the time of submission.
+@end itemize
diff --git a/gnu/usr.bin/send-pr/doc/send-pr.texi b/gnu/usr.bin/send-pr/doc/send-pr.texi
new file mode 100644
index 0000000..1abb296
--- /dev/null
+++ b/gnu/usr.bin/send-pr/doc/send-pr.texi
@@ -0,0 +1,658 @@
+@c $FreeBSD$
+
+\input texinfo @c -*-texinfo-*-
+@setfilename send-pr.info
+@settitle Reporting Problems Using send-pr
+
+@setchapternewpage odd
+
+@include version.texi
+@set SENDPR
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* send-pr: (send-pr). Reporting problems--using send-pr
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+Copyright @copyright{} 1993, 1994, 1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries a copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@titlepage
+@finalout
+@title Reporting Problems
+@subtitle Using @code{send-pr}, version @value{VERSION}
+@subtitle October 1993
+@author Jeffrey M. Osier
+@author Cygnus Support
+@page
+
+@vskip 0pt plus 1filll
+
+Copyright @copyright{} 1993, 1994, 1995 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+
+@end titlepage
+
+@c ---------------------------------------------------------------
+@node Top
+@top Overview
+@cindex foreword to @code{send-pr}
+@cindex overview to @code{send-pr}
+@cindex introduction to @code{send-pr}
+
+This manual documents @code{send-pr},
+@ifinfo
+version @value{VERSION},
+@end ifinfo
+which uses electronic mail to submit support questions and problem
+reports to a central Support Site. No body of work is perfect, and
+support organizations understand this; @code{send-pr} is designed to
+allow users who have problems to submit reports of these problems to
+sites responsible for supporting the products in question, in a defined
+form which can be read by an electronically managed database.
+
+@cindex GNATS
+@code{send-pr} is part of a suite of programs known collectively as
+@sc{gnats}, the @sc{gnu} Problem Report Management System. @sc{gnats}
+consists of several programs which, used in concert, formulate and
+partially administer a database of @dfn{Problem Reports}, or @dfn{PRs},
+at a central Support Site. A PR goes through several states in its
+lifetime; @sc{gnats} tracks the PR and all information associated with it
+through each state and finally acts as an archive for PRs which have
+been @dfn{closed}.
+
+Because @code{send-pr} exists as a shell (@file{/bin/sh}) script and as
+an Elisp file for use with @sc{gnu} Emacs, it can be used from any
+machine on your network which can run a shell script and/or Emacs.
+
+In general, you can use any editor and mailer to submit valid Problem
+Reports, as long as the format required by @sc{gnats} is preserved.
+@code{send-pr} automates the process, however, and ensures that certain
+fields necessary for automatic processing are present. @code{send-pr}
+is strongly recommended for all initial problem-oriented correspondence
+with your Support Site. The organization you submit Problem Reports to
+supplies an address to which further information can be sent; the person
+responsible for the category of the problem you report contacts you
+directly.
+
+@menu
+* send-pr in detail:: Details about send-pr and GNATS
+* Invoking send-pr:: Editing and sending PRs
+* An Example:: A working example
+* Installing send-pr:: Installing send-pr on your system
+* Index::
+@end menu
+
+@node send-pr in detail
+@chapter Details about send-pr and GNATS
+
+@cindex details about @code{send-pr}
+@cindex Problem Reports
+A @dfn{Problem Report} is a message that describes a problem you are
+having with a body of work. @code{send-pr} organizes this message into
+a form which can be understood and automatically processed by @sc{gnats},
+the @sc{gnu} Problem Report Management System. A Problem Report is
+organized into @dfn{fields} which contain data describing you, your
+organization, and the problem you are announcing (@pxref{Fields,,Problem
+Report format}). Problem Reports go through several defined states in
+their lifetimes, from @dfn{open} to @dfn{closed} (@pxref{States,,States
+of Problem Reports}).
+
+@menu
+* States:: States of Problem Reports
+* Fields:: Problem Report format
+@end menu
+
+@include states.texi
+
+@include fields.texi
+
+@node Invoking send-pr
+@chapter Editing and sending PRs
+@cindex editing and sending PRs
+@cindex sending PRs
+@cindex invoking send-pr
+@cindex using send-pr
+@cindex generating new PRs
+
+@include s-usage.texi
+
+@node An Example
+@chapter An Example
+@cindex an example
+@cindex example PR
+@cindex Cygnus Solutions
+@cindex @sc{gnu} software support
+Cygnus Solutions in Sunnyvale, CA, uses @sc{gnats} and @code{send-pr}
+extensively for their support activities. As a support company, Cygnus
+finds problem tracking to be a crucial part of everyday business.
+Cygnus supports the @sc{gnu} compiling tools (including @sc{gnats} and
+@code{send-pr}) over several many platforms
+
+With each shipment of the Cygnus Solutions Developer's Kit, customers
+receive the latest version of @code{send-pr}, which contains an
+up-to-date listing of valid categories (values for the @code{>Category:}
+field). Using these tools, Cygnus' customers can communicate their
+problems to Cygnus effectively and receive automatic confirmation of
+receipt as well as notification of changes in the status of their
+reported problems. Much of Cygnus' support mechanism relies on
+electronic mail.
+
+As an example, let's pretend we're a customer of Cygnus Solutions, and
+that we're having a problem compiling some of our software using the
+@sc{gnu} C compiler, which Cygnus supports.
+
+Assume that we're getting an error in our @code{bifrabulator} program
+wherein the @samp{prestidigitation} routines don't match with the
+@samp{whatsitsname}. We've made sure we're following the rules of the
+program and checked the Release Notes from Cygnus and found that the bug
+isn't already known. In other words, we're pretty sure we've found a
+bug.
+
+@cindex Imaginary Software, Ltd.
+Our first step is to call @code{send-pr}. It really doesn't matter
+whether we use @code{send-pr} from the shell or from within Emacs.
+Indeed, if we use Emacs as a primary editor, calling @code{send-pr} from
+the shell is likely to start @code{send-pr} in an Emacs buffer anyway.
+So, since our company, @emph{Imaginary Software, Ltd.}, uses @sc{gnu}
+software extensively, we're pretty familiar with Emacs, so from within
+Emacs we type
+@smallexample
+M-x send-pr
+@end smallexample
+@noindent
+and we're greeted with the following screen:
+
+@cindex default PR template
+@cindex example of a default template
+@cindex blank PR template
+@cindex @code{bifrabulator}
+@cartouche
+@smallexample
+SEND-PR: -*- text -*-
+SEND-PR: Lines starting with `SEND-PR' will be removed
+SEND-PR: automatically as well as all comments (the text
+SEND-PR: below enclosed in `<' and `>').
+SEND-PR: Please consult the manual if you are not sure
+SEND-PR: how to fill out a problem report.
+SEND-PR:
+SEND-PR: Choose from the following categories:
+SEND-PR:
+SEND-PR: bfd binutils bison
+SEND-PR: byacc clib config cvs diff
+SEND-PR: doc emacs flex g++ gas
+SEND-PR: gcc gdb glob gprof grep
+SEND-PR: info ispell kerberos ld libg++
+SEND-PR: libiberty make makeinfo mas newlib
+SEND-PR: other patch rcs readline send-pr
+SEND-PR: test texindex texinfo texinfo.tex
+SEND-PR: bifrabulator <---@emph{note: this one is fake}
+SEND-PR:
+To: cygnus-bugs@@cygnus.com
+Subject:
+From: jeffrey@@imaginary.com
+Reply-To: jeffrey@@imaginary.com
+X-send-pr-version: send-pr @value{VERSION}
+
+>Submitter-Id: imaginary
+>Originator: Jeffrey Osier
+>Organization:
+Imaginary Software, Ltd.
+>Confidential: <[ yes | no ] (one line)>
+>Synopsis: <synopsis of the problem (one line)>
+>Severity: <[ non-critical | serious | critical ] (one line)>
+>Priority: <[ low | medium | high ] (one line)>
+>Category: <name of the product (one line)>
+>Class: <[sw-bug|doc-bug|change-request|support](oneline)>
+>Release: <release number or tag (one line)>
+>Environment:
+ <machine, os, target, libraries (multiple lines)>
+System: SunOS imaginary.com 4.1.1 1 sun4
+Architecture: sun4
+
+>Description:
+ <precise description of the problem (multiple lines)>
+>How-To-Repeat:
+ <code/input/activities to reproduce (multiple lines)>
+>Fix:
+@iftex
+@hrule
+@end iftex
+-----Emacs: *send-pr* (send-pr Fill)----All------------------
+@iftex
+@hrule
+@end iftex
+>Category: other[]
+@end smallexample
+@end cartouche
+@page
+We know from past experience that we need to set certain information into
+each field, so we compile all the information we know about our problem.
+We have some sample code which we know should work, even though it
+doesn't, so we'll include that. Below is the completed PR; we send this
+using @kbd{C-c C-c}. (The comments have been truncated).
+
+@cindex completed Problem Report
+@cindex example of a completed PR
+@cartouche
+@smallexample
+SEND-PR: Lines starting with `SEND-PR' will be removed
+SEND-PR: automatically as well as all comments (the text
+SEND-PR: @dots{}
+SEND-PR:
+To: cygnus-bugs@@cygnus.com
+Subject: bifrabulator routines don't match
+From: jeffrey@@imaginary.com
+Reply-To: jeffrey@@imaginary.com
+X-send-pr-version: send-pr @value{VERSION}
+
+>Submitter-Id: imaginary
+>Originator: Jeffrey Osier
+>Organization:
+Imaginary Software, Ltd.
+>Confidential: no
+>Synopsis: bifrabulator routines don't match
+>Severity: serious
+>Priority: medium
+>Category: bifrabulator
+>Class: sw-bug
+>Release: progressive-930101
+>Environment:
+System: SunOS imaginary.com 4.1.1 1 sun4
+Architecture: sun4 (SPARC)
+
+>Description:
+ the following code I fed into the bifrabulator came back
+ with a strange error. apparently, the prestidigitation
+ routine doesn't match with the whatsitsname in all cases.
+
+>How-To-Repeat:
+ call the bifrabulator on the following code.
+ @emph{code sample@dots{}}
+
+>Fix:
+@iftex
+@hrule
+@end iftex
+-----Emacs: *send-pr* (send-pr Fill)----All------------------
+@iftex
+@hrule
+@end iftex
+To send the problem report use: C-c C-c
+@end smallexample
+@end cartouche
+
+We type @kbd{C-c C-c}, and off it goes. Now, we depend on Cygnus
+Support to figure out the answer to our problem.
+
+Soon afterward, we get the following message from Cygnus:
+
+@smallexample
+@group
+From: gnats (GNATS management)
+Sender: gnats-admin
+Reply-To: hacker@@cygnus.com
+To: jeffrey@@imaginary.com
+Subject: Re: bifrabulator/1425: routines don't match
+
+Thank you very much for your problem report.
+It has the internal identification: g++/1425.
+The individual assigned to look at your bug is: hacker
+(F.B. Hacker)
+
+Category: bifrabulator
+Responsible: hacker
+Synopsis: bifrabulator routines don't match
+Arrival-Date: Sat Feb 30 03:12:55 1993
+@end group
+@end smallexample
+
+@noindent
+This is our receipt that the bug has been accepted and forwarded to the
+responsible party.
+
+@noindent
+A while later, we get the analysis:
+
+@smallexample
+@group
+To: jeffrey@@imaginary.com
+From: hacker@@cygnus.com
+Subject: Re: bifrabulator/1425: routines don't match
+Reply-To: hacker@@cygnus.com
+
+Got your message, Jeff. It seems that the bifrabulator was
+confusing the prestidigitation routines with the realitychecker
+when lexically parsing the whatsitsname.
+
+I'm working on robustisizing the bifrabulator now.
+
+How about lunch next week?
+--
+F.B. Hacker
+Cygnus Solutions, Sunnyvale, CA 408 542 9600
+#include <std-disclaimer.h>
+@end group
+@end smallexample
+
+@noindent
+About the same time, we get another message from Cygnus.
+
+@cindex state change example
+@cindex example of a state change
+@smallexample
+@group
+From: hacker@@cygnus.com
+To: jeffrey@@imaginary.com
+Subject: Re: bifrabulator/1425: doesn't match prestidig
+Reply-To: hacker@@cygnus.com
+
+
+ `F.B. Hacker' changed the state to `analyzed'.
+
+State-Changed-From-To: open-analyzed
+State-Changed-By: hacker
+State-Changed-When: Fri Feb 31 1993 08:59:16 1993
+State-Changed-Why:
+ figured out the problem, working on a patch this afternoon
+--
+F.B. Hacker
+Cygnus Solutions, Sunnyvale, CA 408 542 9600
+#include <std-disclaimer.h>
+@end group
+@end smallexample
+
+@noindent
+The bug has now been analyzed, and Cygnus is working on a solution.
+
+@noindent
+Sometime later, we get more mail from F.B.:
+
+@smallexample
+@group
+To: jeffrey@@imaginary.com
+From: hacker@@cygnus.com
+Subject: Re: bifrabulator/1425: routines don't match
+Reply-To: hacker@@cygnus.com
+
+There's a patch now that you can ftp over and check out.
+
+Hey, that joke you sent me was great! The one about the
+strings walking into a bar... my boss laughed for an hour!
+--
+F.B. Hacker
+Cygnus Solutions, Sunnyvale, CA 408 542 9600
+#include <std-disclaimer.h>
+@end group
+@end smallexample
+@sp 2
+@smallexample
+@group
+From: hacker@@cygnus.com
+To: jeffrey@@imaginary.com
+Subject: Re: bifrabulator/1425: doesn't match prestidig
+Reply-To: hacker@@cygnus.com
+
+
+ `F.B. Hacker' changed the state to `feedback'.
+
+State-Changed-From-To: analyzed-feedback
+State-Changed-By: hacker
+State-Changed-When: Fri Feb 31 1993 23:43:16 1993
+State-Changed-Why:
+ got the patch finished, notified Jeff at Imaginary Software
+--
+F.B. Hacker
+Cygnus Solutions, Sunnyvale, CA 408 542 9600
+#include <std-disclaimer.h>
+@end group
+@end smallexample
+
+@noindent
+The bug has gone into @dfn{feedback} status now, until we get the patch,
+install it and test it. When everything tests well, we can mail F.B.
+back and tell him the bug's been fixed, and he can change the state of
+the PR from @dfn{feedback} to @dfn{closed}.
+
+Following is a list of valid @samp{>Category:} entries that are
+supported by Cygnus.
+
+@menu
+* Valid Categories::
+@end menu
+
+@c FIXME - is this list up to date?
+@include categ.texi
+
+@node Installing send-pr
+@appendix Installing @code{send-pr} on your system
+@cindex installation
+
+If you receive @code{send-pr} as part of a larger software distribution,
+it probably gets installed when the full distribution is installed. If
+you are using @sc{gnats} at your site as well, you must decide where
+@code{send-pr} sends Problem Reports by default; see @ref{default site,,
+Setting a default @var{site}}.
+
+@menu
+* installation:: installing `send-pr' by itself
+* default site:: setting a default site
+@end menu
+
+@node installation
+@section Installing @code{send-pr} by itself
+@cindex installation procedure
+
+Install @code{send-pr} by following these steps (you may need
+@code{root} access in order to change the @file{aliases} file and to
+install @code{send-pr}):
+
+@itemize @bullet
+@item
+Unpack the distribution into a directory which we refer to as
+@var{srcdir}.
+
+@item
+Edit the file @file{Makefile} to reflect local conventions.
+Specifically, you should edit the variable @samp{prefix} to alter the
+installation location. The default is @file{/usr/local}. All files are
+installed under @samp{prefix} (see below).
+
+@item @emph{Run}
+@smallexample
+make all install [ info ] [ install-info ] [ clean ]
+@end smallexample
+
+@noindent
+The targets mean the following:
+
+@table @code
+@item all
+Builds @code{send-pr} and @code{install-sid}
+
+@item install
+Installs the following:
+
+@table @code
+@item install-sid
+@itemx send-pr
+into @file{@var{prefix}/bin}
+
+@item send-pr.1
+into @file{@var{prefix}/man/man1}
+
+@item @var{site}
+the list of valid @var{categories} for the Support Site from which you
+received @code{send-pr}, installed as
+@w{@file{@var{prefix}/share/gnats/@var{site}}}
+
+@item send-pr.el
+into @w{@file{@var{prefix}/share/emacs/lisp}}@footnote{If your main Emacs
+lisp repository is in a different directory from this, substitute that
+directory for @w{@file{@var{prefix}/share/emacs/lisp}}.}
+@end table
+
+@item info (@emph{optional})
+Builds @file{send-pr.info} from @file{send-pr.texi}@*
+@c FIXME - is this still true?
+(@file{send-pr.info} is included with this distribution)
+
+@item install-info (@emph{optional})
+Installs @file{send-pr.info} into @w{@file{@var{prefix}/info}}
+
+@item clean (@emph{optional})
+Removes all intermediary build files that can be rebuilt from source
+code
+@end table
+
+@item
+Run
+
+@smallexample
+install-sid @var{your-sid}
+@end smallexample
+
+@noindent
+where @var{your-sid} is the identification code you received with
+@w{@code{send-pr}}. @code{send-pr} automatically inserts this value
+into the template field @samp{>Submitter-Id:}. If you've downloaded
+@code{send-pr} from the Net, use @samp{net} for this value.
+
+@item
+Place the following line in
+@w{@file{@var{prefix}/share/emacs/lisp/default.el}}, or instruct your
+users to place the following line in their @file{.emacs} files:
+
+@smallexample
+(autoload 'send-pr "send-pr" "Submit a Problem Report." t)
+@end smallexample
+
+@item
+Create a mail alias for the Support Site from which you received
+@code{send-pr}, and for every site with which you wish to use
+@code{send-pr} to communicate. Each alias must have a suffix of
+@samp{-gnats}. The Support Site(s) will provide the correct addresses
+where these aliases should point. For instance, edit your mail aliases
+file to contain something like:
+
+@smallexample
+# support sites; for use with send-pr
+cygnus-gnats: bugs@@cygnus.com # Cygnus Solutions
+bumblebee-gnats: bumblebugs@@bumblebee.com # Bumblebee Inc.
+mycompany-gnats: bugs@@my.company.com (@emph{if you use @sc{gnats} locally})
+@end smallexample
+
+@code{send-pr} automatically searches for these aliases when you type
+
+@smallexample
+send-pr cygnus
+send-pr bumblebee
+send-pr @var{site}@dots{}
+@end smallexample
+
+@noindent
+@code{send-pr} also uses @var{site} to determine the categories of
+problems accepted by the site in question by looking in
+
+@smallexample
+@var{prefix}/share/gnats/@var{site}
+@end smallexample
+
+@end itemize
+
+@node default site
+@section Setting a default @var{site}
+@cindex default @var{site}
+@cindex setting a default @var{site}
+
+@code{send-pr} is capable of sending Problem Reports to any number of
+Support Sites, using mail aliases which have @samp{-gnats} appended them.
+@code{send-pr} automatically appends the suffix, so that when you type
+
+@smallexample
+send-pr @var{site}
+@end smallexample
+
+@noindent
+the Problem Report goes to the address noted in the @file{aliases} file
+as @w{@samp{@var{site}-gnats}}. You can do this in the Emacs version of
+@code{send-pr} by invoking the program with
+
+@smallexample
+C-u M-x send-pr
+@end smallexample
+
+@noindent
+You are prompted for @var{site}.
+
+@var{site} is also used to error-check the @samp{>Category:} field, as a
+precaution against sending mistaken information (and against sending
+information to the wrong site).
+
+You may also simply type
+
+@smallexample
+send-pr
+@end smallexample
+
+@noindent
+from the shell (or @w{@samp{M-x send-pr}} in Emacs), and the Problem
+Report you generate will be sent to the @var{site}, which is usually the
+site from which you received your distribution of @w{@code{send-pr}}.
+If you use @sc{gnats} at your own organization, the default is usually
+your local address for reporting problems.
+
+To change this, simply edit the file @file{Makefile} before installing
+and change the line
+
+@smallexample
+GNATS_SITE = @var{site}
+@end smallexample
+
+@noindent
+to reflect the site where you wish to send PRs by default.
+
+@c ---------------------------------------------------------------
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@c ---------------------------------------------------------------
+@contents
+@bye
diff --git a/gnu/usr.bin/send-pr/doc/states.texi b/gnu/usr.bin/send-pr/doc/states.texi
new file mode 100644
index 0000000..f38405c
--- /dev/null
+++ b/gnu/usr.bin/send-pr/doc/states.texi
@@ -0,0 +1,58 @@
+@c $FreeBSD$
+
+@node States
+@section States of Problem Reports
+
+@cindex life-cycle of a Problem Report
+@cindex states of Problem Reports
+@cindex Problem Report states
+@cindex automatic notification
+
+Each PR goes through a defined series of states between origination and
+closure. The originator of a PR receives notification automatically of
+any state changes.
+
+Unless your site has customized states (see @pxref{states
+file,,,gnats}), @sc{gnats} uses these states:
+
+@table @dfn
+@cindex @emph{open} state
+@cindex initial state (@dfn{open})
+@cindex state---@dfn{open}
+@item open
+The initial state of a Problem Report. This means the PR has been filed
+and the responsible person(s) notified.
+
+@cindex @emph{analyzed} state
+@cindex state---@dfn{analyzed}
+@item analyzed
+The responsible person has analyzed the problem. The analysis should
+contain a preliminary evaluation of the problem and an estimate of the
+amount of time and resources necessary to solve the problem. It should
+also suggest possible workarounds.
+
+@cindex @emph{feedback} state
+@cindex state---@dfn{feedback}
+@item feedback
+The problem has been solved, and the originator has been given a patch
+or other fix. The PR remains in this state until the originator
+acknowledges that the solution works.
+
+@cindex @emph{closed} state
+@cindex state---@dfn{closed}
+@cindex final state (@dfn{closed})
+@item closed
+A Problem Report is closed (``the bug stops here'') only when any
+changes have been integrated, documented, and tested, and the submitter
+has confirmed the solution.
+
+@cindex @emph{suspended} state
+@cindex state---@dfn{suspended}
+@item suspended
+Work on the problem has been postponed. This happens if a timely
+solution is not possible or is not cost-effective at the present time.
+The PR continues to exist, though a solution is not being actively
+sought. If the problem cannot be solved at all, it should be closed
+rather than suspended.
+@end table
+
diff --git a/gnu/usr.bin/send-pr/doc/version.texi b/gnu/usr.bin/send-pr/doc/version.texi
new file mode 100644
index 0000000..bffedc2
--- /dev/null
+++ b/gnu/usr.bin/send-pr/doc/version.texi
@@ -0,0 +1,3 @@
+@c $FreeBSD$
+
+@set VERSION 3.113
diff --git a/gnu/usr.bin/send-pr/install-sid.sh b/gnu/usr.bin/send-pr/install-sid.sh
new file mode 100755
index 0000000..f7f24e5
--- /dev/null
+++ b/gnu/usr.bin/send-pr/install-sid.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+# Drop in the SUBMITTER id into a site's installed send-pr script.
+# Copyright (C) 1993 Free Software Foundation, Inc.
+# Contributed by Brendan Kehoe (brendan@cygnus.com), based on a
+# version written by Heinz G. Seidl (hgs@ide.com).
+#
+# This file is part of GNU GNATS.
+#
+# GNU GNATS is free software; you can redistribute 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 GNATS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 GNATS; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+COMMAND=`echo $0 | sed -e 's,.*/,,g'`
+USAGE="Usage: $COMMAND [--install-dir=prefix] [--help] [--version] submitter-id"
+
+VERSION=3.2
+
+BINDIR=@BINDIR@
+
+SUBMITTER=
+TEMP=/tmp/sp$$
+
+if [ $# -eq 0 ]; then
+ echo "$USAGE"
+ exit 1
+fi
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -install-dir=*|--install-dir=*|--install-di=*|--install-d=*|--install-=*|--install=*|--instal=*|--insta=*|--inst=*|--ins=*|--in=*|--i=*)
+ I=`echo "$1" | sed 's/-*i[a-z\-]*=//'`
+ BINDIR=$I/bin ;;
+ --version) echo $COMMAND version $VERSION ; exit 1 ;;
+ -*) echo "$USAGE" ; exit 1 ;;
+ *) SUBMITTER=$1 ;;
+ esac
+ shift
+done
+
+path=`echo $0 | sed -e "s;${COMMAND};;"`
+
+[ -z "$path" ] && path=.
+
+if [ -f $BINDIR/send-pr ]; then
+ SPPATH=$BINDIR/send-pr
+elif [ -f $path/send-pr ]; then
+ SPPATH=$path/send-pr
+else
+ echo "$COMMAND: cannot find \`$BINDIR/send-pr' or \`$path/send-pr'" >&2
+ exit 1
+fi
+
+trap 'rm -f $TEMP ; exit 0' 0
+trap 'echo "$COM: Aborting ..."; rm -f $TEMP ; exit 1' 1 2 3 13 15
+
+sed -e "s/^SUBMITTER=.*/SUBMITTER=${SUBMITTER}/" $SPPATH > $TEMP
+
+if grep $SUBMITTER $TEMP > /dev/null; then
+ cp $SPPATH $SPPATH.orig &&
+ rm -f $SPPATH &&
+ cp $TEMP $SPPATH &&
+ chmod a+rx $SPPATH &&
+ rm -f $TEMP $SPPATH.orig ||
+ { echo "$COMMAND: unable to replace send-pr" >&2 ; exit 1; }
+else
+ echo "$COMMAND: something went wrong when sed-ing the submitter into send-pr" >&2
+ exit 1
+fi
+
+echo "$COMMAND: \`$SUBMITTER' is now the default submitter ID for send-pr"
+
+exit 0
diff --git a/gnu/usr.bin/send-pr/send-pr-el.in b/gnu/usr.bin/send-pr/send-pr-el.in
new file mode 100644
index 0000000..8195ecb
--- /dev/null
+++ b/gnu/usr.bin/send-pr/send-pr-el.in
@@ -0,0 +1,813 @@
+;;;; -*-emacs-lisp-*-
+;;;;---------------------------------------------------------------------------
+;;;; EMACS interface for send-pr (by Heinz G. Seidl)
+;;;; Slightly hacked by Brendan Kehoe (brendan@cygnus.com).
+;;;;
+;;;; This file is part of the Problem Report Management System (GNATS)
+;;;; Copyright 1992, 1993, 1997 Cygnus Support
+;;;;
+;;;; This program is free software; you can redistribute it and/or
+;;;; modify it under the terms of the GNU General Public
+;;;; License as published by the Free Software Foundation; either
+;;;; version 2 of the License, or (at your option) any later version.
+;;;;
+;;;; This program is distributed in the hope that it will be useful,
+;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;;; General Public License for more details.
+;;;;
+;;;; You should have received a copy of the GNU Library General Public
+;;;; License along with this program; if not, write to the Free
+;;;; Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+;;;;
+;;;;---------------------------------------------------------------------------
+;;;;
+;;;; This file contains the EMACS interface to the Problem Report Management
+;;;; System (GNATS):
+;;;;
+;;;; - The `send-pr' command and the `send-pr-mode' for sending
+;;;; Problem Reports (PRs).
+;;;;
+;;;; For more information about how to send a PR see send-pr(1).
+;;;;
+;;;;---------------------------------------------------------------------------
+;;;;
+;;;; Configuration: the symbol `DEFAULT-RELEASE' can be replaced by
+;;;; site/release specific strings during the configuration/installation
+;;;; process.
+;;;;
+;;;; Install this file in your EMACS library directory.
+;;;;
+;;;;---------------------------------------------------------------------------
+;;;;
+;;;; $FreeBSD$
+
+(provide 'send-pr)
+
+;;;;---------------------------------------------------------------------------
+;;;; Customization: put the following forms into your default.el file
+;;;; (or into your .emacs)
+;;;;---------------------------------------------------------------------------
+
+;(autoload 'send-pr-mode "send-pr"
+; "Major mode for sending problem reports." t)
+
+;(autoload 'send-pr "send-pr"
+; "Command to create and send a problem report." t)
+
+;;;;---------------------------------------------------------------------------
+;;;; End of Customization Section
+;;;;---------------------------------------------------------------------------
+
+(autoload 'server-buffer-done "server")
+(defvar server-buffer-clients nil)
+(defvar mail-self-blind nil)
+(defvar mail-default-reply-to nil)
+
+(defconst send-pr::version "3.113")
+
+(defvar gnats:root "/home/gnats"
+ "*The top of the tree containing the GNATS database.")
+
+;;;;---------------------------------------------------------------------------
+;;;; hooks
+;;;;---------------------------------------------------------------------------
+
+(defvar text-mode-hook nil) ; we define it here in case it's not defined
+(defvar send-pr-mode-hook text-mode-hook "Called when send-pr is invoked.")
+
+;;;;---------------------------------------------------------------------------
+;;;; Domains and default values for (some of) the Problem Report fields;
+;;;; constants and definitions.
+;;;;---------------------------------------------------------------------------
+
+(defconst gnats::emacs-19p
+ (not (or (and (boundp 'epoch::version) epoch::version)
+ (string-lessp emacs-version "19")))
+ "Is this emacs v19?")
+
+;;; This has to be here rather than at the bottom of this file with
+;;; the other utility functions because it is used by
+;;; gnats::get-config, which is called when send-pr.el is being
+;;; loaded (see the "defconst" below), before the whole file has been
+;;; loaded.
+
+(defun gnats::find-safe-default-directory (&optional buffer)
+"If the directory referred to by `default-directory' for the current
+buffer (or for optional argument BUFFER) does not exist, set it to the home
+directory of the current user if that exists, or to `/'.
+
+Returns the final value of default-directory in the buffer."
+ (let ((homedir (expand-file-name "~/")))
+ (save-excursion
+ (if buffer (set-buffer buffer))
+ (if (not (file-exists-p default-directory))
+ (if (file-exists-p homedir)
+ (setq default-directory homedir)
+ (setq default-directory "/")))
+ default-directory)))
+
+;;; These may be changed during configuration/installation or by the individual
+;;; user in his/her .emacs file.
+;;;
+(defun gnats::get-config (var)
+ (let ((shell-file-name "/bin/sh")
+ (buf (generate-new-buffer " *GNATS config*"))
+ ret)
+ (save-excursion
+ (set-buffer buf)
+ (shell-command-on-region
+ (point-min) (point-max)
+ (concat ". " gnats:root "/gnats-adm/config; echo $" var ) t)
+ (goto-char (point-min))
+ ; We have to use get-buffer, since shell-command-on-region will wipe
+ ; out the buffer if there's no output from the command.
+ (if (or (not (get-buffer "*Shell Command Output*"))
+ (looking-at "^\\.:\\|/bin/sh:\\|\n"))
+ (setq ret nil)
+ (setq ret (buffer-substring (point-min) (- (point-max) 1)))))
+ (if (and ret (string-equal ret "")) (setq ret nil))
+ (kill-buffer buf)
+ ret))
+
+;; const because it must match the script's value
+(defconst send-pr:datadir (or (gnats::get-config "DATADIR") "@DATADIR@")
+ "*Where the `gnats' subdirectory containing category lists lives.")
+
+(defvar send-pr::sites nil
+ "List of GNATS support sites; computed at runtime.")
+(defvar send-pr:default-site
+ (or (gnats::get-config "GNATS_SITE") "freefall")
+ "Default site to send bugs to.")
+(defvar send-pr:::site send-pr:default-site
+ "The site to which a problem report is currently being submitted, or NIL
+if using the default site (buffer local).")
+
+(defvar send-pr:::categories nil
+ "Buffer local list of available categories, derived at runtime from
+send-pr:::site and send-pr::category-alist.")
+(defvar send-pr::category-alist nil
+ "Alist of GNATS support sites and the categories supported at each; computed
+at runtime.")
+
+;;; Ideally we would get all the following values from a central database
+;;; during runtime instead of having them here in the code.
+;;;
+(defconst send-pr::fields
+ (` (("Category" send-pr::set-categories
+ (, (or (gnats::get-config "DEFAULT_CATEGORY") nil)) enum)
+ ("Class" (("sw-bug") ("doc-bug") ("change-request") ("update") ("maintainer-update"))
+ (, (or (gnats::get-config "DEFAULT_CLASS") 0)) enum)
+ ("Confidential" (("yes") ("no"))
+ (, (or (gnats::get-config "DEFAULT_CONFIDENTIAL") 1)) enum)
+ ("Severity" (("non-critical") ("serious") ("critical"))
+ (, (or (gnats::get-config "DEFAULT_SEVERITY") 1)) enum)
+ ("Priority" (("low") ("medium") ("high"))
+ (, (or (gnats::get-config "DEFAULT_PRIORITY") 1)) enum)
+ ("Release" nil
+ (, (or (gnats::get-config "DEFAULT_RELEASE") "@DEFAULT_RELEASE@"))
+ text)
+ ("Submitter-Id" nil
+ (, (or (gnats::get-config "DEFAULT_SUBMITTER") "unknown")) text)
+ ("Synopsis" nil nil text
+ (lambda (a b c) (gnats::set-mail-field "Subject" c)))))
+ "AList, keyed on the name of the field, of:
+1) The field name.
+2) The list of completions. This can be a list, a function to call, or nil.
+3) The default value.
+4) The type of the field.
+5) A sub-function to call when changed.")
+
+(defvar gnats::fields nil)
+
+(defmacro gnats::push (i l)
+ (` (setq (, l) (cons (,@ (list i l))))))
+
+(defun send-pr::set-categories (&optional arg)
+ "Get the list of categories for the current site out of
+send-pr::category-alist if there or from send-pr if not. With arg, force
+update."
+ ;;
+ (let ((entry (assoc send-pr:::site send-pr::category-alist)))
+ (or (and entry (null arg))
+ (let ((oldpr (getenv "GNATS_ROOT")) cats)
+ (send-pr::set-sites arg)
+ (setenv "GNATS_ROOT" gnats:root)
+ (setq cats (gnats::get-value-from-shell
+ "send-pr" "-CL" send-pr:::site))
+ (setenv "GNATS_ROOT" oldpr)
+ (if entry (setcdr entry cats)
+ (setq entry (cons send-pr:::site cats))
+ (gnats::push entry send-pr::category-alist))))
+ (setq send-pr:::categories (cdr entry))))
+
+(defun send-pr::set-sites (&optional arg)
+ "Get the list of sites (by listing the contents of DATADIR/gnats) and assign
+it to send-pr::sites. With arg, force update."
+ (or (and (null arg) send-pr::sites)
+ (progn
+ (setq send-pr::sites nil)
+ (mapcar
+ (function
+ (lambda (file)
+ (or (memq t (mapcar (function (lambda (x) (string= x file)))
+ '("." ".." "pr-edit" "pr-addr")))
+ (not (file-readable-p file))
+ (gnats::push (list (file-name-nondirectory file))
+ send-pr::sites))))
+ (directory-files (format "%s/gnats" send-pr:datadir) t))
+ (setq send-pr::sites (reverse send-pr::sites)))))
+
+(defconst send-pr::pr-buffer-name "*send-pr*"
+ "Name of the temporary buffer, where the problem report gets composed.")
+
+(defconst send-pr::err-buffer-name "*send-pr-error*"
+ "Name of the temporary buffer, where send-pr error messages appear.")
+
+(defvar send-pr:::err-buffer nil
+ "The error buffer used by the current PR buffer.")
+
+(defvar send-pr:::spawn-to-send nil
+ "Whether or not send-pr-mode should spawn a send-pr process to send the PR.")
+
+(defconst gnats::indent 17 "Indent for formatting the value.")
+
+;;;;---------------------------------------------------------------------------
+;;;; `send-pr' - command for creating and sending of problem reports
+;;;;---------------------------------------------------------------------------
+
+(fset 'send-pr 'send-pr:send-pr)
+(defun send-pr:send-pr (&optional site)
+ "Create a buffer and read in the result of `send-pr -P'.
+When finished with editing the problem report use \\[send-pr:submit-pr]
+to send the PR with `send-pr -b -f -'."
+ ;;
+ (interactive
+ (if current-prefix-arg
+ (list (completing-read "Site: " (send-pr::set-sites 'recheck) nil t
+ send-pr:default-site))))
+ (or site (setq site send-pr:default-site))
+ (let ((buf (get-buffer send-pr::pr-buffer-name)))
+ (if (or (not buf)
+ (progn (switch-to-buffer buf)
+ (cond ((or (not (buffer-modified-p buf))
+ (y-or-n-p "Erase previous problem report? "))
+ (erase-buffer) t)
+ (t nil))))
+ (send-pr::start-up site))))
+
+(defun send-pr::start-up (site)
+ (switch-to-buffer (get-buffer-create send-pr::pr-buffer-name))
+ (setq default-directory (expand-file-name "~/"))
+ (auto-save-mode auto-save-default)
+ (let ((oldpr (getenv "GNATS_ROOT"))
+ (case-fold-search nil))
+ (setenv "GNATS_ROOT" gnats:root)
+ (send-pr::insert-template site)
+ (setenv "GNATS_ROOT" oldpr)
+ (goto-char (point-min))
+ (if (looking-at "send-pr:")
+ (cond ((looking-at "send-pr: .* does not have a categories list")
+ (setq send-pr::sites nil)
+ (error "send-pr: the GNATS site %s does not have a categories list" site))
+ (t (error (buffer-substring (point-min) (point-max)))))
+ (save-excursion
+ ;; Clear cruft inserted by bdamaged .cshrcs
+ (goto-char 1)
+ (re-search-forward "^SEND-PR:")
+ (delete-region 1 (match-beginning 0)))))
+ (set-buffer-modified-p nil)
+ (send-pr:send-pr-mode)
+ (setq send-pr:::site site)
+ (setq send-pr:::spawn-to-send t)
+ (send-pr::set-categories)
+ (if (null send-pr:::categories)
+ (progn
+ (and send-pr:::err-buffer (kill-buffer send-pr:::err-buffer))
+ (kill-buffer nil)
+ (message "send-pr: no categories found"))
+ (or (stringp mail-default-reply-to)
+ (setq mail-default-reply-to (getenv "REPLYTO")))
+ (and mail-default-reply-to
+ (gnats::set-mail-field "Reply-To" mail-default-reply-to))
+ (and mail-self-blind
+ (gnats::set-mail-field "BCC" (user-login-name)))
+ (mapcar 'send-pr::maybe-change-field send-pr::fields)
+ (gnats::position-on-field "Description")
+ (message (substitute-command-keys
+ "To send the problem report use: \\[send-pr:submit-pr]"))))
+
+(defvar send-pr::template-alist nil
+ "An alist containing the output of send-pr -P <sitename> for various sites.")
+
+(defun send-pr::insert-template (site)
+ (let ((elt (assoc site send-pr::template-alist)))
+ (if elt
+ (save-excursion (insert (cdr elt)))
+ (call-process "send-pr" nil t nil "-P" site)
+ (save-excursion
+ (setq send-pr::template-alist
+ (cons (cons site (buffer-substring (point-min) (point-max)))
+ send-pr::template-alist))))))
+
+(fset 'do-send-pr 'send-pr:submit-pr) ;backward compat
+(defun send-pr:submit-pr ()
+ "Pipe the contents of the buffer *send-pr* to `send-pr -f -.' unless this
+buffer was loaded with emacsclient, in which case save the buffer and exit."
+ ;;
+ (interactive)
+ (cond
+ ((and (boundp 'server-buffer-clients)
+ server-buffer-clients)
+ (let ((buffer (current-buffer))
+ (version-control nil) (buffer-backed-up nil))
+ (save-buffer buffer)
+ (kill-buffer buffer)
+ (server-buffer-done buffer)))
+ (send-pr:::spawn-to-send
+ (if (or (buffer-modified-p)
+ (not send-pr:::sent)
+ (y-or-n-p "PR already sent; resend? "))
+ (progn
+ (or (and send-pr:::err-buffer
+ (buffer-name send-pr:::err-buffer))
+ (setq send-pr:::err-buffer
+ (get-buffer-create send-pr::err-buffer-name)))
+ (let ((err-buffer send-pr:::err-buffer) mesg ok)
+ (save-excursion (set-buffer err-buffer) (erase-buffer))
+ (message "running send-pr...")
+ (let ((oldpr (getenv "GNATS_ROOT")))
+ (setenv "GNATS_ROOT" gnats:root)
+ ;; ensure that a final newline is present:
+ (if (not (equal (char-after (1- (point-max))) ?\n))
+ (save-excursion (goto-char (point-max))
+ (insert ?\n)))
+ (call-process-region (point-min) (point-max) "send-pr"
+ nil err-buffer nil send-pr:::site
+ "-b" "-f" "-")
+ (setenv "GNATS_ROOT" oldpr))
+ (message "running send-pr...done")
+ ;; stupidly we cannot check the return value in EMACS 18.57,
+ ;; thus we need this kluge to find out whether send-pr succeeded.
+ (if (save-excursion
+ (set-buffer err-buffer)
+ (goto-char (point-min))
+ (setq mesg (buffer-substring (point-min) (- (point-max) 1)))
+ (search-forward "problem report sent" nil t))
+ (progn (message mesg)
+ (kill-buffer err-buffer)
+ (delete-auto-save-file-if-necessary)
+ (set-buffer-modified-p nil)
+ (setq send-pr:::sent t)
+ (bury-buffer))
+ (pop-to-buffer err-buffer))
+ ))))
+ (t
+ (save-buffer)
+ (message "Exit emacs to send the PR."))))
+
+;;;;---------------------------------------------------------------------------
+;;;; send-pr:send-pr-mode mode
+;;;;---------------------------------------------------------------------------
+
+(defvar send-pr-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-c\C-c" 'send-pr:submit-pr)
+ (define-key map "\C-c\C-f" 'gnats:change-field)
+ (define-key map "\M-n" 'gnats:next-field)
+ (define-key map "\M-p" 'gnats:previous-field)
+ (define-key map "\C-\M-f" 'gnats:forward-field)
+ (define-key map "\C-\M-b" 'gnats:backward-field)
+ map)
+ "Keymap for send-pr mode.")
+
+(defconst gnats::keyword "^>\\([-a-zA-Z]+\\):")
+(defconst gnats::before-keyword "[ \t\n\f]*[\n\f]+>\\([-a-zA-Z]+\\):")
+(defconst gnats::after-keyword "^>\\([-a-zA-Z]+\\):[ \t\n\f]+")
+
+(fset 'send-pr-mode 'send-pr:send-pr-mode)
+(defun send-pr:send-pr-mode ()
+ "Major mode for submitting problem reports.
+For information about the form see gnats(1) and send-pr(1).
+Special commands: \\{send-pr-mode-map}
+Turning on send-pr-mode calls the value of the variable send-pr-mode-hook,
+if it is not nil."
+ (interactive)
+ (gnats::patch-exec-path)
+ (put 'send-pr:send-pr-mode 'mode-class 'special)
+ (kill-all-local-variables)
+ (setq major-mode 'send-pr:send-pr-mode)
+ (setq mode-name "send-pr")
+ (use-local-map send-pr-mode-map)
+ (set-syntax-table text-mode-syntax-table)
+ (setq local-abbrev-table text-mode-abbrev-table)
+ (setq buffer-offer-save t)
+ (make-local-variable 'send-pr:::site)
+ (make-local-variable 'send-pr:::categories)
+ (make-local-variable 'send-pr:::err-buffer)
+ (make-local-variable 'send-pr:::spawn-to-send)
+ (make-local-variable 'send-pr:::sent)
+ (setq send-pr:::sent nil)
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate (concat (default-value 'paragraph-separate)
+ "\\|" gnats::keyword "[ \t\n\f]*$"))
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat (default-value 'paragraph-start)
+ "\\|" gnats::keyword))
+ (run-hooks 'send-pr-mode-hook)
+ t)
+
+;;;;---------------------------------------------------------------------------
+;;;; Functions to read and replace field values.
+;;;;---------------------------------------------------------------------------
+
+(defun gnats::position-on-field (field &optional quiet)
+ (goto-char (point-min))
+ (if (not (re-search-forward (concat "^>" field ":") nil t))
+ (if quiet
+ nil
+ (error "Field `>%s:' not found." field))
+ (re-search-forward "[ \t\n\f]*")
+ (if (looking-at gnats::keyword)
+ (backward-char 1))
+ t))
+
+(defun gnats::mail-position-on-field (field)
+ (let (end
+ (case-fold-search t))
+ (goto-char (point-min))
+ (re-search-forward "^$")
+ (setq end (match-beginning 0))
+ (goto-char (point-min))
+ (if (not (re-search-forward (concat "^" field ":") end 'go-to-end))
+ (insert field ": \n")
+ (re-search-forward "[ \t\n\f]*"))
+ (skip-chars-backward "\n")
+ t))
+
+(defun gnats::field-contents (field &optional elem move)
+ (let (pos)
+ (unwind-protect
+ (save-excursion
+ (if (not (gnats::position-on-field field t))
+ nil
+ (setq pos (point-marker))
+ (if (or (looking-at "<.*>$") (eolp))
+ t
+ (looking-at ".*$") ; to set match-{beginning,end}
+ (gnats::nth-word
+ (buffer-substring (match-beginning 0) (match-end 0))
+ elem))))
+ (and move pos (goto-char pos)))))
+
+(defun gnats::functionp (thing)
+ (or (and (symbolp thing) (fboundp thing))
+ (and (listp thing) (eq (car thing) 'lambda))))
+
+(defun gnats::field-values (field)
+ "Return the possible (known) values for field FIELD."
+ (let* ((fields (if (eq major-mode 'gnats:gnats-mode) gnats::fields
+ send-pr::fields))
+ (thing (elt (assoc field fields) 1)))
+ (cond ((gnats::functionp thing) (funcall thing))
+ ((listp thing) thing)
+ (t (error "ACK")))))
+
+(defun gnats::field-default (field)
+ "Return the default value for field FIELD."
+ (let* ((fields (if (eq major-mode 'gnats:gnats-mode) gnats::fields
+ send-pr::fields))
+ (thing (elt (assoc field fields) 2)))
+ (cond ((stringp thing) thing)
+ ((null thing) "")
+ ((numberp thing) (car (elt (gnats::field-values field) thing)))
+ ((gnats::functionp thing)
+ (funcall thing (gnats::field-contents field)))
+ ((eq thing t) (gnats::field-contents field))
+ (t (error "ACK")))))
+
+(defun gnats::field-type (field)
+ "Return the type of field FIELD."
+ (let* ((fields (if (eq major-mode 'gnats:gnats-mode) gnats::fields
+ send-pr::fields))
+ (thing (elt (assoc field fields) 3)))
+ thing))
+
+(defun gnats::field-action (field)
+ "Return the extra handling function for field FIELD."
+ (let* ((fields (if (eq major-mode 'gnats:gnats-mode) gnats::fields
+ send-pr::fields))
+ (thing (elt (assoc field fields) 4)))
+ (cond ((null thing) 'ignore)
+ ((gnats::functionp thing) thing)
+ (t (error "ACK")))))
+
+;;;;---------------------------------------------------------------------------
+;;;; Point movement functions
+;;;;---------------------------------------------------------------------------
+
+(or (fboundp 'defsubst) (fset 'defsubst 'defun))
+
+(defun send-pr::maybe-change-field (field)
+ (setq field (car field))
+ (let ((thing (gnats::field-contents field)))
+ (and thing (eq t thing)
+ (not (eq 'multi-text (gnats::field-type field)))
+ (gnats:change-field field))))
+
+(defun gnats:change-field (&optional field default)
+ "Change the value of the field containing the cursor. With arg, ask the
+user for the field to change. From a program, the function takes optional
+arguments of the field to change and the default value to use."
+ (interactive)
+ (or field current-prefix-arg (setq field (gnats::current-field)))
+ (or field
+ (setq field
+ (completing-read "Field: "
+ (if (eq major-mode 'gnats:gnats-mode)
+ gnats::fields
+ send-pr::fields)
+ nil t)))
+ (gnats::position-on-field field)
+ (sit-for 0)
+ (let* ((old (gnats::field-contents field))
+ new)
+ (if (null old)
+ (error "ACK")
+ (if (or (interactive-p) t)
+ (let ((prompt (concat ">" field ": "))
+ (domain (gnats::field-values field))
+ (type (gnats::field-type field)))
+ (or default (setq default (gnats::field-default field)))
+ (setq new
+ (if (eq type 'enum)
+ (completing-read prompt domain nil t
+ (if gnats::emacs-19p (cons default 0)
+ default))
+ (read-string prompt (if gnats::emacs-19p (cons default 1)
+ default)))))
+ (setq new default))
+ (gnats::set-field field new)
+ (funcall (gnats::field-action field) field old new)
+ new)))
+
+(defun gnats::set-field (field value)
+ (save-excursion
+ (gnats::position-on-field field)
+ (delete-horizontal-space)
+ (looking-at ".*$")
+ (replace-match
+ (concat (make-string (- gnats::indent (length field) 2) ?\40 ) value) t)))
+
+(defun gnats::set-mail-field (field value)
+ (save-excursion
+ (gnats::mail-position-on-field field)
+ (delete-horizontal-space)
+ (looking-at ".*$")
+ (replace-match (concat " " value) t)))
+
+(defun gnats::before-keyword (&optional where)
+ "Returns t if point is in some white space before a keyword.
+If where is nil, then point is not changed; if where is t then point is moved
+to the beginning of the keyword, otherwise it is moved to the beginning
+of the white space it was in."
+ ;;
+ (if (looking-at gnats::before-keyword)
+ (prog1 t
+ (cond ((eq where t)
+ (re-search-forward "^>") (backward-char))
+ ((not (eq where nil))
+ (re-search-backward "[^ \t\n\f]") (forward-char))))
+ nil))
+
+(defun gnats::after-keyword (&optional where)
+ "Returns t if point is in some white space after a keyword.
+If where is nil, then point is not changed; if where is t then point is moved
+to the beginning of the keyword, otherwise it is moved to the end of the white
+space it was in."
+ ;;
+ (if (gnats::looking-after gnats::after-keyword)
+ (prog1 t
+ (cond ((eq where t)
+ (re-search-backward "^>"))
+ ((not (eq where nil))
+ (re-search-forward "[^ \t\n\f]") (backward-char))))
+ nil))
+
+(defun gnats::in-keyword (&optional where)
+ "Returns t if point is within a keyword.
+If where is nil, then point is not changed; if where is t then point is moved
+to the beginning of the keyword."
+ ;;
+ (let ((old-point (point-marker)))
+ (beginning-of-line)
+ (cond ((and (looking-at gnats::keyword)
+ (< old-point (match-end 0)))
+ (prog1 t
+ (if (eq where t)
+ t
+ (goto-char old-point))))
+ (t (goto-char old-point)
+ nil))))
+
+(defun gnats::forward-bofield ()
+ "Moves point to the beginning of a field. Assumes that point is in the
+keyword."
+ ;;
+ (if (re-search-forward "[ \t\n\f]+[^ \t\n\f]" (point-max) '-)
+ (backward-char)
+ t))
+
+(defun gnats::backward-eofield ()
+ "Moves point to the end of a field. Assumes point is in the keyword."
+ ;;
+ (if (re-search-backward "[^ \t\n\f][ \t\n\f]+" (point-min) '-)
+ (forward-char)
+ t))
+
+(defun gnats::forward-eofield ()
+ "Moves point to the end of a field. Assumes that point is in the field."
+ ;;
+ ;; look for the next field
+ (if (re-search-forward gnats::keyword (point-max) '-)
+ (progn (beginning-of-line) (gnats::backward-eofield))
+ (re-search-backward "[^ \t\n\f][ \t\n\f]*" (point-min) '-)
+ (forward-char)))
+
+(defun gnats::backward-bofield ()
+ "Moves point to the beginning of a field. Assumes that point is in the
+field."
+ ;;
+ ;;look for previous field
+ (if (re-search-backward gnats::keyword (point-min) '-)
+ (gnats::forward-bofield)
+ t))
+
+
+(defun gnats:forward-field ()
+ "Move point forward to the end of the field or to the beginning of the next
+field."
+ ;;
+ (interactive)
+ (if (or (gnats::before-keyword t) (gnats::in-keyword t)
+ (gnats::after-keyword t))
+ (gnats::forward-bofield)
+ (gnats::forward-eofield)))
+
+(defun gnats:backward-field ()
+ "Move point backward to the beginning/end of a field."
+ ;;
+ (interactive)
+ (backward-char)
+ (if (or (gnats::before-keyword t) (gnats::in-keyword t)
+ (gnats::after-keyword t))
+ (gnats::backward-eofield)
+ (gnats::backward-bofield)))
+
+(defun gnats:next-field ()
+ "Move point to the beginning of the next field."
+ ;;
+ (interactive)
+ (if (or (gnats::before-keyword t) (gnats::in-keyword t)
+ (gnats::after-keyword t))
+ (gnats::forward-bofield)
+ (if (re-search-forward gnats::keyword (point-max) '-)
+ (gnats::forward-bofield)
+ t)))
+
+(defun gnats:previous-field ()
+ "Move point to the beginning of the previous field."
+ ;;
+ (interactive)
+ (backward-char)
+ (if (or (gnats::after-keyword t) (gnats::in-keyword t)
+ (gnats::before-keyword t))
+ (progn (re-search-backward gnats::keyword (point-min) '-)
+ (gnats::forward-bofield))
+ (gnats::backward-bofield)))
+
+(defun gnats:beginning-of-field ()
+ "Move point to the beginning of the current field."
+ (interactive)
+ (cond ((gnats::in-keyword t)
+ (gnats::forward-bofield))
+ ((gnats::after-keyword 0))
+ (t
+ (gnats::backward-bofield))))
+
+(defun gnats::current-field ()
+ (save-excursion
+ (if (cond ((or (gnats::in-keyword t) (gnats::after-keyword t))
+ (looking-at gnats::keyword))
+ ((re-search-backward gnats::keyword nil t)))
+ (buffer-substring (match-beginning 1) (match-end 1))
+ nil)))
+
+;;;;---------------------------------------------------------------------------
+;;;; Support functions
+;;;;---------------------------------------------------------------------------
+
+(defun gnats::looking-after (regex)
+ "Returns t if point is after regex."
+ ;;
+ (let* ((old-point (point))
+ (start (if (eobp)
+ old-point
+ (forward-char) (point))))
+ (cond ((re-search-backward regex (point-min) t)
+ (goto-char old-point)
+ (cond ((eq (match-end 0) start)
+ t))))))
+
+(defun gnats::nth-word (string &optional elem)
+ "Returns the elem-th word of the string.
+If elem is nil, then the first wort is returned, if elem is 0 then
+the whole string is returned."
+ ;;
+ (if (integerp elem)
+ (cond ((eq elem 0) string)
+ ((eq elem 1) (gnats::first-word string))
+ ((equal string "") "")
+ ((>= elem 2)
+ (let ((i 0) (value ""))
+ (setq string ; strip leading blanks
+ (substring string (or (string-match "[^ \t]" string) 0)))
+ (while (< i elem)
+ (setq value
+ (substring string 0
+ (string-match "[ \t]*$\\|[ \t]+" string)))
+ (setq string
+ (substring string (match-end 0)))
+ (setq i (+ i 1)))
+ value)))
+ (gnats::first-word string)))
+
+(defun gnats::first-word (string)
+ (setq string
+ (substring string (or (string-match "[^ \t]" string) 0)))
+ (substring string 0 (string-match "[ \t]*$\\|[ \t]+" string)))
+
+;;;;---------------------------------------------------------------------------
+
+(defun gnats::patch-exec-path ()
+ ;;
+ "Replaces `//' by `/' in `exec-path'."
+ ;;
+ ;(make-local-variable 'exec-path)
+ (let ((err-buffer (get-buffer-create " *gnats::patch-exec-path*"))
+ (ret))
+ (setq exec-path (save-excursion (set-buffer err-buffer)
+ (prin1 exec-path err-buffer)
+ (goto-char (point-min))
+ (while (search-forward "//" nil t)
+ (replace-match "/" nil t))
+ (goto-char (point-min))
+ (setq ret (read err-buffer))
+ (kill-buffer err-buffer)
+ ret
+ ))))
+
+(defun gnats::get-value-from-shell (&rest command)
+ "Execute shell command to get a list of valid values for `variable'."
+ ;;
+ (let ((err-buffer (get-buffer-create " *gnats::get-value-from-shell*")))
+ (save-excursion
+ (set-buffer err-buffer)
+ (unwind-protect
+ (condition-case var
+ (progn
+ (apply 'call-process
+ (car command) nil err-buffer nil (cdr command))
+ (goto-char (point-min))
+ (if (looking-at "[-a-z]+: ")
+ (error (buffer-substring (point-min) (point-max))))
+ (read err-buffer))
+ (error nil))
+ (kill-buffer err-buffer)))))
+
+(or (fboundp 'setenv)
+ (defun setenv (variable &optional value)
+ "Set the value of the environment variable named VARIABLE to VALUE.
+VARIABLE should be a string. VALUE is optional; if not provided or is
+`nil', the environment variable VARIABLE will be removed.
+This function works by modifying `process-environment'."
+ (interactive "sSet environment variable: \nsSet %s to value: ")
+ (if (string-match "=" variable)
+ (error "Environment variable name `%s' contains `='" variable)
+ (let ((pattern (concat "\\`" (regexp-quote (concat variable "="))))
+ (case-fold-search nil)
+ (scan process-environment))
+ (while scan
+ (cond
+ ((string-match pattern (car scan))
+ (if (eq nil value)
+ (setq process-environment (delq (car scan)
+ process-environment))
+ (setcar scan (concat variable "=" value)))
+ (setq scan nil))
+ ((null (setq scan (cdr scan)))
+ (setq process-environment
+ (cons (concat variable "=" value)
+ process-environment)))))))))
+
+;;;; end of send-pr.el
diff --git a/gnu/usr.bin/send-pr/send-pr.1 b/gnu/usr.bin/send-pr/send-pr.1
new file mode 100644
index 0000000..71d48fc
--- /dev/null
+++ b/gnu/usr.bin/send-pr/send-pr.1
@@ -0,0 +1,313 @@
+.\" -*- nroff -*-
+.\" ---------------------------------------------------------------------------
+.\" man page for send-pr (by Heinz G. Seidl, hgs@cygnus.com)
+.\" updated Feb 1993 for GNATS 3.00 by Jeffrey Osier, jeffrey@cygnus.com
+.\"
+.\" This file is part of the Problem Report Management System (GNATS)
+.\" Copyright 1992 Cygnus Support
+.\"
+.\" This program is free software; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public
+.\" License as published by the Free Software Foundation; either
+.\" version 2 of the License, or (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU Library General Public
+.\" License along with this program; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
+.\"
+.\" ---------------------------------------------------------------------------
+.\"
+.\" $FreeBSD$
+.nh
+.TH SEND-PR 1 3.113 "February 1993"
+.SH NAME
+send-pr \- send problem report (PR) to a central support site
+.SH SYNOPSIS
+.B send-pr
+[
+.I site
+]
+[
+.B \-f
+.I problem-report
+]
+[
+.B \-t
+.I mail-address
+]
+.br
+.in +0.8i
+[
+.B \-P
+]
+[
+.B \-L
+]
+[
+.B \-s
+.I severity
+]
+[
+.B \-V
+]
+.br
+[
+.B \-\-version
+]
+[
+.B \-c
+.I address
+]
+[
+.B \-a
+.I file
+]
+.SH DESCRIPTION
+.B send-pr
+is a tool used to submit
+.I problem reports
+.\" SITE ADMINISTRATORS - change this if you use a local default
+(PRs) to a central support site. In most cases the correct
+.I site
+will be the default. This argument indicates the support site which
+is responsible for the category of problem involved. Some sites may
+use a local address as a default.
+.I site
+values are defined by using the
+.BR aliases (5).
+.LP
+.B send-pr
+invokes an editor on a problem report template (after trying to fill
+in some fields with reasonable default values). When you exit the
+editor,
+.B send-pr
+sends the completed form to the
+.I Problem Report Management System
+(\fBGNATS\fR) at a central support site. At the support site, the PR
+is assigned a unique number and is stored in the \fBGNATS\fR database
+according to its category and submitter-id. \fBGNATS\fR automatically
+replies with an acknowledgement, citing the category and the PR
+number.
+.LP
+To ensure that a PR is handled promptly, it should contain
+one of the available \fIcategories\fR to identify the
+problem area. (Use
+.B `send-pr -L'
+to see a list of categories.)
+.LP
+The more precise your problem description and the more complete your
+information, the faster your support team can solve your problems.
+.SH OPTIONS
+.TP
+.BI \-f " problem-report"
+specify a file (\fIproblem-report\fR) which already contains a
+complete problem report.
+.B send-pr
+sends the contents of the file without invoking the editor. If
+the value for
+.I problem-report
+is
+.BR `\|\-\|' ,
+then
+.B send-pr
+reads from standard input.
+.TP
+.BI \-s " severity"
+Give the problem report the severity
+.IR severity .
+.TP
+.BI \-t " mail-address"
+Change mail address at the support site for problem reports. The
+default
+.I mail-address
+is the address used for the default
+.IR site .
+Use the
+.I site
+argument rather than this option in nearly all cases.
+.TP
+.BI \-c " address"
+Put
+.I address
+in the
+.B Cc:
+header of the message.
+.TP
+.BI \-a " file"
+Copy the specified
+.I file
+into the
+.B Fix:
+section.
+Binary files are uuencoded.
+.TP
+.B \-P
+print the form specified by the environment variable
+.B PR_FORM
+on standard output. If
+.B PR_FORM
+is not set, print the standard blank PR template. No mail is sent.
+.TP
+.B \-L
+print the list of available categories. No mail is sent.
+.TP
+.B \-V
+Display the
+.B send-pr
+version number.
+This may also be specified as
+.B \-\-version.
+.LP
+Note: use
+.B send-pr
+to submit problem reports rather than mailing them directly. Using
+both the template and
+.B send-pr
+itself will help ensure all necessary information will reach the
+support site.
+.SH FREEBSD CATEGORIES
+.TP
+.B advocacy
+This used to be for the advocacy WWW pages. Not quite sure what is used
+for now.
+.TP
+.B alpha
+Alpha processor specific problems.
+.TP
+.B bin
+Corrections or enhancements to system executables.
+.TP
+.B conf
+Corrections or enhancements to the system configuration files.
+.TP
+.B docs
+Corrections or enhancements to the manpages or other documentation.
+.TP
+.B gnu
+Corrections or enhancements to the GNU contributed software.
+.TP
+.B i386
+Intel x86 processor specific problems.
+.TP
+.B ia64
+Intel ia64 processor specific problems.
+.TP
+.B kern
+Changes or enhancements to the architecture independent kernel sources.
+.TP
+.B misc
+Problems that don't fit into any of the other categories.
+.TP
+.B ports
+Corrections or enhancements (including new ports) to the ports collection.
+.TP
+.B sparc64
+SPARC processor specific problems.
+.TP
+.B standards
+Standards conformance issues.
+.TP
+.B www
+Changes or enhancements to the FreeBSD website.
+.SH ENVIRONMENT
+The environment variable
+.B EDITOR
+specifies the editor to invoke on the template.
+.br
+default:
+.B vi
+.sp
+If the environment variable
+.B PR_FORM
+is set, then its value is used as the file name of the template for
+your problem-report editing session. You can use this to start with a
+partially completed form (for example, a form with the identification
+fields already completed).
+.SH "HOW TO FILL OUT A PROBLEM REPORT"
+Problem reports have to be in a particular form so that a program can
+easily manage them. Please remember the following guidelines:
+.IP \(bu 3m
+describe only
+.B one problem
+with each problem report.
+.IP \(bu 3m
+For follow-up mail, use the same subject line as the one in the automatic
+acknowledgement. It consists of category, PR number and the original synopsis
+line. This allows the support site to relate several mail messages to a
+particular PR and to record them automatically.
+.IP \(bu 3m
+Please try to be as accurate as possible in the subject and/or synopsis line.
+.IP \(bu 3m
+The subject and the synopsis line are not confidential. This is
+because open-bugs lists are compiled from them. Avoid confidential
+information there.
+.LP
+See the GNU
+.B Info
+file
+.B send-pr.info
+or the document \fIReporting Problems With send-pr\fR\ for detailed
+information on reporting problems
+.SH "HOW TO SUBMIT TEST CASES, CODE, ETC."
+Submit small code samples with the PR. Contact the support site for
+instructions on submitting larger test cases and problematic source
+code.
+.SH FILES
+.ta \w'/tmp/pbad$$ 'u
+/tmp/p$$ copy of PR used in editing session
+.br
+/tmp/pf$$ copy of empty PR form, for testing purposes
+.br
+/tmp/pbad$$ file for rejected PRs
+.SH EMACS USER INTERFACE
+An Emacs user interface for
+.B send-pr
+with completion of field values is part of the
+.B send-pr
+distribution (invoked with
+.BR "M-x send-pr" ).
+See the file
+.B send-pr.info
+or the ASCII file
+.B INSTALL
+in the top level directory of the distribution for configuration and
+installation information. The Emacs LISP template file is
+.B send-pr-el.in
+and is installed as
+.BR send-pr.el .
+.SH INSTALLATION AND CONFIGURATION
+See
+.B send-pr.info
+or
+.B INSTALL
+for installation instructions.
+.SH SEE ALSO
+.I Reporting Problems Using send-pr
+(also installed as the GNU Info file
+.BR send-pr.info ).
+.SH AUTHORS
+Jeffrey Osier, Brendan Kehoe, Jason Merrill, Heinz G. Seidl (Cygnus
+Support)
+.SH COPYING
+Copyright (c) 1992, 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/gnu/usr.bin/send-pr/send-pr.sh b/gnu/usr.bin/send-pr/send-pr.sh
new file mode 100644
index 0000000..e3c149d
--- /dev/null
+++ b/gnu/usr.bin/send-pr/send-pr.sh
@@ -0,0 +1,571 @@
+#!/bin/sh
+# Submit a problem report to a GNATS site.
+# Copyright (C) 1993 Free Software Foundation, Inc.
+# Contributed by Brendan Kehoe (brendan@cygnus.com), based on a
+# version written by Heinz G. Seidl (hgs@cygnus.com).
+#
+# This file is part of GNU GNATS.
+#
+# GNU GNATS is free software; you can redistribute 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 GNATS is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 GNATS; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# $FreeBSD$
+
+# The version of this send-pr.
+VERSION=3.113
+
+# The submitter-id for your site.
+# "current-users" is the only allowable value for FreeBSD.
+SUBMITTER="current-users"
+
+# Where the GNATS directory lives, if at all.
+[ -z "$GNATS_ROOT" ] &&
+GNATS_ROOT=
+
+# The default mail address for PR submissions.
+GNATS_ADDR=FreeBSD-gnats-submit@freebsd.org
+
+# Where the gnats category tree lives.
+DATADIR=@DATADIR@
+
+# If we've been moved around, try using GCC_EXEC_PREFIX.
+[ ! -d $DATADIR/gnats -a -d "$GCC_EXEC_PREFIX" ] && DATADIR="$GCC_EXEC_PREFIX"
+
+# The default release for this host.
+DEFAULT_RELEASE="@DEFAULT_RELEASE@"
+
+# The default organization.
+DEFAULT_ORGANIZATION=
+
+# The default site to look for.
+GNATS_SITE=freefall
+
+# Newer config information?
+[ -f ${GNATS_ROOT}/gnats-adm/config ] && . ${GNATS_ROOT}/gnats-adm/config
+
+# What mailer to use. This must come after the config file, since it is
+# host-dependent.
+MAIL_AGENT="${MAIL_AGENT:-/usr/sbin/sendmail -oi -t}"
+
+# Path to pw(8)
+PW="/usr/sbin/pw"
+
+ECHON=bsd
+
+if [ $ECHON = bsd ] ; then
+ ECHON1="echo -n"
+ ECHON2=
+elif [ $ECHON = sysv ] ; then
+ ECHON1=echo
+ ECHON2='\c'
+else
+ ECHON1=echo
+ ECHON2=
+fi
+
+#
+
+# find a user name
+if [ "$LOGNAME" = "" ]; then
+ if [ "$USER" != "" ]; then
+ LOGNAME="$USER"
+ else
+ LOGNAME="UNKNOWN"
+ fi
+fi
+
+# Find out the name of the originator of this PR.
+if [ -n "$NAME" ]; then
+ ORIGINATOR="$NAME"
+elif [ -f $HOME/.fullname ]; then
+ ORIGINATOR="`sed -e '1q' $HOME/.fullname`"
+else
+ PTEMP=`mktemp -t p` || exit 1
+ # Must use temp file due to incompatibilities in quoting behavior
+ # and to protect shell metacharacters in the expansion of $LOGNAME
+ $PW usershow $LOGNAME | awk -F: '{ print $8 }' | sed -e 's/,.*//' > $PTEMP
+ ORIGINATOR="`cat $PTEMP`"
+ rm -f $PTEMP
+fi
+
+FROM="$ORIGINATOR <$LOGNAME>"
+REPLY_TO="$ORIGINATOR <${REPLY_TO:-${REPLYTO:-$LOGNAME}}>"
+
+if [ -n "$ORGANIZATION" ]; then
+ if [ -f "$ORGANIZATION" ]; then
+ ORGANIZATION="`cat $ORGANIZATION`"
+ fi
+else
+ if [ -n "$DEFAULT_ORGANIZATION" ]; then
+ ORGANIZATION="$DEFAULT_ORGANIZATION"
+ elif [ -f $HOME/.organization ]; then
+ ORGANIZATION="`cat $HOME/.organization`"
+ fi
+fi
+
+# If they don't have a preferred editor set, then use
+if [ -z "$VISUAL" ]; then
+ if [ -z "$EDITOR" ]; then
+ EDIT=vi
+ else
+ EDIT="$EDITOR"
+ fi
+else
+ EDIT="$VISUAL"
+fi
+
+# Find out some information.
+SYSTEM=`( [ -f /bin/uname ] && /bin/uname -a ) || \
+ ( [ -f /usr/bin/uname ] && /usr/bin/uname -a ) || echo ""`
+ARCH=`[ -f /bin/arch ] && /bin/arch`
+MACHINE=`[ -f /bin/machine ] && /bin/machine`
+
+COMMAND=`echo $0 | sed -e 's,.*/,,'`
+USAGE="Usage: $COMMAND [-PVL] [-t address] [-f filename] [-s severity]
+ [-c address] [-a file] [--version]"
+REMOVE=
+BATCH=
+CC=
+SEVERITY_C=
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -r) ;; # Ignore for backward compat.
+ -t | --to) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+ shift ; GNATS_ADDR="$1"
+ EXPLICIT_GNATS_ADDR=true
+ ;;
+ -f | --file) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+ shift ; IN_FILE="$1"
+ if [ "$IN_FILE" != "-" -a ! -r "$IN_FILE" ]; then
+ echo "$COMMAND: cannot read $IN_FILE"
+ exit 1
+ fi
+ ;;
+ -b | --batch) BATCH=true ;;
+ -c | --cc) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+ shift ; CC="$1"
+ ;;
+ -s | --severity) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
+ shift ; SEVERITY_C="$1"
+ ;;
+ -p | -P | --print) PRINT=true ;;
+ -L | --list) FORMAT=norm ;;
+ -l | -CL | --lisp) FORMAT=lisp ;;
+ -h | --help) echo "$USAGE"; exit 0 ;;
+ -V | --version) echo "$VERSION"; exit 0 ;;
+ -a | --attach) if [ -z "$2" ]; then
+ echo "$USAGE" ; exit 1;
+ fi
+ if [ -e "$2" -a ! -d "$2" ]; then
+ PRETTY_NAME=`basename $2`
+ if file $2 | grep "text" >/dev/null 2>/dev/null ; then
+ ATTACHED_FILES="$ATTACHED_FILES
+--- $PRETTY_NAME begins here ---
+`cat \"$2\"`
+--- $PRETTY_NAME ends here ---
+"
+ else
+ ATTACHED_FILES="$ATTACHED_FILES
+`uuencode \"$PRETTY_NAME\" < \"$2\"`
+"
+ fi
+ shift;
+ fi;
+ ;;
+ -*) echo "$USAGE" ; exit 1 ;;
+ *) if [ -z "$USER_GNATS_SITE" ]; then
+ if [ ! -r "$DATADIR/gnats/$1" ]; then
+ echo "$COMMAND: the GNATS site $1 does not have a categories list."
+ exit 1
+ else
+ # The site name is the alias they'll have to have created.
+ USER_GNATS_SITE=$1
+ fi
+ else
+ echo "$USAGE" ; exit 1
+ fi
+ ;;
+ esac
+ shift
+done
+
+if [ -n "$USER_GNATS_SITE" ] && [ "$USER_GNATS_SITE" != "$GNATS_SITE" ]; then
+ GNATS_SITE=$USER_GNATS_SITE
+ GNATS_ADDR=$USER_GNATS_SITE-gnats
+fi
+
+if [ "$SUBMITTER" = "unknown" -a -z "$IN_FILE" ]; then
+ SUBMITTER="current-users"
+fi
+
+if [ -r "$DATADIR/gnats/$GNATS_SITE" ]; then
+ CATEGORIES=`grep -v '^#' $DATADIR/gnats/$GNATS_SITE | sort`
+else
+ echo "$COMMAND: could not read $DATADIR/gnats/$GNATS_SITE for categories list."
+ exit 1
+fi
+
+if [ -z "$CATEGORIES" ]; then
+ echo "$COMMAND: the categories list for $GNATS_SITE was empty!"
+ exit 1
+fi
+
+case "$FORMAT" in
+ lisp) echo "$CATEGORIES" | \
+ awk 'BEGIN {printf "( "} {printf "(\"%s\") ",$0} END {printf ")\n"}'
+ exit 0
+ ;;
+ norm) l=`echo "$CATEGORIES" | \
+ awk 'BEGIN {max = 0; } { if (length($0) > max) { max = length($0); } }
+ END {print max + 1;}'`
+ c=`expr 70 / $l`
+ if [ $c -eq 0 ]; then c=1; fi
+ echo "$CATEGORIES" | \
+ awk 'BEGIN {print "Known categories:"; i = 0 }
+ { printf ("%-'$l'.'$l's", $0); if ((++i % '$c') == 0) { print "" } }
+ END { print ""; }'
+ exit 0
+ ;;
+esac
+
+ORIGINATOR_C='<name of the PR author (one line)>'
+ORGANIZATION_C='<organization of PR author (multiple lines)>'
+CONFIDENTIAL_C='no <FreeBSD PRs are public data>'
+SYNOPSIS_C='<synopsis of the problem (one line)>'
+if [ -z "$SEVERITY_C" ]; then
+ SEVERITY_C='<[ non-critical | serious | critical ] (one line)>'
+fi
+PRIORITY_C='<[ low | medium | high ] (one line)>'
+CATEGORY_C='<choose from the list of categories above (one line)>'
+CLASS_C='<[ sw-bug | doc-bug | change-request | update | maintainer-update ] (one line)>'
+RELEASE_C='<release number or tag (one line)>'
+ENVIRONMENT_C='<machine, os, target, libraries (multiple lines)>'
+DESCRIPTION_C='<precise description of the problem (multiple lines)>'
+HOW_TO_REPEAT_C='<code/input/activities to reproduce the problem (multiple lines)>'
+FIX_C='<how to correct or work around the problem, if known (multiple lines)>'
+
+# Create temporary files, safely
+REF=`mktemp -t pf` || exit 1
+TEMP=`mktemp -t pf` || exit 1
+# Catch some signals. ($xs kludge needed by Sun /bin/sh)
+xs=0
+trap 'rm -f $REF $TEMP; exit $xs' 0
+trap 'echo "$COMMAND: Aborting ..."; rm -f $REF $TEMP; xs=1; exit' 1 2 3 13 15
+
+# If they told us to use a specific file, then do so.
+if [ -n "$IN_FILE" ]; then
+ if [ "$IN_FILE" = "-" ]; then
+ # The PR is coming from the standard input.
+ if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
+ sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" > $TEMP
+ else
+ cat > $TEMP
+ fi
+ else
+ # Use the file they named.
+ if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
+ sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" $IN_FILE > $TEMP
+ else
+ cat $IN_FILE > $TEMP
+ fi
+ fi
+else
+
+ if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
+ # If their PR_FORM points to a bogus entry, then bail.
+ if [ ! -f "$PR_FORM" -o ! -r "$PR_FORM" -o ! -s "$PR_FORM" ]; then
+ echo "$COMMAND: can't seem to read your template file (\`$PR_FORM'), ignoring PR_FORM"
+ sleep 1
+ PRINT_INTERN=bad_prform
+ fi
+ fi
+
+ if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
+ cp $PR_FORM $TEMP ||
+ ( echo "$COMMAND: could not copy $PR_FORM" ; xs=1; exit )
+ [ -n "$ATTACHED_FILES" ] && echo "$ATTACHED_FILES" >> $TEMP
+ else
+ for file in $TEMP $REF ; do
+ cat > $file << '__EOF__'
+SEND-PR: -*- send-pr -*-
+SEND-PR: Lines starting with `SEND-PR' will be removed automatically, as
+SEND-PR: will all comments (text enclosed in `<' and `>').
+SEND-PR:
+SEND-PR: Please consult the following URL if you are not sure how to
+SEND-PR: fill out a problem report:
+SEND-PR: http://www.freebsd.org/doc/en/articles/problem-reports/article.html
+SEND-PR:
+SEND-PR: Note that the Synopsis field is mandatory.
+SEND-PR:
+SEND-PR: Please note that (unless you state otherwise) if your report
+SEND-PR: includes a patch then it will be taken under the same license as
+SEND-PR: the one on the file(s) you want to change.
+SEND-PR:
+SEND-PR: BE ADVISED THAT FREEBSD PROBLEM REPORTS ARE PUBLIC INFORMATION AND
+SEND-PR: WILL BE PUBLISHED AS-IS ON THE PROJECT'S MAILING LISTS AND WEB SITES.
+SEND-PR: DO NOT SUBMIT ANY INFORMATION YOU DO NOT WANT MADE PUBLIC.
+SEND-PR:
+SEND-PR: For sensitive security issues, consider contacting the FreeBSD
+SEND-PR: security officer team (security-officer@freebsd.org) directly.
+SEND-PR:
+SEND-PR: Choose from the following categories:
+SEND-PR:
+__EOF__
+
+ # Format the categories so they fit onto lines.
+ l=`echo "$CATEGORIES" | \
+ awk 'BEGIN {max = 0; } { if (length($0) > max) { max = length($0); } }
+ END {print max + 1;}'`
+ c=`expr 61 / $l`
+ if [ $c -eq 0 ]; then c=1; fi
+ echo "$CATEGORIES" | \
+ awk 'BEGIN {printf "SEND-PR: "; i = 0 }
+ { printf ("%-'$l'.'$l's", $0);
+ if ((++i % '$c') == 0) { printf "\nSEND-PR: " } }
+ END { printf "\nSEND-PR:\n"; }' >> $file
+
+ cat >> $file << __EOF__
+To: $GNATS_ADDR
+From: $FROM
+Reply-To: $REPLY_TO
+Cc: $CC
+X-send-pr-version: $VERSION
+X-GNATS-Notify:
+
+
+>Submitter-Id: $SUBMITTER
+>Originator: $ORIGINATOR
+>Organization: ${ORGANIZATION-$ORGANIZATION_C}
+>Confidential: $CONFIDENTIAL_C
+>Synopsis: $SYNOPSIS_C
+>Severity: $SEVERITY_C
+>Priority: $PRIORITY_C
+>Category: $CATEGORY_C
+>Class: $CLASS_C
+>Release: ${DEFAULT_RELEASE-$RELEASE_C}
+>Environment:
+`[ -n "$SYSTEM" ] && echo System: $SYSTEM`
+`[ -n "$ARCH" ] && echo Architecture: $ARCH`
+`[ -n "$MACHINE" ] && echo Machine: $MACHINE`
+ $ENVIRONMENT_C
+>Description:
+ $DESCRIPTION_C
+>How-To-Repeat:
+ $HOW_TO_REPEAT_C
+>Fix:
+
+ $FIX_C
+$ATTACHED_FILES
+
+__EOF__
+
+ done
+ fi
+
+ if [ "$PRINT" = true -o "$PRINT_INTERN" = true ]; then
+ cat $TEMP
+ xs=0; exit
+ fi
+
+ chmod u+w $TEMP
+ eval $EDIT $TEMP
+
+ if cmp -s $REF $TEMP ; then
+ echo "$COMMAND: problem report not filled out, therefore not sent"
+ xs=1; exit
+ fi
+fi
+
+#
+# Check the enumeration fields
+
+# This is a "sed-subroutine" with one keyword parameter
+# (with workaround for Sun sed bug)
+#
+SED_CMD='{
+s|||
+s|<.*>||
+s|^[ ]*||
+s|[ ]*$||
+p
+q
+}'
+
+
+while true; do
+ CNT=0
+
+ # 1) Confidential
+ #
+ PATTERN=">Confidential:"
+ CONFIDENTIAL=`eval sed -n -e "\"/$PATTERN/$SED_CMD\"" $TEMP`
+ case "$CONFIDENTIAL" in
+ ""|no) CNT=`expr $CNT + 1` ;;
+ *) echo "$COMMAND: \`$CONFIDENTIAL' is not a valid value for \`Confidential'." ;;
+ esac
+ #
+ # 2) Severity
+ #
+ PATTERN=">Severity:"
+ SEVERITY=`eval sed -n -e "\"/$PATTERN/$SED_CMD\"" $TEMP`
+ case "$SEVERITY" in
+ ""|non-critical|serious|critical) CNT=`expr $CNT + 1` ;;
+ *) echo "$COMMAND: \`$SEVERITY' is not a valid value for \`Severity'."
+ esac
+ #
+ # 3) Priority
+ #
+ PATTERN=">Priority:"
+ PRIORITY=`eval sed -n -e "\"/$PATTERN/$SED_CMD\"" $TEMP`
+ case "$PRIORITY" in
+ ""|low|medium|high) CNT=`expr $CNT + 1` ;;
+ *) echo "$COMMAND: \`$PRIORITY' is not a valid value for \`Priority'."
+ esac
+ #
+ # 4) Category
+ #
+ PATTERN=">Category:"
+ CATEGORY=`eval sed -n -e "\"/$PATTERN/$SED_CMD\"" $TEMP`
+ FOUND=
+ for C in $CATEGORIES
+ do
+ if [ "$C" = "$CATEGORY" ]; then FOUND=true ; break ; fi
+ done
+ if [ -n "$FOUND" ]; then
+ CNT=`expr $CNT + 1`
+ else
+ if [ -z "$CATEGORY" ]; then
+ echo "$COMMAND: you must include a Category: field in your report."
+ else
+ echo "$COMMAND: \`$CATEGORY' is not a known category."
+ fi
+ fi
+ #
+ # 5) Class
+ #
+ PATTERN=">Class:"
+ CLASS=`eval sed -n -e "\"/$PATTERN/$SED_CMD\"" $TEMP`
+ case "$CLASS" in
+ ""|sw-bug|doc-bug|change-request|update|maintainer-update) CNT=`expr $CNT + 1` ;;
+ *) echo "$COMMAND: \`$CLASS' is not a valid value for \`Class'."
+ esac
+ #
+ # 6) Check that synopsis is not empty
+ #
+ if grep "^>Synopsis:[ ]*${SYNOPSIS_C}\$" $TEMP > /dev/null
+ then
+ echo "$COMMAND: Synopsis must not be empty."
+ else
+ CNT=`expr $CNT + 1`
+ fi
+
+ [ $CNT -lt 6 -a -z "$BATCH" ] &&
+ echo "Errors were found with the problem report."
+
+ while true; do
+ if [ -z "$BATCH" ]; then
+ $ECHON1 "s)end, e)dit or a)bort? $ECHON2"
+ read input
+ else
+ if [ $CNT -eq 6 ]; then
+ input=s
+ else
+ input=a
+ fi
+ fi
+ case "$input" in
+ a*)
+ if [ -z "$BATCH" ]; then
+ BAD=`mktemp -t pbad`
+ echo "$COMMAND: the problem report remains in $BAD and is not sent."
+ mv $TEMP $BAD
+ else
+ echo "$COMMAND: the problem report is not sent."
+ fi
+ xs=1; exit
+ ;;
+ e*)
+ eval $EDIT $TEMP
+ continue 2
+ ;;
+ s*)
+ break 2
+ ;;
+ esac
+ done
+done
+
+#
+# Remove the subject field if one is already there. There's no reason
+# for it to be any different than the synopsis.
+#
+if grep '^Subject:' $TEMP > /dev/null
+then
+ ed -s $TEMP << __EOF__
+/^Subject:/d
+w
+q
+__EOF__
+fi
+
+#
+# Add the subject field with the value of $SYNOPSIS. We use the To:
+# field as an anchor, which had better be there.
+#
+SYNOPSIS=`grep '^>Synopsis:' $TEMP | sed -e 's/^>Synopsis:[ ]*//' |
+ sed -e "s;$SYNOPSIS_C;;"`
+ed -s $TEMP << __EOF__
+/^To:/a
+Subject: $SYNOPSIS
+.
+w
+q
+__EOF__
+
+#
+# Remove comments and send the problem report
+# (we have to use patterns, where the comment contains regex chars)
+#
+# /^>Originator:/s;$ORIGINATOR;;
+sed -e "
+/^SEND-PR:/d
+/^>Organization:/,/^>[A-Za-z-]*:/s;$ORGANIZATION_C;;
+/^>Confidential:/s;<.*>;;
+/^>Synopsis:/s;$SYNOPSIS_C;;
+/^>Severity:/s;<.*>;;
+/^>Priority:/s;<.*>;;
+/^>Category:/s;$CATEGORY_C;;
+/^>Class:/s;<.*>;;
+/^>Release:/,/^>[A-Za-z-]*:/s;$RELEASE_C;;
+/^>Environment:/,/^>[A-Za-z-]*:/s;$ENVIRONMENT_C;;
+/^>Description:/,/^>[A-Za-z-]*:/s;$DESCRIPTION_C;;
+/^>How-To-Repeat:/,/^>[A-Za-z-]*:/s;$HOW_TO_REPEAT_C;;
+/^>Fix:/,/^>[A-Za-z-]*:/s;$FIX_C;;
+" $TEMP > $REF
+
+if $MAIL_AGENT < $REF; then
+ echo "$COMMAND: problem report sent"
+ xs=0; exit
+else
+ echo "$COMMAND: mysterious mail failure."
+ if [ -z "$BATCH" ]; then
+ BAD=`mktemp -t pbad`
+ echo "$COMMAND: the problem report remains in $BAD and is not sent."
+ mv $REF $BAD
+ else
+ echo "$COMMAND: the problem report is not sent."
+ fi
+ xs=1; exit
+fi
diff --git a/gnu/usr.bin/sort/Makefile b/gnu/usr.bin/sort/Makefile
new file mode 100644
index 0000000..30dd080
--- /dev/null
+++ b/gnu/usr.bin/sort/Makefile
@@ -0,0 +1,30 @@
+# $FreeBSD$
+
+SORTDIR= ${.CURDIR}/../../../contrib/gnu-sort
+.PATH: ${SORTDIR}/lib ${SORTDIR}/src ${SORTDIR}/man
+
+PROG= sort
+SRCS= sort.c \
+ argmatch.c \
+ dup-safer.c \
+ error.c \
+ fopen-safer.c \
+ getopt.c \
+ getopt1.c \
+ hard-locale.c \
+ human.c \
+ long-options.c \
+ memcoll.c \
+ physmem.c \
+ posixver.c \
+ quote.c \
+ quotearg.c \
+ version-etc.c \
+ xmalloc.c \
+ xmemcoll.c \
+ xstrtoul.c \
+ xstrtoumax.c
+
+CFLAGS+=-I${.CURDIR} -I${SORTDIR}/lib -DHAVE_CONFIG_H
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/sort/config.h b/gnu/usr.bin/sort/config.h
new file mode 100644
index 0000000..8fa7f9a
--- /dev/null
+++ b/gnu/usr.bin/sort/config.h
@@ -0,0 +1,1316 @@
+/* $FreeBSD$ */
+/* config.h. Generated by configure. */
+/* config.hin. Generated from configure.ac by autoheader. */
+
+/* Define if you have the Andrew File System. */
+/* #undef AFS */
+
+/* Define to the function xargmatch calls on failures. */
+#define ARGMATCH_DIE usage (1)
+
+/* Define to the declaration of the xargmatch failure function. */
+#define ARGMATCH_DIE_DECL extern void usage ()
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* 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 to 1 if using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to 1 if using `getloadavg.c'. */
+/* #undef C_GETLOADAVG */
+
+/* Define to 1 for DGUX with <sys/dg_sys_info.h>. */
+/* #undef DGUX */
+
+/* the name of the file descriptor member of DIR */
+/* #undef DIR_FD_MEMBER_NAME */
+
+#ifdef DIR_FD_MEMBER_NAME
+# define DIR_TO_FD(Dir_p) ((Dir_p)->DIR_FD_MEMBER_NAME)
+#else
+# define DIR_TO_FD(Dir_p) -1
+#endif
+
+
+
+/* Define if there is a member named d_ino in the struct describing directory
+ headers. */
+#define D_INO_IN_DIRENT 1
+
+/* Define if there is a member named d_type in the struct describing directory
+ headers. */
+#define D_TYPE_IN_DIRENT 1
+
+/* Define to 1 if translation of program messages to the user's native
+ language is requested. */
+#define ENABLE_NLS 1
+
+/* Define on systems for which file names may have a so-called `drive letter'
+ prefix, define this to compute the length of that prefix, including the
+ colon. */
+#define FILESYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX 0
+
+/* Define if the backslash character may also serve as a file name component
+ separator. */
+#define FILESYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR 0
+
+#if FILESYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
+# define FILESYSTEM_PREFIX_LEN(Filename) \
+ ((Filename)[0] && (Filename)[1] == ':' ? 2 : 0)
+#else
+# define FILESYSTEM_PREFIX_LEN(Filename) 0
+#endif
+
+/* Define to the type of elements in the array set by `getgroups'. Usually
+ this is either `int' or `gid_t'. */
+#define GETGROUPS_T gid_t
+
+/* Define if the `getloadavg' function needs to be run setuid or setgid. */
+/* #undef GETLOADAVG_PRIVILEGED */
+
+/* Define if gettimeofday clobbers localtime's static buffer. */
+/* #undef GETTIMEOFDAY_CLOBBERS_LOCALTIME_BUFFER */
+
+/* The concatenation of the strings `GNU ', and PACKAGE. */
+#define GNU_PACKAGE "GNU textutils"
+
+/* Define to 1 if you have the `acl' function. */
+/* #undef HAVE_ACL */
+
+/* Define to 1 if you have the `alarm' function. */
+#define HAVE_ALARM 1
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define to 1 if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `bcopy' function. */
+#define HAVE_BCOPY 1
+
+/* Define to 1 if you have the <bp-sym.h> header file. */
+/* #undef HAVE_BP_SYM_H */
+
+/* Define to 1 if you have the `btowc' function. */
+/* #undef HAVE_BTOWC */
+
+/* Define to 1 if you have the `bzero' function. */
+#define HAVE_BZERO 1
+
+/* Define to 1 if you have the `canonicalize_file_name' function. */
+/* #undef HAVE_CANONICALIZE_FILE_NAME */
+
+/* Define to 1 if you have the `chsize' function. */
+/* #undef HAVE_CHSIZE */
+
+/* Define to 1 if you have the `clearerr_unlocked' function. */
+/* #undef HAVE_CLEARERR_UNLOCKED */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define if backslash-a works in C strings. */
+#define HAVE_C_BACKSLASH_A 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+ */
+/* #undef HAVE_DCGETTEXT */
+
+/* Define to 1 if you have the declaration of `clearerr_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_CLEARERR_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `dirfd', and to 0 if you don't.
+ */
+#define HAVE_DECL_DIRFD 1
+
+/* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you
+ don't. */
+#define HAVE_DECL_FEOF_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `ferror_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_FERROR_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `fflush_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_FFLUSH_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_FGETS_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `fputc_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_FPUTC_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `fputs_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_FPUTS_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `fread_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_FREAD_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `free', and to 0 if you don't.
+ */
+#define HAVE_DECL_FREE 1
+
+/* Define to 1 if you have the declaration of `fwrite_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_FWRITE_UNLOCKED 0
+
+/* Define to 1 if you have the declaration of `getchar_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_GETCHAR_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETC_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't.
+ */
+#define HAVE_DECL_GETENV 1
+
+/* Define to 1 if you have the declaration of `geteuid', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETEUID 1
+
+/* Define to 1 if you have the declaration of `getgrgid', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETGRGID 1
+
+/* Define to 1 if you have the declaration of `getlogin', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETLOGIN 1
+
+/* Define to 1 if you have the declaration of `getpwuid', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETPWUID 1
+
+/* Define to 1 if you have the declaration of `getuid', and to 0 if you don't.
+ */
+#define HAVE_DECL_GETUID 1
+
+/* Define to 1 if you have the declaration of `getutent', and to 0 if you
+ don't. */
+#define HAVE_DECL_GETUTENT 0
+
+/* Define to 1 if you have the declaration of `lseek', and to 0 if you don't.
+ */
+#define HAVE_DECL_LSEEK 1
+
+/* Define to 1 if you have the declaration of `malloc', and to 0 if you don't.
+ */
+#define HAVE_DECL_MALLOC 1
+
+/* Define to 1 if you have the declaration of `memchr', and to 0 if you don't.
+ */
+#define HAVE_DECL_MEMCHR 1
+
+/* Define to 1 if you have the declaration of `memrchr', and to 0 if you
+ don't. */
+#define HAVE_DECL_MEMRCHR 0
+
+/* Define to 1 if you have the declaration of `nanosleep', and to 0 if you
+ don't. */
+#define HAVE_DECL_NANOSLEEP 1
+
+/* Define to 1 if you have the declaration of `putchar_unlocked', and to 0 if
+ you don't. */
+#define HAVE_DECL_PUTCHAR_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `putc_unlocked', and to 0 if you
+ don't. */
+#define HAVE_DECL_PUTC_UNLOCKED 1
+
+/* Define to 1 if you have the declaration of `realloc', and to 0 if you
+ don't. */
+#define HAVE_DECL_REALLOC 1
+
+/* Define to 1 if you have the declaration of `stpcpy', and to 0 if you don't.
+ */
+#define HAVE_DECL_STPCPY 0
+
+/* Define to 1 if you have the declaration of `strerror', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRERROR 1
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRERROR_R 1
+
+/* Define to 1 if you have the declaration of `strndup', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRNDUP 0
+
+/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRNLEN 0
+
+/* Define to 1 if you have the declaration of `strstr', and to 0 if you don't.
+ */
+#define HAVE_DECL_STRSTR 1
+
+/* Define to 1 if you have the declaration of `strtoimax', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOIMAX 1
+
+/* Define to 1 if you have the declaration of `strtol', and to 0 if you don't.
+ */
+#define HAVE_DECL_STRTOL 1
+
+/* Define to 1 if you have the declaration of `strtoll', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOLL 1
+
+/* Define to 1 if you have the declaration of `strtoul', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOUL 1
+
+/* Define to 1 if you have the declaration of `strtoull', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOULL 1
+
+/* Define to 1 if you have the declaration of `strtoumax', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOUMAX 1
+
+/* Define to 1 if you have the declaration of `ttyname', and to 0 if you
+ don't. */
+#define HAVE_DECL_TTYNAME 1
+
+/* Define to 1 if you have the declaration of wcwidth(), and to 0 otherwise.
+ */
+#define HAVE_DECL_WCWIDTH 0
+
+/* Define to 1 if you have the declaration of `__fpending', and to 0 if you
+ don't. */
+#define HAVE_DECL___FPENDING 0
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the `dirfd' function. */
+/* #undef HAVE_DIRFD */
+
+/* Define if the malloc check has been performed. */
+#define HAVE_DONE_WORKING_MALLOC_CHECK 1
+
+/* Define if the realloc check has been performed. */
+#define HAVE_DONE_WORKING_REALLOC_CHECK 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the `dup2' function. */
+#define HAVE_DUP2 1
+
+/* Define to 1 if you have the `endgrent' function. */
+#define HAVE_ENDGRENT 1
+
+/* Define to 1 if you have the `endpwent' function. */
+#define HAVE_ENDPWENT 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `euidaccess' function. */
+/* #undef HAVE_EUIDACCESS */
+
+/* Define to 1 if you have the `fchdir' function. */
+#define HAVE_FCHDIR 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fdatasync' function. */
+/* #undef HAVE_FDATASYNC */
+
+/* Define to 1 if you have the <fenv.h> header file. */
+/* #undef HAVE_FENV_H */
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+/* #undef HAVE_FEOF_UNLOCKED */
+
+/* Define to 1 if you have the `ferror_unlocked' function. */
+/* #undef HAVE_FERROR_UNLOCKED */
+
+/* Define to 1 if you have the `fesetround' function. */
+/* #undef HAVE_FESETROUND */
+
+/* Define to 1 if you have the `fflush_unlocked' function. */
+/* #undef HAVE_FFLUSH_UNLOCKED */
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+/* #undef HAVE_FGETS_UNLOCKED */
+
+/* Define to 1 if you have the <float.h> header file. */
+#define HAVE_FLOAT_H 1
+
+/* Define to 1 if you have the `floor' function. */
+#define HAVE_FLOOR 1
+
+/* Define to 1 if your system has a working `fnmatch' function. */
+#define HAVE_FNMATCH 1
+
+/* Define to 1 if you have the `fputc_unlocked' function. */
+/* #undef HAVE_FPUTC_UNLOCKED */
+
+/* Define to 1 if you have the `fputs_unlocked' function. */
+/* #undef HAVE_FPUTS_UNLOCKED */
+
+/* Define to 1 if you have the `fread_unlocked' function. */
+/* #undef HAVE_FREAD_UNLOCKED */
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the <fs_info.h> header file. */
+/* #undef HAVE_FS_INFO_H */
+
+/* Define to 1 if you have the `fs_stat_dev' function. */
+/* #undef HAVE_FS_STAT_DEV */
+
+/* Define to 1 if you have the `ftime' function. */
+/* #undef HAVE_FTIME */
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the `fwrite_unlocked' function. */
+/* #undef HAVE_FWRITE_UNLOCKED */
+
+/* Define if struct statfs has the f_fstypename member. */
+#define HAVE_F_FSTYPENAME_IN_STATFS 1
+
+/* Define to 1 if you have the `getchar_unlocked' function. */
+/* #undef HAVE_GETCHAR_UNLOCKED */
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define if getcwd (NULL, 0) allocates memory for result. */
+#define HAVE_GETCWD_NULL 1
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+/* #undef HAVE_GETC_UNLOCKED */
+
+/* Define to 1 if you have the `getdelim' function. */
+/* #undef HAVE_GETDELIM */
+
+/* Define to 1 if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define to 1 if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `getgroups' function. */
+#define HAVE_GETGROUPS 1
+
+/* Define to 1 if you have the `gethostbyaddr' function. */
+#define HAVE_GETHOSTBYADDR 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostname' function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define to 1 if you have the `gethrtime' function. */
+/* #undef HAVE_GETHRTIME */
+
+/* Define to 1 if you have the `getloadavg' function. */
+#define HAVE_GETLOADAVG 1
+
+/* Define to 1 if you have the `getmntent' function. */
+/* #undef HAVE_GETMNTENT */
+
+/* Define to 1 if you have the `getmntinfo' function. */
+#define HAVE_GETMNTINFO 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the `getpass' function. */
+#define HAVE_GETPASS 1
+
+/* Define to 1 if you have the `getspnam' function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+/* #undef HAVE_GETTEXT */
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define to 1 if you have the `getusershell' function. */
+#define HAVE_GETUSERSHELL 1
+
+/* Define to 1 if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define to 1 if you have the `hasmntopt' function. */
+/* #undef HAVE_HASMNTOPT */
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the `inet_ntoa' function. */
+#define HAVE_INET_NTOA 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `iswcntrl' function. */
+/* #undef HAVE_ISWCNTRL */
+
+/* Define to 1 if you have the `iswprint' function. */
+/* #undef HAVE_ISWPRINT */
+
+/* Define to 1 if you have the `iswspace' function. */
+/* #undef HAVE_ISWSPACE */
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define to 1 if you have the `lchown' function. */
+#define HAVE_LCHOWN 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define to 1 if you have the `dgc' library (-ldgc). */
+/* #undef HAVE_LIBDGC */
+
+/* Define to 1 if you have the <libintl.h> header file. */
+/* #undef HAVE_LIBINTL_H */
+
+/* Define to 1 if you have the `kstat' library (-lkstat). */
+/* #undef HAVE_LIBKSTAT */
+
+/* Define to 1 if you have the `ldgc' library (-lldgc). */
+/* #undef HAVE_LIBLDGC */
+
+/* Define to 1 if you have the `ypsec' library (-lypsec). */
+/* #undef HAVE_LIBYPSEC */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the `listmntent' function. */
+/* #undef HAVE_LISTMNTENT */
+
+/* Define to 1 if you have the `localeconv' function. */
+#define HAVE_LOCALECONV 1
+
+/* Define to 1 if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if long double works and has more range or precision than
+ double. */
+/* #undef HAVE_LONG_DOUBLE */
+
+/* Define to 1 if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if you have the long long type. */
+#define HAVE_LONG_LONG 1
+
+/* Define if lstat has the bug that it succeeds when given the zero-length
+ file name argument. The lstat from SunOS4.1.4 and the Hurd as of
+ 1998-11-01) do this. */
+/* #undef HAVE_LSTAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <mach/mach.h> header file. */
+/* #undef HAVE_MACH_MACH_H */
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the `mblen' function. */
+#define HAVE_MBLEN 1
+
+/* Define to 1 if you have the `mbrlen' function. */
+/* #undef HAVE_MBRLEN */
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+/* #undef HAVE_MBRTOWC */
+
+/* Define to 1 if you have the `mbsinit' function. */
+/* #undef HAVE_MBSINIT */
+
+/* Define to 1 if you have the `memchr' function. */
+#define HAVE_MEMCHR 1
+
+/* Define to 1 if you have the `memcmp' function. */
+#define HAVE_MEMCMP 1
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `mempcpy' function. */
+/* #undef HAVE_MEMPCPY */
+
+/* Define to 1 if you have the `memrchr' function. */
+/* #undef HAVE_MEMRCHR */
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mkfifo' function. */
+#define HAVE_MKFIFO 1
+
+/* Define to 1 if you have the `mkstemp' function. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the <mntent.h> header file. */
+/* #undef HAVE_MNTENT_H */
+
+/* Define to 1 if you have the <mnttab.h> header file. */
+/* #undef HAVE_MNTTAB_H */
+
+/* Define to 1 if you have the `modf' function. */
+#define HAVE_MODF 1
+
+/* Define to 1 if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the `next_dev' function. */
+/* #undef HAVE_NEXT_DEV */
+
+/* Define to 1 if you have the <nlist.h> header file. */
+/* #undef HAVE_NLIST_H */
+
+/* Define to 1 if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define to 1 if libc includes obstacks. */
+/* #undef HAVE_OBSTACK */
+
+/* Define to 1 if you have the <OS.h> header file. */
+/* #undef HAVE_OS_H */
+
+/* Define to 1 if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define to 1 if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define if your system has the /proc/uptime special file. */
+/* #undef HAVE_PROC_UPTIME */
+
+/* Define to 1 if you have the `pstat_getdynamic' function. */
+/* #undef HAVE_PSTAT_GETDYNAMIC */
+
+/* Define to 1 if you have the `pstat_getstatic' function. */
+/* #undef HAVE_PSTAT_GETSTATIC */
+
+/* Define to 1 if you have the `putchar_unlocked' function. */
+/* #undef HAVE_PUTCHAR_UNLOCKED */
+
+/* Define to 1 if you have the `putc_unlocked' function. */
+/* #undef HAVE_PUTC_UNLOCKED */
+
+/* Define to 1 if you have the `putenv' function. */
+/* #undef HAVE_PUTENV */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `realpath' function. */
+#define HAVE_REALPATH 1
+
+/* Define to 1 if you have the `resolvepath' function. */
+/* #undef HAVE_RESOLVEPATH */
+
+/* Define to 1 if you have the `rint' function. */
+#define HAVE_RINT 1
+
+/* Define to 1 if you have the `rmdir' function. */
+#define HAVE_RMDIR 1
+
+/* Define to 1 if you have the `rpmatch' function. */
+/* #undef HAVE_RPMATCH */
+
+/* Define to 1 if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define to 1 if you have the `sethostname' function. */
+#define HAVE_SETHOSTNAME 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the <shadow.h> header file. */
+/* #undef HAVE_SHADOW_H */
+
+/* Define to 1 if you have the `sqrt' function. */
+/* #undef HAVE_SQRT */
+
+/* Define if stat has the bug that it succeeds when given the zero-length file
+ name argument. The stat from SunOS4.1.4 and the Hurd as of 1998-11-01) do
+ this. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio_ext.h> header file. */
+/* #undef HAVE_STDIO_EXT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `stime' function. */
+/* #undef HAVE_STIME */
+
+/* Define to 1 if you have the `stpcpy' function. */
+/* #undef HAVE_STPCPY */
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the `strcspn' function. */
+#define HAVE_STRCSPN 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the `strftime' function. */
+#define HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strndup' function. */
+/* #undef HAVE_STRNDUP */
+
+/* Define to 1 if you have the `strnlen' function. */
+/* #undef HAVE_STRNLEN */
+
+/* Define to 1 if you have the `strpbrk' function. */
+#define HAVE_STRPBRK 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtoimax' function. */
+#define HAVE_STRTOIMAX 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the `strtoll' function. */
+/* #undef HAVE_STRTOLL */
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strtoull' function. */
+/* #undef HAVE_STRTOULL */
+
+/* Define to 1 if you have the `strtoumax' function. */
+#define HAVE_STRTOUMAX 1
+
+/* Define to 1 if `f_fstypename' is member of `struct fsstat'. */
+/* #undef HAVE_STRUCT_FSSTAT_F_FSTYPENAME */
+
+/* Define to 1 if `n_un.n_name' is member of `struct nlist'. */
+/* #undef HAVE_STRUCT_NLIST_N_UN_N_NAME */
+
+/* Define to 1 if `sp_pwdp' is member of `struct spwd'. */
+/* #undef HAVE_STRUCT_SPWD_SP_PWDP */
+
+/* Define to 1 if `st_blksize' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+
+/* Define to 1 if `st_blocks' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+
+/* Define if struct timespec is declared in <time.h>. */
+#define HAVE_STRUCT_TIMESPEC 1
+
+/* Define to 1 if `tm_zone' is member of `struct tm'. */
+#define HAVE_STRUCT_TM_TM_ZONE 1
+
+/* Define if struct utimbuf is declared -- usually in <utime.h>. Some systems
+ have utime.h but don't declare the struct anywhere. */
+#define HAVE_STRUCT_UTIMBUF 1
+
+/* Define to 1 if `ut_name' is member of `struct utmpx'. */
+/* #undef HAVE_STRUCT_UTMPX_UT_NAME */
+
+/* Define to 1 if `ut_type' is member of `struct utmpx'. */
+/* #undef HAVE_STRUCT_UTMPX_UT_TYPE */
+
+/* Define to 1 if `ut_user' is member of `struct utmpx'. */
+/* #undef HAVE_STRUCT_UTMPX_UT_USER */
+
+/* Define to 1 if `ut_name' is member of `struct utmp'. */
+#define HAVE_STRUCT_UTMP_UT_NAME 1
+
+/* Define to 1 if `ut_type' is member of `struct utmp'. */
+/* #undef HAVE_STRUCT_UTMP_UT_TYPE */
+
+/* Define to 1 if `ut_user' is member of `struct utmp'. */
+/* #undef HAVE_STRUCT_UTMP_UT_USER */
+
+/* Define to 1 if you have the `strverscmp' function. */
+/* #undef HAVE_STRVERSCMP */
+
+/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use
+ `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
+#define HAVE_ST_BLOCKS 1
+
+/* Define if struct stat has an st_dm_mode member. */
+/* #undef HAVE_ST_DM_MODE */
+
+/* Define to 1 if you have the `sysinfo' function. */
+/* #undef HAVE_SYSINFO */
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/acl.h> header file. */
+#define HAVE_SYS_ACL_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define to 1 if you have the <sys/filsys.h> header file. */
+/* #undef HAVE_SYS_FILSYS_H */
+
+/* Define to 1 if you have the <sys/fstyp.h> header file. */
+/* #undef HAVE_SYS_FSTYP_H */
+
+/* Define to 1 if you have the <sys/fs/s5param.h> header file. */
+/* #undef HAVE_SYS_FS_S5PARAM_H */
+
+/* Define to 1 if you have the <sys/fs_types.h> header file. */
+/* #undef HAVE_SYS_FS_TYPES_H */
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/mntent.h> header file. */
+/* #undef HAVE_SYS_MNTENT_H */
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/pstat.h> header file. */
+/* #undef HAVE_SYS_PSTAT_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+/* #undef HAVE_SYS_STATFS_H */
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+/* #undef HAVE_SYS_STATVFS_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/systeminfo.h> header file. */
+/* #undef HAVE_SYS_SYSTEMINFO_H */
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+#define HAVE_SYS_UCRED_H 1
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+/* #undef HAVE_SYS_VFS_H */
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if struct tm has the tm_gmtoff member. */
+#define HAVE_TM_GMTOFF 1
+
+/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
+ `HAVE_STRUCT_TM_TM_ZONE' instead. */
+#define HAVE_TM_ZONE 1
+
+/* Define to 1 if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define to 1 if you don't have `tm_zone' but do have the external array
+ `tzname'. */
+/* #undef HAVE_TZNAME */
+
+/* Define to 1 if you have the `tzset' function. */
+#define HAVE_TZSET 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the unsigned long long type. */
+#define HAVE_UNSIGNED_LONG_LONG 1
+
+/* Define to 1 if you have the `utime' function. */
+/* #undef HAVE_UTIME */
+
+/* Define if utimes accepts a null argument */
+/* #undef HAVE_UTIMES_NULL */
+
+/* Define to 1 if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
+#define HAVE_UTIME_NULL 1
+
+/* Define to 1 if you have the `utmpname' function. */
+/* #undef HAVE_UTMPNAME */
+
+/* Define to 1 if you have the `utmpxname' function. */
+/* #undef HAVE_UTMPXNAME */
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+/* #undef HAVE_UTMPX_H */
+
+/* Define to 1 if you have the <utmp.h> header file. */
+#define HAVE_UTMP_H 1
+
+/* Define to 1 if you have the <values.h> header file. */
+#define HAVE_VALUES_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define to 1 if you have the `wcrtomb' function. */
+/* #undef HAVE_WCRTOMB */
+
+/* Define to 1 if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if you have the `wcwidth' function. */
+/* #undef HAVE_WCWIDTH */
+
+/* Define if readdir is found to work properly in some unusual cases. */
+#define HAVE_WORKING_READDIR 1
+
+/* Define to 1 if you have the `__argz_count' function. */
+/* #undef HAVE___ARGZ_COUNT */
+
+/* Define to 1 if you have the `__argz_next' function. */
+/* #undef HAVE___ARGZ_NEXT */
+
+/* Define to 1 if you have the `__argz_stringify' function. */
+/* #undef HAVE___ARGZ_STRINGIFY */
+
+/* Define to 1 if you have the `__fpending' function. */
+/* #undef HAVE___FPENDING */
+
+/* Define to 1 if you have the `__secure_getenv' function. */
+/* #undef HAVE___SECURE_GETENV */
+
+/* The host operating system. */
+#define HOST_OPERATING_SYSTEM "FreeBSD"
+
+/* Define as const if the declaration of iconv() needs const. */
+/* #undef ICONV_CONST */
+
+#if FILESYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#else
+# define ISSLASH(C) ((C) == '/')
+#endif
+
+/* Define if `link(2)' dereferences symbolic links. */
+#define LINK_FOLLOWS_SYMLINKS 1
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+/* #undef MAJOR_IN_MKDEV */
+
+/* Define to 1 if `major', `minor', and `makedev' are declared in
+ <sysmacros.h>. */
+/* #undef MAJOR_IN_SYSMACROS */
+
+/* Define if there is no specific function for reading the list of mounted
+ filesystems. fread will be used to read /etc/mnttab. (SVR2) */
+/* #undef MOUNTED_FREAD */
+
+/* Define if (like SVR2) there is no specific function for reading the list of
+ mounted filesystems, and your system has these header files: <sys/fstyp.h>
+ and <sys/statfs.h>. (SVR3) */
+/* #undef MOUNTED_FREAD_FSTYP */
+
+/* Define if there are functions named next_dev and fs_stat_dev for reading
+ the list of mounted filesystems. (BeOS) */
+/* #undef MOUNTED_FS_STAT_DEV */
+
+/* Define if there is a function named getfsstat for reading the list of
+ mounted filesystems. (DEC Alpha running OSF/1) */
+/* #undef MOUNTED_GETFSSTAT */
+
+/* Define if there is a function named getmnt for reading the list of mounted
+ filesystems. (Ultrix) */
+/* #undef MOUNTED_GETMNT */
+
+/* Define if there is a function named getmntent for reading the list of
+ mounted filesystems, and that function takes a single argument. (4.3BSD,
+ SunOS, HP-UX, Dynix, Irix) */
+/* #undef MOUNTED_GETMNTENT1 */
+
+/* Define if there is a function named getmntent for reading the list of
+ mounted filesystems, and that function takes two arguments. (SVR4) */
+/* #undef MOUNTED_GETMNTENT2 */
+
+/* Define if there is a function named getmntinfo for reading the list of
+ mounted filesystems. (4.4BSD) */
+#define MOUNTED_GETMNTINFO 1
+
+/* Define if there is a function named listmntent that can be used to list all
+ mounted filesystems. (UNICOS) */
+/* #undef MOUNTED_LISTMNTENT */
+
+/* Define if there is a function named mntctl that can be used to read the
+ list of mounted filesystems, and there is a system header file that
+ declares `struct vmount.' (AIX) */
+/* #undef MOUNTED_VMOUNT */
+
+/* Define to 1 if assertions should be disabled. */
+/* #undef NDEBUG */
+
+/* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend
+ on `HAVE_STRUCT_NLIST_N_UN_N_NAME */
+/* #undef NLIST_NAME_UNION */
+
+/* Name of package */
+#define PACKAGE "textutils"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "bug-textutils@gnu.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "GNU textutils"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "GNU textutils 2.0.21"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "textutils"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "2.0.21"
+
+/* the number of pending output bytes on stream `fp' */
+#define PENDING_OUTPUT_N_BYTES fp->_p - fp->_bf._base
+
+/* Define to 1 if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define if rename does not work for source paths with a trailing slash, like
+ the one from SunOS 4.1.1_U1. */
+/* #undef RENAME_TRAILING_SLASH_BUG */
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* the value to which errno is set when rmdir fails on a nonempty directory */
+#define RMDIR_ERRNO_NOT_EMPTY 66
+
+/* Define to 1 if the `setvbuf' function takes the buffering type as its
+ second argument and the buffer pointer as the third, as on System V before
+ release 3. */
+/* #undef SETVBUF_REVERSED */
+
+/* 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 to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define if there is no specific function for reading filesystems usage
+ information and you have the <sys/filsys.h> header file. (SVR2) */
+/* #undef STAT_READ_FILSYS */
+
+/* Define if statfs takes 2 args and struct statfs has a field named f_bsize.
+ (4.3BSD, SunOS 4, HP-UX, AIX PS/2) */
+#define STAT_STATFS2_BSIZE 1
+
+/* Define if statfs takes 2 args and struct statfs has a field named f_fsize.
+ (4.4BSD, NetBSD) */
+/* #undef STAT_STATFS2_FSIZE */
+
+/* Define if statfs takes 2 args and the second argument has type struct
+ fs_data. (Ultrix) */
+/* #undef STAT_STATFS2_FS_DATA */
+
+/* Define if statfs takes 3 args. (DEC Alpha running OSF/1) */
+/* #undef STAT_STATFS3_OSF1 */
+
+/* Define if statfs takes 4 args. (SVR3, Dynix, Irix, Dolphin) */
+/* #undef STAT_STATFS4 */
+
+/* Define if there is a function named statvfs. (SVR4) */
+/* #undef STAT_STATVFS */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if strerror_r returns char *. */
+/* #undef STRERROR_R_CHAR_P */
+
+/* Define to be the nanoseconds member of struct stat's st_mtim, if it exists.
+ */
+/* #undef ST_MTIM_NSEC */
+
+/* Define to 1 on System V Release 4. */
+/* #undef SVR4 */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to 1 for Encore UMAX. */
+/* #undef UMAX */
+
+/* Define to 1 for Encore UMAX 4.3 that has <inq_status/cpustats.h> instead of
+ <sys/cpustats.h>. */
+/* #undef UMAX4_3 */
+
+/* Version number of package */
+#define VERSION "2.0.21"
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to 1 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
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to 1 if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define like PROTOTYPES; this can be used by system headers. */
+#define __PROTOTYPES 1
+
+/* Define to rpl_chown if the replacement function should be used. */
+/* #undef chown */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to rpl_fnmatch if the replacement function should be used. */
+/* #undef fnmatch */
+
+/* Define as rpl_getgroups if getgroups doesn't work right. */
+/* #undef getgroups */
+
+/* Define to rpl_gettimeofday if the replacement function should be used. */
+/* #undef gettimeofday */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define as `__inline' if that's what the C compiler calls it, or to nothing
+ if it is not supported. */
+/* #undef inline */
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+/* #undef ino_t */
+
+/* Define to widest signed type if <inttypes.h> doesn't define. */
+/* #undef intmax_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#define major_t unsigned int
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Define to rpl_memcmp if the replacement function should be used. */
+/* #undef memcmp */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#define minor_t unsigned int
+
+/* Define to rpl_mkdir if the replacement function should be used. */
+/* #undef mkdir */
+
+/* Define to rpl_mkstemp if the replacement function should be used. */
+/* #undef mkstemp */
+
+/* Define to rpl_mktime if the replacement function should be used. */
+#define mktime rpl_mktime
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
+
+/* Define to the name of the strftime replacement function. */
+#define my_strftime nstrftime
+
+/* Define to rpl_nanosleep if the replacement function should be used. */
+/* #undef nanosleep */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to rpl_putenv if the replacement function should be used. */
+#define putenv rpl_putenv
+
+/* Define to rpl_realloc if the replacement function should be used. */
+/* #undef realloc */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define to widest unsigned type if <inttypes.h> doesn't define. */
+/* #undef uintmax_t */
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
+
+/* FreeBSD additions */
+#define HAVE_LANGINFO_H 1
+#define HAVE_NL_LANGINFO 1
diff --git a/gnu/usr.bin/sort/libintl.h b/gnu/usr.bin/sort/libintl.h
new file mode 100644
index 0000000..07f4c31
--- /dev/null
+++ b/gnu/usr.bin/sort/libintl.h
@@ -0,0 +1,6 @@
+/* $FreeBSD$ */
+/* Dummy file for trimmed down sort */
+
+# define gettext(Text) Text
+# define textdomain(Domain)
+# define bindtextdomain(a, b)
diff --git a/gnu/usr.bin/sort/unlocked-io.h b/gnu/usr.bin/sort/unlocked-io.h
new file mode 100644
index 0000000..3c7a476
--- /dev/null
+++ b/gnu/usr.bin/sort/unlocked-io.h
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+/* Dummy file for trimmed down sort */
diff --git a/gnu/usr.bin/tar/Makefile b/gnu/usr.bin/tar/Makefile
new file mode 100644
index 0000000..e488179
--- /dev/null
+++ b/gnu/usr.bin/tar/Makefile
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+TARDIR= ${.CURDIR}/../../../contrib/tar
+.PATH: ${TARDIR}/lib ${TARDIR}/src
+
+PROG= tar
+
+SUBDIR= doc
+
+# libtar SRCS
+SRCS= addext.c argmatch.c backupfile.c basename.c dirname.c error.c \
+ exclude.c full-write.c getdate.c getline.c getopt.c getopt1.c \
+ getstr.c hash.c human.c mktime.c modechange.c prepargs.c \
+ print-copyr.c quotearg.c safe-read.c save-cwd.c savedir.c unicodeio.c \
+ xgetcwd.c xmalloc.c xstrdup.c xstrtoul.c xstrtoumax.c
+SRCS+= buffer.c compare.c create.c delete.c extract.c incremen.c list.c \
+ mangle.c misc.c names.c rtapelib.c tar.c update.c
+
+CFLAGS+= -DHAVE_CONFIG_H -I${.CURDIR} -I${TARDIR}/lib -I${TARDIR}/src
+
+NOSHARED?= YES
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/tar/config.h b/gnu/usr.bin/tar/config.h
new file mode 100644
index 0000000..6e72423
--- /dev/null
+++ b/gnu/usr.bin/tar/config.h
@@ -0,0 +1,582 @@
+/* $FreeBSD$ */
+
+#include <paths.h>
+
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.ac by autoheader. */
+
+/* Define if the `closedir' function returns void instead of `int'. */
+/* #undef CLOSEDIR_VOID */
+
+/* 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 using `alloca.c'. */
+/* #undef C_ALLOCA */
+
+/* Define to a string giving the full name of the default archive file. */
+#define DEFAULT_ARCHIVE _PATH_DEFTAPE
+
+/* Define to a number giving the default blocking size for archives. */
+#define DEFAULT_BLOCKING 20
+
+/*
+ [Define], [to], [1], [if], [density], [may], [be], [indicated], [by], [[lmh]], [at], [end], [of], [device.]
+ */
+/* #undef DENSITY_LETTER */
+
+/* Define to a string giving the prefix of the default device, without the
+ part specifying the unit and density. */
+#define DEVICE_PREFIX _PATH_DEFTAPE
+
+/* Define if there is a member named d_ino in the struct describing directory
+ headers. */
+#define D_INO_IN_DIRENT 1
+
+/* Define to 1 if translation of program messages to the user's native
+ language is requested. */
+#define ENABLE_NLS 0
+
+/* Define if you have the `alarm' function. */
+#define HAVE_ALARM 1
+
+/* Define if you have `alloca', as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have the <argz.h> header file. */
+/* #undef HAVE_ARGZ_H */
+
+/* Define if you have the `clock_gettime' function. */
+#define HAVE_CLOCK_GETTIME 1
+
+/* Define if backslash-a works in C strings. */
+#define HAVE_C_BACKSLASH_A 1
+
+/* Define if you have the `dcgettext' function. */
+#define HAVE_DCGETTEXT 1
+
+/* Define to 1 if free is declared. */
+#define HAVE_DECL_FREE 1
+
+/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't.
+ */
+#define HAVE_DECL_GETENV 1
+
+/* Define to 1 if getgrgid is declared. */
+#define HAVE_DECL_GETGRGID 1
+
+/* Define to 1 if getpwuid is declared. */
+#define HAVE_DECL_GETPWUID 1
+
+/* Define to 1 if malloc is declared. */
+#define HAVE_DECL_MALLOC 1
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRERROR_R 1
+
+/* Define to 1 if you have the declaration of `strtoul', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOUL 1
+
+/* Define to 1 if you have the declaration of `strtoull', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOULL 1
+
+/* Define to 1 if you have the declaration of `strtoumax', and to 0 if you
+ don't. */
+#define HAVE_DECL_STRTOUMAX 1
+
+/* Define if you have the <dirent.h> header file, and it defines `DIR'. */
+#define HAVE_DIRENT_H 1
+
+/* Define if the malloc check has been performed. */
+#define HAVE_DONE_WORKING_MALLOC_CHECK 1
+
+/* Define if the realloc check has been performed. */
+#define HAVE_DONE_WORKING_REALLOC_CHECK 1
+
+/* Define if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define if you have the `fchdir' function. */
+#define HAVE_FCHDIR 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the `feof_unlocked' function. */
+/* #undef HAVE_FEOF_UNLOCKED */
+
+/* Define if you have the `fgets_unlocked' function. */
+/* #undef HAVE_FGETS_UNLOCKED */
+
+/* Define if your system has a working `fnmatch' function. */
+#define HAVE_FNMATCH 1
+
+/* Define if you have the `fsync' function. */
+#define HAVE_FSYNC 1
+
+/* Define if you have the `ftime' function. */
+/* #undef HAVE_FTIME */
+
+/* Define if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define if getcwd (NULL, 0) allocates memory for result. */
+#define HAVE_GETCWD_NULL 1
+
+/* Define if you have the `getegid' function. */
+#define HAVE_GETEGID 1
+
+/* Define if you have the `geteuid' function. */
+#define HAVE_GETEUID 1
+
+/* Define if you have the `getgid' function. */
+#define HAVE_GETGID 1
+
+/* Define if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* Define if you have the `getuid' function. */
+#define HAVE_GETUID 1
+
+/* Define if you have the iconv() function. */
+/* #undef HAVE_ICONV */
+
+/* Define if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define if you have the `iswprint' function. */
+/* #undef HAVE_ISWPRINT */
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define if you have the `lchown' function. */
+#define HAVE_LCHOWN 1
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#define HAVE_LC_MESSAGES 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <linux/fd.h> header file. */
+/* #undef HAVE_LINUX_FD_H */
+
+/* Define if you have the <locale.h> header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define if you support file names longer than 14 characters. */
+#define HAVE_LONG_FILE_NAMES 1
+
+/* Define if you have the long long type. */
+#define HAVE_LONG_LONG 1
+
+/* Define if you have the `lstat' function. */
+#define HAVE_LSTAT 1
+
+/* Define if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
+/* #undef HAVE_MBRTOWC */
+
+/* Define if you have the `mbsinit' function. */
+/* #undef HAVE_MBSINIT */
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the `mempcpy' function. */
+/* #undef HAVE_MEMPCPY */
+
+/* Define if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define if you have the `mkfifo' function. */
+#define HAVE_MKFIFO 1
+
+/* Define to 1 if the mknod function is available. */
+#define HAVE_MKNOD 1
+
+/* Define if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define if you have the `munmap' function. */
+#define HAVE_MUNMAP 1
+
+/* Define if you have the `nap' function. */
+/* #undef HAVE_NAP */
+
+/* Define if you have the `napms' function. */
+/* #undef HAVE_NAPMS */
+
+/* Define if you have the <ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <netdb.h> header file. */
+/* #undef HAVE_NETDB_H */
+
+/* Define if you have the <net/errno.h> header file. */
+/* #undef HAVE_NET_ERRNO_H */
+
+/* Define if you have the <nl_types.h> header file. */
+#define HAVE_NL_TYPES_H 1
+
+/* Define if you have the `pathconf' function. */
+#define HAVE_PATHCONF 1
+
+/* Define if you have the `poll' function. */
+#define HAVE_POLL 1
+
+/* Define if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the `readlink' function. */
+#define HAVE_READLINK 1
+
+/* Define if you have the `rename' function. */
+#define HAVE_RENAME 1
+
+/* Define if you have the `rmdir' function. */
+#define HAVE_RMDIR 1
+
+/* Define if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the `setenv' function. */
+#define HAVE_SETENV 1
+
+/* Define if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define if you have the <stdbool.h> header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define if you have the <stddef.h> header file. */
+#define HAVE_STDDEF_H 1
+
+/* Define if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the `stpcpy' function. */
+/* #undef HAVE_STPCPY */
+
+/* Define if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the `strerror_r' function. */
+#define HAVE_STRERROR_R 1
+
+/* Define if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define if you have the `strtoull' function. */
+/* #undef HAVE_STRTOULL */
+
+/* Define if you have the `strtoumax' function. */
+#define HAVE_STRTOUMAX 1
+
+/* Define if `st_blksize' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+
+/* Define if `st_blocks' is member of `struct stat'. */
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+
+/* Define if `tm_zone' is member of `struct tm'. */
+#define HAVE_STRUCT_TM_TM_ZONE 1
+
+/* Define if your `struct stat' has `st_blksize'. Deprecated, use
+ `HAVE_STRUCT_STAT_ST_BLKSIZE' instead. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define if your `struct stat' has `st_blocks'. Deprecated, use
+ `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */
+#define HAVE_ST_BLOCKS 1
+
+/* Define if struct stat has a char st_fstype[] member. */
+/* #undef HAVE_ST_FSTYPE_STRING */
+
+/* Define if you have the `symlink' function. */
+#define HAVE_SYMLINK 1
+
+/* Define if you have the <sys/buf.h> header file. */
+#define HAVE_SYS_BUF_H 1
+
+/* Define if you have the <sys/device.h> header file. */
+/* #undef HAVE_SYS_DEVICE_H */
+
+/* Define if you have the <sys/dir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/gentape.h> header file. */
+/* #undef HAVE_SYS_GENTAPE_H */
+
+/* Define if you have the <sys/inet.h> header file. */
+/* #undef HAVE_SYS_INET_H */
+
+/* Define if you have the <sys/ioccom.h> header file. */
+#define HAVE_SYS_IOCCOM_H 1
+
+/* Define if you have the <sys/io/trioctl.h> header file. */
+/* #undef HAVE_SYS_IO_TRIOCTL_H */
+
+/* Define if you have the <sys/mtio.h> header file. */
+#define HAVE_SYS_MTIO_H 1
+
+/* Define if you have the <sys/ndir.h> header file, and it defines `DIR'. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/tape.h> header file. */
+/* #undef HAVE_SYS_TAPE_H */
+
+/* Define if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <sys/tprintf.h> header file. */
+/* #undef HAVE_SYS_TPRINTF_H */
+
+/* Define if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define if your `struct tm' has `tm_zone'. Deprecated, use
+ `HAVE_STRUCT_TM_TM_ZONE' instead. */
+#define HAVE_TM_ZONE 1
+
+/* Define if you have the `tsearch' function. */
+#define HAVE_TSEARCH 1
+
+/* Define if you don't have `tm_zone' but do have the external array `tzname'.
+ */
+/* #undef HAVE_TZNAME */
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the unsigned long long type. */
+#define HAVE_UNSIGNED_LONG_LONG 1
+
+/* Define if you have the `usleep' function. */
+#define HAVE_USLEEP 1
+
+/* Define to 1 if utime.h exists and declares struct utimbuf. */
+#define HAVE_UTIME_H 1
+
+/* Define if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define if you have the <wchar.h> header file. */
+#define HAVE_WCHAR_H 1
+
+/* Define if you have the <wctype.h> header file. */
+#define HAVE_WCTYPE_H 1
+
+/* Define to 1 if `strerror_r' returns a string. */
+/* #undef HAVE_WORKING_STRERROR_R */
+
+/* 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 as const if the declaration of iconv() needs const. */
+/* #undef ICONV_CONST */
+
+/* Define if `major', `minor', and `makedev' are declared in <mkdev.h>. */
+/* #undef MAJOR_IN_MKDEV */
+
+/* Define if `major', `minor', and `makedev' are declared in <sysmacros.h>. */
+/* #undef MAJOR_IN_SYSMACROS */
+
+/* Define to mt_model (v.g., for DG/UX), else to mt_type. */
+#define MTIO_CHECK_FIELD mt_type
+
+/* Name of package */
+#define PACKAGE "tar"
+
+/* Define if the C compiler supports function prototypes. */
+#define PROTOTYPES 1
+
+/* Define to the full path of your rsh, if any. */
+#define REMOTE_SHELL _PATH_RSH
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* 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. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define to 1 if using the included libintl implementation. */
+/* #undef USE_INCLUDED_LIBINTL */
+
+/* Version number of package */
+#define VERSION "1.13.25"
+
+/* 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
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define unconditionally for setting a GNU environment. */
+#define _GNU_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define if the system does not provide POSIX.1 features except with this
+ defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for `stat' and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define as `__inline' if that's what the C compiler calls it, or to nothing
+ if it is not supported. */
+/* #undef inline */
+
+/* Define to widest signed type if <inttypes.h> doesn't define. */
+/* #undef intmax_t */
+
+/* Type of major device numbers. */
+#define major_t int
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to a type if <wchar.h> does not define. */
+/* #undef mbstate_t */
+
+/* Type of minor device numbers. */
+#define minor_t int
+
+/* Define to rpl_mktime if the replacement function should be used. */
+#define mktime rpl_mktime
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to rpl_realloc if the replacement function should be used. */
+/* #undef realloc */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Type of sizes or error indications. */
+/* #undef ssize_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define to widest unsigned type if <inttypes.h> doesn't define. */
+/* #undef uintmax_t */
diff --git a/gnu/usr.bin/tar/doc/Makefile b/gnu/usr.bin/tar/doc/Makefile
new file mode 100644
index 0000000..2d2657d
--- /dev/null
+++ b/gnu/usr.bin/tar/doc/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+INFO= tar
+SRCDIR= ${.CURDIR}/../../../../contrib/tar/doc
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/tar/localedir.h b/gnu/usr.bin/tar/localedir.h
new file mode 100644
index 0000000..da23dbe
--- /dev/null
+++ b/gnu/usr.bin/tar/localedir.h
@@ -0,0 +1 @@
+/* $FreeBSD$ */
diff --git a/gnu/usr.bin/tar/tar.1 b/gnu/usr.bin/tar/tar.1
new file mode 100644
index 0000000..3cc2ea7
--- /dev/null
+++ b/gnu/usr.bin/tar/tar.1
@@ -0,0 +1,573 @@
+.\" Copyright (c) 1991, 1992, 1993 Free Software Foundation -*- nroff -*-
+.\" See /usr/src/gnu/COPYING for conditions of redistribution
+.\"
+.\" Written by John F. Woods <jfw@jfwhome.funhouse.com>
+.\" Updated by Robert Eckardt <roberte@mep.ruhr-uni-bochum.de>
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 23, 2000
+.Os
+.Dt TAR 1
+.Sh NAME
+.Nm tar
+.Nd "tape archiver; manipulate ""tar"" archive files"
+.Sh SYNOPSIS
+.Nm
+.Op Oo Fl Oc Ns Ar bundled-options Ar Args
+.Op Ar gnu-style-flags
+.Op Ar filenames | Fl C Ar directory-name
+.Ar ...
+.Sh DESCRIPTION
+.Nm Tar
+is short for
+.Dq tape archiver ,
+so named for historical reasons; the
+.Nm
+program creates, adds files to, or extracts files from an archive file
+in
+.Nm
+format, called a
+.Ar tarfile .
+A
+.Ar tarfile
+is often a magnetic tape, but can be a floppy diskette or any
+regular disk file.
+.Pp
+The first argument word of the
+.Nm
+command line is usually a command word of bundled function and modifier
+letters, optionally preceded by a dash;
+it must contain exactly one function letter from the set
+.Cm A ,
+.Cm c ,
+.Cm d ,
+.Cm r ,
+.Cm t ,
+.Cm u ,
+.Cm x ,
+for
+.Em append ,
+.Em create ,
+.Em difference ,
+.Em replace ,
+.Em table of contents ,
+.Em update ,
+and
+.Em extract
+(further described below).
+The command word can also contain other function modifiers described below,
+some of which will take arguments from the command line in the order they
+are specified in the command word (review the
+.Sx EXAMPLES
+section).
+Functions and function modifiers can also be specified
+with the GNU argument convention (preceded by two dashes, one function or
+modifier per word.
+Command-line arguments that specify files to
+add to, extract from, or list from an archive may be given as shell
+pattern matching strings.
+.Sh FUNCTIONS
+Exactly one of the following functions must be specified.
+.Pp
+.Bl -tag -width "--concatenate" -compact
+.It Fl A
+.It Fl -catenate
+.It Fl "-concatenate"
+Append the contents of named file, which must itself be a
+.Nm
+archive,
+to the end of the archive (erasing the old end-of-archive block).
+This has the effect of adding the files contained in the named file to
+the first archive, rather than adding the second archive as an element
+of the first.
+.Em Note :
+This option requires a rewritable
+.Ar tarfile ,
+and therefore does not work on quarter-inch cartridge tapes.
+.It Fl c
+.It Fl -create
+Create a new archive (or truncates an old one) and writes the named files
+to it.
+.It Fl d
+.It Fl -diff
+.It Fl -compare
+Find differences between files in the archive and corresponding files in
+the file system.
+.It Fl -delete
+Delete named files from the archive.
+(Does not work on quarter-inch tapes).
+.It Fl r
+.It Fl -append
+Append files to the end of an archive.
+(Does not work on quarter-inch tapes).
+.It Fl t
+.It Fl -list
+List the contents of an archive; if
+.Ar filename
+arguments are given, only those
+files are listed, otherwise the entire table of contents is listed.
+.It Fl u
+.It Fl -update
+Append the named files if the on-disk version has a modification date
+more recent than their copy in the archive (if any).
+Does not work on quarter-inch tapes.
+.It Fl x
+.It Fl -extract
+.It Fl -get
+Extract files from an archive.
+The owner, modification time, and file permissions are restored, if possible.
+If no
+.Ar file
+arguments are given, extract all the files in the archive.
+If a
+.Ar filename
+argument matches the name of a directory on the tape, that directory and
+its contents are extracted (as well as all directories under that directory).
+If the archive contains multiple entries corresponding to the same file
+(see the
+.Fl -append
+command above), the last one extracted will overwrite all earlier versions.
+.El
+.Sh OPTIONS
+The other options to
+.Nm
+may be combined arbitrarily; single-letter options may be bundled in with
+the command word.
+Verbose options which take arguments will be
+followed by the argument; single-letter options will consume
+successive command line arguments (see the
+.Sx EXAMPLES
+below).
+.Pp
+.Bl -tag -width "--preserve-permissions" -compact
+.It Fl -help
+Prints a message listing and briefly describing all the command
+options to
+.Nm .
+.It Fl -atime-preserve
+Restore the access times on files which are written to tape (note that
+this will change the inode-change time!).
+.It Fl b
+.It Fl -block-size Ar number
+Sets the block size for reading or writing to
+.Ar number
+* 512-byte blocks.
+.It Fl B
+.It Fl -read-full-blocks
+Re-assemble short reads into full blocks (for reading
+.Bx 4.2
+pipes).
+.It Fl C Ar directory
+.It Fl -directory Ar directory
+Change to
+.Ar directory
+before processing the remaining arguments.
+.It Fl -checkpoint
+Print number of buffer reads/writes while reading/writing the archive.
+.It Fl f Xo
+.Oo Ar hostname : Oc Ns Ar file
+.Xc
+.It Fl -file Xo
+.Oo Ar hostname : Oc Ns Ar file
+.Xc
+Read or write the specified
+.Ar file
+(default is
+.Pa /dev/sa0 ) .
+If a
+.Ar hostname
+is specified,
+.Nm
+will use
+.Xr rmt 8
+to read or write the specified
+.Ar file
+on a remote machine.
+.Dq Ar -
+may be used as a filename, for reading
+or writing to/from stdin/stdout.
+.It Fl -force-local
+Archive file is local even if it has a colon.
+.It Fl F Ar file
+.It Fl -info-script Ar file
+.It Fl -new-volume-script Ar file
+Run a script at the end of each archive volume (implies
+.Fl M ) .
+.It Fl -fast-read
+Stop after all non-wildcard extraction targets have been found
+in the archive.
+.It Fl G
+.It Fl -incremental
+Create/list/extract old GNU-format incremental backup.
+.It Fl g Ar file
+.It Fl -listed-incremental Ar file
+Create/list/extract new GNU-format incremental backup.
+.It Fl h
+.It Fl -dereference
+Don't write symlinks as symlinks; write the data of the files they name.
+.It Fl i
+.It Fl -ignore-zeros
+Ignore blocks of zeroes in archive (usually means End-Of-File).
+.It Fl -ignore-failed-read
+Don't exit with non-zero status on unreadable files.
+.It Fl j
+.It Fl y
+.It Fl -bzip
+.It Fl -bzip2
+.It Fl -bunzip2
+Filter the archive through
+.Xr bzip2 1 .
+.It Fl k
+.It Fl -keep-old-files
+Keep files which already exist on disk; don't overwrite them from the archive.
+.It Fl K Ar file
+.It Fl -starting-file Ar file
+Begin at
+.Ar file
+in the archive.
+.It Fl l
+.It Fl -one-file-system
+Stay in local filesystem when creating an archive (do not cross mount
+points).
+.It Fl L Ar number
+.It Fl -tape-length Ar number
+Change tapes after writing
+.Ar number
+* 1024 bytes.
+.It Fl m
+.It Fl -modification-time
+Don't extract file modified time.
+.It Fl M
+.It Fl -multi-volume
+Create/list/extract multi-volume archive.
+.It Fl n
+.It Fl -norecurse
+Don't recurse into subdirectories when creating.
+.It Fl -volno-file Ar file
+File name with volume number to start with.
+.It Fl N Ar date
+.It Fl -after-date Ar date
+.It Fl -newer Ar date
+Only store files with creation time newer than
+.Ar date .
+.It Fl -newer-mtime Ar date
+Only store files with modification time newer than
+.Ar date .
+.It Fl o
+.It Fl -old-archive
+.It Fl -portability
+Write a V7 format archive, rather than POSIX format.
+.It Fl O
+.It Fl -to-stdout
+Extract files to standard output.
+.It Fl p
+.It Fl -same-permissions
+.It Fl -preserve-permissions
+Extract all protection information.
+.It Fl -preserve
+Has the effect of
+.Fl p s .
+.It Fl P
+.It Fl -absolute-paths
+Don't strip leading
+.Ql /
+from file names.
+.It Fl R
+.It Fl -record-number
+Show record number within archive with each message.
+.It Fl -remove-files
+Remove files after adding them to the archive.
+.It Fl s
+.It Fl -same-order
+.It Fl -preserve-order
+List of names to extract is sorted to match archive.
+.It Fl -show-omitted-dirs
+Show directories which were omitted while processing the archive.
+.It Fl S
+.It Fl -sparse
+Handle
+.Dq sparse
+files efficiently.
+.It Fl T Ar file
+.It Fl I Ar file
+.It Fl -files-from Ar file
+Get names of files to extract or create from
+.Ar file ,
+one per line.
+.It Fl -null
+Modifies behavior of
+.Fl T
+to expect null-terminated names; disables
+.Fl C .
+.It Fl -totals
+Prints total bytes written with
+.Fl -create .
+.It Fl U
+.It Fl -unlink
+.It Fl -unlink-first
+Unlink files before creating them.
+.It Fl v
+.It Fl -verbose
+Lists files written to archive with
+.Fl -create
+or extracted with
+.Fl -extract ;
+lists file protection information along with file names with
+.Fl -list .
+.It Fl V Ar volume-name
+.It Fl -label Ar volume-name
+Create archive with the given
+.Ar volume-name .
+.It Fl -version
+Print
+.Nm
+program version number.
+.It Fl w
+.It Fl -interactive
+.It Fl -confirmation
+Ask for confirmation for every action.
+.It Fl W
+.It Fl -verify
+Attempt to verify the archive after writing it.
+.It Fl -exclude Ar pattern
+Exclude files matching the
+.Ar pattern
+(don't extract them, don't add them, don't list them).
+.It Fl X Ar file
+.It Fl -exclude-from Ar file
+Exclude files listed in
+.Ar file .
+.It Fl Z
+.It Fl -compress
+.It Fl -uncompress
+Filter the archive through
+.Xr compress 1 .
+.It Fl z
+.It Fl -gzip
+.It Fl -gunzip
+Filter the archive through
+.Xr gzip 1 .
+.It Fl -use-compress-program Ar program
+Filter the archive through
+.Ar program
+(which must accept
+.Fl d
+to mean
+.Dq decompress ) .
+.It Fl -block-compress
+Block the output of compression program for tapes or floppies
+(otherwise writes will be of odd length, which device drivers may reject).
+.It Fl Xo
+.Op Cm 0 Ns - Ns Cm 7 Ns
+.Op Cm lmh
+.Xc
+Specify tape drive and density.
+.El
+.Sh ENVIRONMENT
+The environment variable
+.Ev TAR_OPTIONS
+can hold a set of default options for
+.Nm .
+These options are interpreted first and can be overwritten by explicit command
+line parameters.
+.Sh EXAMPLES
+To create an archive on tape drive
+.Pa /dev/sa0
+with a block size of 20 blocks, containing files named
+.Pa bert
+and
+.Pa ernie ,
+you can enter
+.Dl "tar cfb /dev/sa0 20 bert ernie"
+or
+.Dl "tar --create --file /dev/sa0 --block-size 20 bert ernie"
+Note that the
+.Fl f
+and
+.Fl b
+flags both require arguments, which they take from the command line in
+the order they were listed in the command word.
+.Pp
+Because
+.Pa /dev/sa0
+is the default device, and 20 is the default block
+size, the above example could have simply been
+.Dl "tar c bert ernie"
+.Pp
+To extract all the C sources and headers from an archive named
+.Pa backup.tar ,
+type
+.Dl "tar xf backup.tar '*.[ch]'"
+Note that the pattern must be quoted to prevent the shell from
+attempting to expand it according the files in the current working
+directory (the shell does not have access to the list of files in
+the archive, of course).
+.Pp
+To move file hierarchies, use a command line like this:
+.Bd -literal
+tar -cf - -C srcdir . | tar xpf - -C destdir
+.Ed
+.Pp
+To create a compressed archive on diskette, using
+.Xr gzip 1 ,
+use a command-line like
+.Dl "tar --block-compress -z -c -v -f /dev/fd1a -b 36 tar/"
+.Pp
+Note that you cannot mix bundled flags and
+.Fl -style
+flags; you can use
+single-letter flags in the manner above, rather than having to type
+.Dl "tar --block-compress --gzip --verbose --file /dev/fd1a --block-size 20 tar/"
+.Pp
+The above-created diskette can be listed with
+.Dl "tar tvfbz /dev/fd1a 36"
+.Pp
+To join two
+.Nm
+archives into a single archive, use
+.Dl "tar Af archive1.tar archive2.tar"
+which will add the files contained in
+.Pa archive2.tar
+onto the end of
+.Pa archive1.tar
+(note that this can't be done by simply typing
+.Dl "cat archive2.tar >> archive1.tar"
+because of the end-of-file block at the end of a
+.Nm
+archive).
+.Pp
+To archive all files from the directory
+.Pa srcdir ,
+which were modified
+after Feb. 9th 1997, 13:00 h, use
+.Dl "tar -c -f backup.tar --newer-mtime 'Feb 9 13:15 1997' srcdir/"
+.Pp
+Other possible time specifications are
+.Sq "02/09/97 13:15" ,
+.Sq "1997-02-09 13:15" ,
+.Sq "13:15 9 Feb 1997" ,
+.Sq "9 Feb 1997 13:15" ,
+.Sq "Feb. 9, 1997 1:15pm" ,
+.Sq "09-Feb" ,
+.Sq "3 weeks ago"
+or
+.Sq "May first Sunday" .
+To specify the correct time zone use either e.g.\&
+.Sq "13:15 CEST"
+or
+.Sq "13:15+200" .
+.Sh ENVIRONMENT
+The
+.Nm
+program examines the following environment variables.
+.Bl -tag -width "POSIXLY_CORRECT"
+.It Ev POSIXLY_CORRECT
+Normally,
+.Nm
+will process flag arguments that appear in the file list.
+If set in the environment, this causes
+.Nm
+to consider the first
+non-flag argument to terminate flag processing, as per the POSIX specification.
+.It Ev SHELL
+In interactive mode, a permissible response to the prompt is to
+request to spawn a subshell, which will be
+.Pa /bin/sh
+unless the
+.Ev SHELL
+variable is set.
+.It Ev TAPE
+Changes
+.Nm Ns 's
+default tape drive (which is still overridden by the
+.Fl f
+flag).
+.It TAR_RSH
+The TAR_RSH environment variable allows you to override the default
+shell used as the transport for
+.Nm .
+.El
+.Sh FILES
+.Bl -tag -width "/dev/sa0"
+.It Pa /dev/sa0
+The default tape drive.
+.El
+.Sh COMPATIBILITY
+The
+.Fl y
+is a
+.Fx
+localism.
+The GNU
+.Nm
+maintainer has now choosen
+.Fl j
+as the offical
+.Xr bzip2 1
+compression option in GNU
+.Nm
+1.13.18 and later.
+The
+.Fl I
+option is for compatibility with Solaris's
+.Nm .
+.Sh SEE ALSO
+.Xr bzip2 1 ,
+.Xr compress 1 ,
+.Xr gzip 1 ,
+.Xr pax 1 ,
+.Xr rmt 8
+.Sh HISTORY
+The
+.Nm
+format has a rich history, dating back to Sixth Edition
+.Ux .
+The current implementation of
+.Nm
+is the GNU implementation, which
+originated as the public-domain
+.Nm
+written by
+.An John Gilmore .
+.Sh AUTHORS
+.An -nosplit
+A cast of thousands, including [as listed in the
+.Pa ChangeLog
+file in the source]
+.An John Gilmore
+(author of original public domain version),
+.An Jay Fenlason
+(first GNU author),
+.An Joy Kendall ,
+.An Jim Kingdon ,
+.An David J. MacKenzie ,
+.An Michael I Bushnell ,
+.An Noah Friedman ,
+and innumerable others who have contributed fixes and additions.
+.Pp
+Man page obtained by the
+.Fx
+group from the
+.Nx 1.0
+release.
+.Sh BUGS
+The
+.Fl C
+feature does not work like historical
+.Nm
+programs, and is probably untrustworthy.
+.Pp
+The
+.Fl A
+command should work to join an arbitrary number of
+.Nm
+archives
+together, but it does not; attempting to do so leaves the
+end-of-archive blocks in place for the second and subsequent archives.
+.Pp
+The
+.Nm
+file format is a semi fixed width field format, and the field
+for device numbers were designed for 16 bit (8 major, 8 minor)
+and can not absorb our 32 bit (8 major, 16+8 minor) numbers.
diff --git a/gnu/usr.bin/texinfo/Makefile b/gnu/usr.bin/texinfo/Makefile
new file mode 100644
index 0000000..dc0d9e4
--- /dev/null
+++ b/gnu/usr.bin/texinfo/Makefile
@@ -0,0 +1,7 @@
+#
+# $FreeBSD$
+#
+
+SUBDIR= libtxi makeinfo info infokey install-info texindex doc
+
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/texinfo/Makefile.inc b/gnu/usr.bin/texinfo/Makefile.inc
new file mode 100644
index 0000000..f13fa38
--- /dev/null
+++ b/gnu/usr.bin/texinfo/Makefile.inc
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+TXIDIR= ${.CURDIR}/../../../../contrib/texinfo
+
+.if exists(${.OBJDIR}/../libtxi)
+LIBTXI= ${.OBJDIR}/../libtxi/libtxi.a
+.else
+LIBTXI= ${.CURDIR}/../libtxi/libtxi.a
+.endif
+
+CFLAGS+= -DHAVE_CONFIG_H -DLOCALEDIR=\"/usr/share/locale\" \
+ -I${TXIDIR} -I${TXIDIR}/lib
+
+.include "../Makefile.inc"
diff --git a/gnu/usr.bin/texinfo/doc/Makefile b/gnu/usr.bin/texinfo/doc/Makefile
new file mode 100644
index 0000000..2a0b1a3
--- /dev/null
+++ b/gnu/usr.bin/texinfo/doc/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+INFO= info info-stnd texinfo
+SRCDIR= ${TXIDIR}/doc
+
+CLEANFILES= texinfo.texi
+
+texinfo.texi: texinfo.txi
+ ln -fs ${.ALLSRC} ${.TARGET}
+
+.include <bsd.info.mk>
diff --git a/gnu/usr.bin/texinfo/info/Makefile b/gnu/usr.bin/texinfo/info/Makefile
new file mode 100644
index 0000000..07dedea
--- /dev/null
+++ b/gnu/usr.bin/texinfo/info/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+PROG= info
+MAN= info.1 info.5 texinfo.5
+
+SRCS= dir.c display.c doc.c dribble.c echo-area.c filesys.c \
+ footnotes.c gc.c indices.c info-utils.c info.c infodoc.c \
+ infomap.c m-x.c man.c nodemenu.c nodes.c search.c session.c \
+ signals.c terminal.c tilde.c variables.c window.c
+
+CFLAGS+= -DINFODIR=\"${INFODIR}:/usr/local/info:/usr/X11R6/info:.\"
+
+DPADD= ${LIBTERMCAP} ${LIBTXI}
+LDADD= -ltermcap ${LIBTXI}
+
+.include <bsd.prog.mk>
+
+.PATH: ${TXIDIR}/info ${TXIDIR}/doc
diff --git a/gnu/usr.bin/texinfo/infokey/Makefile b/gnu/usr.bin/texinfo/infokey/Makefile
new file mode 100644
index 0000000..4f06ef2
--- /dev/null
+++ b/gnu/usr.bin/texinfo/infokey/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+PROG= infokey
+SRCS= infokey.c key.c
+NOMAN= noman
+
+DPADD= ${LIBTXI}
+LDADD= ${LIBTXI}
+
+.include <bsd.prog.mk>
+
+.PATH: ${TXIDIR}/info
diff --git a/gnu/usr.bin/texinfo/install-info/Makefile b/gnu/usr.bin/texinfo/install-info/Makefile
new file mode 100644
index 0000000..325c909
--- /dev/null
+++ b/gnu/usr.bin/texinfo/install-info/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG= install-info
+
+DPADD= ${LIBTXI}
+LDADD= ${LIBTXI}
+
+.include <bsd.prog.mk>
+
+.PATH: ${TXIDIR}/util ${TXIDIR}/doc
diff --git a/gnu/usr.bin/texinfo/libtxi/Makefile b/gnu/usr.bin/texinfo/libtxi/Makefile
new file mode 100644
index 0000000..96df19a
--- /dev/null
+++ b/gnu/usr.bin/texinfo/libtxi/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+LIB= txi
+INTERNALLIB= true
+
+SRCS= getopt.c getopt1.c substring.c xexit.c xmalloc.c xstrdup.c
+
+.include <bsd.lib.mk>
+
+.PATH: ${TXIDIR}/lib
diff --git a/gnu/usr.bin/texinfo/makeinfo/Makefile b/gnu/usr.bin/texinfo/makeinfo/Makefile
new file mode 100644
index 0000000..48c776c
--- /dev/null
+++ b/gnu/usr.bin/texinfo/makeinfo/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+PROG= makeinfo
+SRCS= cmds.c docbook.c defun.c files.c footnote.c html.c \
+ index.c insertion.c lang.c macro.c makeinfo.c multi.c \
+ node.c sectioning.c toc.c xml.c
+
+DPADD= ${LIBTXI}
+LDADD= ${LIBTXI}
+
+.include <bsd.prog.mk>
+
+.PATH: $(TXIDIR)/makeinfo $(TXIDIR)/doc
diff --git a/gnu/usr.bin/texinfo/texindex/Makefile b/gnu/usr.bin/texinfo/texindex/Makefile
new file mode 100644
index 0000000..91c2dfc
--- /dev/null
+++ b/gnu/usr.bin/texinfo/texindex/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG= texindex
+
+DPADD= ${LIBTXI}
+LDADD= ${LIBTXI}
+
+.include <bsd.prog.mk>
+
+.PATH: ${TXIDIR}/util ${TXIDIR}/doc
OpenPOWER on IntegriCloud